Skip to main content

tao/
window.rs

1// Copyright 2014-2021 The winit contributors
2// Copyright 2021-2023 Tauri Programme within The Commons Conservancy
3// SPDX-License-Identifier: Apache-2.0
4
5//! The `Window` struct and associated types.
6use std::fmt;
7
8use crate::{
9  dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Pixel, PixelUnit, Position, Size},
10  error::{ExternalError, NotSupportedError, OsError},
11  event_loop::EventLoopWindowTarget,
12  monitor::{MonitorHandle, VideoMode},
13  platform_impl,
14};
15
16pub use crate::icon::{BadIcon, Icon};
17
18/// Progress State
19#[derive(Debug, Clone, Copy)]
20pub enum ProgressState {
21  None,
22  Normal,
23  /// **Treated as Normal in linux and macOS**
24  Indeterminate,
25  /// **Treated as Normal in linux**
26  Paused,
27  /// **Treated as Normal in linux**
28  Error,
29}
30
31pub struct ProgressBarState {
32  /// The progress bar state.
33  pub state: Option<ProgressState>,
34  /// The progress bar progress. This can be a value ranging from `0` to `100`
35  pub progress: Option<u64>,
36  /// The `.desktop` filename with the Unity desktop window manager, for example `myapp.desktop` **Linux Only**
37  pub desktop_filename: Option<String>,
38}
39
40/// Represents a window.
41///
42/// # Example
43///
44/// ```no_run
45/// use tao::{
46///     event::{Event, WindowEvent},
47///     event_loop::{ControlFlow, EventLoop},
48///     window::Window,
49/// };
50///
51/// let mut event_loop = EventLoop::new();
52/// let window = Window::new(&event_loop).unwrap();
53///
54/// event_loop.run(move |event, _, control_flow| {
55///     *control_flow = ControlFlow::Wait;
56///
57///     match event {
58///         Event::WindowEvent {
59///             event: WindowEvent::CloseRequested,
60///             ..
61///         } => *control_flow = ControlFlow::Exit,
62///         _ => (),
63///     }
64/// });
65/// ```
66pub struct Window {
67  pub(crate) window: platform_impl::Window,
68}
69
70impl fmt::Debug for Window {
71  fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
72    fmtr.pad("Window { .. }")
73  }
74}
75
76impl Drop for Window {
77  fn drop(&mut self) {
78    // If the window is in exclusive fullscreen, we must restore the desktop
79    // video mode (generally this would be done on application exit, but
80    // closing the window doesn't necessarily always mean application exit,
81    // such as when there are multiple windows)
82    if let Some(Fullscreen::Exclusive(_)) = self.fullscreen() {
83      self.set_fullscreen(None);
84    }
85  }
86}
87
88/// Type alias for a color in the RGBA format.
89///
90/// Each value can be 0..255 inclusive.
91pub type RGBA = (u8, u8, u8, u8);
92
93/// Identifier of a window. Unique for each window.
94///
95/// Can be obtained with `window.id()`.
96///
97/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you
98/// can then compare to the ids of your windows.
99#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
100pub struct WindowId(pub(crate) platform_impl::WindowId);
101
102impl WindowId {
103  /// # Safety
104  /// Returns a dummy `WindowId`, useful for unit testing. The only guarantee made about the return
105  /// value of this function is that it will always be equal to itself and to future values returned
106  /// by this function.  No other guarantees are made. This may be equal to a real `WindowId`.
107  ///
108  /// **Passing this into a tao function will result in undefined behavior.**
109  pub unsafe fn dummy() -> Self {
110    WindowId(platform_impl::WindowId::dummy())
111  }
112}
113
114/// Object that allows you to build windows.
115#[derive(Clone, Default)]
116pub struct WindowBuilder {
117  /// The attributes to use to create the window.
118  pub window: WindowAttributes,
119
120  // Platform-specific configuration.
121  pub(crate) platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes,
122}
123
124impl fmt::Debug for WindowBuilder {
125  fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
126    fmtr
127      .debug_struct("WindowBuilder")
128      .field("window", &self.window)
129      .finish()
130  }
131}
132
133/// Attributes to use when creating a window.
134#[derive(Debug, Clone)]
135pub struct WindowAttributes {
136  /// The dimensions of the window. If this is `None`, some platform-specific dimensions will be
137  /// used.
138  ///
139  /// The default is `None`.
140  pub inner_size: Option<Size>,
141
142  /// The window size constraints
143  pub inner_size_constraints: WindowSizeConstraints,
144
145  /// The desired position of the window. If this is `None`, some platform-specific position
146  /// will be chosen.
147  ///
148  /// The default is `None`.
149  ///
150  /// ## Platform-specific
151  ///
152  /// - **macOS**: The top left corner position of the window content, the window's "inner"
153  ///   position. The window title bar will be placed above it.
154  ///   The window will be positioned such that it fits on screen, maintaining
155  ///   set `inner_size` if any.
156  ///   If you need to precisely position the top left corner of the whole window you have to
157  ///   use [`Window::set_outer_position`] after creating the window.
158  /// - **Windows**: The top left corner position of the window title bar, the window's "outer"
159  ///   position.
160  ///   There may be a small gap between this position and the window due to the specifics of the
161  ///   Window Manager.
162  /// - **Linux**: The top left corner of the window, the window's "outer" position.
163  /// - **Linux(Wayland)**: Unsupported.
164  /// - **Others**: Ignored.
165  ///
166  /// See [`Window::set_outer_position`].
167  ///
168  /// [`Window::set_outer_position`]: crate::window::Window::set_outer_position
169  pub position: Option<Position>,
170
171  /// Whether the window is resizable or not.
172  ///
173  /// The default is `true`.
174  pub resizable: bool,
175
176  /// Whether the window is minimizable or not.
177  ///
178  /// The default is `true`.
179  ///
180  /// See [`Window::set_minimizable`] for details.
181  pub minimizable: bool,
182
183  /// Whether the window is maximizable or not.
184  ///
185  /// The default is `true`.
186  ///
187  /// See [`Window::set_maximizable`] for details.
188  pub maximizable: bool,
189
190  /// Whether the window is closable or not.
191  ///
192  /// The default is `true`.
193  ///
194  /// See [`Window::set_closable`] for details.
195  pub closable: bool,
196
197  /// Whether the window should be set as fullscreen upon creation.
198  ///
199  /// The default is `None`.
200  pub fullscreen: Option<Fullscreen>,
201
202  /// The title of the window in the title bar.
203  ///
204  /// The default is `"tao window"`.
205  pub title: String,
206
207  /// Whether the window should be maximized upon creation.
208  ///
209  /// The default is `false`.
210  pub maximized: bool,
211
212  /// Whether the window should be immediately visible upon creation.
213  ///
214  /// The default is `true`.
215  pub visible: bool,
216
217  /// Whether the the window should be transparent. If this is true, writing colors
218  /// with alpha values different than `1.0` will produce a transparent window.
219  ///
220  /// The default is `false`.
221  pub transparent: bool,
222
223  /// Whether the window should have borders and bars.
224  ///
225  /// The default is `true`.
226  pub decorations: bool,
227
228  /// Whether the window should always be on top of other windows.
229  ///
230  /// The default is `false`.
231  ///
232  /// ## Platform-specific:
233  ///
234  /// - **Linux(x11):** Result depends on the system's window manager. Consider this setting a suggestion.
235  /// - **Linux(Wayland):** Unsupported.
236  // TODO: Unsupported in gtk4
237  pub always_on_top: bool,
238
239  /// Whether the window should always be on bottom of other windows.
240  ///
241  /// The default is `false`.
242  ///
243  /// ## Platform-specific:
244  ///
245  /// - **Linux(x11):** Result depends on the system's window manager. Consider this setting a suggestion.
246  /// - **Linux(Wayland):** Unsupported.
247  // TODO: Unsupported in gtk4
248  pub always_on_bottom: bool,
249
250  /// The window icon.
251  ///
252  /// The default is `None`.
253  pub window_icon: Option<Icon>,
254
255  pub preferred_theme: Option<Theme>,
256
257  /// Whether the window should be initially focused or not.
258  ///
259  /// ## Platform-specific:
260  ///
261  /// **Android / iOS:** Unsupported.
262  pub focused: bool,
263
264  /// Whether the window should be focusable or not.
265  ///
266  /// ## Platform-specific:
267  ///
268  /// **Android / iOS:** Unsupported.
269  pub focusable: bool,
270
271  /// Prevents the window contents from being captured by other apps.
272  ///
273  /// ## Platform-specific
274  ///
275  /// - **iOS / Android / Linux:** Unsupported.
276  pub content_protection: bool,
277
278  /// Sets whether the window should be visible on all workspaces.
279  ///
280  /// ## Platform-specific
281  ///
282  /// - **iOS / Android / Windows:** Unsupported.
283  pub visible_on_all_workspaces: bool,
284
285  /// Sets the window background color.
286  ///
287  /// ## Platform-specific:
288  ///
289  /// - **Windows:** alpha channel is ignored. Instead manually draw the window, for example using `softbuffer` crate, see <https://github.com/tauri-apps/tao/blob/dev/examples/transparent.rs>
290  /// - **iOS / Android:** Unsupported.
291  pub background_color: Option<RGBA>,
292}
293
294impl Default for WindowAttributes {
295  #[inline]
296  fn default() -> WindowAttributes {
297    WindowAttributes {
298      inner_size: None,
299      inner_size_constraints: Default::default(),
300      position: None,
301      resizable: true,
302      minimizable: true,
303      maximizable: true,
304      closable: true,
305      title: "tao window".to_owned(),
306      maximized: false,
307      fullscreen: None,
308      visible: true,
309      transparent: false,
310      decorations: true,
311      always_on_top: false,
312      always_on_bottom: false,
313      window_icon: None,
314      preferred_theme: None,
315      focused: true,
316      focusable: true,
317      content_protection: false,
318      visible_on_all_workspaces: false,
319      background_color: None,
320    }
321  }
322}
323
324impl WindowBuilder {
325  /// Initializes a new `WindowBuilder` with default values.
326  #[inline]
327  pub fn new() -> Self {
328    Default::default()
329  }
330
331  /// Requests the window to be of specific dimensions.
332  ///
333  /// See [`Window::set_inner_size`] for details.
334  ///
335  /// [`Window::set_inner_size`]: crate::window::Window::set_inner_size
336  #[inline]
337  pub fn with_inner_size<S: Into<Size>>(mut self, size: S) -> Self {
338    self.window.inner_size = Some(size.into());
339    self
340  }
341
342  /// Sets a minimum dimension size for the window.
343  ///
344  /// See [`Window::set_min_inner_size`] for details.
345  ///
346  /// [`Window::set_min_inner_size`]: crate::window::Window::set_min_inner_size
347  #[inline]
348  pub fn with_min_inner_size<S: Into<Size>>(mut self, min_size: S) -> Self {
349    let size: Size = min_size.into();
350    let (width, height) = crate::extract_width_height(size);
351    self.window.inner_size_constraints.min_width = Some(width);
352    self.window.inner_size_constraints.min_height = Some(height);
353    self
354  }
355
356  /// Sets a maximum dimension size for the window.
357  ///
358  /// See [`Window::set_max_inner_size`] for details.
359  ///
360  /// [`Window::set_max_inner_size`]: crate::window::Window::set_max_inner_size
361  #[inline]
362  pub fn with_max_inner_size<S: Into<Size>>(mut self, max_size: S) -> Self {
363    let size: Size = max_size.into();
364    let (width, height) = crate::extract_width_height(size);
365    self.window.inner_size_constraints.max_width = Some(width);
366    self.window.inner_size_constraints.max_height = Some(height);
367    self
368  }
369
370  /// Sets inner size constraints for the window.
371  ///
372  /// See [`Window::set_inner_size_constraints`] for details.
373  ///
374  /// [`Window::set_inner_size_constraints`]: crate::window::Window::set_inner_size_constraints
375  #[inline]
376  pub fn with_inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self {
377    self.window.inner_size_constraints = constraints;
378    self
379  }
380
381  /// Sets a desired initial position for the window.
382  ///
383  /// See [`WindowAttributes::position`] for details.
384  ///
385  /// [`WindowAttributes::position`]: crate::window::WindowAttributes::position
386  #[inline]
387  pub fn with_position<P: Into<Position>>(mut self, position: P) -> Self {
388    self.window.position = Some(position.into());
389    self
390  }
391
392  /// Sets whether the window is resizable or not.
393  ///
394  /// See [`Window::set_resizable`] for details.
395  ///
396  /// [`Window::set_resizable`]: crate::window::Window::set_resizable
397  #[inline]
398  pub fn with_resizable(mut self, resizable: bool) -> Self {
399    self.window.resizable = resizable;
400    self
401  }
402
403  /// Sets whether the window is minimizable or not.
404  ///
405  /// See [`Window::set_minimizable`] for details.
406  ///
407  /// [`Window::set_minimizable`]: crate::window::Window::set_minimizable
408  #[inline]
409  pub fn with_minimizable(mut self, minimizable: bool) -> Self {
410    self.window.minimizable = minimizable;
411    self
412  }
413
414  /// Sets whether the window is maximizable or not.
415  ///
416  /// See [`Window::set_maximizable`] for details.
417  ///
418  /// [`Window::set_maximizable`]: crate::window::Window::set_maximizable
419  #[inline]
420  pub fn with_maximizable(mut self, maximizable: bool) -> Self {
421    self.window.maximizable = maximizable;
422    self
423  }
424
425  /// Sets whether the window is closable or not.
426  ///
427  /// See [`Window::set_closable`] for details.
428  ///
429  /// [`Window::set_closable`]: crate::window::Window::set_closable
430  #[inline]
431  pub fn with_closable(mut self, closable: bool) -> Self {
432    self.window.closable = closable;
433    self
434  }
435
436  /// Requests a specific title for the window.
437  ///
438  /// See [`Window::set_title`] for details.
439  ///
440  /// [`Window::set_title`]: crate::window::Window::set_title
441  #[inline]
442  pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
443    self.window.title = title.into();
444    self
445  }
446
447  /// Sets the window fullscreen state.
448  ///
449  /// See [`Window::set_fullscreen`] for details.
450  ///
451  /// [`Window::set_fullscreen`]: crate::window::Window::set_fullscreen
452  #[inline]
453  pub fn with_fullscreen(mut self, fullscreen: Option<Fullscreen>) -> Self {
454    self.window.fullscreen = fullscreen;
455    self
456  }
457
458  /// Requests maximized mode.
459  ///
460  /// See [`Window::set_maximized`] for details.
461  ///
462  /// [`Window::set_maximized`]: crate::window::Window::set_maximized
463  #[inline]
464  pub fn with_maximized(mut self, maximized: bool) -> Self {
465    self.window.maximized = maximized;
466    self
467  }
468
469  /// Sets whether the window will be initially hidden or visible.
470  ///
471  /// See [`Window::set_visible`] for details.
472  ///
473  /// [`Window::set_visible`]: crate::window::Window::set_visible
474  #[inline]
475  pub fn with_visible(mut self, visible: bool) -> Self {
476    self.window.visible = visible;
477    self
478  }
479
480  /// Sets whether the background of the window should be transparent.
481  #[inline]
482  pub fn with_transparent(mut self, transparent: bool) -> Self {
483    self.window.transparent = transparent;
484    self
485  }
486
487  /// Sets whether the window should have a border, a title bar, etc.
488  ///
489  /// See [`Window::set_decorations`] for details.
490  ///
491  /// [`Window::set_decorations`]: crate::window::Window::set_decorations
492  #[inline]
493  pub fn with_decorations(mut self, decorations: bool) -> Self {
494    self.window.decorations = decorations;
495    self
496  }
497
498  /// Sets whether or not the window will always be below other windows.
499  ///
500  /// See [`Window::set_always_on_bottom`] for details.
501  ///
502  /// [`Window::set_always_on_bottom`]: crate::window::Window::set_always_on_bottom
503  #[inline]
504  pub fn with_always_on_bottom(mut self, always_on_bottom: bool) -> Self {
505    self.window.always_on_top = false;
506    self.window.always_on_bottom = always_on_bottom;
507    self
508  }
509
510  /// Sets whether or not the window will always be on top of other windows.
511  ///
512  /// See [`Window::set_always_on_top`] for details.
513  ///
514  /// [`Window::set_always_on_top`]: crate::window::Window::set_always_on_top
515  #[inline]
516  pub fn with_always_on_top(mut self, always_on_top: bool) -> Self {
517    self.window.always_on_bottom = false;
518    self.window.always_on_top = always_on_top;
519    self
520  }
521
522  /// Sets the window icon.
523  ///
524  /// See [`Window::set_window_icon`] for details.
525  ///
526  /// [`Window::set_window_icon`]: crate::window::Window::set_window_icon
527  #[inline]
528  pub fn with_window_icon(mut self, window_icon: Option<Icon>) -> Self {
529    self.window.window_icon = window_icon;
530    self
531  }
532
533  /// Forces a theme or uses the system settings if `None` was provided.
534  ///
535  /// ## Platform-specific:
536  ///
537  /// - **Windows**: It is recommended to always use the same theme used
538  ///   in [`EventLoopBuilderExtWindows::with_theme`] for this method also
539  ///   or use `None` so it automatically uses the theme used in [`EventLoopBuilderExtWindows::with_theme`]
540  ///   or falls back to the system preference, because [`EventLoopBuilderExtWindows::with_theme`] changes
541  ///   the theme for some controls like context menus which is app-wide and can't be changed by this method.
542  ///
543  /// [`EventLoopBuilderExtWindows::with_theme`]: crate::platform::windows::EventLoopBuilderExtWindows::with_theme
544  #[allow(rustdoc::broken_intra_doc_links)]
545  #[inline]
546  pub fn with_theme(mut self, theme: Option<Theme>) -> WindowBuilder {
547    self.window.preferred_theme = theme;
548    self
549  }
550
551  /// Whether the window will be initially focused or not.
552  ///
553  /// ## Platform-specific:
554  ///
555  /// **Android / iOS:** Unsupported.
556  #[inline]
557  pub fn with_focused(mut self, focused: bool) -> WindowBuilder {
558    self.window.focused = focused;
559    self
560  }
561
562  /// Whether the window will be focusable or not.
563  ///
564  /// ## Platform-specific:
565  /// **Android / iOS:** Unsupported.
566  #[inline]
567  pub fn with_focusable(mut self, focusable: bool) -> WindowBuilder {
568    self.window.focusable = focusable;
569    self
570  }
571
572  /// Prevents the window contents from being captured by other apps.
573  ///
574  /// ## Platform-specific
575  ///
576  /// - **iOS / Android / Linux:** Unsupported.
577  #[inline]
578  pub fn with_content_protection(mut self, protected: bool) -> WindowBuilder {
579    self.window.content_protection = protected;
580    self
581  }
582
583  /// Sets whether the window should be visible on all workspaces.
584  ///
585  /// ## Platform-specific
586  ///
587  /// - **iOS / Android / Windows:** Unsupported.
588  #[inline]
589  pub fn with_visible_on_all_workspaces(mut self, visible: bool) -> WindowBuilder {
590    self.window.visible_on_all_workspaces = visible;
591    self
592  }
593
594  /// Sets the window background color.
595  ///
596  /// ## Platform-specific:
597  ///
598  /// - **Windows:** alpha channel is ignored. Instead manually draw the window, for example using `softbuffer` crate, see <https://github.com/tauri-apps/tao/blob/dev/examples/transparent.rs>
599  /// - **iOS / Android:** Unsupported.
600  #[inline]
601  pub fn with_background_color(mut self, color: RGBA) -> WindowBuilder {
602    self.window.background_color = Some(color);
603    self
604  }
605
606  /// Builds the window.
607  ///
608  /// Possible causes of error include denied permission, incompatible system, and lack of memory.
609  #[inline]
610  pub fn build<T: 'static>(
611    self,
612    window_target: &EventLoopWindowTarget<T>,
613  ) -> Result<Window, OsError> {
614    platform_impl::Window::new(&window_target.p, self.window, self.platform_specific).map(
615      |window| {
616        window.request_redraw();
617        Window { window }
618      },
619    )
620  }
621}
622
623/// Base Window functions.
624impl Window {
625  /// Creates a new Window for platforms where this is appropriate.
626  ///
627  /// This function is equivalent to [`WindowBuilder::new().build(event_loop)`].
628  ///
629  /// Error should be very rare and only occur in case of permission denied, incompatible system,
630  ///  out of memory, etc.
631  ///
632  /// [`WindowBuilder::new().build(event_loop)`]: crate::window::WindowBuilder::build
633  #[inline]
634  pub fn new<T: 'static>(event_loop: &EventLoopWindowTarget<T>) -> Result<Window, OsError> {
635    let builder = WindowBuilder::new();
636    builder.build(event_loop)
637  }
638
639  /// Returns an identifier unique to the window.
640  #[inline]
641  pub fn id(&self) -> WindowId {
642    WindowId(self.window.id())
643  }
644
645  /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
646  ///
647  /// See the [`dpi`](crate::dpi) module for more information.
648  ///
649  /// Note that this value can change depending on user action (for example if the window is
650  /// moved to another screen); as such, tracking `WindowEvent::ScaleFactorChanged` events is
651  /// the most robust way to track the DPI you need to use to draw.
652  ///
653  /// ## Platform-specific
654  ///
655  /// - **Android:** Always returns 1.0.
656  /// - **iOS:** Can only be called on the main thread. Returns the underlying `UIView`'s
657  ///   [`contentScaleFactor`].
658  ///
659  /// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
660  #[inline]
661  pub fn scale_factor(&self) -> f64 {
662    self.window.scale_factor()
663  }
664
665  /// Emits a `WindowEvent::RedrawRequested` event in the associated event loop after all OS
666  /// events have been processed by the event loop.
667  ///
668  /// This is the **strongly encouraged** method of redrawing windows, as it can integrate with
669  /// OS-requested redraws (e.g. when a window gets resized).
670  ///
671  /// This function can cause `RedrawRequested` events to be emitted after `Event::MainEventsCleared`
672  /// but before `Event::NewEvents` if called in the following circumstances:
673  /// * While processing `MainEventsCleared`.
674  /// * While processing a `RedrawRequested` event that was sent during `MainEventsCleared` or any
675  ///   directly subsequent `RedrawRequested` event.
676  ///
677  /// ## Platform-specific
678  ///
679  /// - **iOS:** Can only be called on the main thread.
680  /// - **Android:** Unsupported.
681  #[inline]
682  pub fn request_redraw(&self) {
683    self.window.request_redraw()
684  }
685}
686
687/// Position and size functions.
688impl Window {
689  /// Returns the position of the top-left hand corner of the window's client area relative to the
690  /// top-left hand corner of the desktop.
691  ///
692  /// The same conditions that apply to `outer_position` apply to this method.
693  ///
694  /// ## Platform-specific
695  ///
696  /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
697  ///   window's [safe area] in the screen space coordinate system.
698  /// - **Android:** Always returns [`NotSupportedError`].
699  ///
700  /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
701  #[inline]
702  pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
703    self.window.inner_position()
704  }
705
706  /// Returns the position of the top-left hand corner of the window relative to the
707  ///  top-left hand corner of the desktop.
708  ///
709  /// Note that the top-left hand corner of the desktop is not necessarily the same as
710  ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
711  ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
712  ///
713  /// The coordinates can be negative if the top-left hand corner of the window is outside
714  ///  of the visible screen region.
715  ///
716  /// ## Platform-specific
717  ///
718  /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
719  ///   window in the screen space coordinate system.
720  /// - **Android:** Always returns [`NotSupportedError`].
721  /// - **Linux(Wayland)**: Has no effect, since Wayland doesn't support a global cordinate system
722  #[inline]
723  pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
724    self.window.outer_position()
725  }
726
727  /// Modifies the position of the window.
728  ///
729  /// See `outer_position` for more information about the coordinates. This automatically un-maximizes the
730  /// window if it's maximized.
731  ///
732  /// ## Platform-specific
733  ///
734  /// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
735  ///   window in the screen space coordinate system.
736  /// - **Android / Linux(Wayland):** Unsupported.
737  #[inline]
738  pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
739    self.window.set_outer_position(position.into())
740  }
741
742  /// Returns the physical size of the window's client area.
743  ///
744  /// The client area is the content of the window, excluding the title bar and borders.
745  ///
746  /// ## Platform-specific
747  ///
748  /// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window's
749  ///   [safe area] in screen space coordinates.
750  ///
751  /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
752  #[inline]
753  pub fn inner_size(&self) -> PhysicalSize<u32> {
754    self.window.inner_size()
755  }
756
757  /// Modifies the inner size of the window.
758  ///
759  /// See `inner_size` for more information about the values. This automatically un-maximizes the
760  /// window if it's maximized.
761  ///
762  /// ## Platform-specific
763  ///
764  /// - **iOS / Android:** Unsupported.
765  #[inline]
766  pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
767    self.window.set_inner_size(size.into())
768  }
769
770  /// Returns the physical size of the entire window.
771  ///
772  /// These dimensions include the title bar and borders. If you don't want that (and you usually don't),
773  /// use `inner_size` instead.
774  ///
775  /// ## Platform-specific
776  ///
777  /// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window in
778  ///   screen space coordinates.
779  #[inline]
780  pub fn outer_size(&self) -> PhysicalSize<u32> {
781    self.window.outer_size()
782  }
783
784  /// Sets a minimum dimension size for the window.
785  ///
786  /// ## Platform-specific
787  ///
788  /// - **iOS / Android:** Unsupported.
789  #[inline]
790  pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
791    self.window.set_min_inner_size(min_size.map(|s| s.into()))
792  }
793
794  /// Sets a maximum dimension size for the window.
795  ///
796  /// ## Platform-specific
797  ///
798  /// - **iOS / Android:** Unsupported.
799  #[inline]
800  pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
801    self.window.set_max_inner_size(max_size.map(|s| s.into()))
802  }
803
804  /// Sets inner size constraints for the window.
805  ///
806  /// ## Platform-specific
807  ///
808  /// - **iOS / Android:** Unsupported.
809  #[inline]
810  pub fn set_inner_size_constraints(&self, constraints: WindowSizeConstraints) {
811    self.window.set_inner_size_constraints(constraints)
812  }
813}
814
815/// Misc. attribute functions.
816impl Window {
817  /// Modifies the title of the window.
818  ///
819  /// ## Platform-specific
820  ///
821  /// - **iOS / Android:** Unsupported.
822  #[inline]
823  pub fn set_title(&self, title: &str) {
824    self.window.set_title(title)
825  }
826
827  /// Gets the current title of the window.
828  ///
829  /// ## Platform-specific
830  ///
831  /// - **iOS / Android:** Unsupported. Returns ane empty string.
832  #[inline]
833  pub fn title(&self) -> String {
834    self.window.title()
835  }
836
837  /// Modifies the window's visibility.
838  ///
839  /// If `false`, this will hide the window. If `true`, this will show the window.
840  /// ## Platform-specific
841  ///
842  /// - **Android:** Unsupported.
843  /// - **iOS:** Can only be called on the main thread.
844  #[inline]
845  pub fn set_visible(&self, visible: bool) {
846    self.window.set_visible(visible)
847  }
848
849  /// Bring the window to front and focus.
850  ///
851  /// ## Platform-specific
852  ///
853  /// - **iOS / Android:** Unsupported.
854  #[inline]
855  pub fn set_focus(&self) {
856    self.window.set_focus()
857  }
858
859  /// Sets whether the window is focusable or not.
860  ///
861  /// ## Platform-specific
862  ///
863  /// - **macOS**: If the window is already focused, it is not possible to unfocus it after calling `set_focusable(false)`.
864  ///   In this case, you might consider calling [`Window::set_focus`] but it will move the window to the back i.e. at the bottom in terms of z-order.
865  /// - **iOS / Android:** Unsupported.
866  #[inline]
867  pub fn set_focusable(&self, focusable: bool) {
868    self.window.set_focusable(focusable)
869  }
870
871  /// Is window active and focused?
872  ///
873  /// ## Platform-specific
874  ///
875  /// - **iOS / Android:** Unsupported.
876  #[inline]
877  pub fn is_focused(&self) -> bool {
878    self.window.is_focused()
879  }
880
881  /// Indicates whether the window is always on top of other windows.
882  ///
883  /// ## Platform-specific
884  ///
885  /// - **iOS / Android:** Unsupported.
886  #[inline]
887  pub fn is_always_on_top(&self) -> bool {
888    self.window.is_always_on_top()
889  }
890
891  /// Sets whether the window is resizable or not.
892  ///
893  /// Note that making the window unresizable doesn't exempt you from handling `Resized`, as that event can still be
894  /// triggered by DPI scaling, entering fullscreen mode, etc.
895  ///
896  /// ## Platform-specific
897  ///
898  /// This only has an effect on desktop platforms.
899  ///
900  /// Due to a bug in XFCE, this has no effect on Xfwm.
901  ///
902  /// ## Platform-specific
903  ///
904  /// - **Linux:** Most size methods like maximized are async and do not work well with calling
905  ///   sequentailly. For setting inner or outer size, you don't need to set resizable to true before
906  ///   it. It can resize no matter what. But if you insist to do so, it has a `100, 100` minimum
907  ///   limitation somehow. For maximizing, it requires resizable is true. If you really want to set
908  ///   resizable to false after it. You might need a mechanism to check the window is really
909  ///   maximized.
910  /// - **iOS / Android:** Unsupported.
911  #[inline]
912  pub fn set_resizable(&self, resizable: bool) {
913    self.window.set_resizable(resizable)
914  }
915
916  /// Sets whether the window is minimizable or not.
917  ///
918  /// ## Platform-specific
919  ///
920  /// - **Linux / iOS / Android:** Unsupported.
921  #[inline]
922  pub fn set_minimizable(&self, minimizable: bool) {
923    self.window.set_minimizable(minimizable)
924  }
925
926  /// Sets whether the window is maximizable or not.
927  ///
928  /// ## Platform-specific
929  ///
930  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
931  /// - **Linux / iOS / Android:** Unsupported.
932  #[inline]
933  pub fn set_maximizable(&self, maximizable: bool) {
934    self.window.set_maximizable(maximizable)
935  }
936
937  /// Sets whether the window is closable or not.
938  ///
939  /// ## Platform-specific
940  ///
941  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
942  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
943  /// - **iOS / Android:** Unsupported.
944  #[inline]
945  pub fn set_closable(&self, closable: bool) {
946    self.window.set_closable(closable)
947  }
948
949  /// Sets the window to minimized or back
950  ///
951  /// ## Platform-specific
952  ///
953  /// - **iOS / Android:** Unsupported.
954  #[inline]
955  pub fn set_minimized(&self, minimized: bool) {
956    self.window.set_minimized(minimized);
957  }
958
959  /// Sets the window to maximized or back.
960  ///
961  /// ## Platform-specific
962  ///
963  /// - **iOS / Android:** Unsupported.
964  #[inline]
965  pub fn set_maximized(&self, maximized: bool) {
966    self.window.set_maximized(maximized)
967  }
968
969  /// Gets the window's current maximized state.
970  ///
971  /// ## Platform-specific
972  ///
973  /// - **iOS / Android:** Unsupported.
974  #[inline]
975  pub fn is_maximized(&self) -> bool {
976    self.window.is_maximized()
977  }
978
979  /// Gets the window's current minimized state.
980  ///
981  /// ## Platform-specific
982  ///
983  /// - **iOS / Android:** Unsupported.
984  #[inline]
985  pub fn is_minimized(&self) -> bool {
986    self.window.is_minimized()
987  }
988
989  /// Gets the window's current visibility state.
990  ///
991  /// ## Platform-specific
992  ///
993  /// - **iOS / Android:** Unsupported.
994  #[inline]
995  pub fn is_visible(&self) -> bool {
996    self.window.is_visible()
997  }
998
999  /// Gets the window's current resizable state.
1000  ///
1001  /// ## Platform-specific
1002  ///
1003  /// - **iOS / Android:** Unsupported.
1004  #[inline]
1005  pub fn is_resizable(&self) -> bool {
1006    self.window.is_resizable()
1007  }
1008
1009  /// Gets the window's current minimizable state.
1010  ///
1011  /// ## Platform-specific
1012  ///
1013  /// - **Linux / iOS / Android:** Unsupported.
1014  #[inline]
1015  pub fn is_minimizable(&self) -> bool {
1016    self.window.is_minimizable()
1017  }
1018
1019  /// Gets the window's current maximizable state.
1020  ///
1021  /// ## Platform-specific
1022  ///
1023  /// - **Linux / iOS / Android:** Unsupported.
1024  #[inline]
1025  pub fn is_maximizable(&self) -> bool {
1026    self.window.is_maximizable()
1027  }
1028
1029  /// Gets the window's current closable state.
1030  ///
1031  /// ## Platform-specific
1032  ///
1033  /// - **iOS / Android:** Unsupported.
1034  #[inline]
1035  pub fn is_closable(&self) -> bool {
1036    self.window.is_closable()
1037  }
1038
1039  /// Gets the window's current decoration state.
1040  ///
1041  /// ## Platform-specific
1042  ///
1043  /// - **iOS / Android:** Unsupported.
1044  pub fn is_decorated(&self) -> bool {
1045    self.window.is_decorated()
1046  }
1047
1048  /// Sets the window to fullscreen or back.
1049  ///
1050  /// ## Platform-specific
1051  ///
1052  /// - **macOS:** `Fullscreen::Exclusive` provides true exclusive mode with a
1053  ///   video mode change. *Caveat!* macOS doesn't provide task switching (or
1054  ///   spaces!) while in exclusive fullscreen mode. This mode should be used
1055  ///   when a video mode change is desired, but for a better user experience,
1056  ///   borderless fullscreen might be preferred.
1057  ///
1058  ///   `Fullscreen::Borderless` provides a borderless fullscreen window on a
1059  ///   separate space. This is the idiomatic way for fullscreen games to work
1060  ///   on macOS. See `WindowExtMacOs::set_simple_fullscreen` if
1061  ///   separate spaces are not preferred.
1062  ///
1063  ///   The dock and the menu bar are always disabled in fullscreen mode.
1064  /// - **iOS:** Can only be called on the main thread.
1065  /// - **Windows:** Screen saver is disabled in fullscreen mode.
1066  /// - **Linux:** The window will only fullscreen to current monitor no matter which enum variant.
1067  /// - **Android:** Unsupported.
1068  #[inline]
1069  pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
1070    self.window.set_fullscreen(fullscreen)
1071  }
1072
1073  /// Gets the window's current fullscreen state.
1074  ///
1075  /// ## Platform-specific
1076  ///
1077  /// - **iOS:** Can only be called on the main thread.
1078  /// - **Android:** Will always return `None`.
1079  #[inline]
1080  pub fn fullscreen(&self) -> Option<Fullscreen> {
1081    self.window.fullscreen()
1082  }
1083
1084  /// Turn window decorations on or off.
1085  ///
1086  /// ## Platform-specific
1087  ///
1088  /// - **iOS / Android:** Unsupported.
1089  ///
1090  /// [`setPrefersStatusBarHidden`]: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc
1091  #[inline]
1092  pub fn set_decorations(&self, decorations: bool) {
1093    self.window.set_decorations(decorations)
1094  }
1095
1096  /// Change whether or not the window will always be below other windows.
1097  ///
1098  /// ## Platform-specific
1099  ///
1100  /// - **Windows**: There is no guarantee that the window will be the bottom most but it will try to be.
1101  /// - **Linux(x11):** Result depends on the system's window manager. Consider this setting a suggestion.
1102  /// - **Linux(Wayland) / iOS / Android:** Unsupported.
1103  // TODO: Unsupported in gtk4
1104  #[inline]
1105  pub fn set_always_on_bottom(&self, always_on_bottom: bool) {
1106    self.window.set_always_on_bottom(always_on_bottom)
1107  }
1108
1109  /// Change whether or not the window will always be on top of other windows.
1110  ///
1111  /// ## Platform-specific
1112  ///
1113  /// - **Linux(x11):** Result depends on the system's window manager. Consider this setting a suggestion.
1114  /// - **Linux(Wayland) / iOS / Android:** Unsupported.
1115  // TODO: Unsupported in gtk4
1116  #[inline]
1117  pub fn set_always_on_top(&self, always_on_top: bool) {
1118    self.window.set_always_on_top(always_on_top)
1119  }
1120
1121  /// Sets the window icon. On Windows and Linux, this is typically the small icon in the top-left
1122  /// corner of the title bar.
1123  ///
1124  /// ## Platform-specific
1125  ///
1126  /// - **iOS / Android / macOS:** Unsupported.
1127  ///
1128  /// On Windows, this sets `ICON_SMALL`. The base size for a window icon is 16x16, but it's
1129  /// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
1130  #[inline]
1131  pub fn set_window_icon(&self, window_icon: Option<Icon>) {
1132    self.window.set_window_icon(window_icon)
1133  }
1134
1135  /// Sets location of IME candidate box in client area coordinates relative to the top left.
1136  ///
1137  /// ## Platform-specific
1138  ///
1139  /// - **iOS / Android:** Unsupported.
1140  #[inline]
1141  pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
1142    self.window.set_ime_position(position.into())
1143  }
1144
1145  /// Sets the taskbar progress state.
1146  ///
1147  /// ## Platform-specific
1148  ///
1149  /// - **Linux / macOS**: Unlike windows, progress bar is app-wide and not specific to this window. Only supported desktop environments with `libunity` (e.g. GNOME).
1150  /// - **iOS / Android:** Unsupported.
1151  #[inline]
1152  pub fn set_progress_bar(&self, _progress: ProgressBarState) {
1153    #[cfg(any(
1154      windows,
1155      target_os = "linux",
1156      target_os = "dragonfly",
1157      target_os = "freebsd",
1158      target_os = "netbsd",
1159      target_os = "openbsd",
1160      target_os = "macos",
1161    ))]
1162    self.window.set_progress_bar(_progress)
1163  }
1164
1165  /// Requests user attention to the window, this has no effect if the application
1166  /// is already focused. How requesting for user attention manifests is platform dependent,
1167  /// see `UserAttentionType` for details.
1168  ///
1169  /// Providing `None` will unset the request for user attention. Unsetting the request for
1170  /// user attention might not be done automatically by the WM when the window receives input.
1171  ///
1172  /// ## Platform-specific
1173  ///
1174  /// - **iOS / Android:** Unsupported.
1175  /// - **macOS:** `None` has no effect.
1176  /// - **Linux:** Urgency levels have the same effect.
1177  #[inline]
1178  pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
1179    self.window.request_user_attention(request_type)
1180  }
1181
1182  /// Returns the current window theme.
1183  ///
1184  /// ## Platform-specific
1185  ///
1186  /// - **iOS / Android:** Unsupported.
1187  #[inline]
1188  pub fn theme(&self) -> Theme {
1189    self.window.theme()
1190  }
1191
1192  /// Sets the theme for this window.
1193  ///
1194  /// ## Platform-specific
1195  ///
1196  /// - **Linux / macOS**: Theme is app-wide and not specific to this window.
1197  /// - **iOS / Android:** Unsupported.
1198  #[inline]
1199  pub fn set_theme(&self, #[allow(unused)] theme: Option<Theme>) {
1200    #[cfg(any(
1201      windows,
1202      target_os = "linux",
1203      target_os = "dragonfly",
1204      target_os = "freebsd",
1205      target_os = "netbsd",
1206      target_os = "openbsd",
1207      target_os = "macos",
1208    ))]
1209    self.window.set_theme(theme)
1210  }
1211
1212  /// Prevents the window contents from being captured by other apps.
1213  ///
1214  /// ## Platform-specific
1215  ///
1216  /// - **iOS / Android / Linux:** Unsupported.
1217  pub fn set_content_protection(&self, #[allow(unused)] enabled: bool) {
1218    #[cfg(any(target_os = "macos", target_os = "windows"))]
1219    self.window.set_content_protection(enabled);
1220  }
1221
1222  /// Sets whether the window should be visible on all workspaces.
1223  ///
1224  /// ## Platform-specific
1225  ///
1226  /// - **iOS / Android / Windows:** Unsupported.
1227  pub fn set_visible_on_all_workspaces(&self, #[allow(unused)] visible: bool) {
1228    #[cfg(any(target_os = "macos", target_os = "linux"))]
1229    self.window.set_visible_on_all_workspaces(visible)
1230  }
1231
1232  /// Sets the window background color.
1233  ///
1234  /// ## Platform-specific:
1235  ///
1236  /// - **Windows:** alpha channel is ignored. Instead manually draw the window, for example using `softbuffer` crate, see <https://github.com/tauri-apps/tao/blob/dev/examples/transparent.rs>
1237  /// - **iOS / Android:** Unsupported.
1238  #[inline]
1239  pub fn set_background_color(&self, color: Option<RGBA>) {
1240    self.window.set_background_color(color)
1241  }
1242}
1243
1244/// Cursor functions.
1245impl Window {
1246  /// Modifies the cursor icon of the window.
1247  ///
1248  /// ## Platform-specific
1249  ///
1250  /// - **iOS / Android:** Unsupported.
1251  #[inline]
1252  pub fn set_cursor_icon(&self, cursor: CursorIcon) {
1253    self.window.set_cursor_icon(cursor);
1254  }
1255
1256  /// Changes the position of the cursor in window coordinates.
1257  ///
1258  /// ## Platform-specific
1259  ///
1260  /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
1261  #[inline]
1262  pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
1263    self.window.set_cursor_position(position.into())
1264  }
1265
1266  /// Grabs the cursor, preventing it from leaving the window.
1267  ///
1268  /// There's no guarantee that the cursor will be hidden. You should
1269  /// hide it by yourself if you want so.
1270  ///
1271  /// ## Platform-specific
1272  ///
1273  /// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward.
1274  /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
1275  #[inline]
1276  pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
1277    self.window.set_cursor_grab(grab)
1278  }
1279
1280  /// Modifies the cursor's visibility.
1281  ///
1282  /// If `false`, this will hide the cursor. If `true`, this will show the cursor.
1283  ///
1284  /// ## Platform-specific
1285  ///
1286  /// - **Windows:** The cursor is only hidden within the confines of the window.
1287  /// - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is
1288  ///   outside of the window.
1289  /// - **iOS / Android:** Unsupported.
1290  #[inline]
1291  pub fn set_cursor_visible(&self, visible: bool) {
1292    self.window.set_cursor_visible(visible)
1293  }
1294
1295  /// Moves the window with the left mouse button until the button is released.
1296  ///
1297  /// There's no guarantee that this will work unless the left mouse button was pressed
1298  /// immediately before this function is called.
1299  ///
1300  /// ## Platform-specific
1301  ///
1302  /// - **macOS:** May prevent the button release event to be triggered.
1303  /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
1304  #[inline]
1305  pub fn drag_window(&self) -> Result<(), ExternalError> {
1306    self.window.drag_window()
1307  }
1308
1309  /// Resizes the window with the left mouse button until the button is released.
1310  ///
1311  /// There's no guarantee that this will work unless the left mouse button was pressed
1312  /// immediately before this function is called.
1313  ///
1314  /// ## Platform-specific
1315  ///
1316  /// - **macOS / iOS / Android:** Always returns an [`ExternalError::NotSupported`].
1317  #[inline]
1318  pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
1319    self.window.drag_resize_window(direction)
1320  }
1321
1322  /// Modifies whether the window catches cursor events.
1323  ///
1324  /// If `true`, the events are passed through the window such that any other window behind it receives them.
1325  /// If `false` the window will catch the cursor events. By default cursor events are not ignored.
1326  ///
1327  /// ## Platform-specific
1328  ///
1329  /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`]
1330  #[inline]
1331  pub fn set_ignore_cursor_events(&self, ignore: bool) -> Result<(), ExternalError> {
1332    self.window.set_ignore_cursor_events(ignore)
1333  }
1334
1335  /// Returns the current cursor position
1336  ///
1337  /// ## Platform-specific
1338  ///
1339  /// - **iOS / Android / Linux(Wayland)**: Unsupported, returns `0,0`.
1340  #[inline]
1341  pub fn cursor_position(&self) -> Result<PhysicalPosition<f64>, ExternalError> {
1342    self.window.cursor_position()
1343  }
1344}
1345
1346/// Monitor info functions.
1347impl Window {
1348  /// Returns the monitor on which the window currently resides.
1349  ///
1350  /// Returns `None` if current monitor can't be detected.
1351  ///
1352  /// ## Platform-specific
1353  ///
1354  /// **iOS:** Can only be called on the main thread.
1355  #[inline]
1356  pub fn current_monitor(&self) -> Option<MonitorHandle> {
1357    self.window.current_monitor()
1358  }
1359
1360  #[inline]
1361  /// Returns the monitor that contains the given point.
1362  ///
1363  /// ## Platform-specific:
1364  ///
1365  /// - **Android / iOS:** Unsupported.
1366  pub fn monitor_from_point(&self, x: f64, y: f64) -> Option<MonitorHandle> {
1367    self.window.monitor_from_point(x, y)
1368  }
1369
1370  /// Returns the list of all the monitors available on the system.
1371  ///
1372  /// This is the same as `EventLoopWindowTarget::available_monitors`, and is provided for convenience.
1373  ///
1374  /// ## Platform-specific
1375  ///
1376  /// **iOS:** Can only be called on the main thread.
1377  #[inline]
1378  pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
1379    self
1380      .window
1381      .available_monitors()
1382      .into_iter()
1383      .map(|inner| MonitorHandle { inner })
1384  }
1385
1386  /// Returns the primary monitor of the system.
1387  ///
1388  /// Returns `None` if it can't identify any monitor as a primary one.
1389  ///
1390  /// This is the same as `EventLoopWindowTarget::primary_monitor`, and is provided for convenience.
1391  ///
1392  /// ## Platform-specific
1393  ///
1394  /// **iOS:** Can only be called on the main thread.
1395  #[inline]
1396  pub fn primary_monitor(&self) -> Option<MonitorHandle> {
1397    self.window.primary_monitor()
1398  }
1399}
1400
1401#[cfg(feature = "rwh_04")]
1402unsafe impl rwh_04::HasRawWindowHandle for Window {
1403  fn raw_window_handle(&self) -> rwh_04::RawWindowHandle {
1404    self.window.raw_window_handle_rwh_04()
1405  }
1406}
1407
1408#[cfg(feature = "rwh_05")]
1409unsafe impl rwh_05::HasRawWindowHandle for Window {
1410  fn raw_window_handle(&self) -> rwh_05::RawWindowHandle {
1411    self.window.raw_window_handle_rwh_05()
1412  }
1413}
1414
1415#[cfg(feature = "rwh_05")]
1416unsafe impl rwh_05::HasRawDisplayHandle for Window {
1417  fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle {
1418    self.window.raw_display_handle_rwh_05()
1419  }
1420}
1421
1422#[cfg(feature = "rwh_06")]
1423impl rwh_06::HasWindowHandle for Window {
1424  fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
1425    let raw = self.window.raw_window_handle_rwh_06()?;
1426    // SAFETY: The window handle will never be deallocated while the window is alive.
1427    Ok(unsafe { rwh_06::WindowHandle::borrow_raw(raw) })
1428  }
1429}
1430
1431#[cfg(feature = "rwh_06")]
1432impl rwh_06::HasDisplayHandle for Window {
1433  fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
1434    let raw = self.window.raw_display_handle_rwh_06()?;
1435    // SAFETY: The window handle will never be deallocated while the window is alive.
1436    Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
1437  }
1438}
1439
1440/// Describes the appearance of the mouse cursor.
1441#[non_exhaustive]
1442#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1443#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1444#[derive(Default)]
1445pub enum CursorIcon {
1446  /// The platform-dependent default cursor.
1447  #[default]
1448  Default,
1449  /// A simple crosshair.
1450  Crosshair,
1451  /// A hand (often used to indicate links in web browsers).
1452  Hand,
1453  /// Self explanatory.
1454  Arrow,
1455  /// Indicates something is to be moved.
1456  Move,
1457  /// Indicates text that may be selected or edited.
1458  Text,
1459  /// Program busy indicator.
1460  Wait,
1461  /// Help indicator (often rendered as a "?")
1462  Help,
1463  /// Progress indicator. Shows that processing is being done. But in contrast
1464  /// with "Wait" the user may still interact with the program. Often rendered
1465  /// as a spinning beach ball, or an arrow with a watch or hourglass.
1466  Progress,
1467
1468  /// Cursor showing that something cannot be done.
1469  NotAllowed,
1470  ContextMenu,
1471  Cell,
1472  VerticalText,
1473  Alias,
1474  Copy,
1475  NoDrop,
1476  /// Indicates something can be grabbed.
1477  Grab,
1478  /// Indicates something is grabbed.
1479  Grabbing,
1480  AllScroll,
1481  ZoomIn,
1482  ZoomOut,
1483
1484  /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
1485  /// is used when the movement starts from the south-east corner of the box.
1486  EResize,
1487  NResize,
1488  NeResize,
1489  NwResize,
1490  SResize,
1491  SeResize,
1492  SwResize,
1493  WResize,
1494  EwResize,
1495  NsResize,
1496  NeswResize,
1497  NwseResize,
1498  ColResize,
1499  RowResize,
1500}
1501
1502/// Fullscreen modes.
1503#[non_exhaustive]
1504#[allow(clippy::large_enum_variant)]
1505#[derive(Clone, Debug, PartialEq)]
1506pub enum Fullscreen {
1507  Exclusive(VideoMode),
1508
1509  /// Providing `None` to `Borderless` will fullscreen on the current monitor.
1510  Borderless(Option<MonitorHandle>),
1511}
1512
1513#[non_exhaustive]
1514#[derive(Default, Clone, Copy, Debug, PartialEq)]
1515pub enum Theme {
1516  #[default]
1517  Light,
1518  Dark,
1519}
1520
1521#[non_exhaustive]
1522#[derive(Debug, Clone, Copy, PartialEq, Default)]
1523pub enum UserAttentionType {
1524  /// ## Platform-specific
1525  /// - **macOS:** Bounces the dock icon until the application is in focus.
1526  /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
1527  Critical,
1528  /// ## Platform-specific
1529  /// - **macOS:** Bounces the dock icon once.
1530  /// - **Windows:** Flashes the taskbar button until the application is in focus.
1531  #[default]
1532  Informational,
1533}
1534
1535/// Window size constraints
1536#[derive(Clone, Copy, PartialEq, Debug, Default)]
1537pub struct WindowSizeConstraints {
1538  /// The minimum width a window can be, If this is `None`, the window will have no minimum width (aside from reserved).
1539  ///
1540  /// The default is `None`.
1541  pub min_width: Option<PixelUnit>,
1542  /// The minimum height a window can be, If this is `None`, the window will have no minimum height (aside from reserved).
1543  ///
1544  /// The default is `None`.
1545  pub min_height: Option<PixelUnit>,
1546  /// The maximum width a window can be, If this is `None`, the window will have no maximum width (aside from reserved).
1547  ///
1548  /// The default is `None`.
1549  pub max_width: Option<PixelUnit>,
1550  /// The maximum height a window can be, If this is `None`, the window will have no maximum height (aside from reserved).
1551  ///
1552  /// The default is `None`.
1553  pub max_height: Option<PixelUnit>,
1554}
1555
1556impl WindowSizeConstraints {
1557  pub fn new(
1558    min_width: Option<PixelUnit>,
1559    min_height: Option<PixelUnit>,
1560    max_width: Option<PixelUnit>,
1561    max_height: Option<PixelUnit>,
1562  ) -> Self {
1563    Self {
1564      min_width,
1565      min_height,
1566      max_width,
1567      max_height,
1568    }
1569  }
1570
1571  /// Returns true if `min_width` or `min_height` is set.
1572  pub fn has_min(&self) -> bool {
1573    self.min_width.is_some() || self.min_height.is_some()
1574  }
1575  /// Returns true if `max_width` or `max_height` is set.
1576  pub fn has_max(&self) -> bool {
1577    self.max_width.is_some() || self.max_height.is_some()
1578  }
1579
1580  /// Returns a physical size that represents the minimum constraints set and fallbacks to [`PixelUnit::MIN`] for unset values
1581  pub fn min_size_physical<T: Pixel>(&self, scale_factor: f64) -> PhysicalSize<T> {
1582    PhysicalSize::new(
1583      self
1584        .min_width
1585        .unwrap_or(PixelUnit::MIN)
1586        .to_physical(scale_factor)
1587        .0,
1588      self
1589        .min_height
1590        .unwrap_or(PixelUnit::MIN)
1591        .to_physical(scale_factor)
1592        .0,
1593    )
1594  }
1595
1596  /// Returns a logical size that represents the minimum constraints set and fallbacks to [`PixelUnit::MIN`] for unset values
1597  pub fn min_size_logical<T: Pixel>(&self, scale_factor: f64) -> LogicalSize<T> {
1598    LogicalSize::new(
1599      self
1600        .min_width
1601        .unwrap_or(PixelUnit::MIN)
1602        .to_logical(scale_factor)
1603        .0,
1604      self
1605        .min_height
1606        .unwrap_or(PixelUnit::MIN)
1607        .to_logical(scale_factor)
1608        .0,
1609    )
1610  }
1611
1612  /// Returns a physical size that represents the maximum constraints set and fallbacks to [`PixelUnit::MAX`] for unset values
1613  pub fn max_size_physical<T: Pixel>(&self, scale_factor: f64) -> PhysicalSize<T> {
1614    PhysicalSize::new(
1615      self
1616        .max_width
1617        .unwrap_or(PixelUnit::MAX)
1618        .to_physical(scale_factor)
1619        .0,
1620      self
1621        .max_height
1622        .unwrap_or(PixelUnit::MAX)
1623        .to_physical(scale_factor)
1624        .0,
1625    )
1626  }
1627
1628  /// Returns a logical size that represents the maximum constraints set and fallbacks to [`PixelUnit::MAX`] for unset values
1629  pub fn max_size_logical<T: Pixel>(&self, scale_factor: f64) -> LogicalSize<T> {
1630    LogicalSize::new(
1631      self
1632        .max_width
1633        .unwrap_or(PixelUnit::MAX)
1634        .to_logical(scale_factor)
1635        .0,
1636      self
1637        .max_height
1638        .unwrap_or(PixelUnit::MAX)
1639        .to_logical(scale_factor)
1640        .0,
1641    )
1642  }
1643
1644  /// Clamps the desired size based on the constraints set
1645  pub fn clamp(&self, desired_size: Size, scale_factor: f64) -> Size {
1646    let min_size: PhysicalSize<f64> = self.min_size_physical(scale_factor);
1647    let max_size: PhysicalSize<f64> = self.max_size_physical(scale_factor);
1648    Size::clamp(desired_size, min_size.into(), max_size.into(), scale_factor)
1649  }
1650}
1651
1652/// Defines the orientation that a window resize will be performed.
1653#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1654pub enum ResizeDirection {
1655  East,
1656  North,
1657  NorthEast,
1658  NorthWest,
1659  South,
1660  SouthEast,
1661  SouthWest,
1662  West,
1663}
1664
1665pub(crate) fn hit_test(
1666  (left, top, right, bottom): (i32, i32, i32, i32),
1667  cx: i32,
1668  cy: i32,
1669  border_x: i32,
1670  border_y: i32,
1671) -> Option<ResizeDirection> {
1672  const LEFT: isize = 0b0001;
1673  const RIGHT: isize = 0b0010;
1674  const TOP: isize = 0b0100;
1675  const BOTTOM: isize = 0b1000;
1676  const TOPLEFT: isize = TOP | LEFT;
1677  const TOPRIGHT: isize = TOP | RIGHT;
1678  const BOTTOMLEFT: isize = BOTTOM | LEFT;
1679  const BOTTOMRIGHT: isize = BOTTOM | RIGHT;
1680
1681  #[rustfmt::skip]
1682  let result = (LEFT * (cx < left + border_x) as isize)
1683             | (RIGHT * (cx >= right - border_x) as isize)
1684             | (TOP * (cy < top + border_y) as isize)
1685             | (BOTTOM * (cy >= bottom - border_y) as isize);
1686
1687  match result {
1688    LEFT => Some(ResizeDirection::West),
1689    RIGHT => Some(ResizeDirection::East),
1690    TOP => Some(ResizeDirection::North),
1691    BOTTOM => Some(ResizeDirection::South),
1692    TOPLEFT => Some(ResizeDirection::NorthWest),
1693    TOPRIGHT => Some(ResizeDirection::NorthEast),
1694    BOTTOMLEFT => Some(ResizeDirection::SouthWest),
1695    BOTTOMRIGHT => Some(ResizeDirection::SouthEast),
1696    _ => None,
1697  }
1698}