Window
Generated from engine/app/window.h at 862e08b. The text under each declaration is the header's own comment, word for word. About the reference says how these pages are made.
#include "engine/app/window.h" · namespace labrador
class WindowNotify
Section titled “class WindowNotify”What a window has to tell whoever owns it. Modelled on DeviceNotify (engine/render/renderer.h) and const-qualified the same way: a handler that only reads the world is const, and one that changes it is not.
THE ACTIVATION FOUR ARE ON THE CHANGING SIDE, because they carry the news into the state stack, where a game's own code runs and may push, pop or transition. Fanning that out from a const handler would compile - the states hang off unique_ptrs, whose constness is one level deep - which is the reason the signature says so rather than leaning on it.
virtual void tick() = 0;The queue is empty, so this is the frame. It is not a window event - it is what the pump does when there is nothing else to do, and it is here because WM_PAINT needs it too: while the user drags an edge Windows owns the loop, and painting is the only way back in.
on_activated · on_deactivated · on_suspending · on_resuming · on_window_moved · on_window_size_changed
Section titled “on_activated · on_deactivated · on_suspending · on_resuming · on_window_moved · on_window_size_changed”virtual void on_activated() = 0;virtual void on_deactivated() = 0;virtual void on_suspending() = 0;virtual void on_resuming() = 0;virtual void on_window_moved() const = 0;virtual void on_window_size_changed(int width, int height) = 0;on_key_down · on_key_up · on_text
Section titled “on_key_down · on_key_up · on_text”virtual void on_key_up(Key key) const = 0;virtual void on_text(char32_t codepoint) const = 0;THE KEYBOARD AND THE MOUSE, and they are here rather than behind a reader in engine/input/ because there is nowhere else they could be. A pad is polled: input/xinput/ asks XInput for a snapshot and owes this file nothing. These two arrive as messages in this window's queue, so the only way into the input module is out through here - which is the whole reason input is fed rather than read, and the reason nothing in it names a window (keyboard.h says it at length).
const, like on_window_moved and for the same reason: they change nothing about the window, and everything they do reach is borrowed and fed rather than asked anything.
Already translated, both directions. Key and MouseButton are the engine's own names, decided in window.cpp from the platform's codes, and codepoint is UTF-32 with any surrogate pair already assembled. Nothing above this line meets a VK_ constant or a UTF-16 unit - message translation lives here, and that is the whole of the job this class exists to hand over.
on_mouse_move · on_mouse_button_down · on_mouse_button_up
Section titled “on_mouse_move · on_mouse_button_down · on_mouse_button_up”virtual void on_mouse_move(int x, int y) const = 0;virtual void on_mouse_button_up(MouseButton button) const = 0;on_mouse_capture_lost
Section titled “on_mouse_capture_lost”virtual void on_mouse_capture_lost() const;Cancel any held gesture without treating capture transfer as release.
on_mouse_wheel · on_mouse_wheel_horizontal
Section titled “on_mouse_wheel · on_mouse_wheel_horizontal”virtual void on_mouse_wheel(float notches) const = 0;virtual void on_mouse_wheel_horizontal(float notches) const = 0;Notches, signed, fractional on a high-resolution wheel. Two functions rather than one with an axis flag, because a caller reading on_mouse_wheel(delta, true) cannot tell which way true points without looking it up (T4).
~WindowNotify (protected)
Section titled “~WindowNotify (protected)”struct WindowOptions
Section titled “struct WindowOptions”What the window needs to exist. The names are ApplicationOptions' names on purpose: this is the subset of them a window can act on, and nothing about their meaning changes on the way across.
window_class_name · window_title
Section titled “window_class_name · window_title”std::wstring window_class_name = L"LabradorWindowClass";std::wstring window_title = L"Labrador";Unique per process, so a game that ever opens two windows needs two.
client_size
Section titled “client_size”CLIENT pixels - the area the game draws into, not the outer rect. Turning one into the other is this class's job and nobody else's.
fullscreen
Section titled “fullscreen”bool fullscreen = false;min_window_width · min_window_height
Section titled “min_window_width · min_window_height”int min_window_width = 320;int min_window_height = 200;class Window
Section titled “class Window”The Win32 window, and the only file in the engine that knows the game runs on Windows at all outside the render and input backends.
ARCHITECTURE says platform code lives in the backend subfolders. This is the third case, named there rather than smuggled: app is already the module allowed to depend on everything, PHILOSOPHY already lists windowing alongside the rendering backend as platform code at the edge, and a second platform moves this pair down a folder without renaming the class or touching a call site.
WHAT IS DELIBERATELY NOT HERE: the handlers themselves. They stay on Application and arrive through WindowNotify, because message translation lives here and what a message means does not.
Nothing forces it. No handler here ends below the seam, so a Window taking these messages would not have to include a backend - which makes this a judgement about layering and nothing else: the better reason to keep them where they are, and a worse one to move them.
Window
Section titled “Window”Registers the class, creates the window and shows it. Throws std::runtime_error naming the step that failed (T6).
notify is taken here rather than set afterwards, and that is a contract rather than a preference: WM_CREATE and the WM_SIZE that ShowWindow fires both arrive before this constructor returns, and that WM_SIZE is load-bearing - it is what corrects the caller to the client size the window really got, which matters most going full screen at launch, where the monitor decides the size and nothing here knows it. A notify set after construction would miss both messages, and the owner would never learn the size it got.
~Window
Section titled “~Window”Destroys the native window if it still exists, and unregisters the class either way. What the constructor makes, this unmakes, on every path out - not only the one where the pump returned.
THE PUMP IS NOT THE ONLY WAY OUT of the scope that owns a Window. create_device throwing, a manifest that does not open, a state's update() throwing out of tick(): each unwinds Application while the window still exists. A window left behind would go on pointing at the destroyed Window through its user data, and a message box shown afterwards - the samples show one - runs a modal message loop, which is a way back into a window procedure that reads that pointer.
notify is never called from in here. The messages DestroyWindow sends arrive after the owner has started destroying itself - in Application's case with the renderer and the input devices already gone - so the user data is detached before the call and every one of them goes to DefWindowProc. That includes WM_DESTROY, so nothing is posted to the thread's queue: a WM_QUIT left there would dismiss the very message box the samples show next.
Window · operator=
Section titled “Window · operator=”Window& operator=(const Window&) = delete;handle
Section titled “handle”HWND handle() const;Null once the native window is gone, whether close() took it or the user did. Nothing that reaches a stale HWND is a valid call, and a caller holding one after run() has returned would be making one.
exit_code
Section titled “exit_code”int exit_code() const;The process exit code, valid once pump_until_quit has returned.
pump_until_quit
Section titled “pump_until_quit”void pump_until_quit();Runs the message loop until WM_QUIT: one message if one is waiting, and otherwise notify->tick(). Ticking only on an empty queue is the loop, not an implementation detail of it - draining the queue first is a defensible design and a different one, and it changes frame pacing.
void close() const;Destroys the window, which ends the pump. The whole of the quit path: a game asking to exit does not need to know it is on Win32. A second call, or a call after the user has already closed it, does nothing: the handle is null by then.
resize_client
Section titled “resize_client”Resizes so client_size pixels are left to draw into, under whatever frame the window is currently wearing.
enter_fullscreen · leave_fullscreen
Section titled “enter_fullscreen · leave_fullscreen”void enter_fullscreen() const;Borderless and monitor-sized, and back again at client_size.
outer_size_for_client
Section titled “outer_size_for_client” const mattmath::Vector2I& client_size, DWORD style, DWORD ex_style);The outer window size that leaves client_size pixels to draw into under style/ex_style. Every Win32 call that sizes a window takes the outer rect and every resolution this engine is asked for is client area, so this conversion sits between the two - without it a windowed 1280x720 would deliver about 1264x681, silently, at every preset.
Public and static because it is the one piece of this class that can be tested without an HINSTANCE and a message pump.
Related types
Section titled “Related types”Named in the public declarations above: Key, MouseButton, Vector2I.
In the samples and tests
Section titled “In the samples and tests”The files that include this header directly. A file can also reach it through another header.
tests/app/window_tests.cpp
Development documentation (unreleased). Built from Labrador 862e08b of 2026-10-08.