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