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,
10};
11
12pub use crate::icon::{BadIcon, Icon};
13
14/// Represents a window.
15///
16/// # Example
17///
18/// ```no_run
19/// use winit::{
20/// event::{Event, WindowEvent},
21/// event_loop::{ControlFlow, EventLoop},
22/// window::Window,
23/// };
24///
25/// let mut event_loop = EventLoop::new();
26/// let window = Window::new(&event_loop).unwrap();
27///
28/// event_loop.run(move |event, _, control_flow| {
29/// *control_flow = ControlFlow::Wait;
30///
31/// match event {
32/// Event::WindowEvent {
33/// event: WindowEvent::CloseRequested,
34/// ..
35/// } => *control_flow = ControlFlow::Exit,
36/// _ => (),
37/// }
38/// });
39/// ```
40pub struct Window {
41 pub(crate) window: platform_impl::Window,
42}
43
44impl fmt::Debug for Window {
45 fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
46 fmtr.pad("Window { .. }")
47 }
48}
49
50impl Drop for Window {
51 fn drop(&mut self) {
52 // If the window is in exclusive fullscreen, we must restore the desktop
53 // video mode (generally this would be done on application exit, but
54 // closing the window doesn't necessarily always mean application exit,
55 // such as when there are multiple windows)
56 if let Some(Fullscreen::Exclusive(_)) = self.fullscreen() {
57 self.set_fullscreen(None);
58 }
59 }
60}
61
62/// Identifier of a window. Unique for each window.
63///
64/// Can be obtained with `window.id()`.
65///
66/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you
67/// can then compare to the ids of your windows.
68#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
69pub struct WindowId(pub(crate) platform_impl::WindowId);
70
71impl WindowId {
72 /// Returns a dummy `WindowId`, useful for unit testing. The only guarantee made about the return
73 /// value of this function is that it will always be equal to itself and to future values returned
74 /// by this function. No other guarantees are made. This may be equal to a real `WindowId`.
75 ///
76 /// **Passing this into a winit function will result in undefined behavior.**
77 pub unsafe fn dummy() -> Self {
78 WindowId(platform_impl::WindowId::dummy())
79 }
80}
81
82/// Object that allows you to build windows.
83#[derive(Clone, Default)]
84pub struct WindowBuilder {
85 /// The attributes to use to create the window.
86 pub window: WindowAttributes,
87
88 // Platform-specific configuration.
89 pub(crate) platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes,
90}
91
92impl fmt::Debug for WindowBuilder {
93 fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
94 fmtr.debug_struct("WindowBuilder")
95 .field("window", &self.window)
96 .finish()
97 }
98}
99
100/// Attributes to use when creating a window.
101#[derive(Debug, Clone)]
102pub struct WindowAttributes {
103 /// The dimensions of the window. If this is `None`, some platform-specific dimensions will be
104 /// used.
105 ///
106 /// The default is `None`.
107 pub inner_size: Option<Size>,
108
109 /// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved).
110 ///
111 /// The default is `None`.
112 pub min_inner_size: Option<Size>,
113
114 /// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform.
115 ///
116 /// The default is `None`.
117 pub max_inner_size: Option<Size>,
118
119 /// The desired position of the window. If this is `None`, some platform-specific position
120 /// will be chosen.
121 ///
122 /// The default is `None`.
123 ///
124 /// ## Platform-specific
125 ///
126 /// - **macOS**: The top left corner position of the window content, the window's "inner"
127 /// position. The window title bar will be placed above it.
128 /// The window will be positioned such that it fits on screen, maintaining
129 /// set `inner_size` if any.
130 /// If you need to precisely position the top left corner of the whole window you have to
131 /// use [`Window::set_outer_position`] after creating the window.
132 /// - **Windows**: The top left corner position of the window title bar, the window's "outer"
133 /// position.
134 /// There may be a small gap between this position and the window due to the specifics of the
135 /// Window Manager.
136 /// - **X11**: The top left corner of the window, the window's "outer" position.
137 /// - **Others**: Ignored.
138 ///
139 /// See [`Window::set_outer_position`].
140 ///
141 /// [`Window::set_outer_position`]: crate::window::Window::set_outer_position
142 pub position: Option<Position>,
143
144 /// Whether the window is resizable or not.
145 ///
146 /// The default is `true`.
147 pub resizable: bool,
148
149 /// Whether the window should be set as fullscreen upon creation.
150 ///
151 /// The default is `None`.
152 pub fullscreen: Option<Fullscreen>,
153
154 /// The title of the window in the title bar.
155 ///
156 /// The default is `"winit window"`.
157 pub title: String,
158
159 /// Whether the window should be maximized upon creation.
160 ///
161 /// The default is `false`.
162 pub maximized: bool,
163
164 /// Whether the window should be immediately visible upon creation.
165 ///
166 /// The default is `true`.
167 pub visible: bool,
168
169 /// Whether the the window should be transparent. If this is true, writing colors
170 /// with alpha values different than `1.0` will produce a transparent window.
171 ///
172 /// The default is `false`.
173 pub transparent: bool,
174
175 /// Whether the window should have borders and bars.
176 ///
177 /// The default is `true`.
178 pub decorations: bool,
179
180 /// Whether the window should always be on top of other windows.
181 ///
182 /// The default is `false`.
183 pub always_on_top: bool,
184
185 /// The window icon.
186 ///
187 /// The default is `None`.
188 pub window_icon: Option<Icon>,
189}
190
191impl Default for WindowAttributes {
192 #[inline]
193 fn default() -> WindowAttributes {
194 WindowAttributes {
195 inner_size: None,
196 min_inner_size: None,
197 max_inner_size: None,
198 position: None,
199 resizable: true,
200 title: "winit window".to_owned(),
201 maximized: false,
202 fullscreen: None,
203 visible: true,
204 transparent: false,
205 decorations: true,
206 always_on_top: false,
207 window_icon: None,
208 }
209 }
210}
211
212impl WindowBuilder {
213 /// Initializes a new `WindowBuilder` with default values.
214 #[inline]
215 pub fn new() -> Self {
216 Default::default()
217 }
218
219 /// Requests the window to be of specific dimensions.
220 ///
221 /// See [`Window::set_inner_size`] for details.
222 ///
223 /// [`Window::set_inner_size`]: crate::window::Window::set_inner_size
224 #[inline]
225 pub fn with_inner_size<S: Into<Size>>(mut self, size: S) -> Self {
226 self.window.inner_size = Some(size.into());
227 self
228 }
229
230 /// Sets a minimum dimension size for the window.
231 ///
232 /// See [`Window::set_min_inner_size`] for details.
233 ///
234 /// [`Window::set_min_inner_size`]: crate::window::Window::set_min_inner_size
235 #[inline]
236 pub fn with_min_inner_size<S: Into<Size>>(mut self, min_size: S) -> Self {
237 self.window.min_inner_size = Some(min_size.into());
238 self
239 }
240
241 /// Sets a maximum dimension size for the window.
242 ///
243 /// See [`Window::set_max_inner_size`] for details.
244 ///
245 /// [`Window::set_max_inner_size`]: crate::window::Window::set_max_inner_size
246 #[inline]
247 pub fn with_max_inner_size<S: Into<Size>>(mut self, max_size: S) -> Self {
248 self.window.max_inner_size = Some(max_size.into());
249 self
250 }
251
252 /// Sets a desired initial position for the window.
253 ///
254 /// See [`WindowAttributes::position`] for details.
255 ///
256 /// [`WindowAttributes::position`]: crate::window::WindowAttributes::position
257 #[inline]
258 pub fn with_position<P: Into<Position>>(mut self, position: P) -> Self {
259 self.window.position = Some(position.into());
260 self
261 }
262
263 /// Sets whether the window is resizable or not.
264 ///
265 /// See [`Window::set_resizable`] for details.
266 ///
267 /// [`Window::set_resizable`]: crate::window::Window::set_resizable
268 #[inline]
269 pub fn with_resizable(mut self, resizable: bool) -> Self {
270 self.window.resizable = resizable;
271 self
272 }
273
274 /// Requests a specific title for the window.
275 ///
276 /// See [`Window::set_title`] for details.
277 ///
278 /// [`Window::set_title`]: crate::window::Window::set_title
279 #[inline]
280 pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
281 self.window.title = title.into();
282 self
283 }
284
285 /// Sets the window fullscreen state.
286 ///
287 /// See [`Window::set_fullscreen`] for details.
288 ///
289 /// [`Window::set_fullscreen`]: crate::window::Window::set_fullscreen
290 #[inline]
291 pub fn with_fullscreen(mut self, fullscreen: Option<Fullscreen>) -> Self {
292 self.window.fullscreen = fullscreen;
293 self
294 }
295
296 /// Requests maximized mode.
297 ///
298 /// See [`Window::set_maximized`] for details.
299 ///
300 /// [`Window::set_maximized`]: crate::window::Window::set_maximized
301 #[inline]
302 pub fn with_maximized(mut self, maximized: bool) -> Self {
303 self.window.maximized = maximized;
304 self
305 }
306
307 /// Sets whether the window will be initially hidden or visible.
308 ///
309 /// See [`Window::set_visible`] for details.
310 ///
311 /// [`Window::set_visible`]: crate::window::Window::set_visible
312 #[inline]
313 pub fn with_visible(mut self, visible: bool) -> Self {
314 self.window.visible = visible;
315 self
316 }
317
318 /// Sets whether the background of the window should be transparent.
319 #[inline]
320 pub fn with_transparent(mut self, transparent: bool) -> Self {
321 self.window.transparent = transparent;
322 self
323 }
324
325 /// Sets whether the window should have a border, a title bar, etc.
326 ///
327 /// See [`Window::set_decorations`] for details.
328 ///
329 /// [`Window::set_decorations`]: crate::window::Window::set_decorations
330 #[inline]
331 pub fn with_decorations(mut self, decorations: bool) -> Self {
332 self.window.decorations = decorations;
333 self
334 }
335
336 /// Sets whether or not the window will always be on top of other windows.
337 ///
338 /// See [`Window::set_always_on_top`] for details.
339 ///
340 /// [`Window::set_always_on_top`]: crate::window::Window::set_always_on_top
341 #[inline]
342 pub fn with_always_on_top(mut self, always_on_top: bool) -> Self {
343 self.window.always_on_top = always_on_top;
344 self
345 }
346
347 /// Sets the window icon.
348 ///
349 /// See [`Window::set_window_icon`] for details.
350 ///
351 /// [`Window::set_window_icon`]: crate::window::Window::set_window_icon
352 #[inline]
353 pub fn with_window_icon(mut self, window_icon: Option<Icon>) -> Self {
354 self.window.window_icon = window_icon;
355 self
356 }
357
358 /// Builds the window.
359 ///
360 /// Possible causes of error include denied permission, incompatible system, and lack of memory.
361 ///
362 /// Platform-specific behavior:
363 /// - **Web**: The window is created but not inserted into the web page automatically. Please
364 /// see the web platform module for more information.
365 #[inline]
366 pub fn build<T: 'static>(
367 self,
368 window_target: &EventLoopWindowTarget<T>,
369 ) -> Result<Window, OsError> {
370 platform_impl::Window::new(&window_target.p, self.window, self.platform_specific).map(
371 |window| {
372 window.request_redraw();
373 Window { window }
374 },
375 )
376 }
377}
378
379/// Base Window functions.
380impl Window {
381 /// Creates a new Window for platforms where this is appropriate.
382 ///
383 /// This function is equivalent to [`WindowBuilder::new().build(event_loop)`].
384 ///
385 /// Error should be very rare and only occur in case of permission denied, incompatible system,
386 /// out of memory, etc.
387 ///
388 /// Platform-specific behavior:
389 /// - **Web**: The window is created but not inserted into the web page automatically. Please
390 /// see the web platform module for more information.
391 ///
392 /// [`WindowBuilder::new().build(event_loop)`]: crate::window::WindowBuilder::build
393 #[inline]
394 pub fn new<T: 'static>(event_loop: &EventLoopWindowTarget<T>) -> Result<Window, OsError> {
395 let builder = WindowBuilder::new();
396 builder.build(event_loop)
397 }
398
399 /// Returns an identifier unique to the window.
400 #[inline]
401 pub fn id(&self) -> WindowId {
402 WindowId(self.window.id())
403 }
404
405 /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
406 ///
407 /// See the [`dpi`](crate::dpi) module for more information.
408 ///
409 /// Note that this value can change depending on user action (for example if the window is
410 /// moved to another screen); as such, tracking `WindowEvent::ScaleFactorChanged` events is
411 /// the most robust way to track the DPI you need to use to draw.
412 ///
413 /// ## Platform-specific
414 ///
415 /// - **X11:** This respects Xft.dpi, and can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
416 /// - **Android:** Always returns 1.0.
417 /// - **iOS:** Can only be called on the main thread. Returns the underlying `UIView`'s
418 /// [`contentScaleFactor`].
419 ///
420 /// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
421 #[inline]
422 pub fn scale_factor(&self) -> f64 {
423 self.window.scale_factor()
424 }
425
426 /// Emits a `WindowEvent::RedrawRequested` event in the associated event loop after all OS
427 /// events have been processed by the event loop.
428 ///
429 /// This is the **strongly encouraged** method of redrawing windows, as it can integrate with
430 /// OS-requested redraws (e.g. when a window gets resized).
431 ///
432 /// This function can cause `RedrawRequested` events to be emitted after `Event::MainEventsCleared`
433 /// but before `Event::NewEvents` if called in the following circumstances:
434 /// * While processing `MainEventsCleared`.
435 /// * While processing a `RedrawRequested` event that was sent during `MainEventsCleared` or any
436 /// directly subsequent `RedrawRequested` event.
437 ///
438 /// ## Platform-specific
439 ///
440 /// - **iOS:** Can only be called on the main thread.
441 /// - **Android:** Unsupported.
442 #[inline]
443 pub fn request_redraw(&self) {
444 self.window.request_redraw()
445 }
446}
447
448/// Position and size functions.
449impl Window {
450 /// Returns the position of the top-left hand corner of the window's client area relative to the
451 /// top-left hand corner of the desktop.
452 ///
453 /// The same conditions that apply to `outer_position` apply to this method.
454 ///
455 /// ## Platform-specific
456 ///
457 /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
458 /// window's [safe area] in the screen space coordinate system.
459 /// - **Web:** Returns the top-left coordinates relative to the viewport. _Note: this returns the
460 /// same value as `outer_position`._
461 /// - **Android / Wayland:** Always returns [`NotSupportedError`].
462 ///
463 /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
464 #[inline]
465 pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
466 self.window.inner_position()
467 }
468
469 /// Returns the position of the top-left hand corner of the window relative to the
470 /// top-left hand corner of the desktop.
471 ///
472 /// Note that the top-left hand corner of the desktop is not necessarily the same as
473 /// the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
474 /// of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
475 ///
476 /// The coordinates can be negative if the top-left hand corner of the window is outside
477 /// of the visible screen region.
478 ///
479 /// ## Platform-specific
480 ///
481 /// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
482 /// window in the screen space coordinate system.
483 /// - **Web:** Returns the top-left coordinates relative to the viewport.
484 /// - **Android / Wayland:** Always returns [`NotSupportedError`].
485 #[inline]
486 pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
487 self.window.outer_position()
488 }
489
490 /// Modifies the position of the window.
491 ///
492 /// See `outer_position` for more information about the coordinates. This automatically un-maximizes the
493 /// window if it's maximized.
494 ///
495 /// ## Platform-specific
496 ///
497 /// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
498 /// window in the screen space coordinate system.
499 /// - **Web:** Sets the top-left coordinates relative to the viewport.
500 /// - **Android / Wayland:** Unsupported.
501 #[inline]
502 pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
503 self.window.set_outer_position(position.into())
504 }
505
506 /// Returns the physical size of the window's client area.
507 ///
508 /// The client area is the content of the window, excluding the title bar and borders.
509 ///
510 /// ## Platform-specific
511 ///
512 /// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window's
513 /// [safe area] in screen space coordinates.
514 /// - **Web:** Returns the size of the canvas element.
515 ///
516 /// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
517 #[inline]
518 pub fn inner_size(&self) -> PhysicalSize<u32> {
519 self.window.inner_size()
520 }
521
522 /// Modifies the inner size of the window.
523 ///
524 /// See `inner_size` for more information about the values. This automatically un-maximizes the
525 /// window if it's maximized.
526 ///
527 /// ## Platform-specific
528 ///
529 /// - **iOS / Android:** Unsupported.
530 /// - **Web:** Sets the size of the canvas element.
531 #[inline]
532 pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
533 self.window.set_inner_size(size.into())
534 }
535
536 /// Returns the physical size of the entire window.
537 ///
538 /// These dimensions include the title bar and borders. If you don't want that (and you usually don't),
539 /// use `inner_size` instead.
540 ///
541 /// ## Platform-specific
542 ///
543 /// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window in
544 /// screen space coordinates.
545 /// - **Web:** Returns the size of the canvas element. _Note: this returns the same value as
546 /// `inner_size`._
547 #[inline]
548 pub fn outer_size(&self) -> PhysicalSize<u32> {
549 self.window.outer_size()
550 }
551
552 /// Sets a minimum dimension size for the window.
553 ///
554 /// ## Platform-specific
555 ///
556 /// - **iOS / Android / Web:** Unsupported.
557 #[inline]
558 pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
559 self.window.set_min_inner_size(min_size.map(|s| s.into()))
560 }
561
562 /// Sets a maximum dimension size for the window.
563 ///
564 /// ## Platform-specific
565 ///
566 /// - **iOS / Android / Web:** Unsupported.
567 #[inline]
568 pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
569 self.window.set_max_inner_size(max_size.map(|s| s.into()))
570 }
571}
572
573/// Misc. attribute functions.
574impl Window {
575 /// Modifies the title of the window.
576 ///
577 /// ## Platform-specific
578 ///
579 /// - **iOS / Android:** Unsupported.
580 #[inline]
581 pub fn set_title(&self, title: &str) {
582 self.window.set_title(title)
583 }
584
585 /// Modifies the window's visibility.
586 ///
587 /// If `false`, this will hide the window. If `true`, this will show the window.
588 /// ## Platform-specific
589 ///
590 /// - **Android / Wayland / Web:** Unsupported.
591 /// - **iOS:** Can only be called on the main thread.
592 #[inline]
593 pub fn set_visible(&self, visible: bool) {
594 self.window.set_visible(visible)
595 }
596
597 /// Sets whether the window is resizable or not.
598 ///
599 /// Note that making the window unresizable doesn't exempt you from handling `Resized`, as that event can still be
600 /// triggered by DPI scaling, entering fullscreen mode, etc.
601 ///
602 /// ## Platform-specific
603 ///
604 /// This only has an effect on desktop platforms.
605 ///
606 /// Due to a bug in XFCE, this has no effect on Xfwm.
607 ///
608 /// ## Platform-specific
609 ///
610 /// - **iOS / Android / Web:** Unsupported.
611 #[inline]
612 pub fn set_resizable(&self, resizable: bool) {
613 self.window.set_resizable(resizable)
614 }
615
616 /// Sets the window to minimized or back
617 ///
618 /// ## Platform-specific
619 ///
620 /// - **iOS / Android / Web:** Unsupported.
621 /// - **Wayland:** Un-minimize is unsupported.
622 #[inline]
623 pub fn set_minimized(&self, minimized: bool) {
624 self.window.set_minimized(minimized);
625 }
626
627 /// Sets the window to maximized or back.
628 ///
629 /// ## Platform-specific
630 ///
631 /// - **iOS / Android / Web:** Unsupported.
632 #[inline]
633 pub fn set_maximized(&self, maximized: bool) {
634 self.window.set_maximized(maximized)
635 }
636
637 /// Gets the window's current maximized state.
638 ///
639 /// ## Platform-specific
640 ///
641 /// - **Wayland / X11:** Not implemented.
642 /// - **iOS / Android / Web:** Unsupported.
643 #[inline]
644 pub fn is_maximized(&self) -> bool {
645 self.window.is_maximized()
646 }
647
648 /// Sets the window to fullscreen or back.
649 ///
650 /// ## Platform-specific
651 ///
652 /// - **macOS:** `Fullscreen::Exclusive` provides true exclusive mode with a
653 /// video mode change. *Caveat!* macOS doesn't provide task switching (or
654 /// spaces!) while in exclusive fullscreen mode. This mode should be used
655 /// when a video mode change is desired, but for a better user experience,
656 /// borderless fullscreen might be preferred.
657 ///
658 /// `Fullscreen::Borderless` provides a borderless fullscreen window on a
659 /// separate space. This is the idiomatic way for fullscreen games to work
660 /// on macOS. See `WindowExtMacOs::set_simple_fullscreen` if
661 /// separate spaces are not preferred.
662 ///
663 /// The dock and the menu bar are always disabled in fullscreen mode.
664 /// - **iOS:** Can only be called on the main thread.
665 /// - **Wayland:** Does not support exclusive fullscreen mode and will no-op a request.
666 /// - **Windows:** Screen saver is disabled in fullscreen mode.
667 /// - **Android:** Unsupported.
668 #[inline]
669 pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
670 self.window.set_fullscreen(fullscreen)
671 }
672
673 /// Gets the window's current fullscreen state.
674 ///
675 /// ## Platform-specific
676 ///
677 /// - **iOS:** Can only be called on the main thread.
678 /// - **Android:** Will always return `None`.
679 /// - **Wayland:** Can return `Borderless(None)` when there are no monitors.
680 #[inline]
681 pub fn fullscreen(&self) -> Option<Fullscreen> {
682 self.window.fullscreen()
683 }
684
685 /// Turn window decorations on or off.
686 ///
687 /// ## Platform-specific
688 ///
689 /// - **iOS / Android / Web:** Unsupported.
690 ///
691 /// [`setPrefersStatusBarHidden`]: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc
692 #[inline]
693 pub fn set_decorations(&self, decorations: bool) {
694 self.window.set_decorations(decorations)
695 }
696
697 /// Change whether or not the window will always be on top of other windows.
698 ///
699 /// ## Platform-specific
700 ///
701 /// - **iOS / Android / Web / Wayland:** Unsupported.
702 #[inline]
703 pub fn set_always_on_top(&self, always_on_top: bool) {
704 self.window.set_always_on_top(always_on_top)
705 }
706
707 /// Sets the window icon. On Windows and X11, this is typically the small icon in the top-left
708 /// corner of the titlebar.
709 ///
710 /// ## Platform-specific
711 ///
712 /// - **iOS / Android / Web / Wayland / macOS:** Unsupported.
713 ///
714 /// On Windows, this sets `ICON_SMALL`. The base size for a window icon is 16x16, but it's
715 /// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
716 ///
717 /// X11 has no universal guidelines for icon sizes, so you're at the whims of the WM. That
718 /// said, it's usually in the same ballpark as on Windows.
719 #[inline]
720 pub fn set_window_icon(&self, window_icon: Option<Icon>) {
721 self.window.set_window_icon(window_icon)
722 }
723
724 /// Sets location of IME candidate box in client area coordinates relative to the top left.
725 ///
726 /// ## Platform-specific
727 ///
728 /// - **iOS / Android / Web:** Unsupported.
729 #[inline]
730 pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
731 self.window.set_ime_position(position.into())
732 }
733
734 /// Requests user attention to the window, this has no effect if the application
735 /// is already focused. How requesting for user attention manifests is platform dependent,
736 /// see `UserAttentionType` for details.
737 ///
738 /// Providing `None` will unset the request for user attention. Unsetting the request for
739 /// user attention might not be done automatically by the WM when the window receives input.
740 ///
741 /// ## Platform-specific
742 ///
743 /// - **iOS / Android / Web / Wayland:** Unsupported.
744 /// - **macOS:** `None` has no effect.
745 /// - **X11:** Requests for user attention must be manually cleared.
746 #[inline]
747 pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
748 self.window.request_user_attention(request_type)
749 }
750}
751
752/// Cursor functions.
753impl Window {
754 /// Modifies the cursor icon of the window.
755 ///
756 /// ## Platform-specific
757 ///
758 /// - **iOS / Android:** Unsupported.
759 #[inline]
760 pub fn set_cursor_icon(&self, cursor: CursorIcon) {
761 self.window.set_cursor_icon(cursor);
762 }
763
764 /// Changes the position of the cursor in window coordinates.
765 ///
766 /// ## Platform-specific
767 ///
768 /// - **iOS / Android / Web / Wayland:** Always returns an [`ExternalError::NotSupported`].
769 #[inline]
770 pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
771 self.window.set_cursor_position(position.into())
772 }
773
774 /// Grabs the cursor, preventing it from leaving the window.
775 ///
776 /// There's no guarantee that the cursor will be hidden. You should
777 /// hide it by yourself if you want so.
778 ///
779 /// ## Platform-specific
780 ///
781 /// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward.
782 /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
783 #[inline]
784 pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
785 self.window.set_cursor_grab(grab)
786 }
787
788 /// Modifies the cursor's visibility.
789 ///
790 /// If `false`, this will hide the cursor. If `true`, this will show the cursor.
791 ///
792 /// ## Platform-specific
793 ///
794 /// - **Windows:** The cursor is only hidden within the confines of the window.
795 /// - **X11:** The cursor is only hidden within the confines of the window.
796 /// - **Wayland:** The cursor is only hidden within the confines of the window.
797 /// - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is
798 /// outside of the window.
799 /// - **iOS / Android:** Unsupported.
800 #[inline]
801 pub fn set_cursor_visible(&self, visible: bool) {
802 self.window.set_cursor_visible(visible)
803 }
804
805 /// Moves the window with the left mouse button until the button is released.
806 ///
807 /// There's no guarantee that this will work unless the left mouse button was pressed
808 /// immediately before this function is called.
809 ///
810 /// ## Platform-specific
811 ///
812 /// - **X11:** Un-grabs the cursor.
813 /// - **Wayland:** Requires the cursor to be inside the window to be dragged.
814 /// - **macOS:** May prevent the button release event to be triggered.
815 /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
816 #[inline]
817 pub fn drag_window(&self) -> Result<(), ExternalError> {
818 self.window.drag_window()
819 }
820}
821
822/// Monitor info functions.
823impl Window {
824 /// Returns the monitor on which the window currently resides.
825 ///
826 /// Returns `None` if current monitor can't be detected.
827 ///
828 /// ## Platform-specific
829 ///
830 /// **iOS:** Can only be called on the main thread.
831 #[inline]
832 pub fn current_monitor(&self) -> Option<MonitorHandle> {
833 self.window.current_monitor()
834 }
835
836 /// Returns the list of all the monitors available on the system.
837 ///
838 /// This is the same as `EventLoopWindowTarget::available_monitors`, and is provided for convenience.
839 ///
840 /// ## Platform-specific
841 ///
842 /// **iOS:** Can only be called on the main thread.
843 #[inline]
844 pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
845 self.window
846 .available_monitors()
847 .into_iter()
848 .map(|inner| MonitorHandle { inner })
849 }
850
851 /// Returns the primary monitor of the system.
852 ///
853 /// Returns `None` if it can't identify any monitor as a primary one.
854 ///
855 /// This is the same as `EventLoopWindowTarget::primary_monitor`, and is provided for convenience.
856 ///
857 /// ## Platform-specific
858 ///
859 /// **iOS:** Can only be called on the main thread.
860 /// **Wayland:** Always returns `None`.
861 #[inline]
862 pub fn primary_monitor(&self) -> Option<MonitorHandle> {
863 self.window.primary_monitor()
864 }
865}
866
867unsafe impl raw_window_handle::HasRawWindowHandle for Window {
868 /// Returns a `raw_window_handle::RawWindowHandle` for the Window
869 ///
870 /// ## Platform-specific
871 ///
872 /// - **Android:** Only available after receiving the Resumed event and before Suspended. *If you*
873 /// *try to get the handle outside of that period, this function will panic*!
874 fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
875 self.window.raw_window_handle()
876 }
877}
878
879/// Describes the appearance of the mouse cursor.
880#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
882pub enum CursorIcon {
883 /// The platform-dependent default cursor.
884 Default,
885 /// A simple crosshair.
886 Crosshair,
887 /// A hand (often used to indicate links in web browsers).
888 Hand,
889 /// Self explanatory.
890 Arrow,
891 /// Indicates something is to be moved.
892 Move,
893 /// Indicates text that may be selected or edited.
894 Text,
895 /// Program busy indicator.
896 Wait,
897 /// Help indicator (often rendered as a "?")
898 Help,
899 /// Progress indicator. Shows that processing is being done. But in contrast
900 /// with "Wait" the user may still interact with the program. Often rendered
901 /// as a spinning beach ball, or an arrow with a watch or hourglass.
902 Progress,
903
904 /// Cursor showing that something cannot be done.
905 NotAllowed,
906 ContextMenu,
907 Cell,
908 VerticalText,
909 Alias,
910 Copy,
911 NoDrop,
912 /// Indicates something can be grabbed.
913 Grab,
914 /// Indicates something is grabbed.
915 Grabbing,
916 AllScroll,
917 ZoomIn,
918 ZoomOut,
919
920 /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
921 /// is used when the movement starts from the south-east corner of the box.
922 EResize,
923 NResize,
924 NeResize,
925 NwResize,
926 SResize,
927 SeResize,
928 SwResize,
929 WResize,
930 EwResize,
931 NsResize,
932 NeswResize,
933 NwseResize,
934 ColResize,
935 RowResize,
936}
937
938impl Default for CursorIcon {
939 fn default() -> Self {
940 CursorIcon::Default
941 }
942}
943
944/// Fullscreen modes.
945#[derive(Clone, Debug, PartialEq)]
946pub enum Fullscreen {
947 Exclusive(VideoMode),
948
949 /// Providing `None` to `Borderless` will fullscreen on the current monitor.
950 Borderless(Option<MonitorHandle>),
951}
952
953#[derive(Clone, Copy, Debug, PartialEq)]
954pub enum Theme {
955 Light,
956 Dark,
957}
958
959/// ## Platform-specific
960///
961/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between `Critical` and `Informational`.
962#[derive(Debug, Clone, Copy, PartialEq)]
963pub enum UserAttentionType {
964 /// ## Platform-specific
965 /// - **macOS:** Bounces the dock icon until the application is in focus.
966 /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
967 Critical,
968 /// ## Platform-specific
969 /// - **macOS:** Bounces the dock icon once.
970 /// - **Windows:** Flashes the taskbar button until the application is in focus.
971 Informational,
972}
973
974impl Default for UserAttentionType {
975 fn default() -> Self {
976 UserAttentionType::Informational
977 }
978}