Harbor

branch main
showing the latest snapshot on main
impl.md 13.1 KB · Markdown
window/impl.md 0644 Raw

Implementation Reference

Implementation details extracted from GLFW and winit for our Odin window library.


GLFW Implementation Details

Architecture Patterns

  • Global state struct containing all library state (initialized flag, platform vtable, error handling, window/cursor/monitor linked lists)
  • Window struct with linked list node (next pointer), settings/state flags, input state arrays, constraints, callbacks, and platform-specific state via macro embedding
  • Monitor struct with name, physical dimensions, video modes array, gamma ramp state
  • Opaque handle pattern - public API only sees pointers, never internal struct details
  • Intrusive linked lists for windows, cursors, errors - next pointer embedded in each structure

Platform Abstraction

  • Virtual function table - _GLFWplatform struct contains ~60 function pointers for all platform operations
  • Platform state macros - GLFW_X11_WINDOW_STATE, GLFW_WIN32_WINDOW_STATE etc. embedded in window struct
  • Conditional compilation - empty stub macros when platform not compiled, same binary types across platforms
  • Platform ID stored in global state for runtime platform identification

Window Management

  • Hints system - stateful configuration before creation (glfwWindowHint(), glfwInitHint())
  • Hints persist until explicitly reset or new window created - allows adding new hints without breaking API
  • Simple creation - glfwCreateWindow(width, height, title, monitor, share)
  • Monitor parameter - NULL for windowed, valid monitor for fullscreen
  • Share parameter - NULL or reference to existing window for OpenGL context sharing
  • Constraints - min/max width/height, aspect ratio numerator/denominator

Input Handling

  • Key state array - keys[GLFW_KEY_LAST + 1] stores PRESS/RELEASE/REPEAT
  • Mouse state array - mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]
  • Sticky input modes - persistent state capture even when callback missed
  • Virtual cursor position - software-tracked cursor for disabled cursor mode
  • Raw mouse motion - platform-specific unfiltered motion data
  • Callback pointers - 17 callbacks stored directly in window struct (null = no-op)

Event Loop

  • pollEvents() - non-blocking, processes queue
  • waitEvents() - blocks until event
  • waitEventsTimeout(t) - blocks with timeout
  • postEmptyEvent() - force wake from wait
  • Internal event functions - _glfwInputKey(), _glfwInputMouseClick() etc. called by platform code

API Design

  • Error handling - thread-local storage via TLS slots, last error only (not queued)
  • Input mode configuration - single function with mode enum (GLFW_CURSOR, GLFW_STICKY_KEYS, etc.)
  • String hints for platform extensions (GLFW_X11_CLASS_NAME, etc.)
  • Callback registration returns previous callback pointer
  • User pointer on windows and monitors for application data

Platform Functions Required

  • init/terminate
  • Cursor: getCursorPos, setCursorPos, setCursorMode, createCursor, createStandardCursor, destroyCursor, setCursor
  • Input: getScancodeName, getKeyScancode, setClipboardString, getClipboardString, rawMouseMotionSupported
  • Monitor: freeMonitor, getMonitorPos, getMonitorContentScale, getMonitorWorkarea, getVideoModes, getVideoMode, getGammaRamp, setGammaRamp
  • Window: createWindow, destroyWindow, setWindowTitle, setWindowIcon, get/setWindowPos, get/setWindowSize, setWindowSizeLimits, setWindowAspectRatio, getFramebufferSize, getWindowFrameSize, getWindowContentScale, iconifyWindow, restoreWindow, maximizeWindow, showWindow, hideWindow, requestWindowAttention, focusWindow, setWindowMonitor
  • Window state: windowFocused, windowIconified, windowVisible, windowMaximized, windowHovered, framebufferTransparent, getWindowOpacity, setWindowResizable, setWindowDecorated, setWindowFloating, setWindowOpacity, setWindowMousePassthrough
  • Events: pollEvents, waitEvents, waitEventsTimeout, postEmptyEvent

Winit Implementation Details

Architecture Patterns

  • Trait-based abstraction - ActiveEventLoop, Window, ApplicationHandler traits
  • Enum-based event system - discriminated unions for events (40+ WindowEvent variants)
  • Separate crates per platform - winit-core (shared), winit-x11, winit-wayland, winit-win32, etc.
  • Runtime backend selection on Linux - check WAYLAND_DISPLAY then DISPLAY env vars
  • Window IDs - distinct u64 identifiers for multi-window handling

ApplicationHandler Callbacks

  • can_create_surfaces() - lifecycle point for surface creation (critical for Android)
  • window_event(event_loop, window_id, event) - per-window events
  • device_event(event_loop, device_id, event) - raw input events
  • about_to_wait() - pre-blocking hook
  • new_events(cause) - start of event batch
  • proxy_wake_up() - inter-thread signaling

