Skip to main content

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    /// Sets the background color of the title bar using RGBA values (0.0-1.0 range).
257    ///
258    /// This is a convenience method that converts f64 RGBA values to the Windows Color format.
259    /// Supported starting with Windows 11 Build 22000.
260    fn set_title_bar_background_color(&self, r: f64, g: f64, b: f64, a: f64);
261
262    /// Enables or disables mouse and keyboard input to the specified window.
263    ///
264    /// A window must be enabled before it can be activated.
265    /// If an application has create a modal dialog box by disabling its owner window
266    /// (as described in [`WindowAttributesExtWindows::with_owner_window`]), the application must
267    /// enable the owner window before destroying the dialog box.
268    /// Otherwise, another window will receive the keyboard focus and be activated.
269    ///
270    /// If a child window is disabled, it is ignored when the system tries to determine which
271    /// window should receive mouse messages.
272    ///
273    /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow#remarks>
274    /// and <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#disabled-windows>
275    fn set_enable(&self, enabled: bool);
276
277    /// This sets `ICON_BIG`. A good ceiling here is 256x256.
278    fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
279
280    /// Whether to show or hide the window icon in the taskbar.
281    fn set_skip_taskbar(&self, skip: bool);
282
283    /// Shows or hides the background drop shadow for undecorated windows.
284    ///
285    /// Enabling the shadow causes a thin 1px line to appear on the top of the window.
286    fn set_undecorated_shadow(&self, shadow: bool);
287
288    /// Sets system-drawn backdrop type.
289    ///
290    /// Requires Windows 11 build 22523+.
291    fn set_system_backdrop(&self, backdrop_type: BackdropType);
292
293    /// Sets the color of the window border.
294    ///
295    /// Supported starting with Windows 11 Build 22000.
296    fn set_border_color(&self, color: Option<Color>);
297
298    /// Sets the background color of the title bar.
299    ///
300    /// Supported starting with Windows 11 Build 22000.
301    fn set_title_background_color(&self, color: Option<Color>);
302
303    /// Sets the color of the window title.
304    ///
305    /// Supported starting with Windows 11 Build 22000.
306    fn set_title_text_color(&self, color: Color);
307
308    /// Sets the preferred style of the window corners.
309    ///
310    /// Supported starting with Windows 11 Build 22000.
311    fn set_corner_preference(&self, preference: CornerPreference);
312
313    /// Cloaks the window such that it is not visible to the user. The window is still composed by DWM.
314    ///
315    /// A cloaked window will not appear on Taskbar. Cloaking is particularly useful when you want a
316    /// window to complete its UI layout, sizing, etc. without flickering in front of the user.
317    /// Not supported on Windows 7 and earlier.
318    fn set_cloaked(&self, cloaked: bool);
319
320    /// Get the raw window handle for this [`Window`] without checking for thread affinity.
321    ///
322    /// Window handles in Win32 have a property called "thread affinity" that ties them to their
323    /// origin thread. Some operations can only happen on the window's origin thread, while others
324    /// can be called from any thread. For example, [`SetWindowSubclass`] is not thread safe while
325    /// [`GetDC`] is thread safe.
326    ///
327    /// In Rust terms, the window handle is `Send` sometimes but `!Send` other times.
328    ///
329    /// Therefore, in order to avoid confusing threading errors, [`Window`] only returns the
330    /// window handle when the [`window_handle`] function is called from the thread that created
331    /// the window. In other cases, it returns an [`Unavailable`] error.
332    ///
333    /// However in some cases you may already know that you are using the window handle for
334    /// operations that are guaranteed to be thread-safe. In which case this function aims
335    /// to provide an escape hatch so these functions are still accessible from other threads.
336    ///
337    /// # Safety
338    ///
339    /// It is the responsibility of the user to only pass the window handle into thread-safe
340    /// Win32 APIs.
341    ///
342    /// [`SetWindowSubclass`]: https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-setwindowsubclass
343    /// [`GetDC`]: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc
344    /// [`Window`]: crate::window::Window
345    /// [`window_handle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/trait.HasWindowHandle.html#tymethod.window_handle
346    /// [`Unavailable`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/enum.HandleError.html#variant.Unavailable
347    ///
348    /// ## Example
349    ///
350    /// ```no_run
351    /// # use rio_window::window::Window;
352    /// # fn scope(window: Window) {
353    /// use std::thread;
354    /// use rio_window::platform::windows::WindowExtWindows;
355    /// use rio_window::raw_window_handle::HasWindowHandle;
356    ///
357    /// // We can get the window handle on the current thread.
358    /// let handle = window.window_handle().unwrap();
359    ///
360    /// // However, on another thread, we can't!
361    /// thread::spawn(move || {
362    ///     assert!(window.window_handle().is_err());
363    ///
364    ///     // We can use this function as an escape hatch.
365    ///     let handle = unsafe { window.window_handle_any_thread().unwrap() };
366    /// });
367    /// # }
368    /// ```
369    unsafe fn window_handle_any_thread(
370        &self,
371    ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError>;
372}
373
374impl WindowExtWindows for Window {
375    #[inline]
376    fn set_title_bar_background_color(&self, r: f64, g: f64, b: f64, _a: f64) {
377        // Convert from 0.0-1.0 range to 0-255 range
378        let r = (r * 255.0) as u8;
379        let g = (g * 255.0) as u8;
380        let b = (b * 255.0) as u8;
381        self.window
382            .set_title_background_color(Color::from_rgb(r, g, b))
383    }
384
385    #[inline]
386    fn set_enable(&self, enabled: bool) {
387        self.window.set_enable(enabled)
388    }
389
390    #[inline]
391    fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
392        self.window.set_taskbar_icon(taskbar_icon)
393    }
394
395    #[inline]
396    fn set_skip_taskbar(&self, skip: bool) {
397        self.window.set_skip_taskbar(skip)
398    }
399
400    #[inline]
401    fn set_undecorated_shadow(&self, shadow: bool) {
402        self.window.set_undecorated_shadow(shadow)
403    }
404
405    #[inline]
406    fn set_system_backdrop(&self, backdrop_type: BackdropType) {
407        self.window.set_system_backdrop(backdrop_type)
408    }
409
410    #[inline]
411    fn set_border_color(&self, color: Option<Color>) {
412        self.window.set_border_color(color.unwrap_or(Color::NONE))
413    }
414
415    #[inline]
416    fn set_title_background_color(&self, color: Option<Color>) {
417        // The windows docs don't mention NONE as a valid options but it works in practice and is
418        // useful to circumvent the Windows option "Show accent color on title bars and
419        // window borders"
420        self.window
421            .set_title_background_color(color.unwrap_or(Color::NONE))
422    }
423
424    #[inline]
425    fn set_title_text_color(&self, color: Color) {
426        self.window.set_title_text_color(color)
427    }
428
429    #[inline]
430    fn set_corner_preference(&self, preference: CornerPreference) {
431        self.window.set_corner_preference(preference)
432    }
433
434    #[inline]
435    fn set_cloaked(&self, cloaked: bool) {
436        self.window.set_cloaked(cloaked)
437    }
438
439    unsafe fn window_handle_any_thread(
440        &self,
441    ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
442        unsafe {
443            let handle = self.window.rwh_06_no_thread_check()?;
444
445            // SAFETY: The handle is valid in this context.
446            Ok(raw_window_handle::WindowHandle::borrow_raw(handle))
447        }
448    }
449}
450
451/// Additional methods for anything that dereference to [`Window`].
452///
453/// [`Window`]: crate::window::Window
454pub trait WindowBorrowExtWindows: Borrow<Window> + Sized {
455    /// Create an object that allows accessing the inner window handle in a thread-unsafe way.
456    ///
457    /// It is possible to call [`window_handle_any_thread`] to get around Windows's thread
458    /// affinity limitations. However, it may be desired to pass the [`Window`] into something
459    /// that requires the [`HasWindowHandle`] trait, while ignoring thread affinity limitations.
460    ///
461    /// This function wraps anything that implements `Borrow<Window>` into a structure that
462    /// uses the inner window handle as a mean of implementing [`HasWindowHandle`]. It wraps
463    /// `Window`, `&Window`, `Arc<Window>`, and other reference types.
464    ///
465    /// # Safety
466    ///
467    /// It is the responsibility of the user to only pass the window handle into thread-safe
468    /// Win32 APIs.
469    ///
470    /// [`Window`]: crate::window::Window
471    unsafe fn any_thread(self) -> AnyThread<Self> {
472        AnyThread(self)
473    }
474}
475
476impl<W: Borrow<Window> + Sized> WindowBorrowExtWindows for W {}
477
478/// Additional methods on `WindowAttributes` that are specific to Windows.
479#[allow(rustdoc::broken_intra_doc_links)]
480pub trait WindowAttributesExtWindows {
481    /// Set an owner to the window to be created. Can be used to create a dialog box, for example.
482    /// This only works when [`WindowAttributes::with_parent_window`] isn't called or set to `None`.
483    /// Can be used in combination with
484    /// [`WindowExtWindows::set_enable(false)`][WindowExtWindows::set_enable] on the owner
485    /// window to create a modal dialog box.
486    ///
487    /// From MSDN:
488    /// - An owned window is always above its owner in the z-order.
489    /// - The system automatically destroys an owned window when its owner is destroyed.
490    /// - An owned window is hidden when its owner is minimized.
491    ///
492    /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
493    fn with_owner_window(self, parent: HWND) -> Self;
494
495    /// Sets a menu on the window to be created.
496    ///
497    /// Parent and menu are mutually exclusive; a child window cannot have a menu!
498    ///
499    /// The menu must have been manually created beforehand with [`CreateMenu`] or similar.
500    ///
501    /// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how
502    /// the menus look. If you use this, it is recommended that you combine it with
503    /// `with_theme(Some(Theme::Light))` to avoid a jarring effect.
504    #[cfg_attr(
505        windows_platform,
506        doc = "[`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu"
507    )]
508    #[cfg_attr(
509        not(windows_platform),
510        doc = "[`CreateMenu`]: #only-available-on-windows"
511    )]
512    fn with_menu(self, menu: HMENU) -> Self;
513
514    /// This sets `ICON_BIG`. A good ceiling here is 256x256.
515    fn with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> Self;
516
517    /// This sets `WS_EX_NOREDIRECTIONBITMAP`.
518    fn with_no_redirection_bitmap(self, flag: bool) -> Self;
519
520    /// Enables or disables drag and drop support (enabled by default). Will interfere with other
521    /// crates that use multi-threaded COM API (`CoInitializeEx` with `COINIT_MULTITHREADED`
522    /// instead of `COINIT_APARTMENTTHREADED`) on the same thread. Note that winit may still
523    /// attempt to initialize COM API regardless of this option. Currently only fullscreen mode
524    /// does that, but there may be more in the future. If you need COM API with
525    /// `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.
526    fn with_drag_and_drop(self, flag: bool) -> Self;
527
528    /// Whether show or hide the window icon in the taskbar.
529    fn with_skip_taskbar(self, skip: bool) -> Self;
530
531    /// Customize the window class name.
532    fn with_class_name<S: Into<String>>(self, class_name: S) -> Self;
533
534    /// Shows or hides the background drop shadow for undecorated windows.
535    ///
536    /// The shadow is hidden by default.
537    /// Enabling the shadow causes a thin 1px line to appear on the top of the window.
538    fn with_undecorated_shadow(self, shadow: bool) -> Self;
539
540    /// Sets system-drawn backdrop type.
541    ///
542    /// Requires Windows 11 build 22523+.
543    fn with_system_backdrop(self, backdrop_type: BackdropType) -> Self;
544
545    /// This sets or removes `WS_CLIPCHILDREN` style.
546    fn with_clip_children(self, flag: bool) -> Self;
547
548    /// Sets the color of the window border.
549    ///
550    /// Supported starting with Windows 11 Build 22000.
551    fn with_border_color(self, color: Option<Color>) -> Self;
552
553    /// Sets the background color of the title bar.
554    ///
555    /// Supported starting with Windows 11 Build 22000.
556    fn with_title_background_color(self, color: Option<Color>) -> Self;
557
558    /// Sets the color of the window title.
559    ///
560    /// Supported starting with Windows 11 Build 22000.
561    fn with_title_text_color(self, color: Color) -> Self;
562
563    /// Sets the preferred style of the window corners.
564    ///
565    /// Supported starting with Windows 11 Build 22000.
566    fn with_corner_preference(self, corners: CornerPreference) -> Self;
567
568    /// Cloaks the window such that it is not visible to the user. The window is still composed by DWM.
569    ///
570    /// Not supported on Windows 7 and earlier.
571    fn with_cloaked(self, cloaked: bool) -> Self;
572}
573
574impl WindowAttributesExtWindows for WindowAttributes {
575    #[inline]
576    fn with_owner_window(mut self, parent: HWND) -> Self {
577        self.platform_specific.owner = Some(parent);
578        self
579    }
580
581    #[inline]
582    fn with_menu(mut self, menu: HMENU) -> Self {
583        self.platform_specific.menu = Some(menu);
584        self
585    }
586
587    #[inline]
588    fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> Self {
589        self.platform_specific.taskbar_icon = taskbar_icon;
590        self
591    }
592
593    #[inline]
594    fn with_no_redirection_bitmap(mut self, flag: bool) -> Self {
595        self.platform_specific.no_redirection_bitmap = flag;
596        self
597    }
598
599    #[inline]
600    fn with_drag_and_drop(mut self, flag: bool) -> Self {
601        self.platform_specific.drag_and_drop = flag;
602        self
603    }
604
605    #[inline]
606    fn with_skip_taskbar(mut self, skip: bool) -> Self {
607        self.platform_specific.skip_taskbar = skip;
608        self
609    }
610
611    #[inline]
612    fn with_class_name<S: Into<String>>(mut self, class_name: S) -> Self {
613        self.platform_specific.class_name = class_name.into();
614        self
615    }
616
617    #[inline]
618    fn with_undecorated_shadow(mut self, shadow: bool) -> Self {
619        self.platform_specific.decoration_shadow = shadow;
620        self
621    }
622
623    #[inline]
624    fn with_system_backdrop(mut self, backdrop_type: BackdropType) -> Self {
625        self.platform_specific.backdrop_type = backdrop_type;
626        self
627    }
628
629    #[inline]
630    fn with_clip_children(mut self, flag: bool) -> Self {
631        self.platform_specific.clip_children = flag;
632        self
633    }
634
635    #[inline]
636    fn with_border_color(mut self, color: Option<Color>) -> Self {
637        self.platform_specific.border_color = Some(color.unwrap_or(Color::NONE));
638        self
639    }
640
641    #[inline]
642    fn with_title_background_color(mut self, color: Option<Color>) -> Self {
643        self.platform_specific.title_background_color =
644            Some(color.unwrap_or(Color::NONE));
645        self
646    }
647
648    #[inline]
649    fn with_title_text_color(mut self, color: Color) -> Self {
650        self.platform_specific.title_text_color = Some(color);
651        self
652    }
653
654    #[inline]
655    fn with_corner_preference(mut self, corners: CornerPreference) -> Self {
656        self.platform_specific.corner_preference = Some(corners);
657        self
658    }
659
660    #[inline]
661    fn with_cloaked(mut self, cloaked: bool) -> Self {
662        self.platform_specific.cloaked = cloaked;
663        self
664    }
665}
666
667/// Additional methods on `MonitorHandle` that are specific to Windows.
668pub trait MonitorHandleExtWindows {
669    /// Returns the name of the monitor adapter specific to the Win32 API.
670    fn native_id(&self) -> String;
671
672    /// Returns the handle of the monitor - `HMONITOR`.
673    fn hmonitor(&self) -> HMONITOR;
674}
675
676impl MonitorHandleExtWindows for MonitorHandle {
677    #[inline]
678    fn native_id(&self) -> String {
679        self.inner.native_identifier()
680    }
681
682    #[inline]
683    fn hmonitor(&self) -> HMONITOR {
684        self.inner.hmonitor()
685    }
686}
687
688/// Additional methods on `DeviceId` that are specific to Windows.
689pub trait DeviceIdExtWindows {
690    /// Returns an identifier that persistently refers to this specific device.
691    ///
692    /// Will return `None` if the device is no longer available.
693    fn persistent_identifier(&self) -> Option<String>;
694}
695
696impl DeviceIdExtWindows for DeviceId {
697    #[inline]
698    fn persistent_identifier(&self) -> Option<String> {
699        self.0.persistent_identifier()
700    }
701}
702
703/// Additional methods on `Icon` that are specific to Windows.
704pub trait IconExtWindows: Sized {
705    /// Create an icon from a file path.
706    ///
707    /// Specify `size` to load a specific icon size from the file, or `None` to load the default
708    /// icon size from the file.
709    ///
710    /// In cases where the specified size does not exist in the file, Windows may perform scaling
711    /// to get an icon of the desired size.
712    fn from_path<P: AsRef<Path>>(
713        path: P,
714        size: Option<PhysicalSize<u32>>,
715    ) -> Result<Self, BadIcon>;
716
717    /// Create an icon from a resource embedded in this executable or library.
718    ///
719    /// Specify `size` to load a specific icon size from the file, or `None` to load the default
720    /// icon size from the file.
721    ///
722    /// In cases where the specified size does not exist in the file, Windows may perform scaling
723    /// to get an icon of the desired size.
724    fn from_resource(
725        ordinal: u16,
726        size: Option<PhysicalSize<u32>>,
727    ) -> Result<Self, BadIcon>;
728}
729
730impl IconExtWindows for Icon {
731    fn from_path<P: AsRef<Path>>(
732        path: P,
733        size: Option<PhysicalSize<u32>>,
734    ) -> Result<Self, BadIcon> {
735        let win_icon = crate::platform_impl::WinIcon::from_path(path, size)?;
736        Ok(Icon { inner: win_icon })
737    }
738
739    fn from_resource(
740        ordinal: u16,
741        size: Option<PhysicalSize<u32>>,
742    ) -> Result<Self, BadIcon> {
743        let win_icon = crate::platform_impl::WinIcon::from_resource(ordinal, size)?;
744        Ok(Icon { inner: win_icon })
745    }
746}