rio_window/platform/windows.rs
1//! # Windows
2//!
3//! The supported OS version is Windows 7 or higher, though Windows 10 is
4//! tested regularly.
5use std::borrow::Borrow;
6use std::ffi::c_void;
7use std::path::Path;
8
9use crate::dpi::PhysicalSize;
10use crate::event::DeviceId;
11use crate::event_loop::EventLoopBuilder;
12use crate::monitor::MonitorHandle;
13use crate::window::{BadIcon, Icon, Window, WindowAttributes};
14
15/// Window Handle type used by Win32 API
16pub type HWND = *mut c_void;
17/// Menu Handle type used by Win32 API
18pub type HMENU = *mut c_void;
19/// Monitor Handle type used by Win32 API
20pub type HMONITOR = *mut c_void;
21
22/// Describes a system-drawn backdrop material of a window.
23///
24/// For a detailed explanation, see [`DWM_SYSTEMBACKDROP_TYPE docs`].
25///
26/// [`DWM_SYSTEMBACKDROP_TYPE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_systembackdrop_type
27#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum BackdropType {
29 /// Corresponds to `DWMSBT_AUTO`.
30 ///
31 /// Usually draws a default backdrop effect on the title bar.
32 #[default]
33 Auto = 0,
34
35 /// Corresponds to `DWMSBT_NONE`.
36 None = 1,
37
38 /// Corresponds to `DWMSBT_MAINWINDOW`.
39 ///
40 /// Draws the Mica backdrop material.
41 MainWindow = 2,
42
43 /// Corresponds to `DWMSBT_TRANSIENTWINDOW`.
44 ///
45 /// Draws the Background Acrylic backdrop material.
46 TransientWindow = 3,
47
48 /// Corresponds to `DWMSBT_TABBEDWINDOW`.
49 ///
50 /// Draws the Alt Mica backdrop material.
51 TabbedWindow = 4,
52}
53
54/// Describes a color used by Windows
55#[repr(transparent)]
56#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
57pub struct Color(u32);
58
59impl Color {
60 // Special constant only valid for the window border and therefore modeled using Option<Color>
61 // for user facing code
62 const NONE: Color = Color(0xfffffffe);
63 /// Use the system's default color
64 pub const SYSTEM_DEFAULT: Color = Color(0xffffffff);
65
66 /// Create a new color from the given RGB values
67 pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
68 Self((r as u32) | ((g as u32) << 8) | ((b as u32) << 16))
69 }
70}
71
72impl Default for Color {
73 fn default() -> Self {
74 Self::SYSTEM_DEFAULT
75 }
76}
77
78/// Describes how the corners of a window should look like.
79///
80/// For a detailed explanation, see [`DWM_WINDOW_CORNER_PREFERENCE docs`].
81///
82/// [`DWM_WINDOW_CORNER_PREFERENCE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference
83#[repr(i32)]
84#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
85pub enum CornerPreference {
86 /// Corresponds to `DWMWCP_DEFAULT`.
87 ///
88 /// Let the system decide when to round window corners.
89 #[default]
90 Default = 0,
91
92 /// Corresponds to `DWMWCP_DONOTROUND`.
93 ///
94 /// Never round window corners.
95 DoNotRound = 1,
96
97 /// Corresponds to `DWMWCP_ROUND`.
98 ///
99 /// Round the corners, if appropriate.
100 Round = 2,
101
102 /// Corresponds to `DWMWCP_ROUNDSMALL`.
103 ///
104 /// Round the corners if appropriate, with a small radius.
105 RoundSmall = 3,
106}
107
108/// A wrapper around a [`Window`] that ignores thread-specific window handle limitations.
109///
110/// See [`WindowBorrowExtWindows::any_thread`] for more information.
111#[derive(Debug)]
112pub struct AnyThread<W>(W);
113
114impl<W: Borrow<Window>> AnyThread<W> {
115 /// Get a reference to the inner window.
116 #[inline]
117 pub fn get_ref(&self) -> &Window {
118 self.0.borrow()
119 }
120
121 /// Get a reference to the inner object.
122 #[inline]
123 pub fn inner(&self) -> &W {
124 &self.0
125 }
126
127 /// Unwrap and get the inner window.
128 #[inline]
129 pub fn into_inner(self) -> W {
130 self.0
131 }
132}
133
134impl<W: Borrow<Window>> AsRef<Window> for AnyThread<W> {
135 fn as_ref(&self) -> &Window {
136 self.get_ref()
137 }
138}
139
140impl<W: Borrow<Window>> Borrow<Window> for AnyThread<W> {
141 fn borrow(&self) -> &Window {
142 self.get_ref()
143 }
144}
145
146impl<W: Borrow<Window>> std::ops::Deref for AnyThread<W> {
147 type Target = Window;
148
149 fn deref(&self) -> &Self::Target {
150 self.get_ref()
151 }
152}
153
154impl<W: Borrow<Window>> raw_window_handle::HasWindowHandle for AnyThread<W> {
155 fn window_handle(
156 &self,
157 ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
158 // SAFETY: The top level user has asserted this is only used safely.
159 unsafe { self.get_ref().window_handle_any_thread() }
160 }
161}
162
163/// Additional methods on `EventLoop` that are specific to Windows.
164pub trait EventLoopBuilderExtWindows {
165 /// Whether to allow the event loop to be created off of the main thread.
166 ///
167 /// By default, the window is only allowed to be created on the main
168 /// thread, to make platform compatibility easier.
169 ///
170 /// # `Window` caveats
171 ///
172 /// Note that any `Window` created on the new thread will be destroyed when the thread
173 /// terminates. Attempting to use a `Window` after its parent thread terminates has
174 /// unspecified, although explicitly not undefined, behavior.
175 fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
176
177 /// Whether to enable process-wide DPI awareness.
178 ///
179 /// By default, `winit` will attempt to enable process-wide DPI awareness. If
180 /// that's undesirable, you can disable it with this function.
181 ///
182 /// # Example
183 ///
184 /// Disable process-wide DPI awareness.
185 ///
186 /// ```
187 /// use rio_window::event_loop::EventLoopBuilder;
188 /// #[cfg(target_os = "windows")]
189 /// use rio_window::platform::windows::EventLoopBuilderExtWindows;
190 ///
191 /// let mut builder = EventLoopBuilder::new();
192 /// #[cfg(target_os = "windows")]
193 /// builder.with_dpi_aware(false);
194 /// # if false { // We can't test this part
195 /// let event_loop = builder.build();
196 /// # }
197 /// ```
198 fn with_dpi_aware(&mut self, dpi_aware: bool) -> &mut Self;
199
200 /// A callback to be executed before dispatching a win32 message to the window procedure.
201 /// Return true to disable winit's internal message dispatching.
202 ///
203 /// # Example
204 ///
205 /// ```
206 /// # use windows_sys::Win32::UI::WindowsAndMessaging::{ACCEL, CreateAcceleratorTableW, TranslateAcceleratorW, DispatchMessageW, TranslateMessage, MSG};
207 /// use rio_window::event_loop::EventLoopBuilder;
208 /// #[cfg(target_os = "windows")]
209 /// use rio_window::platform::windows::EventLoopBuilderExtWindows;
210 ///
211 /// let mut builder = EventLoopBuilder::new();
212 /// #[cfg(target_os = "windows")]
213 /// builder.with_msg_hook(|msg|{
214 /// let msg = msg as *const MSG;
215 /// # let accels: Vec<ACCEL> = Vec::new();
216 /// let translated = unsafe {
217 /// TranslateAcceleratorW(
218 /// (*msg).hwnd,
219 /// CreateAcceleratorTableW(accels.as_ptr() as _, 1),
220 /// msg,
221 /// ) == 1
222 /// };
223 /// translated
224 /// });
225 /// ```
226 fn with_msg_hook<F>(&mut self, callback: F) -> &mut Self
227 where
228 F: FnMut(*const c_void) -> bool + 'static;
229}
230
231impl<T> EventLoopBuilderExtWindows for EventLoopBuilder<T> {
232 #[inline]
233 fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
234 self.platform_specific.any_thread = any_thread;
235 self
236 }
237
238 #[inline]
239 fn with_dpi_aware(&mut self, dpi_aware: bool) -> &mut Self {
240 self.platform_specific.dpi_aware = dpi_aware;
241 self
242 }
243
244 #[inline]
245 fn with_msg_hook<F>(&mut self, callback: F) -> &mut Self
246 where
247 F: FnMut(*const c_void) -> bool + 'static,
248 {
249 self.platform_specific.msg_hook = Some(Box::new(callback));
250 self
251 }
252}
253
254/// Additional methods on `Window` that are specific to Windows.
255pub trait WindowExtWindows {
256 /// Enables or disables mouse and keyboard input to the specified window.
257 ///
258 /// A window must be enabled before it can be activated.
259 /// If an application has create a modal dialog box by disabling its owner window
260 /// (as described in [`WindowAttributesExtWindows::with_owner_window`]), the application must
261 /// enable the owner window before destroying the dialog box.
262 /// Otherwise, another window will receive the keyboard focus and be activated.
263 ///
264 /// If a child window is disabled, it is ignored when the system tries to determine which
265 /// window should receive mouse messages.
266 ///
267 /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow#remarks>
268 /// and <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#disabled-windows>
269 fn set_enable(&self, enabled: bool);
270
271 /// This sets `ICON_BIG`. A good ceiling here is 256x256.
272 fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
273
274 /// Whether to show or hide the window icon in the taskbar.
275 fn set_skip_taskbar(&self, skip: bool);
276
277 /// Shows or hides the background drop shadow for undecorated windows.
278 ///
279 /// Enabling the shadow causes a thin 1px line to appear on the top of the window.
280 fn set_undecorated_shadow(&self, shadow: bool);
281
282 /// Sets system-drawn backdrop type.
283 ///
284 /// Requires Windows 11 build 22523+.
285 fn set_system_backdrop(&self, backdrop_type: BackdropType);
286
287 /// Sets the color of the window border.
288 ///
289 /// Supported starting with Windows 11 Build 22000.
290 fn set_border_color(&self, color: Option<Color>);
291
292 /// Sets the background color of the title bar.
293 ///
294 /// Supported starting with Windows 11 Build 22000.
295 fn set_title_background_color(&self, color: Option<Color>);
296
297 /// Sets the color of the window title.
298 ///
299 /// Supported starting with Windows 11 Build 22000.
300 fn set_title_text_color(&self, color: Color);
301
302 /// Sets the preferred style of the window corners.
303 ///
304 /// Supported starting with Windows 11 Build 22000.
305 fn set_corner_preference(&self, preference: CornerPreference);
306
307 /// Cloaks the window such that it is not visible to the user. The window is still composed by DWM.
308 ///
309 /// A cloaked window will not appear on Taskbar. Cloaking is particularly useful when you want a
310 /// window to complete its UI layout, sizing, etc. without flickering in front of the user.
311 /// Not supported on Windows 7 and earlier.
312 fn set_cloaked(&self, cloaked: bool);
313
314 /// Get the raw window handle for this [`Window`] without checking for thread affinity.
315 ///
316 /// Window handles in Win32 have a property called "thread affinity" that ties them to their
317 /// origin thread. Some operations can only happen on the window's origin thread, while others
318 /// can be called from any thread. For example, [`SetWindowSubclass`] is not thread safe while
319 /// [`GetDC`] is thread safe.
320 ///
321 /// In Rust terms, the window handle is `Send` sometimes but `!Send` other times.
322 ///
323 /// Therefore, in order to avoid confusing threading errors, [`Window`] only returns the
324 /// window handle when the [`window_handle`] function is called from the thread that created
325 /// the window. In other cases, it returns an [`Unavailable`] error.
326 ///
327 /// However in some cases you may already know that you are using the window handle for
328 /// operations that are guaranteed to be thread-safe. In which case this function aims
329 /// to provide an escape hatch so these functions are still accessible from other threads.
330 ///
331 /// # Safety
332 ///
333 /// It is the responsibility of the user to only pass the window handle into thread-safe
334 /// Win32 APIs.
335 ///
336 /// [`SetWindowSubclass`]: https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-setwindowsubclass
337 /// [`GetDC`]: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc
338 /// [`Window`]: crate::window::Window
339 /// [`window_handle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/trait.HasWindowHandle.html#tymethod.window_handle
340 /// [`Unavailable`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/enum.HandleError.html#variant.Unavailable
341 ///
342 /// ## Example
343 ///
344 /// ```no_run
345 /// # use rio_window::window::Window;
346 /// # fn scope(window: Window) {
347 /// use std::thread;
348 /// use rio_window::platform::windows::WindowExtWindows;
349 /// use rio_window::raw_window_handle::HasWindowHandle;
350 ///
351 /// // We can get the window handle on the current thread.
352 /// let handle = window.window_handle().unwrap();
353 ///
354 /// // However, on another thread, we can't!
355 /// thread::spawn(move || {
356 /// assert!(window.window_handle().is_err());
357 ///
358 /// // We can use this function as an escape hatch.
359 /// let handle = unsafe { window.window_handle_any_thread().unwrap() };
360 /// });
361 /// # }
362 /// ```
363 unsafe fn window_handle_any_thread(
364 &self,
365 ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError>;
366}
367
368impl WindowExtWindows for Window {
369 #[inline]
370 fn set_enable(&self, enabled: bool) {
371 self.window.set_enable(enabled)
372 }
373
374 #[inline]
375 fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
376 self.window.set_taskbar_icon(taskbar_icon)
377 }
378
379 #[inline]
380 fn set_skip_taskbar(&self, skip: bool) {
381 self.window.set_skip_taskbar(skip)
382 }
383
384 #[inline]
385 fn set_undecorated_shadow(&self, shadow: bool) {
386 self.window.set_undecorated_shadow(shadow)
387 }
388
389 #[inline]
390 fn set_system_backdrop(&self, backdrop_type: BackdropType) {
391 self.window.set_system_backdrop(backdrop_type)
392 }
393
394 #[inline]
395 fn set_border_color(&self, color: Option<Color>) {
396 self.window.set_border_color(color.unwrap_or(Color::NONE))
397 }
398
399 #[inline]
400 fn set_title_background_color(&self, color: Option<Color>) {
401 // The windows docs don't mention NONE as a valid options but it works in practice and is
402 // useful to circumvent the Windows option "Show accent color on title bars and
403 // window borders"
404 self.window
405 .set_title_background_color(color.unwrap_or(Color::NONE))
406 }
407
408 #[inline]
409 fn set_title_text_color(&self, color: Color) {
410 self.window.set_title_text_color(color)
411 }
412
413 #[inline]
414 fn set_corner_preference(&self, preference: CornerPreference) {
415 self.window.set_corner_preference(preference)
416 }
417
418 #[inline]
419 fn set_cloaked(&self, cloaked: bool) {
420 self.window.set_cloaked(cloaked)
421 }
422
423 unsafe fn window_handle_any_thread(
424 &self,
425 ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
426 unsafe {
427 let handle = self.window.rwh_06_no_thread_check()?;
428
429 // SAFETY: The handle is valid in this context.
430 Ok(raw_window_handle::WindowHandle::borrow_raw(handle))
431 }
432 }
433}
434
435/// Additional methods for anything that dereference to [`Window`].
436///
437/// [`Window`]: crate::window::Window
438pub trait WindowBorrowExtWindows: Borrow<Window> + Sized {
439 /// Create an object that allows accessing the inner window handle in a thread-unsafe way.
440 ///
441 /// It is possible to call [`window_handle_any_thread`] to get around Windows's thread
442 /// affinity limitations. However, it may be desired to pass the [`Window`] into something
443 /// that requires the [`HasWindowHandle`] trait, while ignoring thread affinity limitations.
444 ///
445 /// This function wraps anything that implements `Borrow<Window>` into a structure that
446 /// uses the inner window handle as a mean of implementing [`HasWindowHandle`]. It wraps
447 /// `Window`, `&Window`, `Arc<Window>`, and other reference types.
448 ///
449 /// # Safety
450 ///
451 /// It is the responsibility of the user to only pass the window handle into thread-safe
452 /// Win32 APIs.
453 ///
454 /// [`Window`]: crate::window::Window
455 unsafe fn any_thread(self) -> AnyThread<Self> {
456 AnyThread(self)
457 }
458}
459
460impl<W: Borrow<Window> + Sized> WindowBorrowExtWindows for W {}
461
462/// Additional methods on `WindowAttributes` that are specific to Windows.
463#[allow(rustdoc::broken_intra_doc_links)]
464pub trait WindowAttributesExtWindows {
465 /// Set an owner to the window to be created. Can be used to create a dialog box, for example.
466 /// This only works when [`WindowAttributes::with_parent_window`] isn't called or set to `None`.
467 /// Can be used in combination with
468 /// [`WindowExtWindows::set_enable(false)`][WindowExtWindows::set_enable] on the owner
469 /// window to create a modal dialog box.
470 ///
471 /// From MSDN:
472 /// - An owned window is always above its owner in the z-order.
473 /// - The system automatically destroys an owned window when its owner is destroyed.
474 /// - An owned window is hidden when its owner is minimized.
475 ///
476 /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
477 fn with_owner_window(self, parent: HWND) -> Self;
478
479 /// Sets a menu on the window to be created.
480 ///
481 /// Parent and menu are mutually exclusive; a child window cannot have a menu!
482 ///
483 /// The menu must have been manually created beforehand with [`CreateMenu`] or similar.
484 ///
485 /// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how
486 /// the menus look. If you use this, it is recommended that you combine it with
487 /// `with_theme(Some(Theme::Light))` to avoid a jarring effect.
488 #[cfg_attr(
489 windows_platform,
490 doc = "[`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu"
491 )]
492 #[cfg_attr(
493 not(windows_platform),
494 doc = "[`CreateMenu`]: #only-available-on-windows"
495 )]
496 fn with_menu(self, menu: HMENU) -> Self;
497
498 /// This sets `ICON_BIG`. A good ceiling here is 256x256.
499 fn with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> Self;
500
501 /// This sets `WS_EX_NOREDIRECTIONBITMAP`.
502 fn with_no_redirection_bitmap(self, flag: bool) -> Self;
503
504 /// Enables or disables drag and drop support (enabled by default). Will interfere with other
505 /// crates that use multi-threaded COM API (`CoInitializeEx` with `COINIT_MULTITHREADED`
506 /// instead of `COINIT_APARTMENTTHREADED`) on the same thread. Note that winit may still
507 /// attempt to initialize COM API regardless of this option. Currently only fullscreen mode
508 /// does that, but there may be more in the future. If you need COM API with
509 /// `COINIT_MULTITHREADED` you must initialize it before calling any winit functions. See <https://docs.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize#remarks> for more information.
510 fn with_drag_and_drop(self, flag: bool) -> Self;
511
512 /// Whether show or hide the window icon in the taskbar.
513 fn with_skip_taskbar(self, skip: bool) -> Self;
514
515 /// Customize the window class name.
516 fn with_class_name<S: Into<String>>(self, class_name: S) -> Self;
517
518 /// Shows or hides the background drop shadow for undecorated windows.
519 ///
520 /// The shadow is hidden by default.
521 /// Enabling the shadow causes a thin 1px line to appear on the top of the window.
522 fn with_undecorated_shadow(self, shadow: bool) -> Self;
523
524 /// Sets system-drawn backdrop type.
525 ///
526 /// Requires Windows 11 build 22523+.
527 fn with_system_backdrop(self, backdrop_type: BackdropType) -> Self;
528
529 /// This sets or removes `WS_CLIPCHILDREN` style.
530 fn with_clip_children(self, flag: bool) -> Self;
531
532 /// Sets the color of the window border.
533 ///
534 /// Supported starting with Windows 11 Build 22000.
535 fn with_border_color(self, color: Option<Color>) -> Self;
536
537 /// Sets the background color of the title bar.
538 ///
539 /// Supported starting with Windows 11 Build 22000.
540 fn with_title_background_color(self, color: Option<Color>) -> Self;
541
542 /// Sets the color of the window title.
543 ///
544 /// Supported starting with Windows 11 Build 22000.
545 fn with_title_text_color(self, color: Color) -> Self;
546
547 /// Sets the preferred style of the window corners.
548 ///
549 /// Supported starting with Windows 11 Build 22000.
550 fn with_corner_preference(self, corners: CornerPreference) -> Self;
551
552 /// Cloaks the window such that it is not visible to the user. The window is still composed by DWM.
553 ///
554 /// Not supported on Windows 7 and earlier.
555 fn with_cloaked(self, cloaked: bool) -> Self;
556}
557
558impl WindowAttributesExtWindows for WindowAttributes {
559 #[inline]
560 fn with_owner_window(mut self, parent: HWND) -> Self {
561 self.platform_specific.owner = Some(parent);
562 self
563 }
564
565 #[inline]
566 fn with_menu(mut self, menu: HMENU) -> Self {
567 self.platform_specific.menu = Some(menu);
568 self
569 }
570
571 #[inline]
572 fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> Self {
573 self.platform_specific.taskbar_icon = taskbar_icon;
574 self
575 }
576
577 #[inline]
578 fn with_no_redirection_bitmap(mut self, flag: bool) -> Self {
579 self.platform_specific.no_redirection_bitmap = flag;
580 self
581 }
582
583 #[inline]
584 fn with_drag_and_drop(mut self, flag: bool) -> Self {
585 self.platform_specific.drag_and_drop = flag;
586 self
587 }
588
589 #[inline]
590 fn with_skip_taskbar(mut self, skip: bool) -> Self {
591 self.platform_specific.skip_taskbar = skip;
592 self
593 }
594
595 #[inline]
596 fn with_class_name<S: Into<String>>(mut self, class_name: S) -> Self {
597 self.platform_specific.class_name = class_name.into();
598 self
599 }
600
601 #[inline]
602 fn with_undecorated_shadow(mut self, shadow: bool) -> Self {
603 self.platform_specific.decoration_shadow = shadow;
604 self
605 }
606
607 #[inline]
608 fn with_system_backdrop(mut self, backdrop_type: BackdropType) -> Self {
609 self.platform_specific.backdrop_type = backdrop_type;
610 self
611 }
612
613 #[inline]
614 fn with_clip_children(mut self, flag: bool) -> Self {
615 self.platform_specific.clip_children = flag;
616 self
617 }
618
619 #[inline]
620 fn with_border_color(mut self, color: Option<Color>) -> Self {
621 self.platform_specific.border_color = Some(color.unwrap_or(Color::NONE));
622 self
623 }
624
625 #[inline]
626 fn with_title_background_color(mut self, color: Option<Color>) -> Self {
627 self.platform_specific.title_background_color =
628 Some(color.unwrap_or(Color::NONE));
629 self
630 }
631
632 #[inline]
633 fn with_title_text_color(mut self, color: Color) -> Self {
634 self.platform_specific.title_text_color = Some(color);
635 self
636 }
637
638 #[inline]
639 fn with_corner_preference(mut self, corners: CornerPreference) -> Self {
640 self.platform_specific.corner_preference = Some(corners);
641 self
642 }
643
644 #[inline]
645 fn with_cloaked(mut self, cloaked: bool) -> Self {
646 self.platform_specific.cloaked = cloaked;
647 self
648 }
649}
650
651/// Additional methods on `MonitorHandle` that are specific to Windows.
652pub trait MonitorHandleExtWindows {
653 /// Returns the name of the monitor adapter specific to the Win32 API.
654 fn native_id(&self) -> String;
655
656 /// Returns the handle of the monitor - `HMONITOR`.
657 fn hmonitor(&self) -> HMONITOR;
658}
659
660impl MonitorHandleExtWindows for MonitorHandle {
661 #[inline]
662 fn native_id(&self) -> String {
663 self.inner.native_identifier()
664 }
665
666 #[inline]
667 fn hmonitor(&self) -> HMONITOR {
668 self.inner.hmonitor()
669 }
670}
671
672/// Additional methods on `DeviceId` that are specific to Windows.
673pub trait DeviceIdExtWindows {
674 /// Returns an identifier that persistently refers to this specific device.
675 ///
676 /// Will return `None` if the device is no longer available.
677 fn persistent_identifier(&self) -> Option<String>;
678}
679
680impl DeviceIdExtWindows for DeviceId {
681 #[inline]
682 fn persistent_identifier(&self) -> Option<String> {
683 self.0.persistent_identifier()
684 }
685}
686
687/// Additional methods on `Icon` that are specific to Windows.
688pub trait IconExtWindows: Sized {
689 /// Create an icon from a file path.
690 ///
691 /// Specify `size` to load a specific icon size from the file, or `None` to load the default
692 /// icon size from the file.
693 ///
694 /// In cases where the specified size does not exist in the file, Windows may perform scaling
695 /// to get an icon of the desired size.
696 fn from_path<P: AsRef<Path>>(
697 path: P,
698 size: Option<PhysicalSize<u32>>,
699 ) -> Result<Self, BadIcon>;
700
701 /// Create an icon from a resource embedded in this executable or library.
702 ///
703 /// Specify `size` to load a specific icon size from the file, or `None` to load the default
704 /// icon size from the file.
705 ///
706 /// In cases where the specified size does not exist in the file, Windows may perform scaling
707 /// to get an icon of the desired size.
708 fn from_resource(
709 ordinal: u16,
710 size: Option<PhysicalSize<u32>>,
711 ) -> Result<Self, BadIcon>;
712}
713
714impl IconExtWindows for Icon {
715 fn from_path<P: AsRef<Path>>(
716 path: P,
717 size: Option<PhysicalSize<u32>>,
718 ) -> Result<Self, BadIcon> {
719 let win_icon = crate::platform_impl::WinIcon::from_path(path, size)?;
720 Ok(Icon { inner: win_icon })
721 }
722
723 fn from_resource(
724 ordinal: u16,
725 size: Option<PhysicalSize<u32>>,
726 ) -> Result<Self, BadIcon> {
727 let win_icon = crate::platform_impl::WinIcon::from_resource(ordinal, size)?;
728 Ok(Icon { inner: win_icon })
729 }
730}