- A window backend is the part of the GUI that talks to the OS:
- it creates the OS windows
- it delivers mouse, keyboard and other input
- Every window backend implements tachyon::IWindowBackend (gui_core/windows/gui_window_backend.h).
- The default one is SDLWindowBackend, which Initialize creates.
- To use your own, set it before Initialize:
app.SetWindowBackend(std::make_unique<MyWindowBackend>());
app.SetClipboard(std::make_unique<MyClipboard>());
- The clipboard is what copy and paste in text fields use.
- Without SDL, when built with TACHYON_SDL=OFF:
- the clipboard defaults to LocalClipboard
- Initialize fails with ErrorCode::Unsupported unless you set a window backend
Writing a window backend
- A backend:
- creates, moves, shows and destroys OS windows
- reports their rects, their display scale and the monitors
- delivers input
- All sizes and positions are in physical pixels.
- CreateWindow returns an OSWindowHandle, a void* whose meaning the backend decides.
- GetNativeHandle returns what the graphics backend creates its surface from.
{
public:
};
Makes and manages the OS windows and delivers their input; GUIApplication::SetWindowBackend sets one,...
Definition gui_window_backend.h:105
WindowFlags
How an OS window is made and behaves (IWindowBackend::CreateWindow); flags combine with |.
Definition gui_window_flags.h:12
void * OSWindowHandle
An OS window, opaque; what it points to is up to the window backend.
Definition gui_window_backend.h:37
Integer 2D vector.
Definition gui_base_types.h:19
- PollEvents runs in UpdateFrame, and again in RecordFrame after the UI is built.
- It handles OS events.
- It calls cleanup for each window the OS destroyed.
- Input goes to the IPlatformInputHandler from AttachInputHandlerToWindow (gui_core/input/gui_platform_input_handler.h). Its functions are:
- OnMouseMove, OnMouseButton, OnMouseScroll
- OnKeyboard, OnTextComposition
- OnFileDrop
- Pass each call the window's ID, from the IWindowContext attached with AttachContextToWindow.
- Positions are in screen pixels.
inputHandler->OnMouseMove(id, screenPos, buttons, modifiers);
A 64-bit element ID whose bit layout depends on its IDMode.
Definition gui_id.h:23
- Typed text arrives as OnKeyboard with KeyAction::KeyChar, the codepoint as the key code.
- A drag from another application calls OnFileDrop in steps:
- Begin when it enters the window
- Move as the pointer moves
- on drop: a File for each path, any Text, then Complete
- Complete alone means the drag left the window
- while a modal window is open, only Complete reaches the windows behind it
- The Vulkan backend creates each window's surface through a surface factory, a function that makes a VkSurfaceKHR for one window.
- SDLWindowBackend installs its own when the app calls SetGraphicsContext on it.
- Other backends call VulkanGraphicsContext::SetSurfaceFactory.
vk->SetSurfaceFactory([](VkInstance instance, const VkAllocationCallbacks* callbacks,
{
return MyCreateSurface(instance, callbacks, window);
});
- VulkanGraphicsContext::Initialize creates a hidden 64 x 64 window through the backend, to pick a GPU that can present to it.
- The simplest backend to read is NullWindowBackend (gui_core/windows/null/gui_null_window_backend.h).
- Its windows are only records with a rect.
- No input arrives.
- Initialize wraps your backend to add render-to-image windows (see Rendering the UI into a host image).
- So app.windowBackend is not the object you passed to SetWindowBackend.
Running SDL's event loop yourself
Keep SDLWindowBackend but turn off its event pumping:
app.SetWindowBackend(std::make_unique<tachyon::SDLWindowBackend>(options));
SDLWindowBackendOptions Options
See SDLWindowBackendOptions.
Definition gui_window_backend_sdl.h:44
bool pumpEvents
PollEvents empties SDL's event queue.
Definition gui_window_backend_sdl.h:35
- The backend reads events through SDL event watches.
- So a filter you set with SDL_SetEventFilter stays in place.
- With pumpEvents on, the default:
- PollEvents pumps SDL and empties its queue
- With pumpEvents off:
- GUI windows get their events whenever you pump, with SDL_PollEvent or SDL_PumpEvents
- your own events stay in the queue
- you handle SDL_EVENT_QUIT; the GUI won't close its windows on it
- pump before UpdateFrame
while (true)
{
SDL_Event event;
while (SDL_PollEvent(&event))
if (event.type == SDL_EVENT_QUIT)
app.applicationQuit = true;
if (!app.UpdateFrame())
break;
if (!app.RecordFrame())
break;
app.PresentFrame();
}
- If SDL video is already running, the backend uses it and leaves it running.
- Otherwise it starts SDL, and quits it when destroyed.
- Tested in tests/gpu/gpu_sdl_host_event_loop_test.cpp.
- Options::hooks routes SDL's memory through allocation hooks (see Allocation hooks and headless backends).
- When the app creates the backend, it sets them for you.
- When you create the backend, pass them yourself.
const AllocationHooks * hooks
Hooks for SDL's memory functions, which are process-wide.
Definition gui_window_backend_sdl.h:31
Previous: Using your own Vulkan device | Integration | Next: Your own loop