Skip to main content

lumen_core/
window.rs

1//! Backend-neutral description of the app's window and its native menu bar.
2//!
3//! Every launch path (the CLI, the C-ABI, the SDKs) resolves the same
4//! values - size, title, clear color, chrome, menu bar - before a window
5//! exists, and a window backend consumes them when it opens one. Keeping
6//! the description here means the composition point can build it without
7//! naming a backend, and a second window backend can consume it without
8//! inventing a parallel type.
9//!
10//! The menu tree ([`MenuModel`], [`Menu`], [`MenuEntry`]) is pure data: it
11//! says what the menu bar contains, not how a platform draws it.
12//! `lumen-os-menu` re-exports these types and owns the native attach.
13
14use crate::components::Color;
15
16/// Fallback GPU clear color painted before the very first frame - what a
17/// user sees for an instant during window creation, and behind any pixel
18/// the app's tree doesn't cover. This is the single Rust-side source of
19/// truth for that fallback; `lumen_runtime::run::RunOptions::clear` (the
20/// value every launch path reaches - CLI, FFI, SDK) defaults to it too,
21/// so the two never drift apart the way they used to.
22///
23/// A resolved `--lumen-window-bg` custom property (from the app's own
24/// `:root` or its active skin) overrides this at build time - see
25/// `lumen_runtime::run::app_build::build_app`. This constant is only what
26/// remains when no layer defines that token, or a caller constructs
27/// [`WindowOptions`] directly without going through `RunOptions` at all.
28pub const DEFAULT_CLEAR: Color = Color::rgb(0.07, 0.07, 0.09);
29
30/// Everything a window backend needs to open the app's window.
31pub struct WindowOptions {
32    /// Initial window inner size in logical pixels.
33    pub size: (u32, u32),
34    /// Window title.
35    pub title: String,
36    /// Background clear color (writes [`crate::render_world::Viewport::clear`]
37    /// on init). See [`DEFAULT_CLEAR`] for the fallback this defaults to.
38    pub clear: Color,
39    /// Maximize the window on launch. Useful for full-bleed app demos.
40    pub maximized: bool,
41    /// Suppress OS window chrome (title bar, borders, close/min/max
42    /// buttons). Custom title bars and per-platform window drag must
43    /// be implemented inside the app - see the `<title-bar drag>`
44    /// region (TODO S31).
45    pub frameless: bool,
46    /// Initial outer position in physical pixels. `None` lets the OS
47    /// place the window (the default). Wired up so callers can
48    /// restore the last-known window position from disk (P1.3).
49    pub start_position: Option<(i32, i32)>,
50    /// Callback invoked once per close with the current window
51    /// position, inner size (logical), and maximized flag. `None`
52    /// (the default) disables state persistence. Implementations
53    /// typically serialise to disk via
54    /// `lumenc::window_state::save`.
55    pub on_close_state: Option<Box<dyn FnOnce(WindowGeometry) + Send>>,
56    /// Optional native menu bar spec. Built by the embedder from
57    /// the markup `<menubar>` element. `None` = no menu bar.
58    pub menubar: Option<MenuModel>,
59}
60
61impl Default for WindowOptions {
62    fn default() -> Self {
63        Self {
64            size: (800, 600),
65            title: "Lumen".into(),
66            clear: DEFAULT_CLEAR,
67            maximized: false,
68            frameless: false,
69            start_position: None,
70            on_close_state: None,
71            menubar: None,
72        }
73    }
74}
75
76/// Snapshot of geometry handed to [`WindowOptions::on_close_state`] so
77/// the embedder can persist `(position, size, maximized)` to disk.
78#[derive(Debug, Clone, Copy)]
79pub struct WindowGeometry {
80    /// Outer window position in physical pixels (winit
81    /// `Window::outer_position`).
82    pub position: Option<(i32, i32)>,
83    /// Inner window size in logical pixels.
84    pub size: (u32, u32),
85    /// Last maximized state.
86    pub maximized: bool,
87}
88
89/// The app's native menu bar, as parsed from `<menubar>`.
90#[derive(Debug, Clone, Default)]
91pub struct MenuModel {
92    /// Top-level submenus, in source order.
93    pub menus: Vec<Menu>,
94}
95
96/// One submenu (`<menu label="File">...</menu>`).
97#[derive(Debug, Clone)]
98pub struct Menu {
99    /// Display label shown in the menu bar.
100    pub label: String,
101    /// Items inside the submenu.
102    pub items: Vec<MenuEntry>,
103}
104
105/// One submenu entry - either a clickable item or a separator.
106#[derive(Debug, Clone)]
107pub enum MenuEntry {
108    /// `<menuitem id label accel?>`.
109    Item {
110        /// `id="..."` - dispatched as `MenuClicked { id }` to scripts.
111        id: String,
112        /// Display label.
113        label: String,
114        /// Optional accelerator string in muda format.
115        accelerator: Option<String>,
116    },
117    /// `<separator />`.
118    Separator,
119}