zng_ext_window/
vars.rs

1use std::sync::Arc;
2
3use zng_app::{
4    widget::{WidgetId, info::access::AccessEnabled},
5    window::{MonitorId, WINDOW, WindowId},
6};
7use zng_color::LightDark;
8use zng_ext_image::Img;
9use zng_layout::unit::{
10    Dip, DipPoint, DipRect, DipSideOffsets, DipSize, DipToPx, Factor, FactorUnits, Length, LengthUnits, Point, PxPoint, PxSize, Size,
11};
12use zng_state_map::{StateId, static_id};
13use zng_txt::Txt;
14use zng_unique_id::IdSet;
15use zng_var::{ArcVar, BoxedVar, ReadOnlyArcVar, Var, merge_var, var, var_from};
16use zng_view_api::{
17    config::{ColorScheme, ColorsConfig},
18    window::{CursorIcon, FocusIndicator, RenderMode, VideoMode, WindowButton, WindowState},
19};
20
21use crate::{AutoSize, CursorSource, FrameCaptureMode, MonitorQuery, WindowIcon};
22
23pub(super) struct WindowVarsData {
24    chrome: ArcVar<bool>,
25    icon: ArcVar<WindowIcon>,
26    pub(super) actual_icon: ArcVar<Option<Img>>,
27    cursor: ArcVar<CursorSource>,
28    pub(super) actual_cursor_img: ArcVar<Option<(Img, PxPoint)>>,
29    title: ArcVar<Txt>,
30
31    state: ArcVar<WindowState>,
32    focus_indicator: ArcVar<Option<FocusIndicator>>,
33
34    position: ArcVar<Point>,
35    monitor: ArcVar<MonitorQuery>,
36    video_mode: ArcVar<VideoMode>,
37
38    size: ArcVar<Size>,
39    pub(super) auto_size: ArcVar<AutoSize>,
40    auto_size_origin: ArcVar<Point>,
41    min_size: ArcVar<Size>,
42    max_size: ArcVar<Size>,
43
44    font_size: ArcVar<Length>,
45
46    pub(super) actual_position: ArcVar<DipPoint>,
47    pub(super) global_position: ArcVar<PxPoint>,
48    pub(super) actual_monitor: ArcVar<Option<MonitorId>>,
49    pub(super) actual_size: ArcVar<DipSize>,
50    pub(super) safe_padding: ArcVar<DipSideOffsets>,
51
52    pub(super) scale_factor: ArcVar<Factor>,
53
54    pub(super) restore_state: ArcVar<WindowState>,
55    pub(super) restore_rect: ArcVar<DipRect>,
56
57    enabled_buttons: ArcVar<WindowButton>,
58
59    resizable: ArcVar<bool>,
60    movable: ArcVar<bool>,
61
62    always_on_top: ArcVar<bool>,
63
64    visible: ArcVar<bool>,
65    taskbar_visible: ArcVar<bool>,
66
67    parent: ArcVar<Option<WindowId>>,
68    pub(super) nest_parent: ArcVar<Option<WidgetId>>,
69    modal: ArcVar<bool>,
70    pub(super) children: ArcVar<IdSet<WindowId>>,
71
72    color_scheme: ArcVar<Option<ColorScheme>>,
73    pub(super) actual_color_scheme: ArcVar<ColorScheme>,
74    accent_color: ArcVar<Option<LightDark>>,
75    pub(super) actual_accent_color: ArcVar<LightDark>,
76
77    pub(super) is_open: ArcVar<bool>,
78    pub(super) is_loaded: ArcVar<bool>,
79
80    frame_capture_mode: ArcVar<FrameCaptureMode>,
81    pub(super) render_mode: ArcVar<RenderMode>,
82
83    pub(super) access_enabled: ArcVar<AccessEnabled>,
84    system_shutdown_warn: ArcVar<Txt>,
85}
86
87/// Variables that configure the opening or open window.
88///
89/// You can get the vars for any window using [`WINDOWS.vars`].
90///
91/// You can get the vars for the current context window using [`WINDOW.vars`].
92///
93/// [`WINDOWS.vars`]: crate::WINDOWS::vars
94/// [`WINDOW.vars`]: crate::WINDOW_Ext::vars
95#[derive(Clone)]
96pub struct WindowVars(pub(super) Arc<WindowVarsData>);
97impl WindowVars {
98    pub(super) fn new(default_render_mode: RenderMode, primary_scale_factor: Factor, system_colors: ColorsConfig) -> Self {
99        let vars = Arc::new(WindowVarsData {
100            chrome: var(true),
101            icon: var(WindowIcon::Default),
102            actual_icon: var(None),
103            cursor: var_from(CursorIcon::Default),
104            actual_cursor_img: var(None),
105            title: var(zng_env::about().app.clone()),
106
107            state: var(WindowState::Normal),
108            focus_indicator: var(None),
109
110            position: var(Point::default()),
111            monitor: var(MonitorQuery::default()),
112            video_mode: var(VideoMode::default()),
113            size: var(Size::default()),
114
115            font_size: var(11.pt()),
116
117            actual_position: var(DipPoint::zero()),
118            global_position: var(PxPoint::zero()),
119            actual_monitor: var(None),
120            actual_size: var(DipSize::zero()),
121            safe_padding: var(DipSideOffsets::zero()),
122
123            scale_factor: var(primary_scale_factor),
124
125            restore_state: var(WindowState::Normal),
126            restore_rect: var(DipRect::new(
127                DipPoint::new(Dip::new(30), Dip::new(30)),
128                DipSize::new(Dip::new(800), Dip::new(600)),
129            )),
130
131            enabled_buttons: var(WindowButton::all()),
132
133            min_size: var(Size::new(192, 48)),
134            max_size: var(Size::new(100.pct(), 100.pct())),
135
136            auto_size: var(AutoSize::empty()),
137            auto_size_origin: var(Point::top_left()),
138
139            resizable: var(true),
140            movable: var(true),
141
142            always_on_top: var(false),
143
144            visible: var(true),
145            taskbar_visible: var(true),
146
147            parent: var(None),
148            nest_parent: var(None),
149            modal: var(false),
150            children: var(IdSet::default()),
151
152            color_scheme: var(None),
153            actual_color_scheme: var(system_colors.scheme),
154            accent_color: var(None),
155            actual_accent_color: var(system_colors.accent.into()),
156
157            is_open: var(true),
158            is_loaded: var(false),
159
160            frame_capture_mode: var(FrameCaptureMode::Sporadic),
161            render_mode: var(default_render_mode),
162
163            access_enabled: var(AccessEnabled::empty()),
164            system_shutdown_warn: var(Txt::from("")),
165        });
166        Self(vars)
167    }
168
169    /// Require the window vars from the window state.
170    ///
171    /// # Panics
172    ///
173    /// Panics if called in a custom window context that did not setup the variables.
174    pub(super) fn req() -> Self {
175        WINDOW.req_state(*WINDOW_VARS_ID)
176    }
177
178    /// Defines if the window chrome is visible.
179    ///
180    /// The window chrome is the non-client area of the window, usually a border with resize handles and a title bar.
181    ///
182    /// The default value is `true`.
183    ///
184    /// Note that if the [`WINDOWS.system_chrome`] reports the windowing system prefers a custom chrome **and** does not
185    /// provide one the system chrome is not requested, even if this is `true`. Window widget implementers can use this to
186    /// detect when a fallback chrome must be provided.
187    ///
188    /// [`WINDOWS.system_chrome`]: crate::WINDOWS::system_chrome
189    pub fn chrome(&self) -> ArcVar<bool> {
190        self.0.chrome.clone()
191    }
192
193    /// Window icon.
194    ///
195    /// See [`WindowIcon`] for details.
196    ///
197    /// The default value is [`WindowIcon::Default`].
198    ///
199    /// You can retrieve the custom icon image using [`actual_icon`].
200    ///
201    /// [`actual_icon`]: Self::actual_icon
202    pub fn icon(&self) -> ArcVar<WindowIcon> {
203        self.0.icon.clone()
204    }
205
206    /// Window icon image.
207    ///
208    /// This is `None` if [`icon`] is [`WindowIcon::Default`], otherwise it is an [`Img`]
209    /// reference clone.
210    ///
211    /// [`icon`]: Self::icon
212    /// [`Img`]: zng_ext_image::Img
213    pub fn actual_icon(&self) -> ReadOnlyArcVar<Option<Img>> {
214        self.0.actual_icon.read_only()
215    }
216
217    /// Window cursor icon and visibility.
218    ///
219    /// See [`CursorSource`] for details.
220    ///
221    /// The default is [`CursorIcon::Default`].
222    ///
223    /// [`CursorIcon`]: zng_view_api::window::CursorIcon
224    /// [`CursorIcon::Default`]: zng_view_api::window::CursorIcon::Default
225    pub fn cursor(&self) -> ArcVar<CursorSource> {
226        self.0.cursor.clone()
227    }
228
229    /// Window custom cursor image.
230    ///
231    /// This is `None` if [`cursor`] is not set to a custom image, otherwise it is an [`Img`]
232    /// reference clone with computed hotspot [`PxPoint`].
233    ///
234    /// [`cursor`]: Self::cursor
235    /// [`Img`]: zng_ext_image::Img
236    /// [`PxPoint`]: zng_layout::unit::PxPoint
237    pub fn actual_cursor_img(&self) -> ReadOnlyArcVar<Option<(Img, PxPoint)>> {
238        self.0.actual_cursor_img.read_only()
239    }
240
241    /// Window title text.
242    ///
243    /// The default value is `""`.
244    pub fn title(&self) -> ArcVar<Txt> {
245        self.0.title.clone()
246    }
247
248    /// Window screen state.
249    ///
250    /// Minimized, maximized or fullscreen. See [`WindowState`] for details.
251    ///
252    /// The default value is [`WindowState::Normal`].
253    pub fn state(&self) -> ArcVar<WindowState> {
254        self.0.state.clone()
255    }
256
257    /// Window monitor.
258    ///
259    /// The query selects the monitor to which the [`position`] and [`size`] is relative to.
260    ///
261    /// It evaluate once when the window opens and then once every time the variable updates. You can track
262    /// what the current monitor is by using [`actual_monitor`].
263    ///
264    /// # Behavior After Open
265    ///
266    /// If this variable is changed after the window has opened, and the new query produces a different
267    /// monitor from the [`actual_monitor`] and the window is visible; then the window is moved to
268    /// the new monitor:
269    ///
270    /// * **Maximized**: The window is maximized in the new monitor.
271    /// * **Normal**: The window is centered in the new monitor, keeping the same size, unless the
272    ///   [`position`] and [`size`] where set in the same update, in that case these values are used.
273    /// * **Minimized/Hidden**: The window restore position and size are defined like **Normal**.
274    ///
275    /// [`position`]: WindowVars::position
276    /// [`actual_monitor`]: WindowVars::actual_monitor
277    /// [`size`]: WindowVars::size
278    pub fn monitor(&self) -> ArcVar<MonitorQuery> {
279        self.0.monitor.clone()
280    }
281
282    /// Video mode for exclusive fullscreen.
283    pub fn video_mode(&self) -> ArcVar<VideoMode> {
284        self.0.video_mode.clone()
285    }
286
287    /// Current monitor hosting the window.
288    ///
289    /// This is `None` only if the window has not opened yet (before first render) or if
290    /// no monitors where found in the operating system or if the window is headless without renderer.
291    pub fn actual_monitor(&self) -> ReadOnlyArcVar<Option<MonitorId>> {
292        self.0.actual_monitor.read_only()
293    }
294
295    /// Available video modes in the current monitor.
296    pub fn video_modes(&self) -> BoxedVar<Vec<VideoMode>> {
297        self.0
298            .actual_monitor
299            .flat_map(|&m| {
300                m.and_then(|m| super::MONITORS.monitor(m))
301                    .unwrap_or_else(super::MonitorInfo::fallback)
302                    .video_modes()
303            })
304            .boxed()
305    }
306
307    /// Current scale factor of the current monitor hosting the window.
308    pub fn scale_factor(&self) -> ReadOnlyArcVar<Factor> {
309        self.0.scale_factor.read_only()
310    }
311
312    /// Window actual position on the [monitor].
313    ///
314    /// This is a read-only variable that tracks the computed position of the window, it updates every
315    /// time the window moves.
316    ///
317    /// The initial value is `(0, 0)`, it starts updating once the window opens. The point
318    /// is relative to the origin of the [monitor].
319    ///
320    /// [monitor]: Self::actual_monitor
321    pub fn actual_position(&self) -> ReadOnlyArcVar<DipPoint> {
322        self.0.actual_position.read_only()
323    }
324
325    /// Window actual position on the virtual screen that encompasses all monitors.
326    ///
327    /// This is a read-only variable that tracks the computed position of the window, it updates every
328    /// time the window moves.
329    ///
330    /// The initial value is `(0, 0)`, it starts updating once the window opens.
331    pub fn global_position(&self) -> ReadOnlyArcVar<PxPoint> {
332        self.0.global_position.read_only()
333    }
334
335    /// Window restore state.
336    ///
337    /// The restore state that the window must be set to be restored, if the [current state] is [`Maximized`], [`Fullscreen`] or [`Exclusive`]
338    /// the restore state is [`Normal`], if the [current state] is [`Minimized`] the restore state is the previous state.
339    ///
340    /// When the restore state is [`Normal`] the [`restore_rect`] defines the window position and size.
341    ///
342    /// [current state]: Self::state
343    /// [`Maximized`]: WindowState::Maximized
344    /// [`Fullscreen`]: WindowState::Fullscreen
345    /// [`Exclusive`]: WindowState::Exclusive
346    /// [`Normal`]: WindowState::Normal
347    /// [`Minimized`]: WindowState::Minimized
348    /// [`restore_rect`]: Self::restore_rect
349    pub fn restore_state(&self) -> ReadOnlyArcVar<WindowState> {
350        self.0.restore_state.read_only()
351    }
352
353    /// Window restore position and size when restoring to [`Normal`].
354    ///
355    /// The restore rectangle is the window position and size when its state is [`Normal`], when the state is not [`Normal`]
356    /// this variable tracks the last normal position and size, it will be the window [`actual_position`] and [`actual_size`] again
357    /// when the state is set back to [`Normal`].
358    ///
359    /// This is a read-only variable, to programmatically set it assign the [`position`] and [`size`] variables. The initial
360    /// value is `(30, 30).at(800, 600)`, it starts updating when the window opens.
361    ///
362    /// Note that to restore the window you only need to set [`state`] to [`restore_state`], if the restore state is [`Normal`]
363    /// this position and size will be applied automatically.
364    ///
365    /// [`Normal`]: WindowState::Normal
366    /// [`actual_position`]: Self::actual_position
367    /// [`actual_size`]: Self::actual_size
368    /// [`position`]: Self::position
369    /// [`size`]: Self::size
370    /// [`monitor`]: Self::monitor
371    /// [`actual_monitor`]: Self::actual_monitor
372    /// [`state`]: Self::state
373    /// [`restore_state`]: Self::restore_state
374    pub fn restore_rect(&self) -> ReadOnlyArcVar<DipRect> {
375        self.0.restore_rect.read_only()
376    }
377
378    /// Window top-left offset on the [`monitor`] when the window is [`Normal`].
379    ///
380    /// Relative values are computed in relation to the [`monitor`] size, updating every time the
381    /// position or monitor variable updates.
382    ///
383    /// When the user moves the window this value is considered stale, when it updates it overwrites the window position again,
384    /// note that the window is only moved if it is in the [`Normal`] state, otherwise only the [`restore_rect`] updates.
385    ///
386    /// When the window is moved by the user this variable does **not** update back, to track the current position of the window
387    /// use [`actual_position`], to track the restore position use [`restore_rect`].
388    ///
389    /// The [`Length::Default`] value causes the OS to select a value.
390    ///
391    /// [`restore_rect`]: WindowVars::restore_rect
392    /// [`actual_position`]: WindowVars::actual_position
393    /// [`monitor`]: WindowVars::monitor
394    /// [`Normal`]: WindowState::Normal
395    /// [`Length::Default`]: zng_layout::unit::Length::Default
396    pub fn position(&self) -> ArcVar<Point> {
397        self.0.position.clone()
398    }
399
400    /// Window actual size on the screen.
401    ///
402    /// This is a read-only variable that tracks the computed size of the window, it updates every time
403    /// the window resizes.
404    ///
405    /// The initial value is `(0, 0)`, it starts updating when the window opens.
406    pub fn actual_size(&self) -> ReadOnlyArcVar<DipSize> {
407        self.0.actual_size.read_only()
408    }
409
410    /// Window [`actual_size`], converted to pixels given the [`scale_factor`].
411    ///
412    /// [`actual_size`]: Self::actual_size
413    /// [`scale_factor`]: Self::scale_factor
414    pub fn actual_size_px(&self) -> BoxedVar<PxSize> {
415        merge_var!(self.0.actual_size.clone(), self.0.scale_factor.clone(), |size, factor| {
416            PxSize::new(size.width.to_px(*factor), size.height.to_px(*factor))
417        })
418        .boxed()
419    }
420
421    /// Padding that must be applied to the window content so that it stays clear of screen obstructions
422    /// such as a camera notch cutout.
423    ///
424    /// Note that the *unsafe* area must still be rendered as it may be partially visible, just don't place nay
425    /// interactive or important content outside of this padding.
426    pub fn safe_padding(&self) -> ReadOnlyArcVar<DipSideOffsets> {
427        self.0.safe_padding.read_only()
428    }
429
430    /// Window width and height on the screen when the window is [`Normal`].
431    ///
432    /// Relative values are computed in relation to the [`monitor`] size, updating every time the
433    /// size or monitor variable updates.
434    ///
435    /// When the user resizes the window this value is considered stale, when it updates it overwrites the window size again,
436    /// note that the window is only resized if it is in the [`Normal`] state, otherwise only the [`restore_rect`] updates.
437    ///
438    /// When the window is resized this variable is **not** updated back, to track the current window size use [`actual_size`],
439    /// to track the restore size use [`restore_rect`].
440    ///
441    /// The default value is `(800, 600)`.
442    ///
443    /// [`actual_size`]: WindowVars::actual_size
444    /// [`monitor`]: WindowVars::monitor
445    /// [`restore_rect`]: WindowVars::restore_rect
446    /// [`Normal`]: WindowState::Normal
447    pub fn size(&self) -> ArcVar<Size> {
448        self.0.size.clone()
449    }
450
451    /// Defines if and how the window size is controlled by the content layout.
452    ///
453    /// When enabled overwrites [`size`](Self::size), but is still coerced by [`min_size`](Self::min_size)
454    /// and [`max_size`](Self::max_size). Auto-size is disabled if the user [manually resizes](Self::resizable).
455    ///
456    /// The default value is [`AutoSize::DISABLED`].
457    pub fn auto_size(&self) -> ArcVar<AutoSize> {
458        self.0.auto_size.clone()
459    }
460
461    /// The point in the window content that does not move when the window is resized by [`auto_size`].
462    ///
463    /// When the window size increases it *grows* to the right-bottom, the top-left corner does not move because
464    /// the origin of windows it at the top-left and the position did not change, this variables overwrites this origin
465    /// for [`auto_size`] size changes, the window position is adjusted so that it is the center of the resize.
466    ///
467    /// Note this only applies to resizes, the initial auto-size when the window opens is positioned according to the [`StartPosition`] value.
468    ///
469    /// The default value is [`Point::top_left`].
470    ///
471    /// [`auto_size`]: Self::auto_size
472    /// [`monitor`]: WindowVars::monitor
473    /// [`StartPosition`]: crate::StartPosition
474    /// [`Point::top_left`]: zng_layout::unit::Point::top_left
475    pub fn auto_size_origin(&self) -> ArcVar<Point> {
476        self.0.auto_size_origin.clone()
477    }
478
479    /// Minimal window width and height constraint on the [`size`].
480    ///
481    /// Relative values are computed in relation to the [`monitor`] size, updating every time the
482    /// size or monitor variable updates.
483    ///
484    /// Note that the OS can also define a minimum size that supersedes this variable.
485    ///
486    /// The default value is `(192, 48)`.
487    ///
488    /// [`monitor`]: WindowVars::monitor
489    /// [`size`]: Self::size
490    pub fn min_size(&self) -> ArcVar<Size> {
491        self.0.min_size.clone()
492    }
493
494    /// Maximal window width and height constraint on the [`size`].
495    ///
496    /// Relative values are computed in relation to the [`monitor`] size, updating every time the
497    /// size or monitor variable updates.
498    ///
499    /// Note that the OS can also define a maximum size that supersedes this variable.
500    ///
501    /// The default value is `(100.pct(), 100.pct())`
502    ///
503    /// [`monitor`]: WindowVars::monitor
504    /// [`size`]: Self::size
505    pub fn max_size(&self) -> ArcVar<Size> {
506        self.0.max_size.clone()
507    }
508
509    /// Root font size.
510    ///
511    /// This is the font size in all widget branches  that do not override the font size. The [`rem`] unit is relative to this value.
512    ///
513    /// [`rem`]: LengthUnits::rem
514    pub fn font_size(&self) -> ArcVar<Length> {
515        self.0.font_size.clone()
516    }
517
518    /// Defines if the user can resize the window using the window frame.
519    ///
520    /// Note that even if disabled the window can still be resized from other sources.
521    ///
522    /// The default value is `true`.
523    pub fn resizable(&self) -> ArcVar<bool> {
524        self.0.resizable.clone()
525    }
526
527    /// Defines if the user can move the window using the window frame.
528    ///
529    /// Note that even if disabled the window can still be moved from other sources.
530    ///
531    /// The default value is `true`.
532    pub fn movable(&self) -> ArcVar<bool> {
533        self.0.movable.clone()
534    }
535
536    /// Defines the enabled state of the window chrome buttons.
537    pub fn enabled_buttons(&self) -> ArcVar<WindowButton> {
538        self.0.enabled_buttons.clone()
539    }
540
541    /// Defines if the window should always stay on top of other windows.
542    ///
543    /// Note this only applies to other windows that are not also "always-on-top".
544    ///
545    /// The default value is `false`.
546    pub fn always_on_top(&self) -> ArcVar<bool> {
547        self.0.always_on_top.clone()
548    }
549
550    /// Defines if the window is visible on the screen and in the task-bar.
551    ///
552    /// This variable is observed only after the first frame render, before that the window
553    /// is always not visible.
554    ///
555    /// The default value is `true`.
556    pub fn visible(&self) -> ArcVar<bool> {
557        self.0.visible.clone()
558    }
559
560    /// Defines if the window is visible in the task-bar.
561    ///
562    /// The default value is `true`.
563    pub fn taskbar_visible(&self) -> ArcVar<bool> {
564        self.0.taskbar_visible.clone()
565    }
566
567    /// Defines the parent window.
568    ///
569    /// If a parent is set this behavior applies:
570    ///
571    /// * If the parent is minimized, this window is also minimized.
572    /// * If the parent window is maximized, this window is restored.
573    /// * This window is always on-top of the parent window.
574    /// * If the parent window is closed, this window is also closed.
575    /// * If [`modal`] is set, the parent window cannot be focused while this window is open.
576    /// * If a [`color_scheme`] is not set, the fallback is the parent's actual scheme.
577    /// * If an [`accent_color`] is not set, the fallback is the parent's actual accent.
578    ///
579    /// The default value is `None`.
580    ///
581    /// # Validation
582    ///
583    /// The parent window cannot have a parent, if it has, that parent ID is used instead.
584    /// The parent window must exist. This window (child) cannot have children, it also can't set itself as the parent.
585    ///
586    /// If any of these conditions are not met, an error is logged and the parent var is restored to the previous value.
587    ///
588    /// [`modal`]: Self::modal
589    /// [`color_scheme`]: Self::color_scheme
590    /// [`accent_color`]: Self::accent_color
591    pub fn parent(&self) -> ArcVar<Option<WindowId>> {
592        self.0.parent.clone()
593    }
594
595    /// Gets the widget in [`parent`] that hosts the window, if it is nesting.
596    ///
597    /// Nesting windows are presented as an widget, similar to an "iframe".
598    ///
599    /// [`parent`]: Self::parent
600    pub fn nest_parent(&self) -> ReadOnlyArcVar<Option<WidgetId>> {
601        self.0.nest_parent.read_only()
602    }
603
604    /// Defines the [`parent`](Self::parent) connection.
605    ///
606    /// Value is ignored if `parent` is not set. When this is `true` the parent window cannot be focused while this window is open.
607    ///
608    /// The default value is `false`.
609    pub fn modal(&self) -> ArcVar<bool> {
610        self.0.modal.clone()
611    }
612
613    /// Window children.
614    ///
615    /// This is a set of other windows that have this window as a [`parent`].
616    ///
617    /// [`parent`]: Self::parent
618    pub fn children(&self) -> ReadOnlyArcVar<IdSet<WindowId>> {
619        self.0.children.read_only()
620    }
621
622    /// Override the preferred color scheme.
623    ///
624    /// If set to `None` the system preference is used, see [`actual_color_scheme`].
625    ///
626    /// [`actual_color_scheme`]: Self::actual_color_scheme
627    pub fn color_scheme(&self) -> ArcVar<Option<ColorScheme>> {
628        self.0.color_scheme.clone()
629    }
630
631    /// Actual color scheme to use.
632    ///
633    /// This is the system preference, or [`color_scheme`] if it is set.
634    ///
635    /// [`color_scheme`]: Self::color_scheme
636    pub fn actual_color_scheme(&self) -> ReadOnlyArcVar<ColorScheme> {
637        self.0.actual_color_scheme.read_only()
638    }
639
640    /// Override the preferred accent color.
641    ///
642    /// If set to `None` the system preference is used, see [`actual_accent_color`].
643    ///
644    /// [`actual_accent_color`]: Self::actual_accent_color
645    pub fn accent_color(&self) -> ArcVar<Option<LightDark>> {
646        self.0.accent_color.clone()
647    }
648
649    /// Actual accent color to use.
650    ///
651    /// This is the system preference, or [`color_scheme`] if it is set.
652    ///
653    /// The window widget also sets [`ACCENT_COLOR_VAR`] to this variable.
654    ///
655    /// [`color_scheme`]: Self::color_scheme
656    /// [`ACCENT_COLOR_VAR`]: zng_color::colors::ACCENT_COLOR_VAR
657    pub fn actual_accent_color(&self) -> ReadOnlyArcVar<LightDark> {
658        self.0.actual_accent_color.read_only()
659    }
660
661    /// If the window is open.
662    ///
663    /// This is a read-only variable, it starts set to `true` and will update only once,
664    /// when the window finishes opening.
665    ///
666    /// Note that a window is only actually opened in the view-process after it [`is_loaded`].
667    ///
668    /// [`is_loaded`]: Self::is_loaded
669    pub fn is_open(&self) -> ReadOnlyArcVar<bool> {
670        self.0.is_open.read_only()
671    }
672
673    /// If the window has finished loading.
674    ///
675    /// This is a read-only variable, it starts set to `false` and will update only once, after
676    /// the first window layout and when all loading handles to the window are released.
677    ///
678    /// A window is only opened in the view-process once it is loaded, see [`WINDOWS.loading_handle`] for more details.
679    ///
680    /// [`WINDOWS.loading_handle`]: crate::WINDOWS::loading_handle
681    pub fn is_loaded(&self) -> ReadOnlyArcVar<bool> {
682        self.0.is_loaded.read_only()
683    }
684
685    /// Defines the active user attention required indicator.
686    ///
687    /// This is usually a visual indication on the taskbar icon that prompts the user to focus on the window, it is automatically
688    /// changed to `None` once the window receives focus or you can set it to `None` to cancel the indicator.
689    ///
690    /// Prefer using the `FOCUS` service and advanced `FocusRequest` configs instead of setting this variable directly.
691    pub fn focus_indicator(&self) -> ArcVar<Option<FocusIndicator>> {
692        self.0.focus_indicator.clone()
693    }
694
695    /// Defines if and how the frame pixels are captured for the next rendered frames.
696    ///
697    /// If set to [`Next`] the value will change to [`Sporadic`] after the next frame is rendered.
698    ///
699    /// Note that setting this to [`Next`] does not cause a frame request. Use [`WIDGET.render_update`] for that.
700    ///
701    /// [`Next`]: FrameCaptureMode::Next
702    /// [`Sporadic`]: FrameCaptureMode::Sporadic
703    /// [`WIDGET.render_update`]: zng_app::widget::WIDGET::render_update
704    pub fn frame_capture_mode(&self) -> ArcVar<FrameCaptureMode> {
705        self.0.frame_capture_mode.clone()
706    }
707
708    /// Window actual render mode.
709    ///
710    /// The initial value is the [`default_render_mode`], it can update after the window is created, when the view-process
711    /// actually creates the backend window and after a view-process respawn.
712    ///
713    /// [`default_render_mode`]: crate::WINDOWS::default_render_mode
714    pub fn render_mode(&self) -> ReadOnlyArcVar<RenderMode> {
715        self.0.render_mode.read_only()
716    }
717
718    /// If an accessibility service has requested info from this window.
719    ///
720    /// You can enable this in the app-process using [`enable_access`], the
721    /// view-process can also enable it on the first request for accessibility info by an external tool.
722    ///
723    /// This variable does not update to fully disabled after first enable, but the VIEW bit can disable and re-enable.
724    ///
725    /// [`enable_access`]: crate::WINDOW_Ext::enable_access
726    pub fn access_enabled(&self) -> ReadOnlyArcVar<AccessEnabled> {
727        self.0.access_enabled.read_only()
728    }
729
730    /// Attempt to set a system wide shutdown warning associated with the window.
731    ///
732    /// Operating systems that support this show the text in a warning for the user, it must be a short text
733    /// that identifies the critical operation that cannot be cancelled.
734    ///
735    /// Set to an empty text to remove the warning.
736    ///
737    /// Note that this does not stop the window from closing or the app from exiting normally, you must
738    /// handle window close requests and show some feedback to the user, the view-process will send a window close
739    /// request when a system shutdown attempt is detected.
740    ///
741    /// Note that there is no guarantee that the view-process or operating system will actually set a block, there
742    /// is no error result because operating systems can silently ignore block requests at any moment, even after
743    /// an initial successful block.
744    ///
745    /// ## Current Limitations
746    ///
747    /// The current `zng::view_process` or `zng-view` only implements this feature on Windows and it will only work properly
748    /// under these conditions:
749    ///
750    /// * It must be running in `run_same_process` mode. Windows kills all other processes, so in a run with `init` the app-process
751    ///   will be lost. Note that this also mean that the crash handler and worker processes are also killed.
752    /// * Must be built with `#![windows_subsystem = "windows"]` and must be running from the Windows Explorer (desktop).
753    pub fn system_shutdown_warn(&self) -> ArcVar<Txt> {
754        self.0.system_shutdown_warn.clone()
755    }
756}
757impl PartialEq for WindowVars {
758    fn eq(&self, other: &Self) -> bool {
759        Arc::ptr_eq(&self.0, &other.0)
760    }
761}
762impl Eq for WindowVars {}
763
764static_id! {
765    pub(super) static ref WINDOW_VARS_ID: StateId<WindowVars>;
766}