floem_winit/
window.rs

1//! The [`Window`] struct and associated types.
2use std::fmt;
3
4use crate::{
5    dpi::{PhysicalPosition, PhysicalSize, Position, Size},
6    error::{ExternalError, NotSupportedError, OsError},
7    event_loop::EventLoopWindowTarget,
8    monitor::{MonitorHandle, VideoMode},
9    platform_impl, SendSyncWrapper,
10};
11
12pub use crate::icon::{BadIcon, Icon};
13
14#[doc(inline)]
15pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError};
16
17/// Represents a window.
18///
19///
20/// # Threading
21///
22/// This is `Send + Sync`, meaning that it can be freely used from other
23/// threads.
24///
25/// However, some platforms (macOS, Web and iOS) only allow user interface
26/// interactions on the main thread, so on those platforms, if you use the
27/// window from a thread other than the main, the code is scheduled to run on
28/// the main thread, and your thread may be blocked until that completes.
29///
30///
31/// # Example
32///
33/// ```no_run
34/// use winit::{
35///     event::{Event, WindowEvent},
36///     event_loop::{ControlFlow, EventLoop},
37///     window::Window,
38/// };
39///
40/// let mut event_loop = EventLoop::new().unwrap();
41/// event_loop.set_control_flow(ControlFlow::Wait);
42/// let window = Window::new(&event_loop).unwrap();
43///
44/// event_loop.run(move |event, elwt| {
45///     match event {
46///         Event::WindowEvent {
47///             event: WindowEvent::CloseRequested,
48///             ..
49///         } => elwt.exit(),
50///         _ => (),
51///     }
52/// });
53/// ```
54pub struct Window {
55    pub(crate) window: platform_impl::Window,
56}
57
58impl fmt::Debug for Window {
59    fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
60        fmtr.pad("Window { .. }")
61    }
62}
63
64impl Drop for Window {
65    fn drop(&mut self) {
66        self.window.maybe_wait_on_main(|w| {
67            // If the window is in exclusive fullscreen, we must restore the desktop
68            // video mode (generally this would be done on application exit, but
69            // closing the window doesn't necessarily always mean application exit,
70            // such as when there are multiple windows)
71            if let Some(Fullscreen::Exclusive(_)) = w.fullscreen().map(|f| f.into()) {
72                w.set_fullscreen(None);
73            }
74        })
75    }
76}
77
78/// Identifier of a window. Unique for each window.
79///
80/// Can be obtained with [`window.id()`](`Window::id`).
81///
82/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you
83/// can then compare to the ids of your windows.
84#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
85pub struct WindowId(pub(crate) platform_impl::WindowId);
86
87impl WindowId {
88    /// Returns a dummy id, useful for unit testing.
89    ///
90    /// # Safety
91    ///
92    /// The only guarantee made about the return value of this function is that
93    /// it will always be equal to itself and to future values returned by this function.
94    /// No other guarantees are made. This may be equal to a real [`WindowId`].
95    ///
96    /// **Passing this into a winit function will result in undefined behavior.**
97    pub const unsafe fn dummy() -> Self {
98        #[allow(unused_unsafe)]
99        WindowId(unsafe { platform_impl::WindowId::dummy() })
100    }
101}
102
103impl From<WindowId> for u64 {
104    fn from(window_id: WindowId) -> Self {
105        window_id.0.into()
106    }
107}
108
109impl From<u64> for WindowId {
110    fn from(raw_id: u64) -> Self {
111        Self(raw_id.into())
112    }
113}
114
115/// Object that allows building windows.
116#[derive(Clone, Default)]
117#[must_use]
118pub struct WindowBuilder {
119    /// The attributes to use to create the window.
120    pub(crate) window: WindowAttributes,
121
122    // Platform-specific configuration.
123    pub(crate) platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes,
124}
125
126impl fmt::Debug for WindowBuilder {
127    fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
128        fmtr.debug_struct("WindowBuilder")
129            .field("window", &self.window)
130            .finish()
131    }
132}
133
134/// Attributes to use when creating a window.
135#[derive(Debug, Clone)]
136pub struct WindowAttributes {
137    pub inner_size: Option<Size>,
138    pub min_inner_size: Option<Size>,
139    pub max_inner_size: Option<Size>,
140    pub position: Option<Position>,
141    pub resizable: bool,
142    pub enabled_buttons: WindowButtons,
143    pub title: String,
144    pub maximized: bool,
145    pub visible: bool,
146    pub transparent: bool,
147    pub blur: bool,
148    pub decorations: bool,
149    pub window_icon: Option<Icon>,
150    pub preferred_theme: Option<Theme>,
151    pub resize_increments: Option<Size>,
152    pub content_protected: bool,
153    pub window_level: WindowLevel,
154    pub active: bool,
155    #[cfg(feature = "rwh_06")]
156    pub(crate) parent_window: SendSyncWrapper<Option<rwh_06::RawWindowHandle>>,
157    pub(crate) fullscreen: SendSyncWrapper<Option<Fullscreen>>,
158}
159
160impl Default for WindowAttributes {
161    #[inline]
162    fn default() -> WindowAttributes {
163        WindowAttributes {
164            inner_size: None,
165            min_inner_size: None,
166            max_inner_size: None,
167            position: None,
168            resizable: true,
169            enabled_buttons: WindowButtons::all(),
170            title: "winit window".to_owned(),
171            maximized: false,
172            fullscreen: SendSyncWrapper(None),
173            visible: true,
174            transparent: false,
175            blur: false,
176            decorations: true,
177            window_level: Default::default(),
178            window_icon: None,
179            preferred_theme: None,
180            resize_increments: None,
181            content_protected: false,
182            #[cfg(feature = "rwh_06")]
183            parent_window: SendSyncWrapper(None),
184            active: true,
185        }
186    }
187}
188
189impl WindowAttributes {
190    /// Get the parent window stored on the attributes.
191    #[cfg(feature = "rwh_06")]
192    pub fn parent_window(&self) -> Option<&rwh_06::RawWindowHandle> {
193        self.parent_window.0.as_ref()
194    }
195
196    /// Get `Fullscreen` option stored on the attributes.
197    pub fn fullscreen(&self) -> Option<&Fullscreen> {
198        self.fullscreen.0.as_ref()
199    }
200}
201
202impl WindowBuilder {
203    /// Initializes a new builder with default values.
204    #[inline]
205    pub fn new() -> Self {
206        Default::default()
207    }
208}
209
210impl WindowBuilder {
211    /// Get the current window attributes.
212    pub fn window_attributes(&self) -> &WindowAttributes {
213        &self.window
214    }
215
216    /// Requests the window to be of specific dimensions.
217    ///
218    /// If this is not set, some platform-specific dimensions will be used.
219    ///
220    /// See [`Window::request_inner_size`] for details.
221    #[inline]
222    pub fn with_inner_size<S: Into<Size>>(mut self, size: S) -> Self {
223        self.window.inner_size = Some(size.into());
224        self
225    }
226
227    /// Sets the minimum dimensions a window can have.
228    ///
229    /// If this is not set, the window will have no minimum dimensions (aside
230    /// from reserved).
231    ///
232    /// See [`Window::set_min_inner_size`] for details.
233    #[inline]
234    pub fn with_min_inner_size<S: Into<Size>>(mut self, min_size: S) -> Self {
235        self.window.min_inner_size = Some(min_size.into());
236        self
237    }
238
239    /// Sets the maximum dimensions a window can have.
240    ///
241    /// If this is not set, the window will have no maximum or will be set to
242    /// the primary monitor's dimensions by the platform.
243    ///
244    /// See [`Window::set_max_inner_size`] for details.
245    #[inline]
246    pub fn with_max_inner_size<S: Into<Size>>(mut self, max_size: S) -> Self {
247        self.window.max_inner_size = Some(max_size.into());
248        self
249    }
250
251    /// Sets a desired initial position for the window.
252    ///
253    /// If this is not set, some platform-specific position will be chosen.
254    ///
255    /// See [`Window::set_outer_position`] for details.
256    ///
257    /// ## Platform-specific
258    ///
259    /// - **macOS:** The top left corner position of the window content, the
260    ///   window's "inner" position. The window title bar will be placed above
261    ///   it. The window will be positioned such that it fits on screen,
262    ///   maintaining set `inner_size` if any.
263    ///   If you need to precisely position the top left corner of the whole
264    ///   window you have to use [`Window::set_outer_position`] after creating
265    ///   the window.
266    /// - **Windows:** The top left corner position of the window title bar,
267    ///   the window's "outer" position.
268    ///   There may be a small gap between this position and the window due to
269    ///   the specifics of the Window Manager.
270    /// - **X11:** The top left corner of the window, the window's "outer"
271    ///   position.
272    /// - **Others:** Ignored.
273    #[inline]
274    pub fn with_position<P: Into<Position>>(mut self, position: P) -> Self {
275        self.window.position = Some(position.into());
276        self
277    }
278
279    /// Sets whether the window is resizable or not.
280    ///
281    /// The default is `true`.
282    ///
283    /// See [`Window::set_resizable`] for details.
284    #[inline]
285    pub fn with_resizable(mut self, resizable: bool) -> Self {
286        self.window.resizable = resizable;
287        self
288    }
289
290    /// Sets the enabled window buttons.
291    ///
292    /// The default is [`WindowButtons::all`]
293    ///
294    /// See [`Window::set_enabled_buttons`] for details.
295    #[inline]
296    pub fn with_enabled_buttons(mut self, buttons: WindowButtons) -> Self {
297        self.window.enabled_buttons = buttons;
298        self
299    }
300
301    /// Sets the initial title of the window in the title bar.
302    ///
303    /// The default is `"winit window"`.
304    ///
305    /// See [`Window::set_title`] for details.
306    #[inline]
307    pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
308        self.window.title = title.into();
309        self
310    }
311
312    /// Sets whether the window should be put into fullscreen upon creation.
313    ///
314    /// The default is `None`.
315    ///
316    /// See [`Window::set_fullscreen`] for details.
317    #[inline]
318    pub fn with_fullscreen(mut self, fullscreen: Option<Fullscreen>) -> Self {
319        self.window.fullscreen = SendSyncWrapper(fullscreen);
320        self
321    }
322
323    /// Request that the window is maximized upon creation.
324    ///
325    /// The default is `false`.
326    ///
327    /// See [`Window::set_maximized`] for details.
328    #[inline]
329    pub fn with_maximized(mut self, maximized: bool) -> Self {
330        self.window.maximized = maximized;
331        self
332    }
333
334    /// Sets whether the window will be initially visible or hidden.
335    ///
336    /// The default is to show the window.
337    ///
338    /// See [`Window::set_visible`] for details.
339    #[inline]
340    pub fn with_visible(mut self, visible: bool) -> Self {
341        self.window.visible = visible;
342        self
343    }
344
345    /// Sets whether the background of the window should be transparent.
346    ///
347    /// If this is `true`, writing colors with alpha values different than
348    /// `1.0` will produce a transparent window. On some platforms this
349    /// is more of a hint for the system and you'd still have the alpha
350    /// buffer. To control it see [`Window::set_transparent`].
351    ///
352    /// The default is `false`.
353    #[inline]
354    pub fn with_transparent(mut self, transparent: bool) -> Self {
355        self.window.transparent = transparent;
356        self
357    }
358
359    /// Sets whether the background of the window should be blurred by the system.
360    ///
361    /// The default is `false`.
362    ///
363    /// See [`Window::set_blur`] for details.
364    #[inline]
365    pub fn with_blur(mut self, blur: bool) -> Self {
366        self.window.blur = blur;
367        self
368    }
369
370    /// Get whether the window will support transparency.
371    #[inline]
372    pub fn transparent(&self) -> bool {
373        self.window.transparent
374    }
375
376    /// Sets whether the window should have a border, a title bar, etc.
377    ///
378    /// The default is `true`.
379    ///
380    /// See [`Window::set_decorations`] for details.
381    #[inline]
382    pub fn with_decorations(mut self, decorations: bool) -> Self {
383        self.window.decorations = decorations;
384        self
385    }
386
387    /// Sets the window level.
388    ///
389    /// This is just a hint to the OS, and the system could ignore it.
390    ///
391    /// The default is [`WindowLevel::Normal`].
392    ///
393    /// See [`WindowLevel`] for details.
394    #[inline]
395    pub fn with_window_level(mut self, level: WindowLevel) -> Self {
396        self.window.window_level = level;
397        self
398    }
399
400    /// Sets the window icon.
401    ///
402    /// The default is `None`.
403    ///
404    /// See [`Window::set_window_icon`] for details.
405    #[inline]
406    pub fn with_window_icon(mut self, window_icon: Option<Icon>) -> Self {
407        self.window.window_icon = window_icon;
408        self
409    }
410
411    /// Sets a specific theme for the window.
412    ///
413    /// If `None` is provided, the window will use the system theme.
414    ///
415    /// The default is `None`.
416    ///
417    /// ## Platform-specific
418    ///
419    /// - **macOS:** This is an app-wide setting.
420    /// - **Wayland:** This controls only CSD. When using `None` it'll try to use dbus to get the
421    ///   system preference. When explicit theme is used, this will avoid dbus all together.
422    /// - **x11:** Build window with `_GTK_THEME_VARIANT` hint set to `dark` or `light`.
423    /// - **iOS / Android / Web / x11 / Orbital:** Ignored.
424    #[inline]
425    pub fn with_theme(mut self, theme: Option<Theme>) -> Self {
426        self.window.preferred_theme = theme;
427        self
428    }
429
430    /// Build window with resize increments hint.
431    ///
432    /// The default is `None`.
433    ///
434    /// See [`Window::set_resize_increments`] for details.
435    #[inline]
436    pub fn with_resize_increments<S: Into<Size>>(mut self, resize_increments: S) -> Self {
437        self.window.resize_increments = Some(resize_increments.into());
438        self
439    }
440
441    /// Prevents the window contents from being captured by other apps.
442    ///
443    /// The default is `false`.
444    ///
445    /// ## Platform-specific
446    ///
447    /// - **macOS**: if `false`, [`NSWindowSharingNone`] is used but doesn't completely
448    /// prevent all apps from reading the window content, for instance, QuickTime.
449    /// - **iOS / Android / Web / x11 / Orbital:** Ignored.
450    ///
451    /// [`NSWindowSharingNone`]: https://developer.apple.com/documentation/appkit/nswindowsharingtype/nswindowsharingnone
452    #[inline]
453    pub fn with_content_protected(mut self, protected: bool) -> Self {
454        self.window.content_protected = protected;
455        self
456    }
457
458    /// Whether the window will be initially focused or not.
459    ///
460    /// The window should be assumed as not focused by default
461    /// following by the [`WindowEvent::Focused`].
462    ///
463    /// ## Platform-specific:
464    ///
465    /// **Android / iOS / X11 / Wayland / Orbital:** Unsupported.
466    ///
467    /// [`WindowEvent::Focused`]: crate::event::WindowEvent::Focused.
468    #[inline]
469    pub fn with_active(mut self, active: bool) -> Self {
470        self.window.active = active;
471        self
472    }
473
474    /// Build window with parent window.
475    ///
476    /// The default is `None`.
477    ///
478    /// ## Safety
479    ///
480    /// `parent_window` must be a valid window handle.
481    ///
482    /// ## Platform-specific
483    ///
484    /// - **Windows** : A child window has the WS_CHILD style and is confined
485    /// to the client area of its parent window. For more information, see
486    /// <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
487    /// - **X11**: A child window is confined to the client area of its parent window.
488    /// - **Android / iOS / Wayland / Web:** Unsupported.
489    #[cfg(feature = "rwh_06")]
490    #[inline]
491    pub unsafe fn with_parent_window(
492        mut self,
493        parent_window: Option<rwh_06::RawWindowHandle>,
494    ) -> Self {
495        self.window.parent_window = SendSyncWrapper(parent_window);
496        self
497    }
498
499    /// Builds the window.
500    ///
501    /// Possible causes of error include denied permission, incompatible system, and lack of memory.
502    ///
503    /// ## Platform-specific
504    ///
505    /// - **Web:** The window is created but not inserted into the web page automatically. Please
506    ///   see the web platform module for more information.
507    #[inline]
508    pub fn build<T: 'static>(
509        self,
510        window_target: &EventLoopWindowTarget<T>,
511    ) -> Result<Window, OsError> {
512        let window =
513            platform_impl::Window::new(&window_target.p, self.window, self.platform_specific)?;
514        window.maybe_queue_on_main(|w| w.request_redraw());
515        Ok(Window { window })
516    }
517}
518
519/// Base Window functions.
520impl Window {
521    /// Creates a new Window for platforms where this is appropriate.
522    ///
523    /// This function is equivalent to [`WindowBuilder::new().build(event_loop)`].
524    ///
525    /// Error should be very rare and only occur in case of permission denied, incompatible system,
526    ///  out of memory, etc.
527    ///
528    /// ## Platform-specific
529    ///
530    /// - **Web:** The window is created but not inserted into the web page automatically. Please
531    ///   see the web platform module for more information.
532    ///
533    /// [`WindowBuilder::new().build(event_loop)`]: WindowBuilder::build
534    #[inline]
535    pub fn new<T: 'static>(event_loop: &EventLoopWindowTarget<T>) -> Result<Window, OsError> {
536        let builder = WindowBuilder::new();
537        builder.build(event_loop)
538    }
539
540    /// Returns an identifier unique to the window.
541    #[inline]
542    pub fn id(&self) -> WindowId {
543        self.window.maybe_wait_on_main(|w| WindowId(w.id()))
544    }
545
546    /// Returns the scale factor that can be used to map logical pixels to physical pixels, and
547    /// vice versa.
548    ///
549    /// Note that this value can change depending on user action (for example if the window is
550    /// moved to another screen); as such, tracking [`WindowEvent::ScaleFactorChanged`] events is
551    /// the most robust way to track the DPI you need to use to draw.
552    ///
553    /// This value may differ from [`MonitorHandle::scale_factor`].
554    ///
555    /// See the [`dpi`](crate::dpi) module for more information.
556    ///
557    /// ## Platform-specific
558    ///
559    /// - **X11:** This respects Xft.dpi, and can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
560    /// - **Wayland:** Uses the wp-fractional-scale protocol if available. Falls back to integer-scale factors otherwise.
561    /// - **Android:** Always returns 1.0.
562    /// - **iOS:** Can only be called on the main thread. Returns the underlying `UIView`'s
563    ///   [`contentScaleFactor`].
564    ///
565    /// [`WindowEvent::ScaleFactorChanged`]: crate::event::WindowEvent::ScaleFactorChanged
566    /// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
567    #[inline]
568    pub fn scale_factor(&self) -> f64 {
569        self.window.maybe_wait_on_main(|w| w.scale_factor())
570    }
571
572    /// Queues a [`WindowEvent::RedrawRequested`] event to be emitted that aligns with the windowing
573    /// system drawing loop.
574    ///
575    /// This is the **strongly encouraged** method of redrawing windows, as it can integrate with
576    /// OS-requested redraws (e.g. when a window gets resized). To improve the event delivery
577    /// consider using [`Window::pre_present_notify`] as described in docs.
578    ///
579    /// Applications should always aim to redraw whenever they receive a `RedrawRequested` event.
580    ///
581    /// There are no strong guarantees about when exactly a `RedrawRequest` event will be emitted
582    /// with respect to other events, since the requirements can vary significantly between
583    /// windowing systems.
584    ///
585    /// However as the event aligns with the windowing system drawing loop, it may not arrive in
586    /// same or even next event loop iteration.
587    ///
588    /// ## Platform-specific
589    ///
590    /// - **Windows** This API uses `RedrawWindow` to request a `WM_PAINT` message and `RedrawRequested`
591    ///   is emitted in sync with any `WM_PAINT` messages.
592    /// - **iOS:** Can only be called on the main thread.
593    /// - **Wayland:** The events are aligned with the frame callbacks when [`Window::pre_present_notify`]
594    ///                is used.
595    /// - **Web:** [`WindowEvent::RedrawRequested`] will be aligned with the `requestAnimationFrame`.
596    ///
597    /// [`WindowEvent::RedrawRequested`]: crate::event::WindowEvent::RedrawRequested
598    #[inline]
599    pub fn request_redraw(&self) {
600        self.window.maybe_queue_on_main(|w| w.request_redraw())
601    }
602
603    /// Notify the windowing system before presenting to the window.
604    ///
605    /// You should call this event after your drawing operations, but before you submit
606    /// the buffer to the display or commit your drawings. Doing so will help winit to properly
607    /// schedule and make assumptions about its internal state. For example, it could properly
608    /// throttle [`WindowEvent::RedrawRequested`].
609    ///
610    /// ## Example
611    ///
612    /// This example illustrates how it looks with OpenGL, but it applies to other graphics
613    /// APIs and software rendering.
614    ///
615    /// ```no_run
616    /// # use winit::event_loop::EventLoop;
617    /// # use winit::window::Window;
618    /// # let mut event_loop = EventLoop::new().unwrap();
619    /// # let window = Window::new(&event_loop).unwrap();
620    /// # fn swap_buffers() {}
621    /// // Do the actual drawing with OpenGL.
622    ///
623    /// // Notify winit that we're about to submit buffer to the windowing system.
624    /// window.pre_present_notify();
625    ///
626    /// // Sumbit buffer to the windowing system.
627    /// swap_buffers();
628    /// ```
629    ///
630    /// ## Platform-specific
631    ///
632    /// **Wayland:** - schedules a frame callback to throttle [`WindowEvent::RedrawRequested`].
633    ///
634    /// [`WindowEvent::RedrawRequested`]: crate::event::WindowEvent::RedrawRequested
635    #[inline]
636    pub fn pre_present_notify(&self) {
637        self.window.maybe_queue_on_main(|w| w.pre_present_notify());
638    }
639
640    /// Reset the dead key state of the keyboard.
641    ///
642    /// This is useful when a dead key is bound to trigger an action. Then
643    /// this function can be called to reset the dead key state so that
644    /// follow-up text input won't be affected by the dead key.
645    ///
646    /// ## Platform-specific
647    /// - **Web, macOS:** Does nothing
648    // ---------------------------
649    // Developers' Note: If this cannot be implemented on every desktop platform
650    // at least, then this function should be provided through a platform specific
651    // extension trait
652    pub fn reset_dead_keys(&self) {
653        self.window.maybe_queue_on_main(|w| w.reset_dead_keys())
654    }
655}
656
657/// Position and size functions.
658impl Window {
659    /// Returns the position of the top-left hand corner of the window's client area relative to the
660    /// top-left hand corner of the desktop.
661    ///
662    /// The same conditions that apply to [`Window::outer_position`] apply to this method.
663    ///
664    /// ## Platform-specific
665    ///
666    /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
667    ///   window's [safe area] in the screen space coordinate system.
668    /// - **Web:** Returns the top-left coordinates relative to the viewport. _Note: this returns the
669    ///    same value as [`Window::outer_position`]._
670    /// - **Android / Wayland:** Always returns [`NotSupportedError`].
671    ///
672    /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
673    #[inline]
674    pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
675        self.window.maybe_wait_on_main(|w| w.inner_position())
676    }
677
678    /// Returns the position of the top-left hand corner of the window relative to the
679    /// top-left hand corner of the desktop.
680    ///
681    /// Note that the top-left hand corner of the desktop is not necessarily the same as
682    /// the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
683    /// of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
684    ///
685    /// The coordinates can be negative if the top-left hand corner of the window is outside
686    /// of the visible screen region.
687    ///
688    /// ## Platform-specific
689    ///
690    /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
691    ///   window in the screen space coordinate system.
692    /// - **Web:** Returns the top-left coordinates relative to the viewport.
693    /// - **Android / Wayland:** Always returns [`NotSupportedError`].
694    #[inline]
695    pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
696        self.window.maybe_wait_on_main(|w| w.outer_position())
697    }
698
699    /// Modifies the position of the window.
700    ///
701    /// See [`Window::outer_position`] for more information about the coordinates.
702    /// This automatically un-maximizes the window if it's maximized.
703    ///
704    /// ```no_run
705    /// # use winit::dpi::{LogicalPosition, PhysicalPosition};
706    /// # use winit::event_loop::EventLoop;
707    /// # use winit::window::Window;
708    /// # let mut event_loop = EventLoop::new().unwrap();
709    /// # let window = Window::new(&event_loop).unwrap();
710    /// // Specify the position in logical dimensions like this:
711    /// window.set_outer_position(LogicalPosition::new(400.0, 200.0));
712    ///
713    /// // Or specify the position in physical dimensions like this:
714    /// window.set_outer_position(PhysicalPosition::new(400, 200));
715    /// ```
716    ///
717    /// ## Platform-specific
718    ///
719    /// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
720    ///   window in the screen space coordinate system.
721    /// - **Web:** Sets the top-left coordinates relative to the viewport. Doesn't account for CSS
722    ///   [`transform`].
723    /// - **Android / Wayland:** Unsupported.
724    ///
725    /// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
726    #[inline]
727    pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
728        let position = position.into();
729        self.window
730            .maybe_queue_on_main(move |w| w.set_outer_position(position))
731    }
732
733    /// Returns the physical size of the window's client area.
734    ///
735    /// The client area is the content of the window, excluding the title bar and borders.
736    ///
737    /// ## Platform-specific
738    ///
739    /// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window's
740    ///   [safe area] in screen space coordinates.
741    /// - **Web:** Returns the size of the canvas element. Doesn't account for CSS [`transform`].
742    ///
743    /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
744    /// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
745    #[inline]
746    pub fn inner_size(&self) -> PhysicalSize<u32> {
747        self.window.maybe_wait_on_main(|w| w.inner_size())
748    }
749
750    /// Request the new size for the window.
751    ///
752    /// On platforms where the size is entirely controlled by the user the
753    /// applied size will be returned immediately, resize event in such case
754    /// may not be generated.
755    ///
756    /// On platforms where resizing is disallowed by the windowing system, the current
757    /// inner size is returned immidiatelly, and the user one is ignored.
758    ///
759    /// When `None` is returned, it means that the request went to the display system,
760    /// and the actual size will be delivered later with the [`WindowEvent::Resized`].
761    ///
762    /// See [`Window::inner_size`] for more information about the values.
763    ///
764    /// The request could automatically un-maximize the window if it's maximized.
765    ///
766    /// ```no_run
767    /// # use winit::dpi::{LogicalSize, PhysicalSize};
768    /// # use winit::event_loop::EventLoop;
769    /// # use winit::window::Window;
770    /// # let mut event_loop = EventLoop::new().unwrap();
771    /// # let window = Window::new(&event_loop).unwrap();
772    /// // Specify the size in logical dimensions like this:
773    /// let _ = window.request_inner_size(LogicalSize::new(400.0, 200.0));
774    ///
775    /// // Or specify the size in physical dimensions like this:
776    /// let _ = window.request_inner_size(PhysicalSize::new(400, 200));
777    /// ```
778    ///
779    /// ## Platform-specific
780    ///
781    /// - **Web:** Sets the size of the canvas element. Doesn't account for CSS [`transform`].
782    ///
783    /// [`WindowEvent::Resized`]: crate::event::WindowEvent::Resized
784    /// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
785    #[inline]
786    #[must_use]
787    pub fn request_inner_size<S: Into<Size>>(&self, size: S) -> Option<PhysicalSize<u32>> {
788        let size = size.into();
789        self.window
790            .maybe_wait_on_main(|w| w.request_inner_size(size))
791    }
792
793    /// Returns the physical size of the entire window.
794    ///
795    /// These dimensions include the title bar and borders. If you don't want that (and you usually don't),
796    /// use [`Window::inner_size`] instead.
797    ///
798    /// ## Platform-specific
799    ///
800    /// - **iOS:** Can only be called on the main thread. Returns the [`PhysicalSize`] of the window in
801    ///   screen space coordinates.
802    /// - **Web:** Returns the size of the canvas element. _Note: this returns the same value as
803    ///   [`Window::inner_size`]._
804    #[inline]
805    pub fn outer_size(&self) -> PhysicalSize<u32> {
806        self.window.maybe_wait_on_main(|w| w.outer_size())
807    }
808
809    /// Sets a minimum dimension size for the window.
810    ///
811    /// ```no_run
812    /// # use winit::dpi::{LogicalSize, PhysicalSize};
813    /// # use winit::event_loop::EventLoop;
814    /// # use winit::window::Window;
815    /// # let mut event_loop = EventLoop::new().unwrap();
816    /// # let window = Window::new(&event_loop).unwrap();
817    /// // Specify the size in logical dimensions like this:
818    /// window.set_min_inner_size(Some(LogicalSize::new(400.0, 200.0)));
819    ///
820    /// // Or specify the size in physical dimensions like this:
821    /// window.set_min_inner_size(Some(PhysicalSize::new(400, 200)));
822    /// ```
823    ///
824    /// ## Platform-specific
825    ///
826    /// - **iOS / Android / Orbital:** Unsupported.
827    #[inline]
828    pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
829        let min_size = min_size.map(|s| s.into());
830        self.window
831            .maybe_queue_on_main(move |w| w.set_min_inner_size(min_size))
832    }
833
834    /// Sets a maximum dimension size for the window.
835    ///
836    /// ```no_run
837    /// # use winit::dpi::{LogicalSize, PhysicalSize};
838    /// # use winit::event_loop::EventLoop;
839    /// # use winit::window::Window;
840    /// # let mut event_loop = EventLoop::new().unwrap();
841    /// # let window = Window::new(&event_loop).unwrap();
842    /// // Specify the size in logical dimensions like this:
843    /// window.set_max_inner_size(Some(LogicalSize::new(400.0, 200.0)));
844    ///
845    /// // Or specify the size in physical dimensions like this:
846    /// window.set_max_inner_size(Some(PhysicalSize::new(400, 200)));
847    /// ```
848    ///
849    /// ## Platform-specific
850    ///
851    /// - **iOS / Android / Orbital:** Unsupported.
852    #[inline]
853    pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
854        let max_size = max_size.map(|s| s.into());
855        self.window
856            .maybe_queue_on_main(move |w| w.set_max_inner_size(max_size))
857    }
858
859    /// Returns window resize increments if any were set.
860    ///
861    /// ## Platform-specific
862    ///
863    /// - **iOS / Android / Web / Wayland / Windows / Orbital:** Always returns [`None`].
864    #[inline]
865    pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
866        self.window.maybe_wait_on_main(|w| w.resize_increments())
867    }
868
869    /// Sets window resize increments.
870    ///
871    /// This is a niche constraint hint usually employed by terminal emulators
872    /// and other apps that need "blocky" resizes.
873    ///
874    /// ## Platform-specific
875    ///
876    /// - **macOS:** Increments are converted to logical size and then macOS rounds them to whole numbers.
877    /// - **Wayland / Windows:** Not implemented.
878    /// - **iOS / Android / Web / Orbital:** Unsupported.
879    #[inline]
880    pub fn set_resize_increments<S: Into<Size>>(&self, increments: Option<S>) {
881        let increments = increments.map(Into::into);
882        self.window
883            .maybe_queue_on_main(move |w| w.set_resize_increments(increments))
884    }
885}
886
887/// Misc. attribute functions.
888impl Window {
889    /// Modifies the title of the window.
890    ///
891    /// ## Platform-specific
892    ///
893    /// - **iOS / Android:** Unsupported.
894    #[inline]
895    pub fn set_title(&self, title: &str) {
896        self.window.maybe_wait_on_main(|w| w.set_title(title))
897    }
898
899    /// Change the window transparency state.
900    ///
901    /// This is just a hint that may not change anything about
902    /// the window transparency, however doing a missmatch between
903    /// the content of your window and this hint may result in
904    /// visual artifacts.
905    ///
906    /// The default value follows the [`WindowBuilder::with_transparent`].
907    ///
908    /// ## Platform-specific
909    ///
910    /// - **Web / iOS / Android / Orbital:** Unsupported.
911    /// - **X11:** Can only be set while building the window, with [`WindowBuilder::with_transparent`].
912    #[inline]
913    pub fn set_transparent(&self, transparent: bool) {
914        self.window
915            .maybe_queue_on_main(move |w| w.set_transparent(transparent))
916    }
917
918    /// Change the window blur state.
919    ///
920    /// If `true`, this will make the transparent window background blurry.
921    ///
922    /// ## Platform-specific
923    ///
924    /// - **Android / iOS / X11 / Web / Windows:** Unsupported.
925    /// - **Wayland:** Only works with org_kde_kwin_blur_manager protocol.
926    #[inline]
927    pub fn set_blur(&self, blur: bool) {
928        self.window.maybe_queue_on_main(move |w| w.set_blur(blur))
929    }
930
931    /// Modifies the window's visibility.
932    ///
933    /// If `false`, this will hide the window. If `true`, this will show the window.
934    ///
935    /// ## Platform-specific
936    ///
937    /// - **Android / Wayland / Web:** Unsupported.
938    /// - **iOS:** Can only be called on the main thread.
939    #[inline]
940    pub fn set_visible(&self, visible: bool) {
941        self.window
942            .maybe_queue_on_main(move |w| w.set_visible(visible))
943    }
944
945    /// Gets the window's current visibility state.
946    ///
947    /// `None` means it couldn't be determined, so it is not recommended to use this to drive your rendering backend.
948    ///
949    /// ## Platform-specific
950    ///
951    /// - **X11:** Not implemented.
952    /// - **Wayland / iOS / Android / Web:** Unsupported.
953    #[inline]
954    pub fn is_visible(&self) -> Option<bool> {
955        self.window.maybe_wait_on_main(|w| w.is_visible())
956    }
957
958    /// Sets whether the window is resizable or not.
959    ///
960    /// Note that making the window unresizable doesn't exempt you from handling [`WindowEvent::Resized`], as that
961    /// event can still be triggered by DPI scaling, entering fullscreen mode, etc. Also, the
962    /// window could still be resized by calling [`Window::request_inner_size`].
963    ///
964    /// ## Platform-specific
965    ///
966    /// This only has an effect on desktop platforms.
967    ///
968    /// - **X11:** Due to a bug in XFCE, this has no effect on Xfwm.
969    /// - **iOS / Android / Web:** Unsupported.
970    ///
971    /// [`WindowEvent::Resized`]: crate::event::WindowEvent::Resized
972    #[inline]
973    pub fn set_resizable(&self, resizable: bool) {
974        self.window
975            .maybe_queue_on_main(move |w| w.set_resizable(resizable))
976    }
977
978    /// Gets the window's current resizable state.
979    ///
980    /// ## Platform-specific
981    ///
982    /// - **X11:** Not implemented.
983    /// - **iOS / Android / Web:** Unsupported.
984    #[inline]
985    pub fn is_resizable(&self) -> bool {
986        self.window.maybe_wait_on_main(|w| w.is_resizable())
987    }
988
989    /// Sets the enabled window buttons.
990    ///
991    /// ## Platform-specific
992    ///
993    /// - **Wayland / X11 / Orbital:** Not implemented.
994    /// - **Web / iOS / Android:** Unsupported.
995    pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
996        self.window
997            .maybe_queue_on_main(move |w| w.set_enabled_buttons(buttons))
998    }
999
1000    /// Gets the enabled window buttons.
1001    ///
1002    /// ## Platform-specific
1003    ///
1004    /// - **Wayland / X11 / Orbital:** Not implemented. Always returns [`WindowButtons::all`].
1005    /// - **Web / iOS / Android:** Unsupported. Always returns [`WindowButtons::all`].
1006    pub fn enabled_buttons(&self) -> WindowButtons {
1007        self.window.maybe_wait_on_main(|w| w.enabled_buttons())
1008    }
1009
1010    /// Sets the window to minimized or back
1011    ///
1012    /// ## Platform-specific
1013    ///
1014    /// - **iOS / Android / Web / Orbital:** Unsupported.
1015    /// - **Wayland:** Un-minimize is unsupported.
1016    #[inline]
1017    pub fn set_minimized(&self, minimized: bool) {
1018        self.window
1019            .maybe_queue_on_main(move |w| w.set_minimized(minimized))
1020    }
1021
1022    /// Gets the window's current minimized state.
1023    ///
1024    /// `None` will be returned, if the minimized state couldn't be determined.
1025    ///
1026    /// ## Note
1027    ///
1028    /// - You shouldn't stop rendering for minimized windows, however you could lower the fps.
1029    ///
1030    /// ## Platform-specific
1031    ///
1032    /// - **Wayland**: always `None`.
1033    /// - **iOS / Android / Web / Orbital:** Unsupported.
1034    #[inline]
1035    pub fn is_minimized(&self) -> Option<bool> {
1036        self.window.maybe_wait_on_main(|w| w.is_minimized())
1037    }
1038
1039    /// Sets the window to maximized or back.
1040    ///
1041    /// ## Platform-specific
1042    ///
1043    /// - **iOS / Android / Web / Orbital:** Unsupported.
1044    #[inline]
1045    pub fn set_maximized(&self, maximized: bool) {
1046        self.window
1047            .maybe_queue_on_main(move |w| w.set_maximized(maximized))
1048    }
1049
1050    /// Gets the window's current maximized state.
1051    ///
1052    /// ## Platform-specific
1053    ///
1054    /// - **iOS / Android / Web / Orbital:** Unsupported.
1055    #[inline]
1056    pub fn is_maximized(&self) -> bool {
1057        self.window.maybe_wait_on_main(|w| w.is_maximized())
1058    }
1059
1060    /// Sets the window to fullscreen or back.
1061    ///
1062    /// ## Platform-specific
1063    ///
1064    /// - **macOS:** [`Fullscreen::Exclusive`] provides true exclusive mode with a
1065    ///   video mode change. *Caveat!* macOS doesn't provide task switching (or
1066    ///   spaces!) while in exclusive fullscreen mode. This mode should be used
1067    ///   when a video mode change is desired, but for a better user experience,
1068    ///   borderless fullscreen might be preferred.
1069    ///
1070    ///   [`Fullscreen::Borderless`] provides a borderless fullscreen window on a
1071    ///   separate space. This is the idiomatic way for fullscreen games to work
1072    ///   on macOS. See `WindowExtMacOs::set_simple_fullscreen` if
1073    ///   separate spaces are not preferred.
1074    ///
1075    ///   The dock and the menu bar are disabled in exclusive fullscreen mode.
1076    /// - **iOS:** Can only be called on the main thread.
1077    /// - **Wayland:** Does not support exclusive fullscreen mode and will no-op a request.
1078    /// - **Windows:** Screen saver is disabled in fullscreen mode.
1079    /// - **Android / Orbital:** Unsupported.
1080    /// - **Web:** Does nothing without a [transient activation], but queues the request
1081    ///   for the next activation.
1082    ///
1083    /// [transient activation]: https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation
1084    #[inline]
1085    pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
1086        self.window
1087            .maybe_queue_on_main(move |w| w.set_fullscreen(fullscreen.map(|f| f.into())))
1088    }
1089
1090    /// Gets the window's current fullscreen state.
1091    ///
1092    /// ## Platform-specific
1093    ///
1094    /// - **iOS:** Can only be called on the main thread.
1095    /// - **Android / Orbital:** Will always return `None`.
1096    /// - **Wayland:** Can return `Borderless(None)` when there are no monitors.
1097    /// - **Web:** Can only return `None` or `Borderless(None)`.
1098    #[inline]
1099    pub fn fullscreen(&self) -> Option<Fullscreen> {
1100        self.window
1101            .maybe_wait_on_main(|w| w.fullscreen().map(|f| f.into()))
1102    }
1103
1104    /// Turn window decorations on or off.
1105    ///
1106    /// Enable/disable window decorations provided by the server or Winit.
1107    /// By default this is enabled. Note that fullscreen windows and windows on
1108    /// mobile and web platforms naturally do not have decorations.
1109    ///
1110    /// ## Platform-specific
1111    ///
1112    /// - **iOS / Android / Web:** No effect.
1113    #[inline]
1114    pub fn set_decorations(&self, decorations: bool) {
1115        self.window
1116            .maybe_queue_on_main(move |w| w.set_decorations(decorations))
1117    }
1118
1119    /// Gets the window's current decorations state.
1120    ///
1121    /// Returns `true` when windows are decorated (server-side or by Winit).
1122    /// Also returns `true` when no decorations are required (mobile, web).
1123    ///
1124    /// ## Platform-specific
1125    ///
1126    /// - **iOS / Android / Web:** Always returns `true`.
1127    #[inline]
1128    pub fn is_decorated(&self) -> bool {
1129        self.window.maybe_wait_on_main(|w| w.is_decorated())
1130    }
1131
1132    /// Change the window level.
1133    ///
1134    /// This is just a hint to the OS, and the system could ignore it.
1135    ///
1136    /// See [`WindowLevel`] for details.
1137    pub fn set_window_level(&self, level: WindowLevel) {
1138        self.window
1139            .maybe_queue_on_main(move |w| w.set_window_level(level))
1140    }
1141
1142    /// Sets the window icon.
1143    ///
1144    /// On Windows and X11, this is typically the small icon in the top-left
1145    /// corner of the titlebar.
1146    ///
1147    /// ## Platform-specific
1148    ///
1149    /// - **iOS / Android / Web / Wayland / macOS / Orbital:** Unsupported.
1150    ///
1151    /// - **Windows:** Sets `ICON_SMALL`. The base size for a window icon is 16x16, but it's
1152    ///   recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
1153    ///
1154    /// - **X11:** Has no universal guidelines for icon sizes, so you're at the whims of the WM. That
1155    ///   said, it's usually in the same ballpark as on Windows.
1156    #[inline]
1157    pub fn set_window_icon(&self, window_icon: Option<Icon>) {
1158        self.window
1159            .maybe_queue_on_main(move |w| w.set_window_icon(window_icon))
1160    }
1161
1162    /// Set the IME cursor editing area, where the `position` is the top left corner of that area
1163    /// and `size` is the size of this area starting from the position. An example of such area
1164    /// could be a input field in the UI or line in the editor.
1165    ///
1166    /// The windowing system could place a candidate box close to that area, but try to not obscure
1167    /// the specified area, so the user input to it stays visible.
1168    ///
1169    /// The candidate box is the window / popup / overlay that allows you to select the desired
1170    /// characters. The look of this box may differ between input devices, even on the same
1171    /// platform.
1172    ///
1173    /// (Apple's official term is "candidate window", see their [chinese] and [japanese] guides).
1174    ///
1175    /// ## Example
1176    ///
1177    /// ```no_run
1178    /// # use winit::dpi::{LogicalPosition, PhysicalPosition, LogicalSize, PhysicalSize};
1179    /// # use winit::event_loop::EventLoop;
1180    /// # use winit::window::Window;
1181    /// # let mut event_loop = EventLoop::new().unwrap();
1182    /// # let window = Window::new(&event_loop).unwrap();
1183    /// // Specify the position in logical dimensions like this:
1184    /// window.set_ime_cursor_area(LogicalPosition::new(400.0, 200.0), LogicalSize::new(100, 100));
1185    ///
1186    /// // Or specify the position in physical dimensions like this:
1187    /// window.set_ime_cursor_area(PhysicalPosition::new(400, 200), PhysicalSize::new(100, 100));
1188    /// ```
1189    ///
1190    /// ## Platform-specific
1191    ///
1192    /// - **X11:** - area is not supported, only position.
1193    /// - **iOS / Android / Web / Orbital:** Unsupported.
1194    ///
1195    /// [chinese]: https://support.apple.com/guide/chinese-input-method/use-the-candidate-window-cim12992/104/mac/12.0
1196    /// [japanese]: https://support.apple.com/guide/japanese-input-method/use-the-candidate-window-jpim10262/6.3/mac/12.0
1197    #[inline]
1198    pub fn set_ime_cursor_area<P: Into<Position>, S: Into<Size>>(&self, position: P, size: S) {
1199        let position = position.into();
1200        let size = size.into();
1201        self.window
1202            .maybe_queue_on_main(move |w| w.set_ime_cursor_area(position, size))
1203    }
1204
1205    /// Sets whether the window should get IME events
1206    ///
1207    /// When IME is allowed, the window will receive [`Ime`] events, and during the
1208    /// preedit phase the window will NOT get [`KeyboardInput`] events. The window
1209    /// should allow IME while it is expecting text input.
1210    ///
1211    /// When IME is not allowed, the window won't receive [`Ime`] events, and will
1212    /// receive [`KeyboardInput`] events for every keypress instead. Not allowing
1213    /// IME is useful for games for example.
1214    ///
1215    /// IME is **not** allowed by default.
1216    ///
1217    /// ## Platform-specific
1218    ///
1219    /// - **macOS:** IME must be enabled to receive text-input where dead-key sequences are combined.
1220    /// - **iOS / Android / Web / Orbital:** Unsupported.
1221    /// - **X11**: Enabling IME will disable dead keys reporting during compose.
1222    ///
1223    /// [`Ime`]: crate::event::WindowEvent::Ime
1224    /// [`KeyboardInput`]: crate::event::WindowEvent::KeyboardInput
1225    #[inline]
1226    pub fn set_ime_allowed(&self, allowed: bool) {
1227        self.window
1228            .maybe_queue_on_main(move |w| w.set_ime_allowed(allowed))
1229    }
1230
1231    /// Sets the IME purpose for the window using [`ImePurpose`].
1232    ///
1233    /// ## Platform-specific
1234    ///
1235    /// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported.
1236    #[inline]
1237    pub fn set_ime_purpose(&self, purpose: ImePurpose) {
1238        self.window
1239            .maybe_queue_on_main(move |w| w.set_ime_purpose(purpose))
1240    }
1241
1242    /// Brings the window to the front and sets input focus. Has no effect if the window is
1243    /// already in focus, minimized, or not visible.
1244    ///
1245    /// This method steals input focus from other applications. Do not use this method unless
1246    /// you are certain that's what the user wants. Focus stealing can cause an extremely disruptive
1247    /// user experience.
1248    ///
1249    /// ## Platform-specific
1250    ///
1251    /// - **iOS / Android / Wayland / Orbital:** Unsupported.
1252    #[inline]
1253    pub fn focus_window(&self) {
1254        self.window.maybe_queue_on_main(|w| w.focus_window())
1255    }
1256
1257    /// Gets whether the window has keyboard focus.
1258    ///
1259    /// This queries the same state information as [`WindowEvent::Focused`].
1260    ///
1261    /// [`WindowEvent::Focused`]: crate::event::WindowEvent::Focused
1262    #[inline]
1263    pub fn has_focus(&self) -> bool {
1264        self.window.maybe_wait_on_main(|w| w.has_focus())
1265    }
1266
1267    /// Requests user attention to the window, this has no effect if the application
1268    /// is already focused. How requesting for user attention manifests is platform dependent,
1269    /// see [`UserAttentionType`] for details.
1270    ///
1271    /// Providing `None` will unset the request for user attention. Unsetting the request for
1272    /// user attention might not be done automatically by the WM when the window receives input.
1273    ///
1274    /// ## Platform-specific
1275    ///
1276    /// - **iOS / Android / Web / Orbital:** Unsupported.
1277    /// - **macOS:** `None` has no effect.
1278    /// - **X11:** Requests for user attention must be manually cleared.
1279    /// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect.
1280    #[inline]
1281    pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
1282        self.window
1283            .maybe_queue_on_main(move |w| w.request_user_attention(request_type))
1284    }
1285
1286    /// Sets the current window theme. Use `None` to fallback to system default.
1287    ///
1288    /// ## Platform-specific
1289    ///
1290    /// - **macOS:** This is an app-wide setting.
1291    /// - **Wayland:** Sets the theme for the client side decorations. Using `None` will use dbus
1292    ///   to get the system preference.
1293    /// - **X11:** Sets `_GTK_THEME_VARIANT` hint to `dark` or `light` and if `None` is used, it will default to  [`Theme::Dark`].
1294    /// - **iOS / Android / Web / Orbital:** Unsupported.
1295    #[inline]
1296    pub fn set_theme(&self, theme: Option<Theme>) {
1297        self.window.maybe_queue_on_main(move |w| w.set_theme(theme))
1298    }
1299
1300    /// Returns the current window theme.
1301    ///
1302    /// ## Platform-specific
1303    ///
1304    /// - **macOS:** This is an app-wide setting.
1305    /// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported.
1306    #[inline]
1307    pub fn theme(&self) -> Option<Theme> {
1308        self.window.maybe_wait_on_main(|w| w.theme())
1309    }
1310
1311    /// Prevents the window contents from being captured by other apps.
1312    ///
1313    /// ## Platform-specific
1314    ///
1315    /// - **macOS**: if `false`, [`NSWindowSharingNone`] is used but doesn't completely
1316    /// prevent all apps from reading the window content, for instance, QuickTime.
1317    /// - **iOS / Android / x11 / Wayland / Web / Orbital:** Unsupported.
1318    ///
1319    /// [`NSWindowSharingNone`]: https://developer.apple.com/documentation/appkit/nswindowsharingtype/nswindowsharingnone
1320    pub fn set_content_protected(&self, protected: bool) {
1321        self.window
1322            .maybe_queue_on_main(move |w| w.set_content_protected(protected))
1323    }
1324
1325    /// Gets the current title of the window.
1326    ///
1327    /// ## Platform-specific
1328    ///
1329    /// - **iOS / Android / x11 / Wayland / Web:** Unsupported. Always returns an empty string.
1330    #[inline]
1331    pub fn title(&self) -> String {
1332        self.window.maybe_wait_on_main(|w| w.title())
1333    }
1334}
1335
1336/// Cursor functions.
1337impl Window {
1338    /// Modifies the cursor icon of the window.
1339    ///
1340    /// ## Platform-specific
1341    ///
1342    /// - **iOS / Android / Orbital:** Unsupported.
1343    #[inline]
1344    pub fn set_cursor_icon(&self, cursor: CursorIcon) {
1345        self.window
1346            .maybe_queue_on_main(move |w| w.set_cursor_icon(cursor))
1347    }
1348
1349    /// Changes the position of the cursor in window coordinates.
1350    ///
1351    /// ```no_run
1352    /// # use winit::dpi::{LogicalPosition, PhysicalPosition};
1353    /// # use winit::event_loop::EventLoop;
1354    /// # use winit::window::Window;
1355    /// # let mut event_loop = EventLoop::new().unwrap();
1356    /// # let window = Window::new(&event_loop).unwrap();
1357    /// // Specify the position in logical dimensions like this:
1358    /// window.set_cursor_position(LogicalPosition::new(400.0, 200.0));
1359    ///
1360    /// // Or specify the position in physical dimensions like this:
1361    /// window.set_cursor_position(PhysicalPosition::new(400, 200));
1362    /// ```
1363    ///
1364    /// ## Platform-specific
1365    ///
1366    /// - **iOS / Android / Web / Wayland / Orbital:** Always returns an [`ExternalError::NotSupported`].
1367    #[inline]
1368    pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
1369        let position = position.into();
1370        self.window
1371            .maybe_wait_on_main(|w| w.set_cursor_position(position))
1372    }
1373
1374    /// Set grabbing [mode]([`CursorGrabMode`]) on the cursor preventing it from leaving the window.
1375    ///
1376    /// # Example
1377    ///
1378    /// First try confining the cursor, and if that fails, try locking it instead.
1379    ///
1380    /// ```no_run
1381    /// # use winit::event_loop::EventLoop;
1382    /// # use winit::window::{CursorGrabMode, Window};
1383    /// # let mut event_loop = EventLoop::new().unwrap();
1384    /// # let window = Window::new(&event_loop).unwrap();
1385    /// window.set_cursor_grab(CursorGrabMode::Confined)
1386    ///             .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked))
1387    ///             .unwrap();
1388    /// ```
1389    #[inline]
1390    pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
1391        self.window.maybe_wait_on_main(|w| w.set_cursor_grab(mode))
1392    }
1393
1394    /// Modifies the cursor's visibility.
1395    ///
1396    /// If `false`, this will hide the cursor. If `true`, this will show the cursor.
1397    ///
1398    /// ## Platform-specific
1399    ///
1400    /// - **Windows:** The cursor is only hidden within the confines of the window.
1401    /// - **X11:** The cursor is only hidden within the confines of the window.
1402    /// - **Wayland:** The cursor is only hidden within the confines of the window.
1403    /// - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is
1404    ///   outside of the window.
1405    /// - **iOS / Android / Orbital:** Unsupported.
1406    #[inline]
1407    pub fn set_cursor_visible(&self, visible: bool) {
1408        self.window
1409            .maybe_queue_on_main(move |w| w.set_cursor_visible(visible))
1410    }
1411
1412    /// Moves the window with the left mouse button until the button is released.
1413    ///
1414    /// There's no guarantee that this will work unless the left mouse button was pressed
1415    /// immediately before this function is called.
1416    ///
1417    /// ## Platform-specific
1418    ///
1419    /// - **X11:** Un-grabs the cursor.
1420    /// - **Wayland:** Requires the cursor to be inside the window to be dragged.
1421    /// - **macOS:** May prevent the button release event to be triggered.
1422    /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1423    #[inline]
1424    pub fn drag_window(&self) -> Result<(), ExternalError> {
1425        self.window.maybe_wait_on_main(|w| w.drag_window())
1426    }
1427
1428    /// Resizes the window with the left mouse button until the button is released.
1429    ///
1430    /// There's no guarantee that this will work unless the left mouse button was pressed
1431    /// immediately before this function is called.
1432    ///
1433    /// ## Platform-specific
1434    ///
1435    /// - **macOS:** Always returns an [`ExternalError::NotSupported`]
1436    /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1437    #[inline]
1438    pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
1439        self.window
1440            .maybe_wait_on_main(|w| w.drag_resize_window(direction))
1441    }
1442
1443    /// Show [window menu] at a specified position .
1444    ///
1445    /// This is the context menu that is normally shown when interacting with
1446    /// the title bar. This is useful when implementing custom decorations.
1447    ///
1448    /// ## Platform-specific
1449    /// **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
1450    ///
1451    /// [window menu]: https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu
1452    pub fn show_window_menu(&self, position: impl Into<Position>) {
1453        let position = position.into();
1454        self.window
1455            .maybe_queue_on_main(move |w| w.show_window_menu(position))
1456    }
1457
1458    /// Modifies whether the window catches cursor events.
1459    ///
1460    /// If `true`, the window will catch the cursor events. If `false`, events are passed through
1461    /// the window such that any other window behind it receives them. By default hittest is enabled.
1462    ///
1463    /// ## Platform-specific
1464    ///
1465    /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1466    #[inline]
1467    pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
1468        self.window
1469            .maybe_wait_on_main(|w| w.set_cursor_hittest(hittest))
1470    }
1471}
1472
1473/// Monitor info functions.
1474impl Window {
1475    /// Returns the monitor on which the window currently resides.
1476    ///
1477    /// Returns `None` if current monitor can't be detected.
1478    ///
1479    /// ## Platform-specific
1480    ///
1481    /// **iOS:** Can only be called on the main thread.
1482    #[inline]
1483    pub fn current_monitor(&self) -> Option<MonitorHandle> {
1484        self.window
1485            .maybe_wait_on_main(|w| w.current_monitor().map(|inner| MonitorHandle { inner }))
1486    }
1487
1488    /// Returns the list of all the monitors available on the system.
1489    ///
1490    /// This is the same as [`EventLoopWindowTarget::available_monitors`], and is provided for convenience.
1491    ///
1492    /// ## Platform-specific
1493    ///
1494    /// **iOS:** Can only be called on the main thread.
1495    ///
1496    /// [`EventLoopWindowTarget::available_monitors`]: crate::event_loop::EventLoopWindowTarget::available_monitors
1497    #[inline]
1498    pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
1499        self.window.maybe_wait_on_main(|w| {
1500            w.available_monitors()
1501                .into_iter()
1502                .map(|inner| MonitorHandle { inner })
1503        })
1504    }
1505
1506    /// Returns the primary monitor of the system.
1507    ///
1508    /// Returns `None` if it can't identify any monitor as a primary one.
1509    ///
1510    /// This is the same as [`EventLoopWindowTarget::primary_monitor`], and is provided for convenience.
1511    ///
1512    /// ## Platform-specific
1513    ///
1514    /// **iOS:** Can only be called on the main thread.
1515    /// **Wayland:** Always returns `None`.
1516    ///
1517    /// [`EventLoopWindowTarget::primary_monitor`]: crate::event_loop::EventLoopWindowTarget::primary_monitor
1518    #[inline]
1519    pub fn primary_monitor(&self) -> Option<MonitorHandle> {
1520        self.window
1521            .maybe_wait_on_main(|w| w.primary_monitor().map(|inner| MonitorHandle { inner }))
1522    }
1523}
1524
1525#[cfg(feature = "rwh_06")]
1526impl rwh_06::HasWindowHandle for Window {
1527    fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
1528        let raw = self
1529            .window
1530            .maybe_wait_on_main(|w| w.raw_window_handle_rwh_06().map(SendSyncWrapper))?
1531            .0;
1532
1533        // SAFETY: The window handle will never be deallocated while the window is alive.
1534        Ok(unsafe { rwh_06::WindowHandle::borrow_raw(raw) })
1535    }
1536}
1537
1538#[cfg(feature = "rwh_06")]
1539impl rwh_06::HasDisplayHandle for Window {
1540    fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
1541        let raw = self
1542            .window
1543            .maybe_wait_on_main(|w| w.raw_display_handle_rwh_06().map(SendSyncWrapper))?
1544            .0;
1545
1546        // SAFETY: The window handle will never be deallocated while the window is alive.
1547        Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
1548    }
1549}
1550
1551#[cfg(feature = "rwh_05")]
1552unsafe impl rwh_05::HasRawWindowHandle for Window {
1553    fn raw_window_handle(&self) -> rwh_05::RawWindowHandle {
1554        self.window
1555            .maybe_wait_on_main(|w| SendSyncWrapper(w.raw_window_handle_rwh_05()))
1556            .0
1557    }
1558}
1559
1560#[cfg(feature = "rwh_05")]
1561unsafe impl rwh_05::HasRawDisplayHandle for Window {
1562    /// Returns a [`rwh_05::RawDisplayHandle`] used by the [`EventLoop`] that
1563    /// created a window.
1564    ///
1565    /// [`EventLoop`]: crate::event_loop::EventLoop
1566    fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle {
1567        self.window
1568            .maybe_wait_on_main(|w| SendSyncWrapper(w.raw_display_handle_rwh_05()))
1569            .0
1570    }
1571}
1572
1573#[cfg(feature = "rwh_04")]
1574unsafe impl rwh_04::HasRawWindowHandle for Window {
1575    fn raw_window_handle(&self) -> rwh_04::RawWindowHandle {
1576        self.window
1577            .maybe_wait_on_main(|w| SendSyncWrapper(w.raw_window_handle_rwh_04()))
1578            .0
1579    }
1580}
1581
1582/// The behavior of cursor grabbing.
1583///
1584/// Use this enum with [`Window::set_cursor_grab`] to grab the cursor.
1585#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1587pub enum CursorGrabMode {
1588    /// No grabbing of the cursor is performed.
1589    None,
1590
1591    /// The cursor is confined to the window area.
1592    ///
1593    /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you
1594    /// want to do so.
1595    ///
1596    /// ## Platform-specific
1597    ///
1598    /// - **macOS:** Not implemented. Always returns [`ExternalError::NotSupported`] for now.
1599    /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1600    Confined,
1601
1602    /// The cursor is locked inside the window area to the certain position.
1603    ///
1604    /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you
1605    /// want to do so.
1606    ///
1607    /// ## Platform-specific
1608    ///
1609    /// - **X11 / Windows:** Not implemented. Always returns [`ExternalError::NotSupported`] for now.
1610    /// - **iOS / Android / Orbital:** Always returns an [`ExternalError::NotSupported`].
1611    Locked,
1612}
1613
1614/// Defines the orientation that a window resize will be performed.
1615#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1616pub enum ResizeDirection {
1617    East,
1618    North,
1619    NorthEast,
1620    NorthWest,
1621    South,
1622    SouthEast,
1623    SouthWest,
1624    West,
1625}
1626
1627impl From<ResizeDirection> for CursorIcon {
1628    fn from(direction: ResizeDirection) -> Self {
1629        use ResizeDirection::*;
1630        match direction {
1631            East => CursorIcon::EResize,
1632            North => CursorIcon::NResize,
1633            NorthEast => CursorIcon::NeResize,
1634            NorthWest => CursorIcon::NwResize,
1635            South => CursorIcon::SResize,
1636            SouthEast => CursorIcon::SeResize,
1637            SouthWest => CursorIcon::SwResize,
1638            West => CursorIcon::WResize,
1639        }
1640    }
1641}
1642
1643/// Fullscreen modes.
1644#[derive(Clone, Debug, PartialEq, Eq)]
1645pub enum Fullscreen {
1646    Exclusive(VideoMode),
1647
1648    /// Providing `None` to `Borderless` will fullscreen on the current monitor.
1649    Borderless(Option<MonitorHandle>),
1650}
1651
1652/// The theme variant to use.
1653#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1654#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1655pub enum Theme {
1656    /// Use the light variant.
1657    Light,
1658
1659    /// Use the dark variant.
1660    Dark,
1661}
1662
1663/// ## Platform-specific
1664///
1665/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between [`Critical`] and [`Informational`].
1666///
1667/// [`Critical`]: Self::Critical
1668/// [`Informational`]: Self::Informational
1669#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1670pub enum UserAttentionType {
1671    /// ## Platform-specific
1672    ///
1673    /// - **macOS:** Bounces the dock icon until the application is in focus.
1674    /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
1675    Critical,
1676
1677    /// ## Platform-specific
1678    ///
1679    /// - **macOS:** Bounces the dock icon once.
1680    /// - **Windows:** Flashes the taskbar button until the application is in focus.
1681    #[default]
1682    Informational,
1683}
1684
1685bitflags! {
1686    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1687    pub struct WindowButtons: u32 {
1688        const CLOSE  = 1 << 0;
1689        const MINIMIZE  = 1 << 1;
1690        const MAXIMIZE  = 1 << 2;
1691    }
1692}
1693
1694/// A window level groups windows with respect to their z-position.
1695///
1696/// The relative ordering between windows in different window levels is fixed.
1697/// The z-order of a window within the same window level may change dynamically on user interaction.
1698///
1699/// ## Platform-specific
1700///
1701/// - **iOS / Android / Web / Wayland:** Unsupported.
1702#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
1703pub enum WindowLevel {
1704    /// The window will always be below normal windows.
1705    ///
1706    /// This is useful for a widget-based app.
1707    AlwaysOnBottom,
1708
1709    /// The default.
1710    #[default]
1711    Normal,
1712
1713    /// The window will always be on top of normal windows.
1714    AlwaysOnTop,
1715}
1716
1717/// Generic IME purposes for use in [`Window::set_ime_purpose`].
1718///
1719/// The purpose may improve UX by optimizing the IME for the specific use case,
1720/// if winit can express the purpose to the platform and the platform reacts accordingly.
1721///
1722/// ## Platform-specific
1723///
1724/// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported.
1725#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1726#[non_exhaustive]
1727pub enum ImePurpose {
1728    /// No special hints for the IME (default).
1729    Normal,
1730    /// The IME is used for password input.
1731    Password,
1732    /// The IME is used to input into a terminal.
1733    ///
1734    /// For example, that could alter OSK on Wayland to show extra buttons.
1735    Terminal,
1736}
1737
1738impl Default for ImePurpose {
1739    fn default() -> Self {
1740        Self::Normal
1741    }
1742}
1743
1744/// An opaque token used to activate the [`Window`].
1745///
1746/// [`Window`]: crate::window::Window
1747#[derive(Debug, PartialEq, Eq, Clone)]
1748pub struct ActivationToken {
1749    pub(crate) _token: String,
1750}
1751
1752impl ActivationToken {
1753    pub(crate) fn _new(_token: String) -> Self {
1754        Self { _token }
1755    }
1756}