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}