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