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