1 #![cfg(target_os = "windows")] 2 3 use std::os::raw::c_void; 4 use std::path::Path; 5 6 use libc; 7 use winapi::shared::minwindef::WORD; 8 use winapi::shared::windef::HWND; 9 10 use crate::{ 11 dpi::PhysicalSize, 12 event::DeviceId, 13 event_loop::EventLoop, 14 monitor::MonitorHandle, 15 platform_impl::{EventLoop as WindowsEventLoop, WinIcon}, 16 window::{BadIcon, Icon, Window, WindowBuilder}, 17 }; 18 19 /// Additional methods on `EventLoop` that are specific to Windows. 20 pub trait EventLoopExtWindows { 21 /// Creates an event loop off of the main thread. 22 /// 23 /// # `Window` caveats 24 /// 25 /// Note that any `Window` created on the new thread will be destroyed when the thread 26 /// terminates. Attempting to use a `Window` after its parent thread terminates has 27 /// unspecified, although explicitly not undefined, behavior. new_any_thread() -> Self where Self: Sized28 fn new_any_thread() -> Self 29 where 30 Self: Sized; 31 32 /// By default, winit on Windows will attempt to enable process-wide DPI awareness. If that's 33 /// undesirable, you can create an `EventLoop` using this function instead. new_dpi_unaware() -> Self where Self: Sized34 fn new_dpi_unaware() -> Self 35 where 36 Self: Sized; 37 38 /// Creates a DPI-unaware event loop off of the main thread. 39 /// 40 /// The `Window` caveats in [`new_any_thread`](EventLoopExtWindows::new_any_thread) also apply here. new_dpi_unaware_any_thread() -> Self where Self: Sized41 fn new_dpi_unaware_any_thread() -> Self 42 where 43 Self: Sized; 44 } 45 46 impl<T> EventLoopExtWindows for EventLoop<T> { 47 #[inline] new_any_thread() -> Self48 fn new_any_thread() -> Self { 49 EventLoop { 50 event_loop: WindowsEventLoop::new_any_thread(), 51 _marker: ::std::marker::PhantomData, 52 } 53 } 54 55 #[inline] new_dpi_unaware() -> Self56 fn new_dpi_unaware() -> Self { 57 EventLoop { 58 event_loop: WindowsEventLoop::new_dpi_unaware(), 59 _marker: ::std::marker::PhantomData, 60 } 61 } 62 63 #[inline] new_dpi_unaware_any_thread() -> Self64 fn new_dpi_unaware_any_thread() -> Self { 65 EventLoop { 66 event_loop: WindowsEventLoop::new_dpi_unaware_any_thread(), 67 _marker: ::std::marker::PhantomData, 68 } 69 } 70 } 71 72 /// Additional methods on `Window` that are specific to Windows. 73 pub trait WindowExtWindows { 74 /// Returns the HINSTANCE of the window hinstance(&self) -> *mut libc::c_void75 fn hinstance(&self) -> *mut libc::c_void; 76 /// Returns the native handle that is used by this window. 77 /// 78 /// The pointer will become invalid when the native window was destroyed. hwnd(&self) -> *mut libc::c_void79 fn hwnd(&self) -> *mut libc::c_void; 80 81 /// This sets `ICON_BIG`. A good ceiling here is 256x256. set_taskbar_icon(&self, taskbar_icon: Option<Icon>)82 fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>); 83 84 /// Whether the system theme is currently Windows 10's "Dark Mode". is_dark_mode(&self) -> bool85 fn is_dark_mode(&self) -> bool; 86 } 87 88 impl WindowExtWindows for Window { 89 #[inline] hinstance(&self) -> *mut libc::c_void90 fn hinstance(&self) -> *mut libc::c_void { 91 self.window.hinstance() as *mut _ 92 } 93 94 #[inline] hwnd(&self) -> *mut libc::c_void95 fn hwnd(&self) -> *mut libc::c_void { 96 self.window.hwnd() as *mut _ 97 } 98 99 #[inline] set_taskbar_icon(&self, taskbar_icon: Option<Icon>)100 fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) { 101 self.window.set_taskbar_icon(taskbar_icon) 102 } 103 104 #[inline] is_dark_mode(&self) -> bool105 fn is_dark_mode(&self) -> bool { 106 self.window.is_dark_mode() 107 } 108 } 109 110 /// Additional methods on `WindowBuilder` that are specific to Windows. 111 pub trait WindowBuilderExtWindows { 112 /// Sets a parent to the window to be created. with_parent_window(self, parent: HWND) -> WindowBuilder113 fn with_parent_window(self, parent: HWND) -> WindowBuilder; 114 115 /// This sets `ICON_BIG`. A good ceiling here is 256x256. with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> WindowBuilder116 fn with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> WindowBuilder; 117 118 /// This sets `WS_EX_NOREDIRECTIONBITMAP`. with_no_redirection_bitmap(self, flag: bool) -> WindowBuilder119 fn with_no_redirection_bitmap(self, flag: bool) -> WindowBuilder; 120 121 /// Enables or disables drag and drop support (enabled by default). Will interfere with other crates 122 /// that use multi-threaded COM API (`CoInitializeEx` with `COINIT_MULTITHREADED` instead of 123 /// `COINIT_APARTMENTTHREADED`) on the same thread. Note that winit may still attempt to initialize 124 /// COM API regardless of this option. Currently only fullscreen mode does that, but there may be more in the future. 125 /// If you need COM API with `COINIT_MULTITHREADED` you must initialize it before calling any winit functions. 126 /// See https://docs.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize#remarks for more information. with_drag_and_drop(self, flag: bool) -> WindowBuilder127 fn with_drag_and_drop(self, flag: bool) -> WindowBuilder; 128 } 129 130 impl WindowBuilderExtWindows for WindowBuilder { 131 #[inline] with_parent_window(mut self, parent: HWND) -> WindowBuilder132 fn with_parent_window(mut self, parent: HWND) -> WindowBuilder { 133 self.platform_specific.parent = Some(parent); 134 self 135 } 136 137 #[inline] with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder138 fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder { 139 self.platform_specific.taskbar_icon = taskbar_icon; 140 self 141 } 142 143 #[inline] with_no_redirection_bitmap(mut self, flag: bool) -> WindowBuilder144 fn with_no_redirection_bitmap(mut self, flag: bool) -> WindowBuilder { 145 self.platform_specific.no_redirection_bitmap = flag; 146 self 147 } 148 149 #[inline] with_drag_and_drop(mut self, flag: bool) -> WindowBuilder150 fn with_drag_and_drop(mut self, flag: bool) -> WindowBuilder { 151 self.platform_specific.drag_and_drop = flag; 152 self 153 } 154 } 155 156 /// Additional methods on `MonitorHandle` that are specific to Windows. 157 pub trait MonitorHandleExtWindows { 158 /// Returns the name of the monitor adapter specific to the Win32 API. native_id(&self) -> String159 fn native_id(&self) -> String; 160 161 /// Returns the handle of the monitor - `HMONITOR`. hmonitor(&self) -> *mut c_void162 fn hmonitor(&self) -> *mut c_void; 163 } 164 165 impl MonitorHandleExtWindows for MonitorHandle { 166 #[inline] native_id(&self) -> String167 fn native_id(&self) -> String { 168 self.inner.native_identifier() 169 } 170 171 #[inline] hmonitor(&self) -> *mut c_void172 fn hmonitor(&self) -> *mut c_void { 173 self.inner.hmonitor() as *mut _ 174 } 175 } 176 177 /// Additional methods on `DeviceId` that are specific to Windows. 178 pub trait DeviceIdExtWindows { 179 /// Returns an identifier that persistently refers to this specific device. 180 /// 181 /// Will return `None` if the device is no longer available. persistent_identifier(&self) -> Option<String>182 fn persistent_identifier(&self) -> Option<String>; 183 } 184 185 impl DeviceIdExtWindows for DeviceId { 186 #[inline] persistent_identifier(&self) -> Option<String>187 fn persistent_identifier(&self) -> Option<String> { 188 self.0.persistent_identifier() 189 } 190 } 191 192 /// Additional methods on `Icon` that are specific to Windows. 193 pub trait IconExtWindows: Sized { 194 /// Create an icon from a file path. 195 /// 196 /// Specify `size` to load a specific icon size from the file, or `None` to load the default 197 /// icon size from the file. 198 /// 199 /// In cases where the specified size does not exist in the file, Windows may perform scaling 200 /// to get an icon of the desired size. from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>201 fn from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>) 202 -> Result<Self, BadIcon>; 203 204 /// Create an icon from a resource embedded in this executable or library. 205 /// 206 /// Specify `size` to load a specific icon size from the file, or `None` to load the default 207 /// icon size from the file. 208 /// 209 /// In cases where the specified size does not exist in the file, Windows may perform scaling 210 /// to get an icon of the desired size. from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>211 fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>; 212 } 213 214 impl IconExtWindows for Icon { from_path<P: AsRef<Path>>( path: P, size: Option<PhysicalSize<u32>>, ) -> Result<Self, BadIcon>215 fn from_path<P: AsRef<Path>>( 216 path: P, 217 size: Option<PhysicalSize<u32>>, 218 ) -> Result<Self, BadIcon> { 219 let win_icon = WinIcon::from_path(path, size)?; 220 Ok(Icon { inner: win_icon }) 221 } 222 from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>223 fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> { 224 let win_icon = WinIcon::from_resource(ordinal, size)?; 225 Ok(Icon { inner: win_icon }) 226 } 227 } 228