Display and window ownership
The display owns its windows and monitor inventory. Applications borrow window
pointers and monitor references; copying a CE::Platform::Monitor retains its value, not its
native monitor or display owner. The neutral contracts are
CE::Platform::DisplaySystem,
CE::Platform::Window and
CE::Platform::Monitor.
Access native display/window state, create/mutate windows and perform teardown on the platform owner. Window size getters do not synchronize cross-thread access. Simulation and render workers receive copied logical/framebuffer dimensions through the runtime handoff, rather than querying a live window. Graphics context binding, presentation and resource domains belong to the selected graphics owner.
Native GLFW inventory and selection
CE::Platform::GLFW::DisplaySystem shares GLFW initialization lifetime with other live displays and owns every window it creates. Its windows are destroyed before its GLFW lifetime share is released; the final display terminates GLFW. Input adapters detach while their window is live, and graphics resources/context users finish before window/display destruction. The native input lifetime also requires the original Windows notification window to outlive its initialized adapter.
Construction captures available monitor video modes once, with the primary monitor
first. Construction fails without a primary video mode or monitor inventory.
monitors(), primary_monitor() and monitor_count() describe that fixed inventory;
the returned references remain display-owned. IDs are generated inventory identities,
not native handles or persistent physical-monitor identifiers. Copies from the same
inventory retain their IDs; unknown IDs fail content_scale() and window creation.
There is no runtime monitor hotplug refresh or native-handle rebinding. Monitor topology must remain stable while using this inventory: removal can invalidate its native handles, and video-mode changes do not update captured dimensions. Hotplug support needs an explicit refresh, identity and existing-window rebinding contract before consumers rely on it.
create_window() returns a borrowed pointer owned until display destruction;
callers do not delete it. Dimensions are positive logical coordinates. Invalid
monitor IDs/modes, allocation failures and failed native creation propagate.
Omitting dimensions uses the captured monitor size; omitting or passing an empty
title uses a generated title. Successful creation does not make the window active.
active_window() is initially nullptr. activate_window() accepts the first owned
window and repeated selection of that window. It rejects a foreign window or replacing
the selected one. Selection does not make a graphics context current or establish
renderer/resource-domain switching.
Multiple active rendering windows and selection switching are
deferred extensions.
Sizes, modes and observation
Observation |
Units and freshness |
|---|---|
|
Captured video-mode dimensions; native GLFW does not refresh them. |
|
Cached logical window coordinates, updated by native size callbacks and explicit resize/mode queries. |
|
Cached drawable pixels, independently updated by framebuffer callbacks and explicit queries. Zero dimensions can describe an unavailable drawable. |
|
Current GLFW X/Y monitor scale for an inventory ID; this leaves its dimensions unchanged. |
Pump native events on platform before relying on new callback observations. Logical
and framebuffer dimensions can differ; use valid positive sizes for pixel mapping
and avoid division/render submission while the drawable is unavailable.
CE::Platform::Dimensions<int> describes logical dimensions, while
CE::Platform::FramebufferSize describes drawable pixels.
resize() requests positive logical dimensions and queries the resulting logical
and pixel sizes. The platform may accept different dimensions. set_mode() restores
saved windowed placement for CE::Platform::WindowMode::NORMAL, uses it without decorations for BORDERLESS,
and attaches the chosen monitor at its captured dimensions for FULLSCREEN. Native
fullscreen switching uses the monitor’s queried refresh rate. Mode changes then
query the resulting sizes. Borderless mode preserves the saved windowed extent;
it does not itself select a desktop-sized extent.
mode() reflects the selected mode and can already have changed when a transition
reports a listener failure.
A changed framebuffer size publishes CE::Platform::WindowResized on the canonical typed
CE::Platform::window_resized_event channel. Native GLFW first dispatches the legacy named
"window-resized" notification, then the typed channel, using the same saved size
observation. A logical size change alone does not establish a framebuffer-size
event. Nested resize delivery can interleave these channels; each payload keeps its
own observation even if another listener changes the window again. Queued callbacks
do not have a completion order across channels.
The event contains copied pixel dimensions and a borrowed window pointer. Queued delivery does not extend window lifetime or permit dereferencing it on another owner. Deferred consumers retain the dimensions and use their normal runtime and registration lifetime. The event-delivery contract defines channel identity, payload ownership and optional owner delivery.
Native callback failures follow the
failure-reporting contract. Explicit resize/mode operations
consume earlier callback failures and can propagate listener failures after native
state/dimensions change. A synchronous legacy-dispatch failure prevents the typed
offer for that observation; typed listener failures use the same native callback
boundary. Earlier deliveries and native state changes are not rolled back. should_close()
also consumes deferred callback failure before reading the close flag. Cached size
getters do not consume that failure.
Scale and UI capabilities
A monitor scale query neither establishes per-window scale nor reports scale-change events. A window can move between monitors independently of its original snapshot. Use copied logical/framebuffer sizes for current pixel mapping and an explicit font scale within the adapter’s supported scope.
hide_cursor() selects hidden or normal cursor visibility. Pointer capture, locked
relative motion, cursor shapes, clipboard and IME need their own capability contracts.
The current UI capability boundaries
describe what adapters expose and what further consumer requirements must settle.