lattice_config/window_options.rs
1// `linkme`'s distributed slices use `link_section` to aggregate
2// items at link time. The `options!` macro expansion in this file
3// emits such a declaration; allow the workspace's `unsafe_code =
4// "deny"` lint locally with the same safety rationale documented in
5// `option_decl.rs`, `group.rs`, and `core_options.rs`.
6#![allow(unsafe_code)]
7
8//! GPUI window options (`ui.window.*`). GPUI peer only; the TUI never reads
9//! these. `decorations` is applied at window creation; `start-maximized`
10//! drives a one-shot maximize on launch. See
11//! `docs/dev/architecture/gpui-window-chrome.md`.
12
13use crate::Decorations;
14
15crate::options! {
16 group = crate::Window;
17
18 /// OS window chrome (GPUI only; ignored by the terminal UI). One of:
19 /// `full` (default) — system titlebar + window controls.
20 /// `none` — borderless: no titlebar or controls, like alacritty
21 /// `decorations = none` / kitty / emacs `undecorated`. On macOS a
22 /// `none` window is non-resizable by any means — even Raycast/yabai
23 /// can't move or resize it; it opens at a fixed size.
24 /// `transparent` — frameless-looking but still resizable: a transparent
25 /// titlebar with the traffic-light buttons hidden. Edge-resize works and
26 /// window managers (Raycast/yabai) can drive it; rounded corners + shadow
27 /// remain. The macOS-friendly frameless option.
28 /// Applied at window creation; a change takes effect on the next launch.
29 #[name("ui.window.decorations")]
30 pub WindowDecorationsOption: Decorations = Decorations::Full;
31
32 /// Maximize the window on launch (fill the work area, keep the menu
33 /// bar — not native fullscreen). GPUI peer only; ignored by the TUI.
34 #[name("ui.window.start-maximized")]
35 pub StartMaximized: bool = false;
36}
37
38#[cfg(test)]
39mod tests {
40 #![allow(clippy::unwrap_used, clippy::panic)]
41 use crate::{ConfigRegistry, Decorations, StartMaximized, WindowDecorationsOption};
42
43 fn reg() -> ConfigRegistry {
44 let r = ConfigRegistry::new();
45 r.init_from_linkme();
46 r
47 }
48
49 #[test]
50 fn defaults_match_spec() {
51 let r = reg();
52 assert_eq!(
53 *r.get_typed::<WindowDecorationsOption>().unwrap(),
54 Decorations::Full
55 );
56 assert!(!*r.get_typed::<StartMaximized>().unwrap());
57 }
58
59 #[test]
60 fn set_decorations_none_parses() {
61 let r = reg();
62 r.parse_and_set_command("ui.window.decorations=none")
63 .unwrap();
64 assert_eq!(
65 *r.get_typed::<WindowDecorationsOption>().unwrap(),
66 Decorations::None_
67 );
68 }
69
70 #[test]
71 fn set_start_maximized_true_parses() {
72 let r = reg();
73 r.parse_and_set_command("ui.window.start-maximized=true")
74 .unwrap();
75 assert!(*r.get_typed::<StartMaximized>().unwrap());
76 }
77
78 #[test]
79 fn bad_decorations_value_errors() {
80 let r = reg();
81 assert!(
82 r.parse_and_set_command("ui.window.decorations=wat")
83 .is_err()
84 );
85 }
86
87 // Regression: the `ui.window.*` options must resolve through the real TOML
88 // FILE path (load_file -> walk_table -> apply_scalar), not just the `:set`
89 // path — a `[ui.window]` table with hyphenated leaf keys must apply. This is
90 // the boundary a maximize-on-launch bug report pointed at (the read was fine;
91 // the bug was the apply mechanism).
92 #[test]
93 fn toml_file_path_applies_ui_window_table() {
94 let r = reg();
95 let dir = std::env::temp_dir();
96 let path = dir.join(format!("lattice_probe_{}.toml", std::process::id()));
97 std::fs::write(
98 &path,
99 "[ui.window]\ndecorations = \"none\"\nstart-maximized = true\n",
100 )
101 .unwrap();
102 let out = crate::load_file(&r, &path, &[]);
103 std::fs::remove_file(&path).ok();
104 assert!(out.messages.is_empty(), "load messages: {:?}", out.messages);
105 assert_eq!(
106 *r.get_typed::<WindowDecorationsOption>().unwrap(),
107 Decorations::None_,
108 "decorations from file"
109 );
110 assert!(
111 *r.get_typed::<StartMaximized>().unwrap(),
112 "start-maximized from file"
113 );
114 }
115}