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, Theme, 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 /// Returns the current window theme. theme(&self) -> Theme85 fn theme(&self) -> Theme; 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] theme(&self) -> Theme105 fn theme(&self) -> Theme { 106 self.window.theme() 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 /// Forces a theme or uses the system settings if `None` was provided. with_theme(self, theme: Option<Theme>) -> WindowBuilder130 fn with_theme(self, theme: Option<Theme>) -> WindowBuilder; 131 } 132 133 impl WindowBuilderExtWindows for WindowBuilder { 134 #[inline] with_parent_window(mut self, parent: HWND) -> WindowBuilder135 fn with_parent_window(mut self, parent: HWND) -> WindowBuilder { 136 self.platform_specific.parent = Some(parent); 137 self 138 } 139 140 #[inline] with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder141 fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder { 142 self.platform_specific.taskbar_icon = taskbar_icon; 143 self 144 } 145 146 #[inline] with_no_redirection_bitmap(mut self, flag: bool) -> WindowBuilder147 fn with_no_redirection_bitmap(mut self, flag: bool) -> WindowBuilder { 148 self.platform_specific.no_redirection_bitmap = flag; 149 self 150 } 151 152 #[inline] with_drag_and_drop(mut self, flag: bool) -> WindowBuilder153 fn with_drag_and_drop(mut self, flag: bool) -> WindowBuilder { 154 self.platform_specific.drag_and_drop = flag; 155 self 156 } 157 158 #[inline] with_theme(mut self, theme: Option<Theme>) -> WindowBuilder159 fn with_theme(mut self, theme: Option<Theme>) -> WindowBuilder { 160 self.platform_specific.preferred_theme = theme; 161 self 162 } 163 } 164 165 /// Additional methods on `MonitorHandle` that are specific to Windows. 166 pub trait MonitorHandleExtWindows { 167 /// Returns the name of the monitor adapter specific to the Win32 API. native_id(&self) -> String168 fn native_id(&self) -> String; 169 170 /// Returns the handle of the monitor - `HMONITOR`. hmonitor(&self) -> *mut c_void171 fn hmonitor(&self) -> *mut c_void; 172 } 173 174 impl MonitorHandleExtWindows for MonitorHandle { 175 #[inline] native_id(&self) -> String176 fn native_id(&self) -> String { 177 self.inner.native_identifier() 178 } 179 180 #[inline] hmonitor(&self) -> *mut c_void181 fn hmonitor(&self) -> *mut c_void { 182 self.inner.hmonitor() as *mut _ 183 } 184 } 185 186 /// Additional methods on `DeviceId` that are specific to Windows. 187 pub trait DeviceIdExtWindows { 188 /// Returns an identifier that persistently refers to this specific device. 189 /// 190 /// Will return `None` if the device is no longer available. persistent_identifier(&self) -> Option<String>191 fn persistent_identifier(&self) -> Option<String>; 192 } 193 194 impl DeviceIdExtWindows for DeviceId { 195 #[inline] persistent_identifier(&self) -> Option<String>196 fn persistent_identifier(&self) -> Option<String> { 197 self.0.persistent_identifier() 198 } 199 } 200 201 /// Additional methods on `Icon` that are specific to Windows. 202 pub trait IconExtWindows: Sized { 203 /// Create an icon from a file path. 204 /// 205 /// Specify `size` to load a specific icon size from the file, or `None` to load the default 206 /// icon size from the file. 207 /// 208 /// In cases where the specified size does not exist in the file, Windows may perform scaling 209 /// to get an icon of the desired size. from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>210 fn from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>) 211 -> Result<Self, BadIcon>; 212 213 /// Create an icon from a resource embedded in this executable or library. 214 /// 215 /// Specify `size` to load a specific icon size from the file, or `None` to load the default 216 /// icon size from the file. 217 /// 218 /// In cases where the specified size does not exist in the file, Windows may perform scaling 219 /// to get an icon of the desired size. from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>220 fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>; 221 } 222 223 impl IconExtWindows for Icon { from_path<P: AsRef<Path>>( path: P, size: Option<PhysicalSize<u32>>, ) -> Result<Self, BadIcon>224 fn from_path<P: AsRef<Path>>( 225 path: P, 226 size: Option<PhysicalSize<u32>>, 227 ) -> Result<Self, BadIcon> { 228 let win_icon = WinIcon::from_path(path, size)?; 229 Ok(Icon { inner: win_icon }) 230 } 231 from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>232 fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> { 233 let win_icon = WinIcon::from_resource(ordinal, size)?; 234 Ok(Icon { inner: win_icon }) 235 } 236 } 237