Window Attributes (Builder Pattern)

  • surface_size, min_surface_size, max_surface_size, surface_resize_increments
  • position
  • resizable
  • enabled_buttons (bitflags for min/max/close)
  • title
  • maximized, visible, transparent, blur, decorations
  • window_icon
  • preferred_theme (Light/Dark)
  • content_protected
  • window_level (Normal, AlwaysOnTop, AlwaysOnBottom)
  • active
  • cursor
  • parent_window
  • fullscreen (Borderless or Exclusive with video mode)
  • platform (boxed trait object for platform-specific extensions)

Keyboard Input Hierarchy

  1. Physical scancode (XKB keycode, Windows scancode)
  2. Platform-native NativeKeyCode: Xkb(u32), Windows(u16), MacOS(u16)
  3. Logical key via NativeKey (keysym, vkcode)
  4. Named key enum: Enter, Escape, ArrowUp, F1-F24, etc.

Key Modifiers

  • Shift, Control, Alt, Super (meta/win/cmd)
  • Separate left/right tracking
  • CapsLock, NumLock state

Pointer Events

  • PointerMoved { position, primary, source }
  • PointerEntered { position, primary, kind }
  • PointerLeft { position, primary, kind }
  • PointerButton { state, position, button }
  • MouseWheel { delta: LineDelta | PixelDelta, phase }
  • Primary vs secondary pointer for multi-touch

Event Loop Control Flow

  • Poll - continuous polling (games)
  • Wait - block until events (UI apps, most efficient)
  • WaitUntil(instant) - block with timeout

StartCause (Why event loop woke)

  • Init - first iteration
  • Poll - Poll control flow triggered
  • WaitCancelled { start, requested_resume } - new events interrupted wait
  • ResumeTimeReached { start, requested_resume } - WaitUntil timeout fired

Window Events (Key Variants)

  • SurfaceResized, Moved, CloseRequested, Destroyed
  • Focused(bool), Occluded(bool)
  • KeyboardInput { device_id, event, is_synthetic }
  • ModifiersChanged
  • PointerMoved, PointerEntered, PointerLeft, PointerButton
  • MouseWheel, AxisMotion
  • Touch, TouchpadPressure
  • PinchGesture, PanGesture, DoubleTapGesture, RotationGesture
  • DragEntered, DragMoved, DragDropped, DragLeft
  • ScaleFactorChanged { scale_factor, surface_size_writer }
  • ThemeChanged
  • Ime(Enabled, Preedit, Commit, Disabled)
  • RedrawRequested

Coordinate Systems

  • Surface coordinates - relative to drawable area (0,0 at content top-left)
  • Window coordinates - relative to window including decorations
  • Desktop coordinates - absolute screen position
  • Methods: surface_size(), outer_size(), surface_position(), outer_position()

DPI/Scaling

  • scale_factor() on Window
  • ScaleFactorChanged event when DPI changes
  • Physical and Logical types that auto-convert
  • Fractional scaling support (Wayland)

Monitor API

  • available_monitors() - iterator of MonitorHandle
  • primary_monitor() - Option<MonitorHandle>
  • MonitorHandle: id, native_id, name, position, scale_factor, video_modes, current_video_mode

Cross-Thread Communication

  • EventLoopProxy::wake_up() - coalesced (multiple calls = 1 proxy_wake_up event)
  • Used for background threads signaling work completion

Raw Window Handles

  • raw_window_handle() → RawWindowHandle for Vulkan/OpenGL/Metal/DirectX
  • raw_display_handle() → DisplayHandle for display connection

X11-Specific

  • Window types: Desktop, Dock, Toolbar, Menu, Utility, Splash, Dialog, DropdownMenu, PopupMenu, Tooltip, Notification, Combo, Dnd, Normal
  • XAtom handling
  • Drag & drop (XDND protocol)
  • Input method integration
  • XSettings for desktop settings

Wayland-Specific

  • Client-side decorations (CSD) option
  • xdg_toplevel access
  • Activation tokens
  • Fractional scaling protocol
  • Tablet input v2

Current Implementation Status

Core Data Structures

  • [x] Global library state (Platform_Event_Loop in platform_linux.odin)
  • [x] Window struct (Platform_Window with union of X11/Wayland data)
  • [x] Monitor struct (Monitor_Info with id, name, dimensions, modes, position, scale)
  • [x] Event enum (discriminated union: Window_Event, Device_Event, Loop_Event)

