| 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 | |