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