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: &Window| {
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: Fullscreen| f.into()) {
72 w.set_fullscreen(monitor: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&mut DebugStruct<'_, '_>.debug_struct("WindowBuilder")
129 .field(name:"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:** 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:** 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:** 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 /// - **Wayland**: Cursor must be in [`CursorGrabMode::Locked`].
1367 /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1368 #[inline]
1369 pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
1370 let position = position.into();
1371 self.window
1372 .maybe_wait_on_main(|w| w.set_cursor_position(position))
1373 }
1374
1375 /// Set grabbing [mode](CursorGrabMode) on the cursor preventing it from leaving the window.
1376 ///
1377 /// # Example
1378 ///
1379 /// First try confining the cursor, and if that fails, try locking it instead.
1380 ///
1381 /// ```no_run
1382 /// # use winit::event_loop::EventLoop;
1383 /// # use winit::window::{CursorGrabMode, Window};
1384 /// # let mut event_loop = EventLoop::new().unwrap();
1385 /// # let window = Window::new(&event_loop).unwrap();
1386 /// window.set_cursor_grab(CursorGrabMode::Confined)
1387 /// .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked))
1388 /// .unwrap();
1389 /// ```
1390 #[inline]
1391 pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
1392 self.window.maybe_wait_on_main(|w| w.set_cursor_grab(mode))
1393 }
1394
1395 /// Modifies the cursor's visibility.
1396 ///
1397 /// If `false`, this will hide the cursor. If `true`, this will show the cursor.
1398 ///
1399 /// ## Platform-specific
1400 ///
1401 /// - **Windows:** The cursor is only hidden within the confines of the window.
1402 /// - **X11:** The cursor is only hidden within the confines of the window.
1403 /// - **Wayland:** The cursor is only hidden within the confines of the window.
1404 /// - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is
1405 /// outside of the window.
1406 /// - **iOS / Android:** Unsupported.
1407 #[inline]
1408 pub fn set_cursor_visible(&self, visible: bool) {
1409 self.window
1410 .maybe_queue_on_main(move |w| w.set_cursor_visible(visible))
1411 }
1412
1413 /// Moves the window with the left mouse button until the button is released.
1414 ///
1415 /// There's no guarantee that this will work unless the left mouse button was pressed
1416 /// immediately before this function is called.
1417 ///
1418 /// ## Platform-specific
1419 ///
1420 /// - **X11:** Un-grabs the cursor.
1421 /// - **Wayland:** Requires the cursor to be inside the window to be dragged.
1422 /// - **macOS:** May prevent the button release event to be triggered.
1423 /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
1424 #[inline]
1425 pub fn drag_window(&self) -> Result<(), ExternalError> {
1426 self.window.maybe_wait_on_main(|w| w.drag_window())
1427 }
1428
1429 /// Resizes the window with the left mouse button until the button is released.
1430 ///
1431 /// There's no guarantee that this will work unless the left mouse button was pressed
1432 /// immediately before this function is called.
1433 ///
1434 /// ## Platform-specific
1435 ///
1436 /// - **macOS:** Always returns an [`ExternalError::NotSupported`]
1437 /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
1438 #[inline]
1439 pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
1440 self.window
1441 .maybe_wait_on_main(|w| w.drag_resize_window(direction))
1442 }
1443
1444 /// Show [window menu] at a specified position .
1445 ///
1446 /// This is the context menu that is normally shown when interacting with
1447 /// the title bar. This is useful when implementing custom decorations.
1448 ///
1449 /// ## Platform-specific
1450 /// **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
1451 ///
1452 /// [window menu]: https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu
1453 pub fn show_window_menu(&self, position: impl Into<Position>) {
1454 let position = position.into();
1455 self.window
1456 .maybe_queue_on_main(move |w| w.show_window_menu(position))
1457 }
1458
1459 /// Modifies whether the window catches cursor events.
1460 ///
1461 /// If `true`, the window will catch the cursor events. If `false`, events are passed through
1462 /// the window such that any other window behind it receives them. By default hittest is enabled.
1463 ///
1464 /// ## Platform-specific
1465 ///
1466 /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`].
1467 #[inline]
1468 pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
1469 self.window
1470 .maybe_wait_on_main(|w| w.set_cursor_hittest(hittest))
1471 }
1472}
1473
1474/// Monitor info functions.
1475impl Window {
1476 /// Returns the monitor on which the window currently resides.
1477 ///
1478 /// Returns `None` if current monitor can't be detected.
1479 #[inline]
1480 pub fn current_monitor(&self) -> Option<MonitorHandle> {
1481 self.window
1482 .maybe_wait_on_main(|w| w.current_monitor().map(|inner| MonitorHandle { inner }))
1483 }
1484
1485 /// Returns the list of all the monitors available on the system.
1486 ///
1487 /// This is the same as [`EventLoopWindowTarget::available_monitors`], and is provided for convenience.
1488 ///
1489 /// [`EventLoopWindowTarget::available_monitors`]: crate::event_loop::EventLoopWindowTarget::available_monitors
1490 #[inline]
1491 pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
1492 self.window.maybe_wait_on_main(|w| {
1493 w.available_monitors()
1494 .into_iter()
1495 .map(|inner| MonitorHandle { inner })
1496 })
1497 }
1498
1499 /// Returns the primary monitor of the system.
1500 ///
1501 /// Returns `None` if it can't identify any monitor as a primary one.
1502 ///
1503 /// This is the same as [`EventLoopWindowTarget::primary_monitor`], and is provided for convenience.
1504 ///
1505 /// ## Platform-specific
1506 ///
1507 /// **Wayland / Web:** Always returns `None`.
1508 ///
1509 /// [`EventLoopWindowTarget::primary_monitor`]: crate::event_loop::EventLoopWindowTarget::primary_monitor
1510 #[inline]
1511 pub fn primary_monitor(&self) -> Option<MonitorHandle> {
1512 self.window
1513 .maybe_wait_on_main(|w| w.primary_monitor().map(|inner| MonitorHandle { inner }))
1514 }
1515}
1516
1517#[cfg(feature = "rwh_06")]
1518impl rwh_06::HasWindowHandle for Window {
1519 fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
1520 let raw: RawWindowHandle = self
1521 .window
1522 .maybe_wait_on_main(|w: &Window| w.raw_window_handle_rwh_06().map(op:SendSyncWrapper))?
1523 .0;
1524
1525 // SAFETY: The window handle will never be deallocated while the window is alive.
1526 Ok(unsafe { rwh_06::WindowHandle::borrow_raw(raw) })
1527 }
1528}
1529
1530#[cfg(feature = "rwh_06")]
1531impl rwh_06::HasDisplayHandle for Window {
1532 fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
1533 let raw: RawDisplayHandle = self
1534 .window
1535 .maybe_wait_on_main(|w: &Window| w.raw_display_handle_rwh_06().map(op:SendSyncWrapper))?
1536 .0;
1537
1538 // SAFETY: The window handle will never be deallocated while the window is alive.
1539 Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
1540 }
1541}
1542
1543#[cfg(feature = "rwh_05")]
1544unsafe impl rwh_05::HasRawWindowHandle for Window {
1545 fn raw_window_handle(&self) -> rwh_05::RawWindowHandle {
1546 self.window
1547 .maybe_wait_on_main(|w: &Window| SendSyncWrapper(w.raw_window_handle_rwh_05()))
1548 .0
1549 }
1550}
1551
1552#[cfg(feature = "rwh_05")]
1553unsafe impl rwh_05::HasRawDisplayHandle for Window {
1554 /// Returns a [`rwh_05::RawDisplayHandle`] used by the [`EventLoop`] that
1555 /// created a window.
1556 ///
1557 /// [`EventLoop`]: crate::event_loop::EventLoop
1558 fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle {
1559 self.window
1560 .maybe_wait_on_main(|w: &Window| SendSyncWrapper(w.raw_display_handle_rwh_05()))
1561 .0
1562 }
1563}
1564
1565#[cfg(feature = "rwh_04")]
1566unsafe impl rwh_04::HasRawWindowHandle for Window {
1567 fn raw_window_handle(&self) -> rwh_04::RawWindowHandle {
1568 self.window
1569 .maybe_wait_on_main(|w| SendSyncWrapper(w.raw_window_handle_rwh_04()))
1570 .0
1571 }
1572}
1573
1574/// The behavior of cursor grabbing.
1575///
1576/// Use this enum with [`Window::set_cursor_grab`] to grab the cursor.
1577#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1578#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1579pub enum CursorGrabMode {
1580 /// No grabbing of the cursor is performed.
1581 None,
1582
1583 /// The cursor is confined to the window area.
1584 ///
1585 /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you
1586 /// want to do so.
1587 ///
1588 /// ## Platform-specific
1589 ///
1590 /// - **macOS:** Not implemented. Always returns [`ExternalError::NotSupported`] for now.
1591 /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
1592 Confined,
1593
1594 /// The cursor is locked inside the window area to the certain position.
1595 ///
1596 /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you
1597 /// want to do so.
1598 ///
1599 /// ## Platform-specific
1600 ///
1601 /// - **X11 / Windows:** Not implemented. Always returns [`ExternalError::NotSupported`] for now.
1602 /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
1603 Locked,
1604}
1605
1606/// Defines the orientation that a window resize will be performed.
1607#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1608pub enum ResizeDirection {
1609 East,
1610 North,
1611 NorthEast,
1612 NorthWest,
1613 South,
1614 SouthEast,
1615 SouthWest,
1616 West,
1617}
1618
1619impl From<ResizeDirection> for CursorIcon {
1620 fn from(direction: ResizeDirection) -> Self {
1621 use ResizeDirection::*;
1622 match direction {
1623 East => CursorIcon::EResize,
1624 North => CursorIcon::NResize,
1625 NorthEast => CursorIcon::NeResize,
1626 NorthWest => CursorIcon::NwResize,
1627 South => CursorIcon::SResize,
1628 SouthEast => CursorIcon::SeResize,
1629 SouthWest => CursorIcon::SwResize,
1630 West => CursorIcon::WResize,
1631 }
1632 }
1633}
1634
1635/// Fullscreen modes.
1636#[derive(Clone, Debug, PartialEq, Eq)]
1637pub enum Fullscreen {
1638 Exclusive(VideoMode),
1639
1640 /// Providing `None` to `Borderless` will fullscreen on the current monitor.
1641 Borderless(Option<MonitorHandle>),
1642}
1643
1644/// The theme variant to use.
1645#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1647pub enum Theme {
1648 /// Use the light variant.
1649 Light,
1650
1651 /// Use the dark variant.
1652 Dark,
1653}
1654
1655/// ## Platform-specific
1656///
1657/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between [`Critical`] and [`Informational`].
1658///
1659/// [`Critical`]: Self::Critical
1660/// [`Informational`]: Self::Informational
1661#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1662pub enum UserAttentionType {
1663 /// ## Platform-specific
1664 ///
1665 /// - **macOS:** Bounces the dock icon until the application is in focus.
1666 /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
1667 Critical,
1668
1669 /// ## Platform-specific
1670 ///
1671 /// - **macOS:** Bounces the dock icon once.
1672 /// - **Windows:** Flashes the taskbar button until the application is in focus.
1673 #[default]
1674 Informational,
1675}
1676
1677bitflags! {
1678 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1679 pub struct WindowButtons: u32 {
1680 const CLOSE = 1 << 0;
1681 const MINIMIZE = 1 << 1;
1682 const MAXIMIZE = 1 << 2;
1683 }
1684}
1685
1686/// A window level groups windows with respect to their z-position.
1687///
1688/// The relative ordering between windows in different window levels is fixed.
1689/// The z-order of a window within the same window level may change dynamically on user interaction.
1690///
1691/// ## Platform-specific
1692///
1693/// - **iOS / Android / Web / Wayland:** Unsupported.
1694#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
1695pub enum WindowLevel {
1696 /// The window will always be below normal windows.
1697 ///
1698 /// This is useful for a widget-based app.
1699 AlwaysOnBottom,
1700
1701 /// The default.
1702 #[default]
1703 Normal,
1704
1705 /// The window will always be on top of normal windows.
1706 AlwaysOnTop,
1707}
1708
1709/// Generic IME purposes for use in [`Window::set_ime_purpose`].
1710///
1711/// The purpose may improve UX by optimizing the IME for the specific use case,
1712/// if winit can express the purpose to the platform and the platform reacts accordingly.
1713///
1714/// ## Platform-specific
1715///
1716/// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported.
1717#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1718#[non_exhaustive]
1719pub enum ImePurpose {
1720 /// No special hints for the IME (default).
1721 Normal,
1722 /// The IME is used for password input.
1723 Password,
1724 /// The IME is used to input into a terminal.
1725 ///
1726 /// For example, that could alter OSK on Wayland to show extra buttons.
1727 Terminal,
1728}
1729
1730impl Default for ImePurpose {
1731 fn default() -> Self {
1732 Self::Normal
1733 }
1734}
1735
1736/// An opaque token used to activate the [`Window`].
1737///
1738/// [`Window`]: crate::window::Window
1739#[derive(Debug, PartialEq, Eq, Clone)]
1740pub struct ActivationToken {
1741 pub(crate) _token: String,
1742}
1743
1744impl ActivationToken {
1745 pub(crate) fn _new(_token: String) -> Self {
1746 Self { _token }
1747 }
1748}
1749