Window Management

  • [x] Window creation with attributes (create_window() + Window_Attributes)
  • [x] Window destruction (destroy_window())
  • [x] Title (set_title())
  • [ ] Window icon
  • [x] Position (outer_position(), set_outer_position(), set_position(), get_position())
  • [x] Size (surface_size(), request_surface_size(), outer_size(), set_size())
  • [x] Min/max size constraints (set_min_surface_size(), set_max_surface_size())
  • [ ] Aspect ratio constraints
  • [x] Visible (set_visible(), is_visible())
  • [x] Focused (focus(), is_focused())
  • [x] Maximized (set_maximized(), is_maximized() - state tracking TODO)
  • [x] Minimized (set_minimized(), is_minimized() - state tracking TODO)
  • [x] Fullscreen (set_fullscreen(), get_fullscreen() - borderless + exclusive)
  • [x] Decorations (set_decorations(), is_decorated() - state tracking TODO)
  • [x] Resizable (set_resizable(), is_resizable() - state tracking TODO)
  • [ ] Floating/always-on-top
  • [ ] Mouse passthrough
  • [ ] Opacity
  • [~] Content scale / DPI (scale_factor() - hardcoded 1.0, detection TODO)

Input Handling

  • [x] Keyboard input with scancodes (Key_Input event, Key_Code enum 126+ keys)
  • [ ] Key state array for polling
  • [x] Modifier keys tracking (Modifiers struct: shift, ctrl, alt, super)
  • [x] Mouse button input (Mouse_Button_Input event)
  • [x] Cursor position (Pointer_Moved event with position)
  • [x] Scroll wheel (Mouse_Wheel event with line + pixel deltas)
  • [ ] Cursor modes (normal, hidden, disabled/grabbed)
  • [ ] Raw mouse motion (relative pointer protocol)
  • [ ] Cursor shapes (standard cursors)
  • [~] Key repeat detection (TODO in both X11 and Wayland)

Event System

  • [x] Poll events (poll() - non-blocking)
  • [x] Wait events (run() with Wait control flow - blocking)
  • [x] Wait events with timeout (Wait_Until control flow)
  • [ ] Post empty event / wake from wait (TODO in code)
  • [x] Callback-based design (winit-style Event_Handler callback)
  • [x] Start cause tracking (Init, Poll, Wait_Cancelled, Resume_Time_Reached)
  • [x] Loop events (New_Events, About_To_Wait, Loop_Exiting)

Monitor/Display

  • [x] Enumerate monitors (get_monitors())
  • [x] Primary monitor (get_primary_monitor())
  • [x] Monitor name (get_monitor_name())
  • [x] Monitor position (get_monitor_position())
  • [x] Monitor workarea (get_monitor_workarea())
  • [x] Physical size (get_monitor_physical_size())
  • [x] Content scale (get_monitor_content_scale())
  • [x] Video modes enumeration (get_video_modes())
  • [x] Current video mode (get_current_video_mode())
  • [x] Combined info (get_monitor_info())

Platform Abstraction

  • [x] Platform-specific state embedded in structs (union in Platform_Window)
  • [x] Runtime platform selection (X11 vs Wayland via select_backend())
  • [x] Environment variable checks (WAYLAND_DISPLAY, ODIN_WINDOW_BACKEND)
  • [x] X11 backend (complete)
  • [x] Wayland backend (functional - window creation, input, monitors, decorations)

Raw Handle Support

  • [x] raw_window_handle() - X11 window ID or Wayland wl_surface
  • [x] raw_display_handle() - X11 display or Wayland wl_display

API Design (Implemented Choices)

  • [x] Distinct handle types (Window_Id, Device_Id, Monitor_Handle)
  • [x] Attributes struct pattern (not hints)
  • [x] Callback-based events (winit-style)
  • [ ] User pointer on objects
  • [x] Error handling via Error enum return values
  • [ ] Thread-local error storage

Not Yet Implemented

Window Features

  • Window icon
  • Aspect ratio constraints
  • Floating/always-on-top window level
  • Mouse passthrough
  • Window opacity
  • Proper DPI detection (currently hardcoded to 1.0)
  • State tracking for maximized/minimized/resizable/decorated flags

Input Features

  • Key state array for polling (currently event-only)
  • Cursor visibility modes (hidden, disabled/grabbed)
  • Raw mouse motion (Wayland relative-pointer protocol)
  • Standard cursor shapes
  • Key repeat detection (marked TODO)
  • Event loop wake-up mechanism (marked TODO)

Advanced Features

  • Clipboard access (copy/paste)
  • Custom cursor images
  • Drag & drop
  • Input method (IME) integration
  • Touch input
  • Gamepad/joystick
  • Pointer gestures (pinch, pan, rotate)
  • Tablet input

Wayland-Specific Incomplete

  • Exclusive fullscreen with specific video mode
  • Pointer constraints (cursor locking)
  • Activation tokens
  • Fractional scaling (protocol exists, not wired through)