From 2b93692acd660915edefcda9bbd2d75712052454 Mon Sep 17 00:00:00 2001 From: Clemens Wasser Date: Fri, 5 Nov 2021 23:29:53 +0100 Subject: [PATCH] Adopt windows-rs Change from using the unofficial winapi bindings, to using the official windows bindings from Microsoft. --- Cargo.toml | 51 +- src/platform/windows.rs | 18 +- src/platform_impl/windows/dark_mode.rs | 82 +- src/platform_impl/windows/dpi.rs | 47 +- src/platform_impl/windows/drop_handler.rs | 299 +++--- src/platform_impl/windows/event.rs | 457 ++++----- src/platform_impl/windows/event_loop.rs | 888 +++++++++--------- .../windows/event_loop/runner.rs | 47 +- src/platform_impl/windows/icon.rs | 102 +- src/platform_impl/windows/mod.rs | 55 +- src/platform_impl/windows/monitor.rs | 132 ++- src/platform_impl/windows/raw_input.rs | 105 +-- src/platform_impl/windows/util.rs | 168 ++-- src/platform_impl/windows/window.rs | 433 +++++---- src/platform_impl/windows/window_state.rs | 85 +- 15 files changed, 1525 insertions(+), 1444 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 310253f922..84954c1a59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,31 +58,34 @@ features = ["display_link"] [target.'cfg(target_os = "windows")'.dependencies] parking_lot = "0.11" -[target.'cfg(target_os = "windows")'.dependencies.winapi] -version = "0.3.9" +[target.'cfg(target_os = "windows")'.dependencies.windows] +version = "0.25" features = [ - "combaseapi", - "commctrl", - "dwmapi", - "errhandlingapi", - "imm", - "hidusage", - "libloaderapi", - "objbase", - "ole2", - "processthreadsapi", - "shellapi", - "shellscalingapi", - "shobjidl_core", - "unknwnbase", - "winbase", - "windowsx", - "winerror", - "wingdi", - "winnt", - "winuser", - "mmsystem", - "timeapi" + "build", + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media_Multimedia", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", ] [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 7df4cced4c..458d4641ee 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -3,8 +3,10 @@ use std::os::raw::c_void; use std::path::Path; -use winapi::shared::minwindef::WORD; -use winapi::shared::windef::{HMENU, HWND}; +use windows::Win32::{ + Foundation::HWND, + UI::{Input::KeyboardAndMouse::EnableWindow, WindowsAndMessaging::HMENU}, +}; use crate::{ dpi::PhysicalSize, @@ -102,18 +104,18 @@ pub trait WindowExtWindows { impl WindowExtWindows for Window { #[inline] fn hinstance(&self) -> *mut c_void { - self.window.hinstance() as *mut _ + self.window.hinstance().0 as *mut c_void } #[inline] fn hwnd(&self) -> *mut c_void { - self.window.hwnd() as *mut _ + self.window.hwnd().0 as *mut c_void } #[inline] fn set_enable(&self, enabled: bool) { unsafe { - winapi::um::winuser::EnableWindow(self.hwnd() as _, enabled as _); + EnableWindow(HWND(self.hwnd() as isize), enabled); } } @@ -238,7 +240,7 @@ impl MonitorHandleExtWindows for MonitorHandle { #[inline] fn hmonitor(&self) -> *mut c_void { - self.inner.hmonitor() as *mut _ + self.inner.hmonitor().0 as *mut c_void } } @@ -276,7 +278,7 @@ pub trait IconExtWindows: Sized { /// /// In cases where the specified size does not exist in the file, Windows may perform scaling /// to get an icon of the desired size. - fn from_resource(ordinal: WORD, size: Option>) -> Result; + fn from_resource(ordinal: u16, size: Option>) -> Result; } impl IconExtWindows for Icon { @@ -288,7 +290,7 @@ impl IconExtWindows for Icon { Ok(Icon { inner: win_icon }) } - fn from_resource(ordinal: WORD, size: Option>) -> Result { + fn from_resource(ordinal: u16, size: Option>) -> Result { let win_icon = WinIcon::from_resource(ordinal, size)?; Ok(Icon { inner: win_icon }) } diff --git a/src/platform_impl/windows/dark_mode.rs b/src/platform_impl/windows/dark_mode.rs index b010d29b55..f469c8840e 100644 --- a/src/platform_impl/windows/dark_mode.rs +++ b/src/platform_impl/windows/dark_mode.rs @@ -1,29 +1,29 @@ /// This is a simple implementation of support for Windows Dark Mode, /// which is inspired by the solution in https://github.com/ysc3839/win32-darkmode -use std::ffi::OsStr; +use std::ffi::{c_void, OsStr}; +use std::iter::once; use std::os::windows::ffi::OsStrExt; -use winapi::{ - shared::{ - basetsd::SIZE_T, - minwindef::{BOOL, DWORD, FALSE, WORD}, - ntdef::{NTSTATUS, NT_SUCCESS, PVOID}, - windef::HWND, - winerror::S_OK, - }, - um::{libloaderapi, uxtheme, winnt, winuser}, +use windows::runtime::Handle; +use windows::Win32::Foundation::{BOOL, HWND, NTSTATUS, PSTR, PWSTR}; +use windows::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA}; +use windows::Win32::System::SystemInformation::OSVERSIONINFOW; +use windows::Win32::UI::Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTA, HIGHCONTRASTW_FLAGS}; +use windows::Win32::UI::Controls::SetWindowTheme; +use windows::Win32::UI::WindowsAndMessaging::{ + SystemParametersInfoA, SPI_GETHIGHCONTRAST, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, }; use crate::window::Theme; lazy_static! { - static ref WIN10_BUILD_VERSION: Option = { - type RtlGetVersion = unsafe extern "system" fn (*mut winnt::OSVERSIONINFOW) -> NTSTATUS; + static ref WIN10_BUILD_VERSION: Option = { + type RtlGetVersion = unsafe extern "system" fn (*mut OSVERSIONINFOW) -> NTSTATUS; let handle = get_function!("ntdll.dll", RtlGetVersion); if let Some(rtl_get_version) = handle { unsafe { - let mut vi = winnt::OSVERSIONINFOW { + let mut vi = OSVERSIONINFOW { dwOSVersionInfoSize: 0, dwMajorVersion: 0, dwMinorVersion: 0, @@ -34,7 +34,7 @@ lazy_static! { let status = (rtl_get_version)(&mut vi as _); - if NT_SUCCESS(status) && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 { + if (status.0 as i32) >= 0 && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 { Some(vi.dwBuildNumber) } else { None @@ -54,8 +54,8 @@ lazy_static! { } }; - static ref DARK_THEME_NAME: Vec = widestring("DarkMode_Explorer"); - static ref LIGHT_THEME_NAME: Vec = widestring(""); + static ref DARK_THEME_NAME: Vec = OsStr::new("DarkMode_Explorer").encode_wide().chain(once(0)).collect(); + static ref LIGHT_THEME_NAME: Vec = OsStr::new("").encode_wide().chain(once(0)).collect(); } /// Attempt to set a theme on a window, if necessary. @@ -77,9 +77,9 @@ pub fn try_theme(hwnd: HWND, preferred_theme: Option) -> Theme { Theme::Light => LIGHT_THEME_NAME.as_ptr(), }; - let status = unsafe { uxtheme::SetWindowTheme(hwnd, theme_name as _, std::ptr::null()) }; + let status = unsafe { SetWindowTheme(hwnd, PWSTR(theme_name as *mut u16), None) }; - if status == S_OK && set_dark_mode_for_window(hwnd, is_dark_mode) { + if status.is_ok() && set_dark_mode_for_window(hwnd, is_dark_mode) { return theme; } } @@ -103,8 +103,8 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool { #[repr(C)] struct WINDOWCOMPOSITIONATTRIBDATA { Attrib: WINDOWCOMPOSITIONATTRIB, - pvData: PVOID, - cbData: SIZE_T, + pvData: *mut c_void, + cbData: usize, } lazy_static! { @@ -115,7 +115,7 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool { if let Some(set_window_composition_attribute) = *SET_WINDOW_COMPOSITION_ATTRIBUTE { unsafe { // SetWindowCompositionAttribute needs a bigbool (i32), not bool. - let mut is_dark_mode_bigbool = is_dark_mode as BOOL; + let mut is_dark_mode_bigbool = is_dark_mode; let mut data = WINDOWCOMPOSITIONATTRIBDATA { Attrib: WCA_USEDARKMODECOLORS, @@ -125,7 +125,7 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool { let status = set_window_composition_attribute(hwnd, &mut data as *mut _); - status != FALSE + status.as_bool() } } else { false @@ -141,24 +141,17 @@ fn should_apps_use_dark_mode() -> bool { lazy_static! { static ref SHOULD_APPS_USE_DARK_MODE: Option = { unsafe { - const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: WORD = 132; + const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: PSTR = PSTR(132 as *mut u8); - let module = libloaderapi::LoadLibraryA("uxtheme.dll\0".as_ptr() as _); + let module = LoadLibraryA(PSTR("uxtheme.dll\0".as_ptr() as *mut u8)); - if module.is_null() { + if module.is_invalid() { return None; } - let handle = libloaderapi::GetProcAddress( - module, - winuser::MAKEINTRESOURCEA(UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL), - ); + let handle = GetProcAddress(module, UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL); - if handle.is_null() { - None - } else { - Some(std::mem::transmute(handle)) - } + handle.map(|handle| std::mem::transmute(handle)) } }; } @@ -169,27 +162,20 @@ fn should_apps_use_dark_mode() -> bool { } fn is_high_contrast() -> bool { - let mut hc = winuser::HIGHCONTRASTA { + let mut hc = HIGHCONTRASTA { cbSize: 0, - dwFlags: 0, - lpszDefaultScheme: std::ptr::null_mut(), + dwFlags: HIGHCONTRASTW_FLAGS(0), + lpszDefaultScheme: PSTR(std::ptr::null_mut()), }; let ok = unsafe { - winuser::SystemParametersInfoA( - winuser::SPI_GETHIGHCONTRAST, + SystemParametersInfoA( + SPI_GETHIGHCONTRAST, std::mem::size_of_val(&hc) as _, &mut hc as *mut _ as _, - 0, + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0), ) }; - ok != FALSE && (winuser::HCF_HIGHCONTRASTON & hc.dwFlags) == 1 -} - -fn widestring(src: &'static str) -> Vec { - OsStr::new(src) - .encode_wide() - .chain(Some(0).into_iter()) - .collect() + ok.as_bool() && (hc.dwFlags & HCF_HIGHCONTRASTON) == HCF_HIGHCONTRASTON } diff --git a/src/platform_impl/windows/dpi.rs b/src/platform_impl/windows/dpi.rs index f7ec439135..74dcb8f838 100644 --- a/src/platform_impl/windows/dpi.rs +++ b/src/platform_impl/windows/dpi.rs @@ -2,24 +2,29 @@ use std::sync::Once; +use windows::{ + runtime::Handle, + Win32::{ + Foundation::{HWND, S_OK}, + Graphics::Gdi::{ + GetDC, GetDeviceCaps, MonitorFromWindow, HMONITOR, LOGPIXELSX, MONITOR_DEFAULTTONEAREST, + }, + UI::{ + HiDpi::{ + DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, MDT_EFFECTIVE_DPI, + PROCESS_PER_MONITOR_DPI_AWARE, + }, + WindowsAndMessaging::IsProcessDPIAware, + }, + }, +}; + use crate::platform_impl::platform::util::{ ENABLE_NON_CLIENT_DPI_SCALING, GET_DPI_FOR_MONITOR, GET_DPI_FOR_WINDOW, SET_PROCESS_DPI_AWARE, SET_PROCESS_DPI_AWARENESS, SET_PROCESS_DPI_AWARENESS_CONTEXT, }; -use winapi::{ - shared::{ - minwindef::FALSE, - windef::{DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, HMONITOR, HWND}, - winerror::S_OK, - }, - um::{ - shellscalingapi::{MDT_EFFECTIVE_DPI, PROCESS_PER_MONITOR_DPI_AWARE}, - wingdi::{GetDeviceCaps, LOGPIXELSX}, - winuser::{self, MONITOR_DEFAULTTONEAREST}, - }, -}; -const DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2: DPI_AWARENESS_CONTEXT = -4isize as _; +const DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2: DPI_AWARENESS_CONTEXT = DPI_AWARENESS_CONTEXT(-4); pub fn become_dpi_aware() { static ENABLE_DPI_AWARENESS: Once = Once::new(); @@ -27,8 +32,8 @@ pub fn become_dpi_aware() { unsafe { if let Some(SetProcessDpiAwarenessContext) = *SET_PROCESS_DPI_AWARENESS_CONTEXT { // We are on Windows 10 Anniversary Update (1607) or later. - if SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) - == FALSE + if !SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) + .as_bool() { // V2 only works with Windows 10 Creators Update (1703). Try using the older // V1 if we can't set V2. @@ -36,7 +41,7 @@ pub fn become_dpi_aware() { } } else if let Some(SetProcessDpiAwareness) = *SET_PROCESS_DPI_AWARENESS { // We are on Windows 8.1 or later. - SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); + let _ = SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); } else if let Some(SetProcessDPIAware) = *SET_PROCESS_DPI_AWARE { // We are on Vista or later. SetProcessDPIAware(); @@ -76,8 +81,8 @@ pub fn dpi_to_scale_factor(dpi: u32) -> f64 { } pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 { - let hdc = winuser::GetDC(hwnd); - if hdc.is_null() { + let hdc = GetDC(hwnd); + if hdc.is_invalid() { panic!("[winit] `GetDC` returned null!"); } if let Some(GetDpiForWindow) = *GET_DPI_FOR_WINDOW { @@ -88,8 +93,8 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 { } } else if let Some(GetDpiForMonitor) = *GET_DPI_FOR_MONITOR { // We are on Windows 8.1 or later. - let monitor = winuser::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - if monitor.is_null() { + let monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + if monitor.is_invalid() { return BASE_DPI; } @@ -102,7 +107,7 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 { } } else { // We are on Vista or later. - if winuser::IsProcessDPIAware() != FALSE { + if IsProcessDPIAware().as_bool() { // If the process is DPI aware, then scaling must be handled by the application using // this DPI value. GetDeviceCaps(hdc, LOGPIXELSX) as u32 diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index 3514d5772b..de9469ba7e 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -1,253 +1,174 @@ -use std::{ - ffi::OsString, - os::windows::ffi::OsStringExt, - path::PathBuf, - ptr, - sync::atomic::{AtomicUsize, Ordering}, -}; +use std::{ffi::OsString, os::windows::ffi::OsStringExt, path::PathBuf, ptr}; -use winapi::{ - ctypes::c_void, - shared::{ - guiddef::REFIID, - minwindef::{DWORD, UINT, ULONG}, - windef::{HWND, POINTL}, - winerror::S_OK, - }, - um::{ - objidl::IDataObject, - oleidl::{IDropTarget, IDropTargetVtbl, DROPEFFECT_COPY, DROPEFFECT_NONE}, - shellapi, unknwnbase, - winnt::HRESULT, +use windows::Win32::{ + Foundation::{DV_E_FORMATETC, HWND, POINTL, PWSTR}, + System::{ + Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL}, + SystemServices::CF_HDROP, }, + UI::Shell::{DragFinish, DragQueryFileW, HDROP}, +}; +use windows::{ + runtime::implement, + Win32::System::Ole::{DROPEFFECT_COPY, DROPEFFECT_NONE}, }; +// FIXME: Remove hack +#[allow(non_snake_case)] +mod Windows { + pub use windows::*; +} + use crate::platform_impl::platform::WindowId; use crate::{event::Event, window::WindowId as SuperWindowId}; #[repr(C)] -pub struct FileDropHandlerData { - pub interface: IDropTarget, - refcount: AtomicUsize, +#[implement(Windows::Win32::System::Ole::IDropTarget)] +pub struct FileDropHandler { window: HWND, send_event: Box)>, - cursor_effect: DWORD, + cursor_effect: u32, hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */ } -pub struct FileDropHandler { - pub data: *mut FileDropHandlerData, -} - #[allow(non_snake_case)] impl FileDropHandler { - pub fn new(window: HWND, send_event: Box)>) -> FileDropHandler { - let data = Box::new(FileDropHandlerData { - interface: IDropTarget { - lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl, - }, - refcount: AtomicUsize::new(1), + pub fn new(window: HWND, send_event: Box)>) -> Self { + Self { window, send_event, cursor_effect: DROPEFFECT_NONE, hovered_is_valid: false, - }); - FileDropHandler { - data: Box::into_raw(data), } } - // Implement IUnknown - pub unsafe extern "system" fn QueryInterface( - _this: *mut unknwnbase::IUnknown, - _riid: REFIID, - _ppvObject: *mut *mut c_void, - ) -> HRESULT { - // This function doesn't appear to be required for an `IDropTarget`. - // An implementation would be nice however. - unimplemented!(); - } - - pub unsafe extern "system" fn AddRef(this: *mut unknwnbase::IUnknown) -> ULONG { - let drop_handler_data = Self::from_interface(this); - let count = drop_handler_data.refcount.fetch_add(1, Ordering::Release) + 1; - count as ULONG - } - - pub unsafe extern "system" fn Release(this: *mut unknwnbase::IUnknown) -> ULONG { - let drop_handler = Self::from_interface(this); - let count = drop_handler.refcount.fetch_sub(1, Ordering::Release) - 1; - if count == 0 { - // Destroy the underlying data - Box::from_raw(drop_handler as *mut FileDropHandlerData); - } - count as ULONG - } - - pub unsafe extern "system" fn DragEnter( - this: *mut IDropTarget, - pDataObj: *const IDataObject, - _grfKeyState: DWORD, - _pt: *const POINTL, - pdwEffect: *mut DWORD, - ) -> HRESULT { + pub unsafe fn DragEnter( + &mut self, + pdataobj: &Option, + _grfkeystate: u32, + _pt: POINTL, + pdweffect: *mut u32, + ) -> windows::runtime::Result<()> { use crate::event::WindowEvent::HoveredFile; - let drop_handler = Self::from_interface(this); - let hdrop = Self::iterate_filenames(pDataObj, |filename| { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), + let hdrop = Self::iterate_filenames(pdataobj, |filename| { + self.send_event(Event::WindowEvent { + window_id: SuperWindowId(WindowId(self.window)), event: HoveredFile(filename), }); }); - drop_handler.hovered_is_valid = hdrop.is_some(); - drop_handler.cursor_effect = if drop_handler.hovered_is_valid { + + self.hovered_is_valid = hdrop.is_some(); + self.cursor_effect = if self.hovered_is_valid { DROPEFFECT_COPY } else { DROPEFFECT_NONE }; - *pdwEffect = drop_handler.cursor_effect; + *pdweffect = self.cursor_effect; - S_OK + Ok(()) } - pub unsafe extern "system" fn DragOver( - this: *mut IDropTarget, - _grfKeyState: DWORD, - _pt: *const POINTL, - pdwEffect: *mut DWORD, - ) -> HRESULT { - let drop_handler = Self::from_interface(this); - *pdwEffect = drop_handler.cursor_effect; + pub unsafe fn DragOver( + &self, + _grfkeystate: u32, + _pt: POINTL, + pdweffect: *mut u32, + ) -> windows::runtime::Result<()> { + *pdweffect = self.cursor_effect; - S_OK + Ok(()) } - pub unsafe extern "system" fn DragLeave(this: *mut IDropTarget) -> HRESULT { + pub unsafe fn DragLeave(&self) -> windows::runtime::Result<()> { use crate::event::WindowEvent::HoveredFileCancelled; - let drop_handler = Self::from_interface(this); - if drop_handler.hovered_is_valid { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), + if self.hovered_is_valid { + self.send_event(Event::WindowEvent { + window_id: SuperWindowId(WindowId(self.window)), event: HoveredFileCancelled, }); } - S_OK + Ok(()) } - pub unsafe extern "system" fn Drop( - this: *mut IDropTarget, - pDataObj: *const IDataObject, - _grfKeyState: DWORD, - _pt: *const POINTL, - _pdwEffect: *mut DWORD, - ) -> HRESULT { + pub unsafe fn Drop( + &self, + pdataobj: &Option, + _grfkeystate: u32, + _pt: POINTL, + _pdweffect: *mut u32, + ) -> windows::runtime::Result<()> { use crate::event::WindowEvent::DroppedFile; - let drop_handler = Self::from_interface(this); - let hdrop = Self::iterate_filenames(pDataObj, |filename| { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), + let hdrop = Self::iterate_filenames(pdataobj, |filename| { + self.send_event(Event::WindowEvent { + window_id: SuperWindowId(WindowId(self.window)), event: DroppedFile(filename), }); }); if let Some(hdrop) = hdrop { - shellapi::DragFinish(hdrop); + DragFinish(hdrop); } - S_OK + Ok(()) } - unsafe fn from_interface<'a, InterfaceT>(this: *mut InterfaceT) -> &'a mut FileDropHandlerData { - &mut *(this as *mut _) - } - - unsafe fn iterate_filenames( - data_obj: *const IDataObject, - callback: F, - ) -> Option + unsafe fn iterate_filenames(data_obj: &Option, callback: F) -> Option where F: Fn(PathBuf), { - use winapi::{ - shared::{ - winerror::{DV_E_FORMATETC, SUCCEEDED}, - wtypes::{CLIPFORMAT, DVASPECT_CONTENT}, - }, - um::{ - objidl::{FORMATETC, TYMED_HGLOBAL}, - shellapi::DragQueryFileW, - winuser::CF_HDROP, - }, - }; - - let drop_format = FORMATETC { - cfFormat: CF_HDROP as CLIPFORMAT, - ptd: ptr::null(), - dwAspect: DVASPECT_CONTENT, - lindex: -1, - tymed: TYMED_HGLOBAL, - }; - - let mut medium = std::mem::zeroed(); - let get_data_result = (*data_obj).GetData(&drop_format, &mut medium); - if SUCCEEDED(get_data_result) { - let hglobal = (*medium.u).hGlobal(); - let hdrop = (*hglobal) as shellapi::HDROP; - - // The second parameter (0xFFFFFFFF) instructs the function to return the item count - let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, ptr::null_mut(), 0); - - for i in 0..item_count { - // Get the length of the path string NOT including the terminating null character. - // Previously, this was using a fixed size array of MAX_PATH length, but the - // Windows API allows longer paths under certain circumstances. - let character_count = DragQueryFileW(hdrop, i, ptr::null_mut(), 0) as usize; - let str_len = character_count + 1; - - // Fill path_buf with the null-terminated file name - let mut path_buf = Vec::with_capacity(str_len); - DragQueryFileW(hdrop, i, path_buf.as_mut_ptr(), str_len as UINT); - path_buf.set_len(str_len); - - callback(OsString::from_wide(&path_buf[0..character_count]).into()); + if let Some(data_obj) = data_obj { + let drop_format = FORMATETC { + cfFormat: CF_HDROP.0 as u16, + ptd: ptr::null_mut(), + dwAspect: DVASPECT_CONTENT.0 as u32, + lindex: -1, + tymed: TYMED_HGLOBAL.0 as u32, + }; + + match data_obj.GetData(&drop_format) { + Ok(medium) => { + let hglobal = medium.Anonymous.hGlobal; + let hdrop = *(hglobal as *const HDROP); + + // The second parameter (0xFFFFFFFF) instructs the function to return the item count + let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, PWSTR(ptr::null_mut()), 0); + + for i in 0..item_count { + // Get the length of the path string NOT including the terminating null character. + // Previously, this was using a fixed size array of MAX_PATH length, but the + // Windows API allows longer paths under certain circumstances. + let character_count = + DragQueryFileW(hdrop, i, PWSTR(ptr::null_mut()), 0) as usize; + let str_len = character_count + 1; + + // Fill path_buf with the null-terminated file name + let mut path_buf = Vec::with_capacity(str_len); + DragQueryFileW(hdrop, i, PWSTR(path_buf.as_mut_ptr()), str_len as u32); + path_buf.set_len(str_len); + + callback(OsString::from_wide(&path_buf[0..character_count]).into()); + } + + Some(hdrop) + } + Err(error) => { + if error.code() == DV_E_FORMATETC { + // If the dropped item is not a file this error will occur. + // In this case it is OK to return without taking further action. + debug!("Error occured while processing dropped/hovered item: item is not a file."); + } else { + debug!("Unexpected error occured while processing dropped/hovered item."); + } + None + } } - - Some(hdrop) - } else if get_data_result == DV_E_FORMATETC { - // If the dropped item is not a file this error will occur. - // In this case it is OK to return without taking further action. - debug!("Error occured while processing dropped/hovered item: item is not a file."); - None } else { - debug!("Unexpected error occured while processing dropped/hovered item."); - None + unreachable!() } } -} -impl FileDropHandlerData { fn send_event(&self, event: Event<'static, ()>) { - (self.send_event)(event); + (self.send_event)(event) } } - -impl Drop for FileDropHandler { - fn drop(&mut self) { - unsafe { - FileDropHandler::Release(self.data as *mut unknwnbase::IUnknown); - } - } -} - -static DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl { - parent: unknwnbase::IUnknownVtbl { - QueryInterface: FileDropHandler::QueryInterface, - AddRef: FileDropHandler::AddRef, - Release: FileDropHandler::Release, - }, - DragEnter: FileDropHandler::DragEnter, - DragOver: FileDropHandler::DragOver, - DragLeave: FileDropHandler::DragLeave, - Drop: FileDropHandler::Drop, -}; diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index 77bd31d2ae..1237b6f7b6 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -1,37 +1,56 @@ use std::{ char, - os::raw::c_int, - ptr, - sync::atomic::{AtomicBool, AtomicPtr, Ordering}, + sync::atomic::{AtomicBool, AtomicIsize, Ordering}, }; -use crate::event::{ModifiersState, ScanCode, VirtualKeyCode}; - -use winapi::{ - shared::minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM}, - um::winuser, +use windows::Win32::{ + Foundation::{LPARAM, PWSTR, WPARAM}, + UI::{ + Input::KeyboardAndMouse::{ + GetKeyState, GetKeyboardLayout, GetKeyboardState, MapVirtualKeyA, ToUnicodeEx, + VIRTUAL_KEY, VK_ADD, VK_APPS, VK_BACK, VK_BROWSER_BACK, VK_BROWSER_FAVORITES, + VK_BROWSER_FORWARD, VK_BROWSER_HOME, VK_BROWSER_REFRESH, VK_BROWSER_SEARCH, + VK_BROWSER_STOP, VK_CAPITAL, VK_CONTROL, VK_CONVERT, VK_DECIMAL, VK_DELETE, VK_DIVIDE, + VK_DOWN, VK_END, VK_ESCAPE, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, + VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, VK_F3, + VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_HOME, VK_INSERT, VK_KANA, VK_KANJI, + VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, + VK_LWIN, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP, + VK_MENU, VK_MULTIPLY, VK_NEXT, VK_NONCONVERT, VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, + VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, + VK_NUMPAD9, VK_OEM_1, VK_OEM_102, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, + VK_OEM_7, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_PLUS, VK_PAUSE, VK_PRIOR, + VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN, VK_SCROLL, VK_SHIFT, + VK_SLEEP, VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_TAB, VK_UP, VK_VOLUME_DOWN, + VK_VOLUME_MUTE, VK_VOLUME_UP, + }, + TextServices::HKL, + WindowsAndMessaging::{MAPVK_VK_TO_CHAR, MAPVK_VSC_TO_VK_EX}, + }, }; -fn key_pressed(vkey: c_int) -> bool { - unsafe { (winuser::GetKeyState(vkey) & (1 << 15)) == (1 << 15) } +use crate::event::{ModifiersState, ScanCode, VirtualKeyCode}; + +fn key_pressed(vkey: VIRTUAL_KEY) -> bool { + unsafe { (GetKeyState(vkey.0 as i32) & (1 << 15)) == (1 << 15) } } pub fn get_key_mods() -> ModifiersState { - let filter_out_altgr = layout_uses_altgr() && key_pressed(winuser::VK_RMENU); + let filter_out_altgr = layout_uses_altgr() && key_pressed(VK_RMENU); let mut mods = ModifiersState::empty(); - mods.set(ModifiersState::SHIFT, key_pressed(winuser::VK_SHIFT)); + mods.set(ModifiersState::SHIFT, key_pressed(VK_SHIFT)); mods.set( ModifiersState::CTRL, - key_pressed(winuser::VK_CONTROL) && !filter_out_altgr, + key_pressed(VK_CONTROL) && !filter_out_altgr, ); mods.set( ModifiersState::ALT, - key_pressed(winuser::VK_MENU) && !filter_out_altgr, + key_pressed(VK_MENU) && !filter_out_altgr, ); mods.set( ModifiersState::LOGO, - key_pressed(winuser::VK_LWIN) || key_pressed(winuser::VK_RWIN), + key_pressed(VK_LWIN) || key_pressed(VK_RWIN), ); mods } @@ -85,23 +104,23 @@ impl From for ModifiersState { } } -pub fn get_pressed_keys() -> impl Iterator { +pub fn get_pressed_keys() -> impl Iterator { let mut keyboard_state = vec![0u8; 256]; - unsafe { winuser::GetKeyboardState(keyboard_state.as_mut_ptr()) }; + unsafe { GetKeyboardState(keyboard_state.as_mut_ptr()) }; keyboard_state .into_iter() .enumerate() .filter(|(_, p)| (*p & (1 << 7)) != 0) // whether or not a key is pressed is communicated via the high-order bit - .map(|(i, _)| i as c_int) + .map(|(i, _)| VIRTUAL_KEY(i as u16)) } unsafe fn get_char(keyboard_state: &[u8; 256], v_key: u32, hkl: HKL) -> Option { let mut unicode_bytes = [0u16; 5]; - let len = winuser::ToUnicodeEx( + let len = ToUnicodeEx( v_key, 0, keyboard_state.as_ptr(), - unicode_bytes.as_mut_ptr(), + PWSTR(unicode_bytes.as_mut_ptr()), unicode_bytes.len() as _, 0, hkl, @@ -126,21 +145,21 @@ unsafe fn get_char(keyboard_state: &[u8; 256], v_key: u32, hkl: HKL) -> Option bool { unsafe { - static ACTIVE_LAYOUT: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + static ACTIVE_LAYOUT: AtomicIsize = AtomicIsize::new(0); static USES_ALTGR: AtomicBool = AtomicBool::new(false); - let hkl = winuser::GetKeyboardLayout(0); - let old_hkl = ACTIVE_LAYOUT.swap(hkl, Ordering::SeqCst); + let hkl = GetKeyboardLayout(0); + let old_hkl = ACTIVE_LAYOUT.swap(hkl.0, Ordering::SeqCst); - if hkl == old_hkl { + if hkl.0 == old_hkl { return USES_ALTGR.load(Ordering::SeqCst); } let mut keyboard_state_altgr = [0u8; 256]; // AltGr is an alias for Ctrl+Alt for... some reason. Whatever it is, those are the keypresses // we have to emulate to do an AltGr test. - keyboard_state_altgr[winuser::VK_MENU as usize] = 0x80; - keyboard_state_altgr[winuser::VK_CONTROL as usize] = 0x80; + keyboard_state_altgr[VK_MENU.0 as usize] = 0x80; + keyboard_state_altgr[VK_CONTROL.0 as usize] = 0x80; let keyboard_state_empty = [0u8; 256]; @@ -160,206 +179,204 @@ fn layout_uses_altgr() -> bool { } } -pub fn vkey_to_winit_vkey(vkey: c_int) -> Option { +pub fn vkey_to_winit_vkey(vkey: VIRTUAL_KEY) -> Option { // VK_* codes are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx match vkey { - //winuser::VK_LBUTTON => Some(VirtualKeyCode::Lbutton), - //winuser::VK_RBUTTON => Some(VirtualKeyCode::Rbutton), - //winuser::VK_CANCEL => Some(VirtualKeyCode::Cancel), - //winuser::VK_MBUTTON => Some(VirtualKeyCode::Mbutton), - //winuser::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1), - //winuser::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2), - winuser::VK_BACK => Some(VirtualKeyCode::Back), - winuser::VK_TAB => Some(VirtualKeyCode::Tab), - //winuser::VK_CLEAR => Some(VirtualKeyCode::Clear), - winuser::VK_RETURN => Some(VirtualKeyCode::Return), - winuser::VK_LSHIFT => Some(VirtualKeyCode::LShift), - winuser::VK_RSHIFT => Some(VirtualKeyCode::RShift), - winuser::VK_LCONTROL => Some(VirtualKeyCode::LControl), - winuser::VK_RCONTROL => Some(VirtualKeyCode::RControl), - winuser::VK_LMENU => Some(VirtualKeyCode::LAlt), - winuser::VK_RMENU => Some(VirtualKeyCode::RAlt), - winuser::VK_PAUSE => Some(VirtualKeyCode::Pause), - winuser::VK_CAPITAL => Some(VirtualKeyCode::Capital), - winuser::VK_KANA => Some(VirtualKeyCode::Kana), - //winuser::VK_HANGUEL => Some(VirtualKeyCode::Hanguel), - //winuser::VK_HANGUL => Some(VirtualKeyCode::Hangul), - //winuser::VK_JUNJA => Some(VirtualKeyCode::Junja), - //winuser::VK_FINAL => Some(VirtualKeyCode::Final), - //winuser::VK_HANJA => Some(VirtualKeyCode::Hanja), - winuser::VK_KANJI => Some(VirtualKeyCode::Kanji), - winuser::VK_ESCAPE => Some(VirtualKeyCode::Escape), - winuser::VK_CONVERT => Some(VirtualKeyCode::Convert), - winuser::VK_NONCONVERT => Some(VirtualKeyCode::NoConvert), - //winuser::VK_ACCEPT => Some(VirtualKeyCode::Accept), - //winuser::VK_MODECHANGE => Some(VirtualKeyCode::Modechange), - winuser::VK_SPACE => Some(VirtualKeyCode::Space), - winuser::VK_PRIOR => Some(VirtualKeyCode::PageUp), - winuser::VK_NEXT => Some(VirtualKeyCode::PageDown), - winuser::VK_END => Some(VirtualKeyCode::End), - winuser::VK_HOME => Some(VirtualKeyCode::Home), - winuser::VK_LEFT => Some(VirtualKeyCode::Left), - winuser::VK_UP => Some(VirtualKeyCode::Up), - winuser::VK_RIGHT => Some(VirtualKeyCode::Right), - winuser::VK_DOWN => Some(VirtualKeyCode::Down), - //winuser::VK_SELECT => Some(VirtualKeyCode::Select), - //winuser::VK_PRINT => Some(VirtualKeyCode::Print), - //winuser::VK_EXECUTE => Some(VirtualKeyCode::Execute), - winuser::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot), - winuser::VK_INSERT => Some(VirtualKeyCode::Insert), - winuser::VK_DELETE => Some(VirtualKeyCode::Delete), - //winuser::VK_HELP => Some(VirtualKeyCode::Help), - 0x30 => Some(VirtualKeyCode::Key0), - 0x31 => Some(VirtualKeyCode::Key1), - 0x32 => Some(VirtualKeyCode::Key2), - 0x33 => Some(VirtualKeyCode::Key3), - 0x34 => Some(VirtualKeyCode::Key4), - 0x35 => Some(VirtualKeyCode::Key5), - 0x36 => Some(VirtualKeyCode::Key6), - 0x37 => Some(VirtualKeyCode::Key7), - 0x38 => Some(VirtualKeyCode::Key8), - 0x39 => Some(VirtualKeyCode::Key9), - 0x41 => Some(VirtualKeyCode::A), - 0x42 => Some(VirtualKeyCode::B), - 0x43 => Some(VirtualKeyCode::C), - 0x44 => Some(VirtualKeyCode::D), - 0x45 => Some(VirtualKeyCode::E), - 0x46 => Some(VirtualKeyCode::F), - 0x47 => Some(VirtualKeyCode::G), - 0x48 => Some(VirtualKeyCode::H), - 0x49 => Some(VirtualKeyCode::I), - 0x4A => Some(VirtualKeyCode::J), - 0x4B => Some(VirtualKeyCode::K), - 0x4C => Some(VirtualKeyCode::L), - 0x4D => Some(VirtualKeyCode::M), - 0x4E => Some(VirtualKeyCode::N), - 0x4F => Some(VirtualKeyCode::O), - 0x50 => Some(VirtualKeyCode::P), - 0x51 => Some(VirtualKeyCode::Q), - 0x52 => Some(VirtualKeyCode::R), - 0x53 => Some(VirtualKeyCode::S), - 0x54 => Some(VirtualKeyCode::T), - 0x55 => Some(VirtualKeyCode::U), - 0x56 => Some(VirtualKeyCode::V), - 0x57 => Some(VirtualKeyCode::W), - 0x58 => Some(VirtualKeyCode::X), - 0x59 => Some(VirtualKeyCode::Y), - 0x5A => Some(VirtualKeyCode::Z), - winuser::VK_LWIN => Some(VirtualKeyCode::LWin), - winuser::VK_RWIN => Some(VirtualKeyCode::RWin), - winuser::VK_APPS => Some(VirtualKeyCode::Apps), - winuser::VK_SLEEP => Some(VirtualKeyCode::Sleep), - winuser::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0), - winuser::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1), - winuser::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2), - winuser::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3), - winuser::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4), - winuser::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5), - winuser::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6), - winuser::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7), - winuser::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8), - winuser::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9), - winuser::VK_MULTIPLY => Some(VirtualKeyCode::NumpadMultiply), - winuser::VK_ADD => Some(VirtualKeyCode::NumpadAdd), - //winuser::VK_SEPARATOR => Some(VirtualKeyCode::Separator), - winuser::VK_SUBTRACT => Some(VirtualKeyCode::NumpadSubtract), - winuser::VK_DECIMAL => Some(VirtualKeyCode::NumpadDecimal), - winuser::VK_DIVIDE => Some(VirtualKeyCode::NumpadDivide), - winuser::VK_F1 => Some(VirtualKeyCode::F1), - winuser::VK_F2 => Some(VirtualKeyCode::F2), - winuser::VK_F3 => Some(VirtualKeyCode::F3), - winuser::VK_F4 => Some(VirtualKeyCode::F4), - winuser::VK_F5 => Some(VirtualKeyCode::F5), - winuser::VK_F6 => Some(VirtualKeyCode::F6), - winuser::VK_F7 => Some(VirtualKeyCode::F7), - winuser::VK_F8 => Some(VirtualKeyCode::F8), - winuser::VK_F9 => Some(VirtualKeyCode::F9), - winuser::VK_F10 => Some(VirtualKeyCode::F10), - winuser::VK_F11 => Some(VirtualKeyCode::F11), - winuser::VK_F12 => Some(VirtualKeyCode::F12), - winuser::VK_F13 => Some(VirtualKeyCode::F13), - winuser::VK_F14 => Some(VirtualKeyCode::F14), - winuser::VK_F15 => Some(VirtualKeyCode::F15), - winuser::VK_F16 => Some(VirtualKeyCode::F16), - winuser::VK_F17 => Some(VirtualKeyCode::F17), - winuser::VK_F18 => Some(VirtualKeyCode::F18), - winuser::VK_F19 => Some(VirtualKeyCode::F19), - winuser::VK_F20 => Some(VirtualKeyCode::F20), - winuser::VK_F21 => Some(VirtualKeyCode::F21), - winuser::VK_F22 => Some(VirtualKeyCode::F22), - winuser::VK_F23 => Some(VirtualKeyCode::F23), - winuser::VK_F24 => Some(VirtualKeyCode::F24), - winuser::VK_NUMLOCK => Some(VirtualKeyCode::Numlock), - winuser::VK_SCROLL => Some(VirtualKeyCode::Scroll), - winuser::VK_BROWSER_BACK => Some(VirtualKeyCode::NavigateBackward), - winuser::VK_BROWSER_FORWARD => Some(VirtualKeyCode::NavigateForward), - winuser::VK_BROWSER_REFRESH => Some(VirtualKeyCode::WebRefresh), - winuser::VK_BROWSER_STOP => Some(VirtualKeyCode::WebStop), - winuser::VK_BROWSER_SEARCH => Some(VirtualKeyCode::WebSearch), - winuser::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::WebFavorites), - winuser::VK_BROWSER_HOME => Some(VirtualKeyCode::WebHome), - winuser::VK_VOLUME_MUTE => Some(VirtualKeyCode::Mute), - winuser::VK_VOLUME_DOWN => Some(VirtualKeyCode::VolumeDown), - winuser::VK_VOLUME_UP => Some(VirtualKeyCode::VolumeUp), - winuser::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::NextTrack), - winuser::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::PrevTrack), - winuser::VK_MEDIA_STOP => Some(VirtualKeyCode::MediaStop), - winuser::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::PlayPause), - winuser::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Mail), - winuser::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::MediaSelect), - /*winuser::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1), - winuser::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),*/ - winuser::VK_OEM_PLUS => Some(VirtualKeyCode::Equals), - winuser::VK_OEM_COMMA => Some(VirtualKeyCode::Comma), - winuser::VK_OEM_MINUS => Some(VirtualKeyCode::Minus), - winuser::VK_OEM_PERIOD => Some(VirtualKeyCode::Period), - winuser::VK_OEM_1 => map_text_keys(vkey), - winuser::VK_OEM_2 => map_text_keys(vkey), - winuser::VK_OEM_3 => map_text_keys(vkey), - winuser::VK_OEM_4 => map_text_keys(vkey), - winuser::VK_OEM_5 => map_text_keys(vkey), - winuser::VK_OEM_6 => map_text_keys(vkey), - winuser::VK_OEM_7 => map_text_keys(vkey), - /* winuser::VK_OEM_8 => Some(VirtualKeyCode::Oem_8), */ - winuser::VK_OEM_102 => Some(VirtualKeyCode::OEM102), - /*winuser::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey), - winuser::VK_PACKET => Some(VirtualKeyCode::Packet), - winuser::VK_ATTN => Some(VirtualKeyCode::Attn), - winuser::VK_CRSEL => Some(VirtualKeyCode::Crsel), - winuser::VK_EXSEL => Some(VirtualKeyCode::Exsel), - winuser::VK_EREOF => Some(VirtualKeyCode::Ereof), - winuser::VK_PLAY => Some(VirtualKeyCode::Play), - winuser::VK_ZOOM => Some(VirtualKeyCode::Zoom), - winuser::VK_NONAME => Some(VirtualKeyCode::Noname), - winuser::VK_PA1 => Some(VirtualKeyCode::Pa1), - winuser::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/ + //VK_LBUTTON => Some(VirtualKeyCode::Lbutton), + //VK_RBUTTON => Some(VirtualKeyCode::Rbutton), + //VK_CANCEL => Some(VirtualKeyCode::Cancel), + //VK_MBUTTON => Some(VirtualKeyCode::Mbutton), + //VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1), + //VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2), + VK_BACK => Some(VirtualKeyCode::Back), + VK_TAB => Some(VirtualKeyCode::Tab), + //VK_CLEAR => Some(VirtualKeyCode::Clear), + VK_RETURN => Some(VirtualKeyCode::Return), + VK_LSHIFT => Some(VirtualKeyCode::LShift), + VK_RSHIFT => Some(VirtualKeyCode::RShift), + VK_LCONTROL => Some(VirtualKeyCode::LControl), + VK_RCONTROL => Some(VirtualKeyCode::RControl), + VK_LMENU => Some(VirtualKeyCode::LAlt), + VK_RMENU => Some(VirtualKeyCode::RAlt), + VK_PAUSE => Some(VirtualKeyCode::Pause), + VK_CAPITAL => Some(VirtualKeyCode::Capital), + VK_KANA => Some(VirtualKeyCode::Kana), + //VK_HANGUEL => Some(VirtualKeyCode::Hanguel), + //VK_HANGUL => Some(VirtualKeyCode::Hangul), + //VK_JUNJA => Some(VirtualKeyCode::Junja), + //VK_FINAL => Some(VirtualKeyCode::Final), + //VK_HANJA => Some(VirtualKeyCode::Hanja), + VK_KANJI => Some(VirtualKeyCode::Kanji), + VK_ESCAPE => Some(VirtualKeyCode::Escape), + VK_CONVERT => Some(VirtualKeyCode::Convert), + VK_NONCONVERT => Some(VirtualKeyCode::NoConvert), + //VK_ACCEPT => Some(VirtualKeyCode::Accept), + //VK_MODECHANGE => Some(VirtualKeyCode::Modechange), + VK_SPACE => Some(VirtualKeyCode::Space), + VK_PRIOR => Some(VirtualKeyCode::PageUp), + VK_NEXT => Some(VirtualKeyCode::PageDown), + VK_END => Some(VirtualKeyCode::End), + VK_HOME => Some(VirtualKeyCode::Home), + VK_LEFT => Some(VirtualKeyCode::Left), + VK_UP => Some(VirtualKeyCode::Up), + VK_RIGHT => Some(VirtualKeyCode::Right), + VK_DOWN => Some(VirtualKeyCode::Down), + //VK_SELECT => Some(VirtualKeyCode::Select), + //VK_PRINT => Some(VirtualKeyCode::Print), + //VK_EXECUTE => Some(VirtualKeyCode::Execute), + VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot), + VK_INSERT => Some(VirtualKeyCode::Insert), + VK_DELETE => Some(VirtualKeyCode::Delete), + //VK_HELP => Some(VirtualKeyCode::Help), + VIRTUAL_KEY(0x30) => Some(VirtualKeyCode::Key0), + VIRTUAL_KEY(0x31) => Some(VirtualKeyCode::Key1), + VIRTUAL_KEY(0x32) => Some(VirtualKeyCode::Key2), + VIRTUAL_KEY(0x33) => Some(VirtualKeyCode::Key3), + VIRTUAL_KEY(0x34) => Some(VirtualKeyCode::Key4), + VIRTUAL_KEY(0x35) => Some(VirtualKeyCode::Key5), + VIRTUAL_KEY(0x36) => Some(VirtualKeyCode::Key6), + VIRTUAL_KEY(0x37) => Some(VirtualKeyCode::Key7), + VIRTUAL_KEY(0x38) => Some(VirtualKeyCode::Key8), + VIRTUAL_KEY(0x39) => Some(VirtualKeyCode::Key9), + VIRTUAL_KEY(0x41) => Some(VirtualKeyCode::A), + VIRTUAL_KEY(0x42) => Some(VirtualKeyCode::B), + VIRTUAL_KEY(0x43) => Some(VirtualKeyCode::C), + VIRTUAL_KEY(0x44) => Some(VirtualKeyCode::D), + VIRTUAL_KEY(0x45) => Some(VirtualKeyCode::E), + VIRTUAL_KEY(0x46) => Some(VirtualKeyCode::F), + VIRTUAL_KEY(0x47) => Some(VirtualKeyCode::G), + VIRTUAL_KEY(0x48) => Some(VirtualKeyCode::H), + VIRTUAL_KEY(0x49) => Some(VirtualKeyCode::I), + VIRTUAL_KEY(0x4A) => Some(VirtualKeyCode::J), + VIRTUAL_KEY(0x4B) => Some(VirtualKeyCode::K), + VIRTUAL_KEY(0x4C) => Some(VirtualKeyCode::L), + VIRTUAL_KEY(0x4D) => Some(VirtualKeyCode::M), + VIRTUAL_KEY(0x4E) => Some(VirtualKeyCode::N), + VIRTUAL_KEY(0x4F) => Some(VirtualKeyCode::O), + VIRTUAL_KEY(0x50) => Some(VirtualKeyCode::P), + VIRTUAL_KEY(0x51) => Some(VirtualKeyCode::Q), + VIRTUAL_KEY(0x52) => Some(VirtualKeyCode::R), + VIRTUAL_KEY(0x53) => Some(VirtualKeyCode::S), + VIRTUAL_KEY(0x54) => Some(VirtualKeyCode::T), + VIRTUAL_KEY(0x55) => Some(VirtualKeyCode::U), + VIRTUAL_KEY(0x56) => Some(VirtualKeyCode::V), + VIRTUAL_KEY(0x57) => Some(VirtualKeyCode::W), + VIRTUAL_KEY(0x58) => Some(VirtualKeyCode::X), + VIRTUAL_KEY(0x59) => Some(VirtualKeyCode::Y), + VIRTUAL_KEY(0x5A) => Some(VirtualKeyCode::Z), + VK_LWIN => Some(VirtualKeyCode::LWin), + VK_RWIN => Some(VirtualKeyCode::RWin), + VK_APPS => Some(VirtualKeyCode::Apps), + VK_SLEEP => Some(VirtualKeyCode::Sleep), + VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0), + VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1), + VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2), + VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3), + VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4), + VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5), + VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6), + VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7), + VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8), + VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9), + VK_MULTIPLY => Some(VirtualKeyCode::NumpadMultiply), + VK_ADD => Some(VirtualKeyCode::NumpadAdd), + //VK_SEPARATOR => Some(VirtualKeyCode::Separator), + VK_SUBTRACT => Some(VirtualKeyCode::NumpadSubtract), + VK_DECIMAL => Some(VirtualKeyCode::NumpadDecimal), + VK_DIVIDE => Some(VirtualKeyCode::NumpadDivide), + VK_F1 => Some(VirtualKeyCode::F1), + VK_F2 => Some(VirtualKeyCode::F2), + VK_F3 => Some(VirtualKeyCode::F3), + VK_F4 => Some(VirtualKeyCode::F4), + VK_F5 => Some(VirtualKeyCode::F5), + VK_F6 => Some(VirtualKeyCode::F6), + VK_F7 => Some(VirtualKeyCode::F7), + VK_F8 => Some(VirtualKeyCode::F8), + VK_F9 => Some(VirtualKeyCode::F9), + VK_F10 => Some(VirtualKeyCode::F10), + VK_F11 => Some(VirtualKeyCode::F11), + VK_F12 => Some(VirtualKeyCode::F12), + VK_F13 => Some(VirtualKeyCode::F13), + VK_F14 => Some(VirtualKeyCode::F14), + VK_F15 => Some(VirtualKeyCode::F15), + VK_F16 => Some(VirtualKeyCode::F16), + VK_F17 => Some(VirtualKeyCode::F17), + VK_F18 => Some(VirtualKeyCode::F18), + VK_F19 => Some(VirtualKeyCode::F19), + VK_F20 => Some(VirtualKeyCode::F20), + VK_F21 => Some(VirtualKeyCode::F21), + VK_F22 => Some(VirtualKeyCode::F22), + VK_F23 => Some(VirtualKeyCode::F23), + VK_F24 => Some(VirtualKeyCode::F24), + VK_NUMLOCK => Some(VirtualKeyCode::Numlock), + VK_SCROLL => Some(VirtualKeyCode::Scroll), + VK_BROWSER_BACK => Some(VirtualKeyCode::NavigateBackward), + VK_BROWSER_FORWARD => Some(VirtualKeyCode::NavigateForward), + VK_BROWSER_REFRESH => Some(VirtualKeyCode::WebRefresh), + VK_BROWSER_STOP => Some(VirtualKeyCode::WebStop), + VK_BROWSER_SEARCH => Some(VirtualKeyCode::WebSearch), + VK_BROWSER_FAVORITES => Some(VirtualKeyCode::WebFavorites), + VK_BROWSER_HOME => Some(VirtualKeyCode::WebHome), + VK_VOLUME_MUTE => Some(VirtualKeyCode::Mute), + VK_VOLUME_DOWN => Some(VirtualKeyCode::VolumeDown), + VK_VOLUME_UP => Some(VirtualKeyCode::VolumeUp), + VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::NextTrack), + VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::PrevTrack), + VK_MEDIA_STOP => Some(VirtualKeyCode::MediaStop), + VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::PlayPause), + VK_LAUNCH_MAIL => Some(VirtualKeyCode::Mail), + VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::MediaSelect), + /*VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1), + VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),*/ + VK_OEM_PLUS => Some(VirtualKeyCode::Equals), + VK_OEM_COMMA => Some(VirtualKeyCode::Comma), + VK_OEM_MINUS => Some(VirtualKeyCode::Minus), + VK_OEM_PERIOD => Some(VirtualKeyCode::Period), + VK_OEM_1 => map_text_keys(vkey), + VK_OEM_2 => map_text_keys(vkey), + VK_OEM_3 => map_text_keys(vkey), + VK_OEM_4 => map_text_keys(vkey), + VK_OEM_5 => map_text_keys(vkey), + VK_OEM_6 => map_text_keys(vkey), + VK_OEM_7 => map_text_keys(vkey), + /* VK_OEM_8 => Some(VirtualKeyCode::Oem_8), */ + VK_OEM_102 => Some(VirtualKeyCode::OEM102), + /*VK_PROCESSKEY => Some(VirtualKeyCode::Processkey), + VK_PACKET => Some(VirtualKeyCode::Packet), + VK_ATTN => Some(VirtualKeyCode::Attn), + VK_CRSEL => Some(VirtualKeyCode::Crsel), + VK_EXSEL => Some(VirtualKeyCode::Exsel), + VK_EREOF => Some(VirtualKeyCode::Ereof), + VK_PLAY => Some(VirtualKeyCode::Play), + VK_ZOOM => Some(VirtualKeyCode::Zoom), + VK_NONAME => Some(VirtualKeyCode::Noname), + VK_PA1 => Some(VirtualKeyCode::Pa1), + VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/ _ => None, } } pub fn handle_extended_keys( - vkey: c_int, - mut scancode: UINT, + vkey: VIRTUAL_KEY, + mut scancode: u32, extended: bool, -) -> Option<(c_int, UINT)> { +) -> Option<(VIRTUAL_KEY, u32)> { // Welcome to hell https://blog.molecular-matters.com/2011/09/05/properly-handling-keyboard-input/ scancode |= if extended { 0xE000 } else { 0x0000 }; let vkey = match vkey { - winuser::VK_SHIFT => unsafe { - winuser::MapVirtualKeyA(scancode, winuser::MAPVK_VSC_TO_VK_EX) as _ - }, - winuser::VK_CONTROL => { + VK_SHIFT => VIRTUAL_KEY(unsafe { MapVirtualKeyA(scancode, MAPVK_VSC_TO_VK_EX) } as u16), + VK_CONTROL => { if extended { - winuser::VK_RCONTROL + VK_RCONTROL } else { - winuser::VK_LCONTROL + VK_LCONTROL } } - winuser::VK_MENU => { + VK_MENU => { if extended { - winuser::VK_RMENU + VK_RMENU } else { - winuser::VK_LMENU + VK_LMENU } } _ => { @@ -367,20 +384,20 @@ pub fn handle_extended_keys( // When VK_PAUSE is pressed it emits a LeftControl + NumLock scancode event sequence, but reports VK_PAUSE // as the virtual key on both events, or VK_PAUSE on the first event or 0xFF when using raw input. // Don't emit anything for the LeftControl event in the pair... - 0xE01D if vkey == winuser::VK_PAUSE => return None, + 0xE01D if vkey == VK_PAUSE => return None, // ...and emit the Pause event for the second event in the pair. - 0x45 if vkey == winuser::VK_PAUSE || vkey == 0xFF => { + 0x45 if vkey == VK_PAUSE || vkey == VIRTUAL_KEY(0xFF) => { scancode = 0xE059; - winuser::VK_PAUSE + VK_PAUSE } // VK_PAUSE has an incorrect vkey value when used with modifiers. VK_PAUSE also reports a different // scancode when used with modifiers than when used without 0xE046 => { scancode = 0xE059; - winuser::VK_PAUSE + VK_PAUSE } // VK_SCROLL has an incorrect vkey value when used with modifiers. - 0x46 => winuser::VK_SCROLL, + 0x46 => VK_SCROLL, _ => vkey, } } @@ -392,18 +409,16 @@ pub fn process_key_params( wparam: WPARAM, lparam: LPARAM, ) -> Option<(ScanCode, Option)> { - let scancode = ((lparam >> 16) & 0xff) as UINT; - let extended = (lparam & 0x01000000) != 0; - handle_extended_keys(wparam as _, scancode, extended) + let scancode = ((lparam.0 >> 16) & 0xff) as u32; + let extended = (lparam.0 & 0x01000000) != 0; + handle_extended_keys(VIRTUAL_KEY(wparam.0 as u16), scancode, extended) .map(|(vkey, scancode)| (scancode, vkey_to_winit_vkey(vkey))) } // This is needed as windows doesn't properly distinguish // some virtual key codes for different keyboard layouts -fn map_text_keys(win_virtual_key: i32) -> Option { - let char_key = - unsafe { winuser::MapVirtualKeyA(win_virtual_key as u32, winuser::MAPVK_VK_TO_CHAR) } - & 0x7FFF; +fn map_text_keys(win_virtual_key: VIRTUAL_KEY) -> Option { + let char_key = unsafe { MapVirtualKeyA(win_virtual_key.0 as u32, MAPVK_VK_TO_CHAR) } & 0x7FFF; match char::from_u32(char_key) { Some(';') => Some(VirtualKeyCode::Semicolon), Some('/') => Some(VirtualKeyCode::Slash), diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 0275f3fc9d..6b4e6819fc 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -17,17 +17,67 @@ use std::{ time::{Duration, Instant}, }; -use winapi::{ - shared::{ - basetsd::LONG_PTR, - minwindef::{BOOL, DWORD, HIWORD, INT, LOWORD, LPARAM, LRESULT, UINT, WORD, WPARAM}, - windef::{HWND, POINT, RECT}, - windowsx, winerror, - }, - um::{ - libloaderapi, mmsystem, ole2, processthreadsapi, timeapi, winbase, - winnt::{HANDLE, LONG, LPCSTR, SHORT}, - winuser, +use windows::{ + runtime::Handle, + Win32::{ + Devices::HumanInterfaceDevice::MOUSE_MOVE_RELATIVE, + Foundation::{ + BOOL, HANDLE, HWND, LPARAM, LRESULT, POINT, PSTR, PWSTR, RECT, WAIT_TIMEOUT, + WIN32_ERROR, WPARAM, + }, + Graphics::Gdi::{ + ClientToScreen, GetMonitorInfoW, GetUpdateRect, MonitorFromRect, MonitorFromWindow, + RedrawWindow, ScreenToClient, ValidateRect, HBRUSH, MONITORINFO, MONITOR_DEFAULTTONULL, + RDW_INTERNALPAINT, SC_SCREENSAVE, + }, + Media::Multimedia::{ + timeBeginPeriod, timeEndPeriod, timeGetDevCaps, TIMECAPS, TIMERR_NOERROR, + }, + System::{ + LibraryLoader::GetModuleHandleW, + Ole::{IDropTarget, RevokeDragDrop}, + Threading::{GetCurrentThreadId, MsgWaitForMultipleObjectsEx, MWMO_INPUTAVAILABLE}, + WindowsProgramming::INFINITE, + }, + UI::{ + Controls::{HOVER_DEFAULT, WM_MOUSELEAVE}, + Input::{ + KeyboardAndMouse::{ + MapVirtualKeyA, ReleaseCapture, SetCapture, TrackMouseEvent, TME_LEAVE, + TRACKMOUSEEVENT, VIRTUAL_KEY, VK_F4, + }, + Pointer::{ + POINTER_FLAG_DOWN, POINTER_FLAG_UP, POINTER_FLAG_UPDATE, POINTER_INFO, + POINTER_PEN_INFO, POINTER_TOUCH_INFO, + }, + Touch::{ + CloseTouchInputHandle, GetTouchInputInfo, HTOUCHINPUT, TOUCHEVENTF_DOWN, + TOUCHEVENTF_MOVE, TOUCHEVENTF_UP, TOUCHINPUT, + }, + HRAWINPUT, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + }, + WindowsAndMessaging::{ + CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, GetClientRect, + GetCursorPos, GetMessageW, GetWindowLongW, LoadCursorW, PeekMessageW, PostMessageW, + PostThreadMessageW, RegisterClassExW, RegisterWindowMessageA, SetCursor, + SetWindowPos, TranslateMessage, CREATESTRUCTW, GIDC_ARRIVAL, GIDC_REMOVAL, + GWL_EXSTYLE, GWL_STYLE, GWL_USERDATA, HCURSOR, HICON, HMENU, HTCAPTION, HTCLIENT, + MAPVK_VK_TO_VSC, MINMAXINFO, MSG, PM_NOREMOVE, PM_QS_PAINT, PM_REMOVE, PT_PEN, + PT_TOUCH, QS_ALLEVENTS, RI_KEY_E0, RI_KEY_E1, RI_MOUSE_WHEEL, SC_MINIMIZE, + SC_RESTORE, SIZE_MAXIMIZED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, + WINDOWPOS, WINDOW_EX_STYLE, WINDOW_STYLE, WM_CAPTURECHANGED, WM_CHAR, WM_CLOSE, + WM_CREATE, WM_DESTROY, WM_DPICHANGED, WM_DROPFILES, WM_ENTERSIZEMOVE, + WM_EXITSIZEMOVE, WM_GETMINMAXINFO, WM_INPUT, WM_INPUT_DEVICE_CHANGE, WM_KEYDOWN, + WM_KEYUP, WM_KILLFOCUS, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, + WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCCREATE, WM_NCDESTROY, + WM_NCLBUTTONDOWN, WM_PAINT, WM_POINTERDOWN, WM_POINTERUP, WM_POINTERUPDATE, + WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SETFOCUS, WM_SETTINGCHANGE, WM_SIZE, + WM_SYSCHAR, WM_SYSCOMMAND, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TOUCH, + WM_WINDOWPOSCHANGED, WM_WINDOWPOSCHANGING, WM_XBUTTONDOWN, WM_XBUTTONUP, + WNDCLASSEXW, WNDCLASS_STYLES, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, + WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, + }, + }, }, }; @@ -39,7 +89,6 @@ use crate::{ platform_impl::platform::{ dark_mode::try_theme, dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling}, - drop_handler::FileDropHandler, event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey}, monitor::{self, MonitorHandle}, raw_input, util, @@ -52,13 +101,13 @@ use crate::{ use runner::{EventLoopRunner, EventLoopRunnerShared}; type GetPointerFrameInfoHistory = unsafe extern "system" fn( - pointerId: UINT, - entriesCount: *mut UINT, - pointerCount: *mut UINT, - pointerInfo: *mut winuser::POINTER_INFO, + pointerId: u32, + entriesCount: *mut u32, + pointerCount: *mut u32, + pointerInfo: *mut POINTER_INFO, ) -> BOOL; -type SkipPointerFrameMessages = unsafe extern "system" fn(pointerId: UINT) -> BOOL; +type SkipPointerFrameMessages = unsafe extern "system" fn(pointerId: u32) -> BOOL; type GetPointerDeviceRects = unsafe extern "system" fn( device: HANDLE, pointerDeviceRect: *mut RECT, @@ -66,10 +115,10 @@ type GetPointerDeviceRects = unsafe extern "system" fn( ) -> BOOL; type GetPointerTouchInfo = - unsafe extern "system" fn(pointerId: UINT, touchInfo: *mut winuser::POINTER_TOUCH_INFO) -> BOOL; + unsafe extern "system" fn(pointerId: u32, touchInfo: *mut POINTER_TOUCH_INFO) -> BOOL; type GetPointerPenInfo = - unsafe extern "system" fn(pointId: UINT, penInfo: *mut winuser::POINTER_PEN_INFO) -> BOOL; + unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL; lazy_static! { static ref GET_POINTER_FRAME_INFO_HISTORY: Option = @@ -86,7 +135,7 @@ lazy_static! { pub(crate) struct WindowData { pub window_state: Arc>, pub event_loop_runner: EventLoopRunnerShared, - pub _file_drop_handler: Option, + pub _drop_target: Option, pub userdata_removed: Cell, pub recurse_depth: Cell, } @@ -114,14 +163,14 @@ pub struct EventLoop { } pub struct EventLoopWindowTarget { - thread_id: DWORD, + thread_id: u32, thread_msg_target: HWND, pub(crate) runner_shared: EventLoopRunnerShared, } macro_rules! main_thread_check { ($fn_name:literal) => {{ - let thread_id = unsafe { processthreadsapi::GetCurrentThreadId() }; + let thread_id = unsafe { GetCurrentThreadId() }; if thread_id != main_thread_id() { panic!(concat!( "Initializing the event loop outside of the main thread is a significant \ @@ -153,18 +202,17 @@ impl EventLoop { } pub fn new_dpi_unaware_any_thread() -> EventLoop { - let thread_id = unsafe { processthreadsapi::GetCurrentThreadId() }; + let thread_id = unsafe { GetCurrentThreadId() }; let thread_msg_target = create_event_target_window::(); - let send_thread_msg_target = thread_msg_target as usize; - thread::spawn(move || wait_thread(thread_id, send_thread_msg_target as HWND)); + thread::spawn(move || wait_thread(thread_id, thread_msg_target)); let wait_thread_id = get_wait_thread_id(); let runner_shared = Rc::new(EventLoopRunner::new(thread_msg_target, wait_thread_id)); let thread_msg_sender = - insert_event_target_window_data::(thread_msg_target, runner_shared.clone()); + insert_event_target_window_data(thread_msg_target, runner_shared.clone()); raw_input::register_all_mice_and_keyboards_for_raw_input(thread_msg_target); EventLoop { @@ -214,11 +262,11 @@ impl EventLoop { runner.poll(); 'main: loop { - if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) { + if !GetMessageW(&mut msg, None, 0, 0).as_bool() { break 'main; } - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); + TranslateMessage(&msg); + DispatchMessageW(&msg); if let Err(payload) = runner.take_panic_error() { runner.reset_runner(); @@ -283,8 +331,8 @@ impl EventLoopWindowTarget { /// /// Full details of CRT initialization can be found here: /// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-160 -fn main_thread_id() -> DWORD { - static mut MAIN_THREAD_ID: DWORD = 0; +fn main_thread_id() -> u32 { + static mut MAIN_THREAD_ID: u32 = 0; /// Function pointer used in CRT initialization section to set the above static field's value. @@ -298,7 +346,7 @@ fn main_thread_id() -> DWORD { #[link_section = ".CRT$XCU"] static INIT_MAIN_THREAD_ID: unsafe fn() = { unsafe fn initer() { - MAIN_THREAD_ID = processthreadsapi::GetCurrentThreadId(); + MAIN_THREAD_ID = GetCurrentThreadId(); } initer }; @@ -306,33 +354,31 @@ fn main_thread_id() -> DWORD { unsafe { MAIN_THREAD_ID } } -fn get_wait_thread_id() -> DWORD { +fn get_wait_thread_id() -> u32 { unsafe { let mut msg = mem::zeroed(); - let result = winuser::GetMessageW( + let result = GetMessageW( &mut msg, - -1 as _, + HWND(-1), *SEND_WAIT_THREAD_ID_MSG_ID, *SEND_WAIT_THREAD_ID_MSG_ID, ); assert_eq!( msg.message, *SEND_WAIT_THREAD_ID_MSG_ID, "this shouldn't be possible. please open an issue with Winit. error code: {}", - result + result.0 ); - msg.lParam as DWORD + msg.lParam.0 as u32 } } lazy_static! { - static ref WAIT_PERIOD_MIN: Option = unsafe { - let mut caps = mmsystem::TIMECAPS { + static ref WAIT_PERIOD_MIN: Option = unsafe { + let mut caps = TIMECAPS { wPeriodMin: 0, wPeriodMax: 0, }; - if timeapi::timeGetDevCaps(&mut caps, mem::size_of::() as _) - == mmsystem::TIMERR_NOERROR - { + if timeGetDevCaps(&mut caps, mem::size_of::() as u32) == TIMERR_NOERROR { Some(caps.wPeriodMin) } else { None @@ -340,16 +386,16 @@ lazy_static! { }; } -fn wait_thread(parent_thread_id: DWORD, msg_window_id: HWND) { +fn wait_thread(parent_thread_id: u32, msg_window_id: HWND) { unsafe { - let mut msg: winuser::MSG; + let mut msg: MSG; - let cur_thread_id = processthreadsapi::GetCurrentThreadId(); - winuser::PostThreadMessageW( + let cur_thread_id = GetCurrentThreadId(); + PostThreadMessageW( parent_thread_id, *SEND_WAIT_THREAD_ID_MSG_ID, - 0, - cur_thread_id as LPARAM, + WPARAM(0), + LPARAM(cur_thread_id as isize), ); let mut wait_until_opt = None; @@ -360,21 +406,19 @@ fn wait_thread(parent_thread_id: DWORD, msg_window_id: HWND) { msg = mem::zeroed(); if wait_until_opt.is_some() { - if 0 != winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, winuser::PM_REMOVE) { - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); + if PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() { + TranslateMessage(&msg); + DispatchMessageW(&msg); } + } else if !GetMessageW(&mut msg, None, 0, 0).as_bool() { + break 'main; } else { - if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) { - break 'main; - } else { - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); - } + TranslateMessage(&msg); + DispatchMessageW(&msg); } if msg.message == *WAIT_UNTIL_MSG_ID { - wait_until_opt = Some(*WaitUntilInstantBox::from_raw(msg.lParam as *mut _)); + wait_until_opt = Some(*WaitUntilInstantBox::from_raw(msg.lParam.0 as *mut _)); } else if msg.message == *CANCEL_WAIT_UNTIL_MSG_ID { wait_until_opt = None; } @@ -386,28 +430,38 @@ fn wait_thread(parent_thread_id: DWORD, msg_window_id: HWND) { // `WaitUntil`, so we request the Windows scheduler to use a higher accuracy if possible. // If we couldn't query the timer capabilities, then we use the default resolution. if let Some(period) = *WAIT_PERIOD_MIN { - timeapi::timeBeginPeriod(period); + timeBeginPeriod(period); } // `MsgWaitForMultipleObjects` is bound by the granularity of the scheduler period. // Because of this, we try to reduce the requested time just enough to undershoot `wait_until` // by the smallest amount possible, and then we busy loop for the remaining time inside the // NewEvents message handler. - let resume_reason = winuser::MsgWaitForMultipleObjectsEx( + let resume_reason = MsgWaitForMultipleObjectsEx( 0, ptr::null(), dur2timeout(wait_until - now).saturating_sub(WAIT_PERIOD_MIN.unwrap_or(1)), - winuser::QS_ALLEVENTS, - winuser::MWMO_INPUTAVAILABLE, + QS_ALLEVENTS, + MWMO_INPUTAVAILABLE, ); if let Some(period) = *WAIT_PERIOD_MIN { - timeapi::timeEndPeriod(period); + timeEndPeriod(period); } - if resume_reason == winerror::WAIT_TIMEOUT { - winuser::PostMessageW(msg_window_id, *PROCESS_NEW_EVENTS_MSG_ID, 0, 0); + if WIN32_ERROR(resume_reason) == WAIT_TIMEOUT { + PostMessageW( + msg_window_id, + *PROCESS_NEW_EVENTS_MSG_ID, + WPARAM(0), + LPARAM(0), + ); wait_until_opt = None; } } else { - winuser::PostMessageW(msg_window_id, *PROCESS_NEW_EVENTS_MSG_ID, 0, 0); + PostMessageW( + msg_window_id, + *PROCESS_NEW_EVENTS_MSG_ID, + WPARAM(0), + LPARAM(0), + ); wait_until_opt = None; } } @@ -416,7 +470,7 @@ fn wait_thread(parent_thread_id: DWORD, msg_window_id: HWND) { } // Implementation taken from https://github.com/rust-lang/rust/blob/db5476571d9b27c862b95c1e64764b0ac8980e23/src/libstd/sys/windows/mod.rs -fn dur2timeout(dur: Duration) -> DWORD { +fn dur2timeout(dur: Duration) -> u32 { // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the // timeouts in windows APIs are typically u32 milliseconds. To translate, we // have two pieces to take care of: @@ -435,25 +489,25 @@ fn dur2timeout(dur: Duration) -> DWORD { }) }) .map(|ms| { - if ms > DWORD::max_value() as u64 { - winbase::INFINITE + if ms > u32::MAX as u64 { + INFINITE } else { - ms as DWORD + ms as u32 } }) - .unwrap_or(winbase::INFINITE) + .unwrap_or(INFINITE) } impl Drop for EventLoop { fn drop(&mut self) { unsafe { - winuser::DestroyWindow(self.window_target.p.thread_msg_target); + DestroyWindow(self.window_target.p.thread_msg_target); } } } pub(crate) struct EventLoopThreadExecutor { - thread_id: DWORD, + thread_id: u32, target_window: HWND, } @@ -463,7 +517,7 @@ unsafe impl Sync for EventLoopThreadExecutor {} impl EventLoopThreadExecutor { /// Check to see if we're in the parent event loop's thread. pub(super) fn in_event_loop_thread(&self) -> bool { - let cur_thread_id = unsafe { processthreadsapi::GetCurrentThreadId() }; + let cur_thread_id = unsafe { GetCurrentThreadId() }; self.thread_id == cur_thread_id } @@ -494,13 +548,16 @@ impl EventLoopThreadExecutor { let raw = Box::into_raw(boxed2); - let res = winuser::PostMessageW( + let res = PostMessageW( self.target_window, *EXEC_MSG_ID, - raw as *mut () as usize as WPARAM, - 0, + WPARAM(raw as usize), + LPARAM(0), + ); + assert!( + res.as_bool(), + "PostMessage failed ; is the messages queue full?" ); - assert!(res != 0, "PostMessage failed ; is the messages queue full?"); } } } @@ -526,7 +583,8 @@ impl Clone for EventLoopProxy { impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { unsafe { - if winuser::PostMessageW(self.target_window, *USER_EVENT_MSG_ID, 0, 0) != 0 { + if PostMessageW(self.target_window, *USER_EVENT_MSG_ID, WPARAM(0), LPARAM(0)).as_bool() + { self.event_send.send(event).ok(); Ok(()) } else { @@ -543,7 +601,7 @@ lazy_static! { // WPARAM and LPARAM are unused. static ref USER_EVENT_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::WakeupMsg\0".as_ptr() as LPCSTR) + RegisterWindowMessageA(PSTR("Winit::WakeupMsg\0".as_ptr() as *mut u8)) } }; // Message sent when we want to execute a closure in the thread. @@ -551,43 +609,43 @@ lazy_static! { // and LPARAM is unused. static ref EXEC_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr() as *const i8) + RegisterWindowMessageA(PSTR("Winit::ExecMsg\0".as_ptr() as *mut u8)) } }; static ref PROCESS_NEW_EVENTS_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::ProcessNewEvents\0".as_ptr() as *const i8) + RegisterWindowMessageA(PSTR("Winit::ProcessNewEvents\0".as_ptr() as *mut u8)) } }; /// lparam is the wait thread's message id. static ref SEND_WAIT_THREAD_ID_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::SendWaitThreadId\0".as_ptr() as *const i8) + RegisterWindowMessageA(PSTR("Winit::SendWaitThreadId\0".as_ptr() as *mut u8)) } }; /// lparam points to a `Box` signifying the time `PROCESS_NEW_EVENTS_MSG_ID` should /// be sent. static ref WAIT_UNTIL_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::WaitUntil\0".as_ptr() as *const i8) + RegisterWindowMessageA(PSTR("Winit::WaitUntil\0".as_ptr() as *mut u8)) } }; static ref CANCEL_WAIT_UNTIL_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::CancelWaitUntil\0".as_ptr() as *const i8) + RegisterWindowMessageA(PSTR("Winit::CancelWaitUntil\0".as_ptr() as *mut u8)) } }; // Message sent by a `Window` when it wants to be destroyed by the main thread. // WPARAM and LPARAM are unused. pub static ref DESTROY_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::DestroyMsg\0".as_ptr() as LPCSTR) + RegisterWindowMessageA(PSTR("Winit::DestroyMsg\0".as_ptr() as *mut u8)) } }; // WPARAM is a bool specifying the `WindowFlags::MARKER_RETAIN_STATE_ON_SIZE` flag. See the // documentation in the `window_state` module for more information. pub static ref SET_RETAIN_STATE_ON_SIZE_MSG_ID: u32 = unsafe { - winuser::RegisterWindowMessageA("Winit::SetRetainMaximized\0".as_ptr() as LPCSTR) + RegisterWindowMessageA(PSTR("Winit::SetRetainMaximized\0".as_ptr() as *mut u8)) }; static ref THREAD_EVENT_TARGET_WINDOW_CLASS: Vec = { use std::ffi::OsStr; @@ -602,29 +660,29 @@ lazy_static! { fn create_event_target_window() -> HWND { unsafe { - let class = winuser::WNDCLASSEXW { - cbSize: mem::size_of::() as UINT, - style: 0, + let class = WNDCLASSEXW { + cbSize: mem::size_of::() as u32, + style: WNDCLASS_STYLES(0), lpfnWndProc: Some(thread_event_target_callback::), cbClsExtra: 0, cbWndExtra: 0, - hInstance: libloaderapi::GetModuleHandleW(ptr::null()), - hIcon: ptr::null_mut(), - hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly - hbrBackground: ptr::null_mut(), - lpszMenuName: ptr::null(), - lpszClassName: THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr(), - hIconSm: ptr::null_mut(), + hInstance: GetModuleHandleW(None), + hIcon: HICON(0), + hCursor: HCURSOR(0), // must be null in order for cursor state to work properly + hbrBackground: HBRUSH(0), + lpszMenuName: PWSTR(ptr::null_mut()), + lpszClassName: PWSTR(THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr() as *mut u16), + hIconSm: HICON(0), }; - winuser::RegisterClassExW(&class); + RegisterClassExW(&class); } unsafe { - let window = winuser::CreateWindowExW( - winuser::WS_EX_NOACTIVATE - | winuser::WS_EX_TRANSPARENT - | winuser::WS_EX_LAYERED + let window = CreateWindowExW( + WS_EX_NOACTIVATE + | WS_EX_TRANSPARENT + | WS_EX_LAYERED // WS_EX_TOOLWINDOW prevents this window from ever showing up in the taskbar, which // we want to avoid. If you remove this style, this window won't show up in the // taskbar *initially*, but it can show up at some later point. This can sometimes @@ -632,26 +690,27 @@ fn create_event_target_window() -> HWND { // difficult to reproduce. Alternatively, it can be manually triggered by killing // `explorer.exe` and then starting the process back up. // It is unclear why the bug is triggered by waiting for several hours. - | winuser::WS_EX_TOOLWINDOW, - THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr(), - ptr::null_mut(), - 0, + | WS_EX_TOOLWINDOW, + PWSTR(THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr() as *mut u16), + PWSTR(ptr::null_mut()), + WS_OVERLAPPED, 0, 0, 0, 0, - ptr::null_mut(), - ptr::null_mut(), - libloaderapi::GetModuleHandleW(ptr::null()), + HWND(0), + HMENU(0), + GetModuleHandleW(None), ptr::null_mut(), ); - winuser::SetWindowLongPtrW( + + super::SetWindowLongPtrW( window, - winuser::GWL_STYLE, + GWL_STYLE, // The window technically has to be visible to receive WM_PAINT messages (which are used // for delivering events during resizes), but it isn't displayed to the user because of // the LAYERED style. - (winuser::WS_VISIBLE | winuser::WS_POPUP) as WindowLongPtr, + (WS_VISIBLE | WS_POPUP).0 as isize, ); window } @@ -669,13 +728,7 @@ fn insert_event_target_window_data( }; let input_ptr = Box::into_raw(Box::new(userdata)); - unsafe { - winuser::SetWindowLongPtrW( - thread_msg_target, - winuser::GWL_USERDATA, - input_ptr as WindowLongPtr, - ) - }; + unsafe { super::SetWindowLongPtrW(thread_msg_target, GWL_USERDATA, input_ptr as isize) }; tx } @@ -684,7 +737,7 @@ fn insert_event_target_window_data( /// the window. unsafe fn capture_mouse(window: HWND, window_state: &mut WindowState) { window_state.mouse.capture_count += 1; - winuser::SetCapture(window); + SetCapture(window); } /// Release mouse input, stopping windows on this thread from receiving mouse input when the cursor @@ -694,7 +747,7 @@ unsafe fn release_mouse(mut window_state: parking_lot::MutexGuard<'_, WindowStat if window_state.mouse.capture_count == 0 { // ReleaseCapture() causes a WM_CAPTURECHANGED where we lock the window_state. drop(window_state); - winuser::ReleaseCapture(); + ReleaseCapture(); } } @@ -730,18 +783,20 @@ unsafe fn flush_paint_messages( return; } - if 0 == winuser::PeekMessageW( + if !PeekMessageW( &mut msg, redraw_window, - winuser::WM_PAINT, - winuser::WM_PAINT, - winuser::PM_REMOVE | winuser::PM_QS_PAINT, - ) { + WM_PAINT, + WM_PAINT, + PM_REMOVE | PM_QS_PAINT, + ) + .as_bool() + { return; } - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); + TranslateMessage(&msg); + DispatchMessageW(&msg); }); true } else { @@ -752,15 +807,20 @@ unsafe fn flush_paint_messages( unsafe fn process_control_flow(runner: &EventLoopRunner) { match runner.control_flow() { ControlFlow::Poll => { - winuser::PostMessageW(runner.thread_msg_target(), *PROCESS_NEW_EVENTS_MSG_ID, 0, 0); + PostMessageW( + runner.thread_msg_target(), + *PROCESS_NEW_EVENTS_MSG_ID, + WPARAM(0), + LPARAM(0), + ); } ControlFlow::Wait => (), ControlFlow::WaitUntil(until) => { - winuser::PostThreadMessageW( + PostThreadMessageW( runner.wait_thread_id(), *WAIT_UNTIL_MSG_ID, - 0, - Box::into_raw(WaitUntilInstantBox::new(until)) as LPARAM, + WPARAM(0), + LPARAM(Box::into_raw(WaitUntilInstantBox::new(until)) as isize), ); } ControlFlow::Exit => (), @@ -788,11 +848,6 @@ fn update_modifiers(window: HWND, userdata: &WindowData) { } } -#[cfg(target_arch = "x86_64")] -type WindowLongPtr = LONG_PTR; -#[cfg(target_arch = "x86")] -type WindowLongPtr = LONG; - /// Any window whose callback is configured to this function will have its events propagated /// through the events loop of the thread the window was created in. // @@ -802,35 +857,32 @@ type WindowLongPtr = LONG; // FIXME: detect WM_DWMCOMPOSITIONCHANGED and call DwmEnableBlurBehindWindow if necessary pub(super) unsafe extern "system" fn public_window_callback( window: HWND, - msg: UINT, + msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { - let userdata = winuser::GetWindowLongPtrW(window, winuser::GWL_USERDATA); + let userdata = super::GetWindowLongPtrW(window, GWL_USERDATA); + let userdata_ptr = match (userdata, msg) { - (0, winuser::WM_NCCREATE) => { - let createstruct = &mut *(lparam as *mut winuser::CREATESTRUCTW); - let initdata = createstruct.lpCreateParams as LONG_PTR; + (0, WM_NCCREATE) => { + let createstruct = &mut *(lparam.0 as *mut CREATESTRUCTW); + let initdata = createstruct.lpCreateParams as isize; let initdata = &mut *(initdata as *mut InitData<'_, T>); let runner = initdata.event_loop.runner_shared.clone(); if let Some((win, userdata)) = runner.catch_unwind(|| (initdata.post_init)(window)) { initdata.window = Some(win); let userdata = Box::into_raw(Box::new(userdata)); - winuser::SetWindowLongPtrW( - window, - winuser::GWL_USERDATA, - userdata as WindowLongPtr, - ); + super::SetWindowLongPtrW(window, GWL_USERDATA, userdata as isize); userdata } else { - return -1; + return LRESULT(-1); } } // Getting here should quite frankly be impossible, // but we'll make window creation fail here just in case. - (0, winuser::WM_CREATE) => return -1, - (0, _) => return winuser::DefWindowProcW(window, msg, wparam, lparam), + (0, WM_CREATE) => return LRESULT(-1), + (0, _) => return DefWindowProcW(window, msg, wparam, lparam), _ => userdata as *mut WindowData, }; @@ -839,7 +891,7 @@ pub(super) unsafe extern "system" fn public_window_callback( userdata.recurse_depth.set(userdata.recurse_depth.get() + 1); - let result = public_window_callback_inner(window, msg, wparam, lparam, &userdata); + let result = public_window_callback_inner(window, msg, wparam, lparam, userdata); let userdata_removed = userdata.userdata_removed.get(); let recurse_depth = userdata.recurse_depth.get() - 1; @@ -857,86 +909,81 @@ pub(super) unsafe extern "system" fn public_window_callback( unsafe fn public_window_callback_inner( window: HWND, - msg: UINT, + msg: u32, wparam: WPARAM, lparam: LPARAM, userdata: &WindowData, ) -> LRESULT { - winuser::RedrawWindow( + RedrawWindow( userdata.event_loop_runner.thread_msg_target(), ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, + None, + RDW_INTERNALPAINT, ); // I decided to bind the closure to `callback` and pass it to catch_unwind rather than passing // the closure to catch_unwind directly so that the match body indendation wouldn't change and // the git blame and history would be preserved. let callback = || match msg { - winuser::WM_ENTERSIZEMOVE => { + WM_ENTERSIZEMOVE => { userdata .window_state .lock() .set_window_flags_in_place(|f| f.insert(WindowFlags::MARKER_IN_SIZE_MOVE)); - 0 + LRESULT(0) } - winuser::WM_EXITSIZEMOVE => { + WM_EXITSIZEMOVE => { userdata .window_state .lock() .set_window_flags_in_place(|f| f.remove(WindowFlags::MARKER_IN_SIZE_MOVE)); - 0 + LRESULT(0) } - winuser::WM_NCCREATE => { + WM_NCCREATE => { enable_non_client_dpi_scaling(window); - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_NCLBUTTONDOWN => { - if wparam == winuser::HTCAPTION as _ { - winuser::PostMessageW(window, winuser::WM_MOUSEMOVE, 0, lparam); + WM_NCLBUTTONDOWN => { + if wparam.0 == HTCAPTION as usize { + PostMessageW(window, WM_MOUSEMOVE, WPARAM(0), lparam); } - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_CLOSE => { + WM_CLOSE => { use crate::event::WindowEvent::CloseRequested; userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: CloseRequested, }); - 0 + LRESULT(0) } - winuser::WM_DESTROY => { + WM_DESTROY => { use crate::event::WindowEvent::Destroyed; - ole2::RevokeDragDrop(window); + let _ = RevokeDragDrop(window); userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: Destroyed, }); userdata.event_loop_runner.remove_window(window); - 0 + LRESULT(0) } - winuser::WM_NCDESTROY => { - winuser::SetWindowLongPtrW(window, winuser::GWL_USERDATA, 0); + WM_NCDESTROY => { + super::SetWindowLongPtrW(window, GWL_USERDATA, 0); userdata.userdata_removed.set(true); - 0 + LRESULT(0) } - winuser::WM_PAINT => { + WM_PAINT => { if userdata.event_loop_runner.should_buffer() { // this branch can happen in response to `UpdateWindow`, if win32 decides to // redraw the window outside the normal flow of the event loop. - winuser::RedrawWindow( - window, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + RedrawWindow(window, ptr::null(), None, RDW_INTERNALPAINT); } else { let managing_redraw = flush_paint_messages(Some(window), &userdata.event_loop_runner); @@ -947,31 +994,32 @@ unsafe fn public_window_callback_inner( } } - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_WINDOWPOSCHANGING => { + WM_WINDOWPOSCHANGING => { let mut window_state = userdata.window_state.lock(); if let Some(ref mut fullscreen) = window_state.fullscreen { - let window_pos = &mut *(lparam as *mut winuser::WINDOWPOS); + let window_pos = &mut *(lparam.0 as *mut WINDOWPOS); let new_rect = RECT { left: window_pos.x, top: window_pos.y, right: window_pos.x + window_pos.cx, bottom: window_pos.y + window_pos.cy, }; - let new_monitor = - winuser::MonitorFromRect(&new_rect, winuser::MONITOR_DEFAULTTONULL); + let new_monitor = MonitorFromRect(&new_rect, MONITOR_DEFAULTTONULL); match fullscreen { Fullscreen::Borderless(ref mut fullscreen_monitor) => { - if !new_monitor.is_null() + if !new_monitor.is_invalid() && fullscreen_monitor .as_ref() .map(|monitor| new_monitor != monitor.inner.hmonitor()) .unwrap_or(true) { if let Ok(new_monitor_info) = monitor::get_monitor_info(new_monitor) { - let new_monitor_rect = new_monitor_info.rcMonitor; + let new_monitor_rect = new_monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor; window_pos.x = new_monitor_rect.left; window_pos.y = new_monitor_rect.top; window_pos.cx = new_monitor_rect.right - new_monitor_rect.left; @@ -985,7 +1033,9 @@ unsafe fn public_window_callback_inner( Fullscreen::Exclusive(ref video_mode) => { let old_monitor = video_mode.video_mode.monitor.hmonitor(); if let Ok(old_monitor_info) = monitor::get_monitor_info(old_monitor) { - let old_monitor_rect = old_monitor_info.rcMonitor; + let old_monitor_rect = old_monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor; window_pos.x = old_monitor_rect.left; window_pos.y = old_monitor_rect.top; window_pos.cx = old_monitor_rect.right - old_monitor_rect.left; @@ -995,15 +1045,15 @@ unsafe fn public_window_callback_inner( } } - 0 + LRESULT(0) } // WM_MOVE supplies client area positions, so we send Moved here instead. - winuser::WM_WINDOWPOSCHANGED => { + WM_WINDOWPOSCHANGED => { use crate::event::WindowEvent::Moved; - let windowpos = lparam as *const winuser::WINDOWPOS; - if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE { + let windowpos = lparam.0 as *const WINDOWPOS; + if (*windowpos).flags & SWP_NOMOVE != SWP_NOMOVE { let physical_position = PhysicalPosition::new((*windowpos).x as i32, (*windowpos).y as i32); userdata.send_event(Event::WindowEvent { @@ -1013,13 +1063,13 @@ unsafe fn public_window_callback_inner( } // This is necessary for us to still get sent WM_SIZE. - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_SIZE => { + WM_SIZE => { use crate::event::WindowEvent::Resized; - let w = LOWORD(lparam as DWORD) as u32; - let h = HIWORD(lparam as DWORD) as u32; + let w = (lparam.0 & 0xffff) as u32; // LOWORD + let h = ((lparam.0 >> 16) & 0xffff) as u32; // HIWORD let physical_size = PhysicalSize::new(w, h); let event = Event::WindowEvent { @@ -1034,28 +1084,28 @@ unsafe fn public_window_callback_inner( .window_flags() .contains(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE) { - let maximized = wparam == winuser::SIZE_MAXIMIZED; + let maximized = wparam.0 == SIZE_MAXIMIZED as usize; w.set_window_flags_in_place(|f| f.set(WindowFlags::MAXIMIZED, maximized)); } } userdata.send_event(event); - 0 + LRESULT(0) } - winuser::WM_CHAR | winuser::WM_SYSCHAR => { + WM_CHAR | WM_SYSCHAR => { use crate::event::WindowEvent::ReceivedCharacter; use std::char; - let is_high_surrogate = (0xD800..=0xDBFF).contains(&wparam); - let is_low_surrogate = (0xDC00..=0xDFFF).contains(&wparam); + let is_high_surrogate = (0xD800..=0xDBFF).contains(&wparam.0); + let is_low_surrogate = (0xDC00..=0xDFFF).contains(&wparam.0); if is_high_surrogate { - userdata.window_state.lock().high_surrogate = Some(wparam as u16); + userdata.window_state.lock().high_surrogate = Some(wparam.0 as u16); } else if is_low_surrogate { let high_surrogate = userdata.window_state.lock().high_surrogate.take(); if let Some(high_surrogate) = high_surrogate { - let pair = [high_surrogate, wparam as u16]; + let pair = [high_surrogate, wparam.0 as u16]; if let Some(Ok(chr)) = char::decode_utf16(pair.iter().copied()).next() { userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), @@ -1066,39 +1116,39 @@ unsafe fn public_window_callback_inner( } else { userdata.window_state.lock().high_surrogate = None; - if let Some(chr) = char::from_u32(wparam as u32) { + if let Some(chr) = char::from_u32(wparam.0 as u32) { userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: ReceivedCharacter(chr), }); } } - 0 + LRESULT(0) } // this is necessary for us to maintain minimize/restore state - winuser::WM_SYSCOMMAND => { - if wparam == winuser::SC_RESTORE { + WM_SYSCOMMAND => { + if wparam.0 == SC_RESTORE as usize { let mut w = userdata.window_state.lock(); w.set_window_flags_in_place(|f| f.set(WindowFlags::MINIMIZED, false)); } - if wparam == winuser::SC_MINIMIZE { + if wparam.0 == SC_MINIMIZE as usize { let mut w = userdata.window_state.lock(); w.set_window_flags_in_place(|f| f.set(WindowFlags::MINIMIZED, true)); } // Send `WindowEvent::Minimized` here if we decide to implement one - if wparam == winuser::SC_SCREENSAVE { + if wparam.0 == SC_SCREENSAVE as usize { let window_state = userdata.window_state.lock(); if window_state.fullscreen.is_some() { - return 0; + return LRESULT(0); } } - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_MOUSEMOVE => { + WM_MOUSEMOVE => { use crate::event::WindowEvent::{CursorEntered, CursorMoved}; let mouse_was_outside_window = { let mut w = userdata.window_state.lock(); @@ -1119,16 +1169,16 @@ unsafe fn public_window_callback_inner( }); // Calling TrackMouseEvent in order to receive mouse leave events. - winuser::TrackMouseEvent(&mut winuser::TRACKMOUSEEVENT { - cbSize: mem::size_of::() as DWORD, - dwFlags: winuser::TME_LEAVE, + TrackMouseEvent(&mut TRACKMOUSEEVENT { + cbSize: mem::size_of::() as u32, + dwFlags: TME_LEAVE, hwndTrack: window, - dwHoverTime: winuser::HOVER_DEFAULT, + dwHoverTime: HOVER_DEFAULT, }); } - let x = windowsx::GET_X_LPARAM(lparam) as f64; - let y = windowsx::GET_Y_LPARAM(lparam) as f64; + let x = (lparam.0 & 0xffff) as f64; // GET_X_LPARAM + let y = ((lparam.0 >> 16) & 0xffff) as f64; // GET_Y_LPARAM let position = PhysicalPosition::new(x, y); let cursor_moved; { @@ -1152,10 +1202,10 @@ unsafe fn public_window_callback_inner( }); } - 0 + LRESULT(0) } - winuser::WM_MOUSELEAVE => { + WM_MOUSELEAVE => { use crate::event::WindowEvent::CursorLeft; { let mut w = userdata.window_state.lock(); @@ -1171,15 +1221,15 @@ unsafe fn public_window_callback_inner( }, }); - 0 + LRESULT(0) } - winuser::WM_MOUSEWHEEL => { + WM_MOUSEWHEEL => { use crate::event::MouseScrollDelta::LineDelta; - let value = (wparam >> 16) as i16; + let value = (wparam.0 >> 16) as i16; let value = value as i32; - let value = value as f32 / winuser::WHEEL_DELTA as f32; + let value = value as f32 / WHEEL_DELTA as f32; update_modifiers(window, userdata); @@ -1193,15 +1243,15 @@ unsafe fn public_window_callback_inner( }, }); - 0 + LRESULT(0) } - winuser::WM_MOUSEHWHEEL => { + WM_MOUSEHWHEEL => { use crate::event::MouseScrollDelta::LineDelta; - let value = (wparam >> 16) as i16; + let value = (wparam.0 >> 16) as i16; let value = value as i32; - let value = value as f32 / winuser::WHEEL_DELTA as f32; + let value = value as f32 / WHEEL_DELTA as f32; update_modifiers(window, userdata); @@ -1215,13 +1265,13 @@ unsafe fn public_window_callback_inner( }, }); - 0 + LRESULT(0) } - winuser::WM_KEYDOWN | winuser::WM_SYSKEYDOWN => { + WM_KEYDOWN | WM_SYSKEYDOWN => { use crate::event::{ElementState::Pressed, VirtualKeyCode}; - if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 { - winuser::DefWindowProcW(window, msg, wparam, lparam) + if msg == WM_SYSKEYDOWN && wparam.0 == VK_F4.0 as usize { + DefWindowProcW(window, msg, wparam, lparam) } else { if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { update_modifiers(window, userdata); @@ -1249,11 +1299,11 @@ unsafe fn public_window_callback_inner( }); } } - 0 + LRESULT(0) } } - winuser::WM_KEYUP | winuser::WM_SYSKEYUP => { + WM_KEYUP | WM_SYSKEYUP => { use crate::event::ElementState::Released; if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { update_modifiers(window, userdata); @@ -1273,10 +1323,10 @@ unsafe fn public_window_callback_inner( }, }); } - 0 + LRESULT(0) } - winuser::WM_LBUTTONDOWN => { + WM_LBUTTONDOWN => { use crate::event::{ElementState::Pressed, MouseButton::Left, WindowEvent::MouseInput}; capture_mouse(window, &mut *userdata.window_state.lock()); @@ -1292,10 +1342,10 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_LBUTTONUP => { + WM_LBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Left, WindowEvent::MouseInput, }; @@ -1313,10 +1363,10 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_RBUTTONDOWN => { + WM_RBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Right, WindowEvent::MouseInput, }; @@ -1334,10 +1384,10 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_RBUTTONUP => { + WM_RBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Right, WindowEvent::MouseInput, }; @@ -1355,10 +1405,10 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_MBUTTONDOWN => { + WM_MBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Middle, WindowEvent::MouseInput, }; @@ -1376,10 +1426,10 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_MBUTTONUP => { + WM_MBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Middle, WindowEvent::MouseInput, }; @@ -1397,14 +1447,14 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_XBUTTONDOWN => { + WM_XBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Other, WindowEvent::MouseInput, }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + let xbutton = ((wparam.0 >> 16) & 0xffff) as u16; // GET_XBUTTON_WPARAM capture_mouse(window, &mut *userdata.window_state.lock()); @@ -1419,14 +1469,14 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_XBUTTONUP => { + WM_XBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Other, WindowEvent::MouseInput, }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + let xbutton = ((wparam.0 >> 16) & 0xffff) as u16; // GET_XBUTTON_WPARAM release_mouse(userdata.window_state.lock()); @@ -1441,31 +1491,32 @@ unsafe fn public_window_callback_inner( modifiers: event::get_key_mods(), }, }); - 0 + LRESULT(0) } - winuser::WM_CAPTURECHANGED => { + WM_CAPTURECHANGED => { // lparam here is a handle to the window which is gaining mouse capture. // If it is the same as our window, then we're essentially retaining the capture. This // can happen if `SetCapture` is called on our window when it already has the mouse // capture. - if lparam != window as isize { + if lparam.0 != window.0 { userdata.window_state.lock().mouse.capture_count = 0; } - 0 + LRESULT(0) } - winuser::WM_TOUCH => { - let pcount = LOWORD(wparam as DWORD) as usize; + WM_TOUCH => { + let pcount = wparam.0 & 0xffff; // LOWORD let mut inputs = Vec::with_capacity(pcount); inputs.set_len(pcount); - let htouch = lparam as winuser::HTOUCHINPUT; - if winuser::GetTouchInputInfo( + let htouch = HTOUCHINPUT(lparam.0); + if GetTouchInputInfo( htouch, - pcount as UINT, + pcount as u32, inputs.as_mut_ptr(), - mem::size_of::() as INT, - ) > 0 + mem::size_of::() as i32, + ) + .as_bool() { for input in &inputs { let mut location = POINT { @@ -1473,7 +1524,7 @@ unsafe fn public_window_callback_inner( y: input.y / 100, }; - if winuser::ScreenToClient(window, &mut location as *mut _) == 0 { + if !ScreenToClient(window, &mut location as *mut _).as_bool() { continue; } @@ -1483,11 +1534,11 @@ unsafe fn public_window_callback_inner( userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: WindowEvent::Touch(Touch { - phase: if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { + phase: if input.dwFlags & TOUCHEVENTF_DOWN == TOUCHEVENTF_DOWN { TouchPhase::Started - } else if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { + } else if input.dwFlags & TOUCHEVENTF_UP == TOUCHEVENTF_UP { TouchPhase::Ended - } else if input.dwFlags & winuser::TOUCHEVENTF_MOVE != 0 { + } else if input.dwFlags & TOUCHEVENTF_MOVE == TOUCHEVENTF_MOVE { TouchPhase::Moved } else { continue; @@ -1500,11 +1551,11 @@ unsafe fn public_window_callback_inner( }); } } - winuser::CloseTouchInputHandle(htouch); - 0 + CloseTouchInputHandle(htouch); + LRESULT(0) } - winuser::WM_POINTERDOWN | winuser::WM_POINTERUPDATE | winuser::WM_POINTERUP => { + WM_POINTERDOWN | WM_POINTERUPDATE | WM_POINTERUP => { if let ( Some(GetPointerFrameInfoHistory), Some(SkipPointerFrameMessages), @@ -1514,30 +1565,32 @@ unsafe fn public_window_callback_inner( *SKIP_POINTER_FRAME_MESSAGES, *GET_POINTER_DEVICE_RECTS, ) { - let pointer_id = LOWORD(wparam as DWORD) as UINT; - let mut entries_count = 0 as UINT; - let mut pointers_count = 0 as UINT; - if GetPointerFrameInfoHistory( + let pointer_id = (wparam.0 & 0xffff) as u32; //LOWORD + let mut entries_count = 0_u32; + let mut pointers_count = 0_u32; + if !GetPointerFrameInfoHistory( pointer_id, &mut entries_count as *mut _, &mut pointers_count as *mut _, std::ptr::null_mut(), - ) == 0 + ) + .as_bool() { - return 0; + return LRESULT(0); } let pointer_info_count = (entries_count * pointers_count) as usize; let mut pointer_infos = Vec::with_capacity(pointer_info_count); pointer_infos.set_len(pointer_info_count); - if GetPointerFrameInfoHistory( + if !GetPointerFrameInfoHistory( pointer_id, &mut entries_count as *mut _, &mut pointers_count as *mut _, pointer_infos.as_mut_ptr(), - ) == 0 + ) + .as_bool() { - return 0; + return LRESULT(0); } // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory @@ -1547,11 +1600,12 @@ unsafe fn public_window_callback_inner( let mut device_rect = mem::MaybeUninit::uninit(); let mut display_rect = mem::MaybeUninit::uninit(); - if (GetPointerDeviceRects( + if !GetPointerDeviceRects( pointer_info.sourceDevice, device_rect.as_mut_ptr(), display_rect.as_mut_ptr(), - )) == 0 + ) + .as_bool() { continue; } @@ -1579,36 +1633,35 @@ unsafe fn public_window_callback_inner( y: y.floor() as i32, }; - if winuser::ScreenToClient(window, &mut location as *mut _) == 0 { + if !ScreenToClient(window, &mut location as *mut _).as_bool() { continue; } let force = match pointer_info.pointerType { - winuser::PT_TOUCH => { + PT_TOUCH => { let mut touch_info = mem::MaybeUninit::uninit(); GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| { - match GetPointerTouchInfo( + if GetPointerTouchInfo( pointer_info.pointerId, touch_info.as_mut_ptr(), - ) { - 0 => None, - _ => normalize_pointer_pressure( - touch_info.assume_init().pressure, - ), + ) + .as_bool() + { + normalize_pointer_pressure(touch_info.assume_init().pressure) + } else { + None } }) } - winuser::PT_PEN => { + PT_PEN => { let mut pen_info = mem::MaybeUninit::uninit(); GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| { - match GetPointerPenInfo( - pointer_info.pointerId, - pen_info.as_mut_ptr(), - ) { - 0 => None, - _ => { - normalize_pointer_pressure(pen_info.assume_init().pressure) - } + if GetPointerPenInfo(pointer_info.pointerId, pen_info.as_mut_ptr()) + .as_bool() + { + normalize_pointer_pressure(pen_info.assume_init().pressure) + } else { + None } }) } @@ -1621,11 +1674,15 @@ unsafe fn public_window_callback_inner( userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: WindowEvent::Touch(Touch { - phase: if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 { + phase: if pointer_info.pointerFlags & POINTER_FLAG_DOWN + == POINTER_FLAG_DOWN + { TouchPhase::Started - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { + } else if pointer_info.pointerFlags & POINTER_FLAG_UP == POINTER_FLAG_UP + { TouchPhase::Ended - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UPDATE != 0 + } else if pointer_info.pointerFlags & POINTER_FLAG_UPDATE + == POINTER_FLAG_UPDATE { TouchPhase::Moved } else { @@ -1641,14 +1698,13 @@ unsafe fn public_window_callback_inner( SkipPointerFrameMessages(pointer_id); } - 0 + LRESULT(0) } - winuser::WM_SETFOCUS => { + WM_SETFOCUS => { use crate::event::{ElementState::Released, WindowEvent::Focused}; for windows_keycode in event::get_pressed_keys() { - let scancode = - winuser::MapVirtualKeyA(windows_keycode as _, winuser::MAPVK_VK_TO_VSC); + let scancode = MapVirtualKeyA(windows_keycode.0 as u32, MAPVK_VK_TO_VSC); let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); update_modifiers(window, userdata); @@ -1674,18 +1730,17 @@ unsafe fn public_window_callback_inner( event: Focused(true), }); - 0 + LRESULT(0) } - winuser::WM_KILLFOCUS => { + WM_KILLFOCUS => { use crate::event::{ ElementState::Released, ModifiersState, WindowEvent::{Focused, ModifiersChanged}, }; for windows_keycode in event::get_pressed_keys() { - let scancode = - winuser::MapVirtualKeyA(windows_keycode as _, winuser::MAPVK_VK_TO_VSC); + let scancode = MapVirtualKeyA(windows_keycode.0 as u32, MAPVK_VK_TO_VSC); let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); #[allow(deprecated)] @@ -1714,16 +1769,16 @@ unsafe fn public_window_callback_inner( window_id: RootWindowId(WindowId(window)), event: Focused(false), }); - 0 + LRESULT(0) } - winuser::WM_SETCURSOR => { + WM_SETCURSOR => { let set_cursor_to = { let window_state = userdata.window_state.lock(); // The return value for the preceding `WM_NCHITTEST` message is conveniently // provided through the low-order word of lParam. We use that here since // `WM_MOUSEMOVE` seems to come after `WM_SETCURSOR` for a given cursor movement. - let in_client_area = LOWORD(lparam as DWORD) == winuser::HTCLIENT as WORD; + let in_client_area = (lparam.0 & 0xffff) == (HTCLIENT as isize); // LOWORD if in_client_area { Some(window_state.mouse.cursor) } else { @@ -1733,21 +1788,21 @@ unsafe fn public_window_callback_inner( match set_cursor_to { Some(cursor) => { - let cursor = winuser::LoadCursorW(ptr::null_mut(), cursor.to_windows_cursor()); - winuser::SetCursor(cursor); - 0 + let cursor = LoadCursorW(None, cursor.to_windows_cursor()); + SetCursor(cursor); + LRESULT(0) } - None => winuser::DefWindowProcW(window, msg, wparam, lparam), + None => DefWindowProcW(window, msg, wparam, lparam), } } - winuser::WM_DROPFILES => { + WM_DROPFILES => { // See `FileDropHandler` for implementation. - 0 + LRESULT(0) } - winuser::WM_GETMINMAXINFO => { - let mmi = lparam as *mut winuser::MINMAXINFO; + WM_GETMINMAXINFO => { + let mmi = lparam.0 as *mut MINMAXINFO; let window_state = userdata.window_state.lock(); @@ -1770,19 +1825,19 @@ unsafe fn public_window_callback_inner( } } - 0 + LRESULT(0) } // Only sent on Windows 8.1 or newer. On Windows 7 and older user has to log out to change // DPI, therefore all applications are closed while DPI is changing. - winuser::WM_DPICHANGED => { + WM_DPICHANGED => { use crate::event::WindowEvent::ScaleFactorChanged; // This message actually provides two DPI values - x and y. However MSDN says that // "you only need to use either the X-axis or the Y-axis value when scaling your // application since they are the same". // https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx - let new_dpi_x = u32::from(LOWORD(wparam as DWORD)); + let new_dpi_x = (wparam.0 & 0xffff) as u32; // LOWORD let new_scale_factor = dpi_to_scale_factor(new_dpi_x); let old_scale_factor: f64; @@ -1792,18 +1847,18 @@ unsafe fn public_window_callback_inner( window_state.scale_factor = new_scale_factor; if new_scale_factor == old_scale_factor { - return 0; + return LRESULT(0); } window_state.fullscreen.is_none() && !window_state.window_flags().contains(WindowFlags::MAXIMIZED) }; - let style = winuser::GetWindowLongW(window, winuser::GWL_STYLE) as _; - let style_ex = winuser::GetWindowLongW(window, winuser::GWL_EXSTYLE) as _; + let style = WINDOW_STYLE(GetWindowLongW(window, GWL_STYLE) as u32); + let style_ex = WINDOW_EX_STYLE(GetWindowLongW(window, GWL_EXSTYLE) as u32); // New size as suggested by Windows. - let suggested_rect = *(lparam as *const RECT); + let suggested_rect = *(lparam.0 as *const RECT); // The window rect provided is the window's outer size, not it's inner size. However, // win32 doesn't provide an `UnadjustWindowRectEx` function to get the client rect from @@ -1825,9 +1880,9 @@ unsafe fn public_window_callback_inner( let old_physical_inner_rect = { let mut old_physical_inner_rect = mem::zeroed(); - winuser::GetClientRect(window, &mut old_physical_inner_rect); + GetClientRect(window, &mut old_physical_inner_rect); let mut origin = mem::zeroed(); - winuser::ClientToScreen(window, &mut origin); + ClientToScreen(window, &mut origin); old_physical_inner_rect.left += origin.x; old_physical_inner_rect.right += origin.x; @@ -1885,8 +1940,8 @@ unsafe fn public_window_callback_inner( let mut conservative_rect = RECT { left: suggested_ul.0, top: suggested_ul.1, - right: suggested_ul.0 + new_physical_inner_size.width as LONG, - bottom: suggested_ul.1 + new_physical_inner_size.height as LONG, + right: suggested_ul.0 + new_physical_inner_size.width as i32, + bottom: suggested_ul.1 + new_physical_inner_size.height as i32, }; conservative_rect = util::adjust_window_rect_with_styles( @@ -1903,7 +1958,7 @@ unsafe fn public_window_callback_inner( let bias = { let cursor_pos = { let mut pos = mem::zeroed(); - winuser::GetCursorPos(&mut pos); + GetCursorPos(&mut pos); pos }; let suggested_cursor_horizontal_ratio = (cursor_pos.x - suggested_rect.left) @@ -1913,7 +1968,7 @@ unsafe fn public_window_callback_inner( (cursor_pos.x - (suggested_cursor_horizontal_ratio * (conservative_rect.right - conservative_rect.left) as f64) - as LONG) + as i32) - conservative_rect.left }; conservative_rect.left += bias; @@ -1922,17 +1977,18 @@ unsafe fn public_window_callback_inner( // Check to see if the new window rect is on the monitor with the new DPI factor. // If it isn't, offset the window so that it is. - let new_dpi_monitor = winuser::MonitorFromWindow(window, 0); - let conservative_rect_monitor = winuser::MonitorFromRect(&conservative_rect, 0); + let new_dpi_monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); + let conservative_rect_monitor = + MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL); new_outer_rect = if conservative_rect_monitor == new_dpi_monitor { conservative_rect } else { let get_monitor_rect = |monitor| { - let mut monitor_info = winuser::MONITORINFO { - cbSize: mem::size_of::() as _, + let mut monitor_info = MONITORINFO { + cbSize: mem::size_of::() as _, ..mem::zeroed() }; - winuser::GetMonitorInfoW(monitor, &mut monitor_info); + GetMonitorInfoW(monitor, &mut monitor_info); monitor_info.rcMonitor }; let wrong_monitor = conservative_rect_monitor; @@ -1968,7 +2024,9 @@ unsafe fn public_window_callback_inner( conservative_rect.top += delta_nudge_to_dpi_monitor.1; conservative_rect.bottom += delta_nudge_to_dpi_monitor.1; - if winuser::MonitorFromRect(&conservative_rect, 0) == new_dpi_monitor { + if MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL) + == new_dpi_monitor + { break; } } @@ -1977,20 +2035,20 @@ unsafe fn public_window_callback_inner( }; } - winuser::SetWindowPos( + SetWindowPos( window, - ptr::null_mut(), + None, new_outer_rect.left, new_outer_rect.top, new_outer_rect.right - new_outer_rect.left, new_outer_rect.bottom - new_outer_rect.top, - winuser::SWP_NOZORDER | winuser::SWP_NOACTIVATE, + SWP_NOZORDER | SWP_NOACTIVATE, ); - 0 + LRESULT(0) } - winuser::WM_SETTINGCHANGE => { + WM_SETTINGCHANGE => { use crate::event::WindowEvent::ThemeChanged; let preferred_theme = userdata.window_state.lock().preferred_theme; @@ -2009,21 +2067,21 @@ unsafe fn public_window_callback_inner( } } - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } _ => { if msg == *DESTROY_MSG_ID { - winuser::DestroyWindow(window); - 0 + DestroyWindow(window); + LRESULT(0) } else if msg == *SET_RETAIN_STATE_ON_SIZE_MSG_ID { let mut window_state = userdata.window_state.lock(); window_state.set_window_flags_in_place(|f| { - f.set(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE, wparam != 0) + f.set(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE, wparam.0 != 0) }); - 0 + LRESULT(0) } else { - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } } }; @@ -2031,31 +2089,26 @@ unsafe fn public_window_callback_inner( userdata .event_loop_runner .catch_unwind(callback) - .unwrap_or(-1) + .unwrap_or(LRESULT(-1)) } unsafe extern "system" fn thread_event_target_callback( window: HWND, - msg: UINT, + msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { let userdata_ptr = - winuser::GetWindowLongPtrW(window, winuser::GWL_USERDATA) as *mut ThreadMsgTargetData; + super::GetWindowLongPtrW(window, GWL_USERDATA) as *mut ThreadMsgTargetData; if userdata_ptr.is_null() { // `userdata_ptr` will always be null for the first `WM_GETMINMAXINFO`, as well as `WM_NCCREATE` and // `WM_CREATE`. - return winuser::DefWindowProcW(window, msg, wparam, lparam); + return DefWindowProcW(window, msg, wparam, lparam); } let userdata = Box::from_raw(userdata_ptr); - if msg != winuser::WM_PAINT { - winuser::RedrawWindow( - window, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + if msg != WM_PAINT { + RedrawWindow(window, ptr::null(), None, RDW_INTERNALPAINT); } let mut userdata_removed = false; @@ -2064,15 +2117,15 @@ unsafe extern "system" fn thread_event_target_callback( // the closure to catch_unwind directly so that the match body indendation wouldn't change and // the git blame and history would be preserved. let callback = || match msg { - winuser::WM_NCDESTROY => { - winuser::SetWindowLongPtrW(window, winuser::GWL_USERDATA, 0); + WM_NCDESTROY => { + super::SetWindowLongPtrW(window, GWL_USERDATA, 0); userdata_removed = true; - 0 + LRESULT(0) } // Because WM_PAINT comes after all other messages, we use it during modal loops to detect // when the event queue has been emptied. See `process_event` for more details. - winuser::WM_PAINT => { - winuser::ValidateRect(window, ptr::null()); + WM_PAINT => { + ValidateRect(window, ptr::null()); // If the WM_PAINT handler in `public_window_callback` has already flushed the redraw // events, `handling_events` will return false and we won't emit a second // `RedrawEventsCleared` event. @@ -2080,12 +2133,7 @@ unsafe extern "system" fn thread_event_target_callback( if userdata.event_loop_runner.should_buffer() { // This branch can be triggered when a nested win32 event loop is triggered // inside of the `event_handler` callback. - winuser::RedrawWindow( - window, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + RedrawWindow(window, ptr::null(), None, RDW_INTERNALPAINT); } else { // This WM_PAINT handler will never be re-entrant because `flush_paint_messages` // doesn't call WM_PAINT for the thread event target (i.e. this window). @@ -2096,38 +2144,38 @@ unsafe extern "system" fn thread_event_target_callback( } // Default WM_PAINT behaviour. This makes sure modals and popups are shown immediatly when opening them. - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } - winuser::WM_INPUT_DEVICE_CHANGE => { - let event = match wparam as _ { - winuser::GIDC_ARRIVAL => DeviceEvent::Added, - winuser::GIDC_REMOVAL => DeviceEvent::Removed, + WM_INPUT_DEVICE_CHANGE => { + let event = match wparam.0 as u32 { + GIDC_ARRIVAL => DeviceEvent::Added, + GIDC_REMOVAL => DeviceEvent::Removed, _ => unreachable!(), }; userdata.send_event(Event::DeviceEvent { - device_id: wrap_device_id(lparam as _), + device_id: wrap_device_id(lparam.0 as u32), event, }); - 0 + LRESULT(0) } - winuser::WM_INPUT => { + WM_INPUT => { use crate::event::{ DeviceEvent::{Button, Key, Motion, MouseMotion, MouseWheel}, ElementState::{Pressed, Released}, MouseScrollDelta::LineDelta, }; - if let Some(data) = raw_input::get_raw_input_data(lparam as _) { - let device_id = wrap_device_id(data.header.hDevice as _); + if let Some(data) = raw_input::get_raw_input_data(HRAWINPUT(lparam.0)) { + let device_id = wrap_device_id(data.header.hDevice.0 as u32); - if data.header.dwType == winuser::RIM_TYPEMOUSE { - let mouse = data.data.mouse(); + if data.header.dwType == RIM_TYPEMOUSE.0 { + let mouse = data.data.mouse; - if util::has_flag(mouse.usFlags, winuser::MOUSE_MOVE_RELATIVE) { + if util::has_flag(mouse.usFlags as u32, MOUSE_MOVE_RELATIVE) { let x = mouse.lLastX as f64; let y = mouse.lLastY as f64; @@ -2153,9 +2201,10 @@ unsafe extern "system" fn thread_event_target_callback( } } - if util::has_flag(mouse.usButtonFlags, winuser::RI_MOUSE_WHEEL) { - let delta = - mouse.usButtonData as SHORT as f32 / winuser::WHEEL_DELTA as f32; + let mouse_button_flags = mouse.Anonymous.Anonymous.usButtonFlags; + + if util::has_flag(mouse_button_flags as u32, RI_MOUSE_WHEEL) { + let delta = mouse_button_flags as f32 / WHEEL_DELTA as f32; userdata.send_event(Event::DeviceEvent { device_id, event: MouseWheel { @@ -2164,38 +2213,40 @@ unsafe extern "system" fn thread_event_target_callback( }); } - let button_state = raw_input::get_raw_mouse_button_state(mouse.usButtonFlags); + let button_state = + raw_input::get_raw_mouse_button_state(mouse_button_flags as u32); // Left, middle, and right, respectively. for (index, state) in button_state.iter().enumerate() { if let Some(state) = *state { // This gives us consistency with X11, since there doesn't // seem to be anything else reasonable to do for a mouse // button ID. - let button = (index + 1) as _; + let button = (index + 1) as u32; userdata.send_event(Event::DeviceEvent { device_id, event: Button { button, state }, }); } } - } else if data.header.dwType == winuser::RIM_TYPEKEYBOARD { - let keyboard = data.data.keyboard(); + } else if data.header.dwType == RIM_TYPEKEYBOARD.0 { + let keyboard = data.data.keyboard; - let pressed = keyboard.Message == winuser::WM_KEYDOWN - || keyboard.Message == winuser::WM_SYSKEYDOWN; - let released = keyboard.Message == winuser::WM_KEYUP - || keyboard.Message == winuser::WM_SYSKEYUP; + let pressed = + keyboard.Message == WM_KEYDOWN || keyboard.Message == WM_SYSKEYDOWN; + let released = keyboard.Message == WM_KEYUP || keyboard.Message == WM_SYSKEYUP; if pressed || released { let state = if pressed { Pressed } else { Released }; - let scancode = keyboard.MakeCode as _; - let extended = util::has_flag(keyboard.Flags, winuser::RI_KEY_E0 as _) - | util::has_flag(keyboard.Flags, winuser::RI_KEY_E1 as _); + let scancode = keyboard.MakeCode; + let extended = util::has_flag(keyboard.Flags, RI_KEY_E0 as u16) + | util::has_flag(keyboard.Flags, RI_KEY_E1 as u16); - if let Some((vkey, scancode)) = - handle_extended_keys(keyboard.VKey as _, scancode, extended) - { + if let Some((vkey, scancode)) = handle_extended_keys( + VIRTUAL_KEY(keyboard.VKey), + scancode as u32, + extended, + ) { let virtual_keycode = vkey_to_winit_vkey(vkey); #[allow(deprecated)] @@ -2213,26 +2264,26 @@ unsafe extern "system" fn thread_event_target_callback( } } - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } _ if msg == *USER_EVENT_MSG_ID => { if let Ok(event) = userdata.user_event_receiver.recv() { userdata.send_event(Event::UserEvent(event)); } - 0 + LRESULT(0) } _ if msg == *EXEC_MSG_ID => { - let mut function: ThreadExecFn = Box::from_raw(wparam as usize as *mut _); + let mut function: ThreadExecFn = Box::from_raw(wparam.0 as usize as *mut _); function(); - 0 + LRESULT(0) } _ if msg == *PROCESS_NEW_EVENTS_MSG_ID => { - winuser::PostThreadMessageW( + PostThreadMessageW( userdata.event_loop_runner.wait_thread_id(), *CANCEL_WAIT_UNTIL_MSG_ID, - 0, - 0, + WPARAM(0), + LPARAM(0), ); // if the control_flow is WaitUntil, make sure the given moment has actually passed @@ -2240,22 +2291,17 @@ unsafe extern "system" fn thread_event_target_callback( if let ControlFlow::WaitUntil(wait_until) = userdata.event_loop_runner.control_flow() { let mut msg = mem::zeroed(); while Instant::now() < wait_until { - if 0 != winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) { + if PeekMessageW(&mut msg, None, 0, 0, PM_NOREMOVE).as_bool() { // This works around a "feature" in PeekMessageW. If the message PeekMessageW // gets is a WM_PAINT message that had RDW_INTERNALPAINT set (i.e. doesn't // have an update region), PeekMessageW will remove that window from the // redraw queue even though we told it not to remove messages from the // queue. We fix it by re-dispatching an internal paint message to that // window. - if msg.message == winuser::WM_PAINT { + if msg.message == WM_PAINT { let mut rect = mem::zeroed(); - if 0 == winuser::GetUpdateRect(msg.hwnd, &mut rect, 0) { - winuser::RedrawWindow( - msg.hwnd, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + if !GetUpdateRect(msg.hwnd, &mut rect, false).as_bool() { + RedrawWindow(msg.hwnd, ptr::null(), None, RDW_INTERNALPAINT); } } @@ -2264,15 +2310,15 @@ unsafe extern "system" fn thread_event_target_callback( } } userdata.event_loop_runner.poll(); - 0 + LRESULT(0) } - _ => winuser::DefWindowProcW(window, msg, wparam, lparam), + _ => DefWindowProcW(window, msg, wparam, lparam), }; let result = userdata .event_loop_runner .catch_unwind(callback) - .unwrap_or(-1); + .unwrap_or(LRESULT(-1)); if userdata_removed { mem::drop(userdata); } else { diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index cf32767465..ba7158279c 100644 --- a/src/platform_impl/windows/event_loop/runner.rs +++ b/src/platform_impl/windows/event_loop/runner.rs @@ -7,9 +7,9 @@ use std::{ time::Instant, }; -use winapi::{ - shared::{minwindef::DWORD, windef::HWND}, - um::winuser, +use windows::Win32::{ + Foundation::HWND, + Graphics::Gdi::{RedrawWindow, RDW_INTERNALPAINT}, }; use crate::{ @@ -24,7 +24,7 @@ pub(crate) type EventLoopRunnerShared = Rc>; pub(crate) struct EventLoopRunner { // The event loop's win32 handles pub(super) thread_msg_target: HWND, - wait_thread_id: DWORD, + wait_thread_id: u32, control_flow: Cell, runner_state: Cell, @@ -33,7 +33,7 @@ pub(crate) struct EventLoopRunner { event_handler: Cell, &mut ControlFlow)>>>, event_buffer: RefCell>>, - owned_windows: Cell>, + owned_windows: Cell>, panic_error: Cell>, } @@ -63,7 +63,7 @@ enum BufferedEvent { } impl EventLoopRunner { - pub(crate) fn new(thread_msg_target: HWND, wait_thread_id: DWORD) -> EventLoopRunner { + pub(crate) fn new(thread_msg_target: HWND, wait_thread_id: u32) -> EventLoopRunner { EventLoopRunner { thread_msg_target, wait_thread_id, @@ -113,7 +113,7 @@ impl EventLoopRunner { self.thread_msg_target } - pub fn wait_thread_id(&self) -> DWORD { + pub fn wait_thread_id(&self) -> u32 { self.wait_thread_id } @@ -174,20 +174,20 @@ impl EventLoopRunner { } pub fn register_window(&self, window: HWND) { let mut owned_windows = self.owned_windows.take(); - owned_windows.insert(window); + owned_windows.insert(window.0); self.owned_windows.set(owned_windows); } pub fn remove_window(&self, window: HWND) { let mut owned_windows = self.owned_windows.take(); - owned_windows.remove(&window); + owned_windows.remove(&window.0); self.owned_windows.set(owned_windows); } pub fn owned_windows(&self, mut f: impl FnMut(HWND)) { let mut owned_windows = self.owned_windows.take(); for hwnd in &owned_windows { - f(*hwnd); + f(HWND(*hwnd)); } let new_owned_windows = self.owned_windows.take(); owned_windows.extend(&new_owned_windows); @@ -208,18 +208,16 @@ impl EventLoopRunner { self.move_state_to(RunnerState::HandlingRedrawEvents); } self.call_event_handler(event); + } else if self.should_buffer() { + // If the runner is already borrowed, we're in the middle of an event loop invocation. Add + // the event to a buffer to be processed later. + self.event_buffer + .borrow_mut() + .push_back(BufferedEvent::from_event(event)) } else { - if self.should_buffer() { - // If the runner is already borrowed, we're in the middle of an event loop invocation. Add - // the event to a buffer to be processed later. - self.event_buffer - .borrow_mut() - .push_back(BufferedEvent::from_event(event)) - } else { - self.move_state_to(RunnerState::HandlingMainEvents); - self.call_event_handler(event); - self.dispatch_buffered_events(); - } + self.move_state_to(RunnerState::HandlingMainEvents); + self.call_event_handler(event); + self.dispatch_buffered_events(); } } @@ -392,12 +390,7 @@ impl EventLoopRunner { }; self.call_event_handler(Event::NewEvents(start_cause)); self.dispatch_buffered_events(); - winuser::RedrawWindow( - self.thread_msg_target, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + RedrawWindow(self.thread_msg_target, ptr::null(), None, RDW_INTERNALPAINT); } unsafe fn call_redraw_events_cleared(&self) { diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index 1308c7467e..d7a934384d 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -1,13 +1,11 @@ -use std::{fmt, io, iter::once, mem, os::windows::ffi::OsStrExt, path::Path, ptr, sync::Arc}; - -use winapi::{ - ctypes::{c_int, wchar_t}, - shared::{ - minwindef::{BYTE, LPARAM, WORD, WPARAM}, - windef::{HICON, HWND}, - }, - um::libloaderapi, - um::winuser, +use std::{fmt, io, iter::once, mem, os::windows::ffi::OsStrExt, path::Path, sync::Arc}; + +use windows::runtime::Handle; +use windows::Win32::Foundation::{HWND, LPARAM, PWSTR, WPARAM}; +use windows::Win32::System::LibraryLoader::GetModuleHandleW; +use windows::Win32::UI::WindowsAndMessaging::{ + CreateIcon, DestroyIcon, LoadImageW, SendMessageW, HICON, ICON_BIG, ICON_SMALL, IMAGE_ICON, + LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_SETICON, }; use crate::dpi::PhysicalSize; @@ -32,28 +30,28 @@ impl RgbaIcon { } assert_eq!(and_mask.len(), pixel_count); let handle = unsafe { - winuser::CreateIcon( - ptr::null_mut(), - self.width as c_int, - self.height as c_int, + CreateIcon( + None, + self.width as i32, + self.height as i32, 1, - (PIXEL_SIZE * 8) as BYTE, - and_mask.as_ptr() as *const BYTE, - rgba.as_ptr() as *const BYTE, - ) as HICON + (PIXEL_SIZE * 8) as u8, + and_mask.as_ptr() as *const u8, + rgba.as_ptr() as *const u8, + ) }; - if !handle.is_null() { - Ok(WinIcon::from_handle(handle)) - } else { + if handle.is_invalid() { Err(BadIcon::OsError(io::Error::last_os_error())) + } else { + Ok(WinIcon::from_handle(handle)) } } } #[derive(Debug)] pub enum IconType { - Small = winuser::ICON_SMALL as isize, - Big = winuser::ICON_BIG as isize, + Small = ICON_SMALL as isize, + Big = ICON_BIG as isize, } #[derive(Debug)] @@ -88,42 +86,42 @@ impl WinIcon { let (width, height) = size.map(Into::into).unwrap_or((0, 0)); let handle = unsafe { - winuser::LoadImageW( - ptr::null_mut(), - wide_path.as_ptr() as *const wchar_t, - winuser::IMAGE_ICON, - width as c_int, - height as c_int, - winuser::LR_DEFAULTSIZE | winuser::LR_LOADFROMFILE, - ) as HICON + LoadImageW( + None, + PWSTR(wide_path.as_ptr() as *mut u16), + IMAGE_ICON, + width as i32, + height as i32, + LR_DEFAULTSIZE | LR_LOADFROMFILE, + ) }; - if !handle.is_null() { - Ok(WinIcon::from_handle(handle)) - } else { + if handle.is_invalid() { Err(BadIcon::OsError(io::Error::last_os_error())) + } else { + Ok(WinIcon::from_handle(HICON(handle.0))) } } pub fn from_resource( - resource_id: WORD, + resource_id: u16, size: Option>, ) -> Result { // width / height of 0 along with LR_DEFAULTSIZE tells windows to load the default icon size let (width, height) = size.map(Into::into).unwrap_or((0, 0)); let handle = unsafe { - winuser::LoadImageW( - libloaderapi::GetModuleHandleW(ptr::null_mut()), - winuser::MAKEINTRESOURCEW(resource_id), - winuser::IMAGE_ICON, - width as c_int, - height as c_int, - winuser::LR_DEFAULTSIZE, - ) as HICON + LoadImageW( + GetModuleHandleW(None), + PWSTR(resource_id as *mut u16), + IMAGE_ICON, + width as i32, + height as i32, + LR_DEFAULTSIZE, + ) }; - if !handle.is_null() { - Ok(WinIcon::from_handle(handle)) - } else { + if handle.is_invalid() { Err(BadIcon::OsError(io::Error::last_os_error())) + } else { + Ok(WinIcon::from_handle(HICON(handle.0))) } } @@ -134,11 +132,11 @@ impl WinIcon { pub fn set_for_window(&self, hwnd: HWND, icon_type: IconType) { unsafe { - winuser::SendMessageW( + SendMessageW( hwnd, - winuser::WM_SETICON, - icon_type as WPARAM, - self.as_raw_handle() as LPARAM, + WM_SETICON, + WPARAM(icon_type as usize), + LPARAM(self.as_raw_handle().0), ); } } @@ -152,7 +150,7 @@ impl WinIcon { impl Drop for RaiiIcon { fn drop(&mut self) { - unsafe { winuser::DestroyIcon(self.handle) }; + unsafe { DestroyIcon(self.handle) }; } } @@ -164,6 +162,6 @@ impl fmt::Debug for WinIcon { pub fn unset_for_window(hwnd: HWND, icon_type: IconType) { unsafe { - winuser::SendMessageW(hwnd, winuser::WM_SETICON, icon_type as WPARAM, 0 as LPARAM); + SendMessageW(hwnd, WM_SETICON, WPARAM(icon_type as usize), LPARAM(0)); } } diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 9215a92306..3012be97b7 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -1,6 +1,11 @@ #![cfg(target_os = "windows")] -use winapi::{self, shared::windef::HMENU, shared::windef::HWND}; +use std::hash::Hash; + +use windows::Win32::{ + Foundation::{HANDLE, HWND}, + UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX}, +}; pub use self::{ event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}, @@ -50,7 +55,7 @@ unsafe impl Sync for PlatformSpecificWindowBuilderAttributes {} // Cursor name in UTF-16. Used to set cursor in `WM_SETCURSOR`. #[derive(Debug, Clone, Copy)] -pub struct Cursor(pub *const winapi::ctypes::wchar_t); +pub struct Cursor(pub *const u16); unsafe impl Send for Cursor {} unsafe impl Sync for Cursor {} @@ -66,7 +71,7 @@ impl DeviceId { impl DeviceId { pub fn persistent_identifier(&self) -> Option { if self.0 != 0 { - raw_input::get_raw_input_device_name(self.0 as _) + raw_input::get_raw_input_device_name(HANDLE(self.0 as isize)) } else { None } @@ -82,19 +87,55 @@ fn wrap_device_id(id: u32) -> RootDeviceId { pub type OsError = std::io::Error; -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct WindowId(HWND); unsafe impl Send for WindowId {} unsafe impl Sync for WindowId {} +// FIXME: HWND should derive these. +impl PartialOrd for WindowId { + fn partial_cmp(&self, other: &Self) -> Option { + self.0 .0.partial_cmp(&other.0 .0) + } +} + +impl Ord for WindowId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0 .0.cmp(&other.0 .0) + } +} + +impl Hash for WindowId { + fn hash(&self, state: &mut H) { + self.0 .0.hash(state); + } +} + impl WindowId { pub const unsafe fn dummy() -> Self { - use std::ptr::null_mut; - - WindowId(null_mut()) + WindowId(HWND(0)) } } +#[allow(non_snake_case)] +#[inline(always)] +unsafe fn GetWindowLongPtrW(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize { + #[cfg(target_pointer_width = "64")] + return windows::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW(hwnd, nindex); + #[cfg(target_pointer_width = "32")] + return windows::Win32::UI::WindowsAndMessaging::GetWindowLongW(hwnd, nindex) as isize; +} + +#[allow(non_snake_case)] +#[inline(always)] +unsafe fn SetWindowLongPtrW(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX, dwnewlong: isize) -> isize { + #[cfg(target_pointer_width = "64")] + return windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW(hwnd, nindex, dwnewlong); + #[cfg(target_pointer_width = "32")] + return windows::Win32::UI::WindowsAndMessaging::SetWindowLongW(hwnd, nindex, dwnewlong as i32) + as isize; +} + #[macro_use] mod util; mod dark_mode; diff --git a/src/platform_impl/windows/monitor.rs b/src/platform_impl/windows/monitor.rs index ff88d102db..7c113999da 100644 --- a/src/platform_impl/windows/monitor.rs +++ b/src/platform_impl/windows/monitor.rs @@ -1,17 +1,22 @@ -use winapi::{ - shared::{ - minwindef::{BOOL, DWORD, LPARAM, TRUE, WORD}, - windef::{HDC, HMONITOR, HWND, LPRECT, POINT}, - }, - um::{wingdi, winuser}, -}; - use std::{ collections::{BTreeSet, VecDeque}, - io, mem, ptr, + ffi::OsString, + hash::Hash, + io, mem, + os::windows::prelude::OsStringExt, + ptr, +}; + +use windows::Win32::{ + Foundation::{BOOL, HWND, LPARAM, POINT, PWSTR, RECT}, + Graphics::Gdi::{ + EnumDisplayMonitors, EnumDisplaySettingsExW, GetMonitorInfoW, MonitorFromPoint, + MonitorFromWindow, DEVMODEW, DM_BITSPERPEL, DM_DISPLAYFREQUENCY, DM_PELSHEIGHT, + DM_PELSWIDTH, ENUM_DISPLAY_SETTINGS_MODE, HDC, HMONITOR, MONITORINFO, MONITORINFOEXW, + MONITOR_DEFAULTTONEAREST, MONITOR_DEFAULTTOPRIMARY, + }, }; -use super::util; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode}, @@ -27,7 +32,7 @@ pub struct VideoMode { pub(crate) bit_depth: u16, pub(crate) refresh_rate: u16, pub(crate) monitor: MonitorHandle, - pub(crate) native_video_mode: wingdi::DEVMODEW, + pub(crate) native_video_mode: DEVMODEW, } impl PartialEq for VideoMode { @@ -81,7 +86,7 @@ impl VideoMode { } } -#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct MonitorHandle(HMONITOR); // Send is not implemented for HMONITOR, we have to wrap it and implement it manually. @@ -91,25 +96,44 @@ pub struct MonitorHandle(HMONITOR); unsafe impl Send for MonitorHandle {} +// FIXME: HMONITOR should derive these. +impl Hash for MonitorHandle { + fn hash(&self, state: &mut H) { + self.0 .0.hash(state); + } +} + +impl PartialOrd for MonitorHandle { + fn partial_cmp(&self, other: &Self) -> Option { + self.0 .0.partial_cmp(&other.0 .0) + } +} + +impl Ord for MonitorHandle { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0 .0.cmp(&other.0 .0) + } +} + unsafe extern "system" fn monitor_enum_proc( hmonitor: HMONITOR, _hdc: HDC, - _place: LPRECT, + _place: *mut RECT, data: LPARAM, ) -> BOOL { - let monitors = data as *mut VecDeque; + let monitors = data.0 as *mut VecDeque; (*monitors).push_back(MonitorHandle::new(hmonitor)); - TRUE // continue enumeration + true.into() // continue enumeration } pub fn available_monitors() -> VecDeque { let mut monitors: VecDeque = VecDeque::new(); unsafe { - winuser::EnumDisplayMonitors( - ptr::null_mut(), - ptr::null_mut(), + EnumDisplayMonitors( + None, + ptr::null(), Some(monitor_enum_proc), - &mut monitors as *mut _ as LPARAM, + LPARAM(&mut monitors as *mut _ as isize), ); } monitors @@ -117,12 +141,12 @@ pub fn available_monitors() -> VecDeque { pub fn primary_monitor() -> MonitorHandle { const ORIGIN: POINT = POINT { x: 0, y: 0 }; - let hmonitor = unsafe { winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY) }; + let hmonitor = unsafe { MonitorFromPoint(ORIGIN, MONITOR_DEFAULTTOPRIMARY) }; MonitorHandle::new(hmonitor) } pub fn current_monitor(hwnd: HWND) -> MonitorHandle { - let hmonitor = unsafe { winuser::MonitorFromWindow(hwnd, winuser::MONITOR_DEFAULTTONEAREST) }; + let hmonitor = unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) }; MonitorHandle::new(hmonitor) } @@ -137,16 +161,17 @@ impl Window { } } -pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result { - let mut monitor_info: winuser::MONITORINFOEXW = unsafe { mem::zeroed() }; - monitor_info.cbSize = mem::size_of::() as DWORD; +pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result { + let mut monitor_info: MONITORINFOEXW = unsafe { mem::zeroed() }; + monitor_info.__AnonymousBase_winuser_L13571_C43.cbSize = + mem::size_of::() as u32; let status = unsafe { - winuser::GetMonitorInfoW( + GetMonitorInfoW( hmonitor, - &mut monitor_info as *mut winuser::MONITORINFOEXW as *mut winuser::MONITORINFO, + &mut monitor_info as *mut MONITORINFOEXW as *mut MONITORINFO, ) }; - if status == 0 { + if !status.as_bool() { Err(io::Error::last_os_error()) } else { Ok(monitor_info) @@ -161,7 +186,11 @@ impl MonitorHandle { #[inline] pub fn name(&self) -> Option { let monitor_info = get_monitor_info(self.0).unwrap(); - Some(util::wchar_ptr_to_string(monitor_info.szDevice.as_ptr())) + Some( + OsString::from_wide(&monitor_info.szDevice) + .to_string_lossy() + .to_string(), + ) } #[inline] @@ -178,8 +207,22 @@ impl MonitorHandle { pub fn size(&self) -> PhysicalSize { let monitor_info = get_monitor_info(self.0).unwrap(); PhysicalSize { - width: (monitor_info.rcMonitor.right - monitor_info.rcMonitor.left) as u32, - height: (monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top) as u32, + width: (monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .right + - monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .left) as u32, + height: (monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .bottom + - monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .top) as u32, } } @@ -187,8 +230,14 @@ impl MonitorHandle { pub fn position(&self) -> PhysicalPosition { let monitor_info = get_monitor_info(self.0).unwrap(); PhysicalPosition { - x: monitor_info.rcMonitor.left, - y: monitor_info.rcMonitor.top, + x: monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .left, + y: monitor_info + .__AnonymousBase_winuser_L13571_C43 + .rcMonitor + .top, } } @@ -209,17 +258,22 @@ impl MonitorHandle { unsafe { let monitor_info = get_monitor_info(self.0).unwrap(); let device_name = monitor_info.szDevice.as_ptr(); - let mut mode: wingdi::DEVMODEW = mem::zeroed(); - mode.dmSize = mem::size_of_val(&mode) as WORD; - if winuser::EnumDisplaySettingsExW(device_name, i, &mut mode, 0) == 0 { + let mut mode: DEVMODEW = mem::zeroed(); + mode.dmSize = mem::size_of_val(&mode) as u16; + if !EnumDisplaySettingsExW( + PWSTR(device_name as _), + ENUM_DISPLAY_SETTINGS_MODE(i), + &mut mode, + 0, + ) + .as_bool() + { break; } i += 1; - const REQUIRED_FIELDS: DWORD = wingdi::DM_BITSPERPEL - | wingdi::DM_PELSWIDTH - | wingdi::DM_PELSHEIGHT - | wingdi::DM_DISPLAYFREQUENCY; + const REQUIRED_FIELDS: u32 = + (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY) as u32; assert!(mode.dmFields & REQUIRED_FIELDS == REQUIRED_FIELDS); modes.insert(RootVideoMode { diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index 73b136a82f..6fa21372e3 100644 --- a/src/platform_impl/windows/raw_input.rs +++ b/src/platform_impl/windows/raw_input.rs @@ -1,22 +1,26 @@ use std::{ + ffi::OsString, mem::{self, size_of}, + os::windows::prelude::OsStringExt, ptr, }; -use winapi::{ - ctypes::wchar_t, - shared::{ - hidusage::{HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC}, - minwindef::{TRUE, UINT, USHORT}, - windef::HWND, +use windows::Win32::{ + Devices::HumanInterfaceDevice::{ + HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC, }, - um::{ - winnt::HANDLE, - winuser::{ - self, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, RAWINPUTHEADER, - RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDI_DEVICEINFO, RIDI_DEVICENAME, RID_DEVICE_INFO, - RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE, RID_INPUT, - RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + Foundation::{HANDLE, HWND}, + UI::{ + Input::{ + GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList, + RegisterRawInputDevices, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, + RAWINPUTHEADER, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDI_DEVICEINFO, RIDI_DEVICENAME, + RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE, + RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + }, + WindowsAndMessaging::{ + RI_MOUSE_LEFT_BUTTON_DOWN, RI_MOUSE_LEFT_BUTTON_UP, RI_MOUSE_MIDDLE_BUTTON_DOWN, + RI_MOUSE_MIDDLE_BUTTON_UP, RI_MOUSE_RIGHT_BUTTON_DOWN, RI_MOUSE_RIGHT_BUTTON_UP, }, }, }; @@ -25,23 +29,21 @@ use crate::{event::ElementState, platform_impl::platform::util}; #[allow(dead_code)] pub fn get_raw_input_device_list() -> Option> { - let list_size = size_of::() as UINT; + let list_size = size_of::() as u32; let mut num_devices = 0; - let status = - unsafe { winuser::GetRawInputDeviceList(ptr::null_mut(), &mut num_devices, list_size) }; + let status = unsafe { GetRawInputDeviceList(ptr::null_mut(), &mut num_devices, list_size) }; - if status == UINT::max_value() { + if status == u32::MAX { return None; } let mut buffer = Vec::with_capacity(num_devices as _); - let num_stored = unsafe { - winuser::GetRawInputDeviceList(buffer.as_ptr() as _, &mut num_devices, list_size) - }; + let num_stored = + unsafe { GetRawInputDeviceList(buffer.as_mut_ptr(), &mut num_devices, list_size) }; - if num_stored == UINT::max_value() { + if num_stored == u32::MAX { return None; } @@ -63,9 +65,9 @@ impl From for RawDeviceInfo { fn from(info: RID_DEVICE_INFO) -> Self { unsafe { match info.dwType { - RIM_TYPEMOUSE => RawDeviceInfo::Mouse(*info.u.mouse()), - RIM_TYPEKEYBOARD => RawDeviceInfo::Keyboard(*info.u.keyboard()), - RIM_TYPEHID => RawDeviceInfo::Hid(*info.u.hid()), + RIM_TYPEMOUSE => RawDeviceInfo::Mouse(info.Anonymous.mouse), + RIM_TYPEKEYBOARD => RawDeviceInfo::Keyboard(info.Anonymous.keyboard), + RIM_TYPEHID => RawDeviceInfo::Hid(info.Anonymous.hid), _ => unreachable!(), } } @@ -75,13 +77,13 @@ impl From for RawDeviceInfo { #[allow(dead_code)] pub fn get_raw_input_device_info(handle: HANDLE) -> Option { let mut info: RID_DEVICE_INFO = unsafe { mem::zeroed() }; - let info_size = size_of::() as UINT; + let info_size = size_of::() as u32; info.cbSize = info_size; let mut minimum_size = 0; let status = unsafe { - winuser::GetRawInputDeviceInfoW( + GetRawInputDeviceInfoW( handle, RIDI_DEVICEINFO, &mut info as *mut _ as _, @@ -89,7 +91,7 @@ pub fn get_raw_input_device_info(handle: HANDLE) -> Option { ) }; - if status == UINT::max_value() || status == 0 { + if status == u32::MAX || status == 0 { return None; } @@ -101,25 +103,25 @@ pub fn get_raw_input_device_info(handle: HANDLE) -> Option { pub fn get_raw_input_device_name(handle: HANDLE) -> Option { let mut minimum_size = 0; let status = unsafe { - winuser::GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, ptr::null_mut(), &mut minimum_size) + GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, ptr::null_mut(), &mut minimum_size) }; if status != 0 { return None; } - let mut name: Vec = Vec::with_capacity(minimum_size as _); + let mut name: Vec = Vec::with_capacity(minimum_size as _); let status = unsafe { - winuser::GetRawInputDeviceInfoW( + GetRawInputDeviceInfoW( handle, RIDI_DEVICENAME, - name.as_ptr() as _, + name.as_mut_ptr() as _, &mut minimum_size, ) }; - if status == UINT::max_value() || status == 0 { + if status == u32::MAX || status == 0 { return None; } @@ -127,17 +129,14 @@ pub fn get_raw_input_device_name(handle: HANDLE) -> Option { unsafe { name.set_len(minimum_size as _) }; - Some(util::wchar_to_string(&name)) + Some(OsString::from_wide(&name).to_string_lossy().to_string()) } pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool { - let device_size = size_of::() as UINT; - - let success = unsafe { - winuser::RegisterRawInputDevices(devices.as_ptr() as _, devices.len() as _, device_size) - }; + let device_size = size_of::() as u32; - success == TRUE + unsafe { RegisterRawInputDevices(devices.as_ptr() as _, devices.len() as u32, device_size) } + .as_bool() } pub fn register_all_mice_and_keyboards_for_raw_input(window_handle: HWND) -> bool { @@ -165,11 +164,11 @@ pub fn register_all_mice_and_keyboards_for_raw_input(window_handle: HWND) -> boo pub fn get_raw_input_data(handle: HRAWINPUT) -> Option { let mut data: RAWINPUT = unsafe { mem::zeroed() }; - let mut data_size = size_of::() as UINT; - let header_size = size_of::() as UINT; + let mut data_size = size_of::() as u32; + let header_size = size_of::() as u32; let status = unsafe { - winuser::GetRawInputData( + GetRawInputData( handle, RID_INPUT, &mut data as *mut _ as _, @@ -178,7 +177,7 @@ pub fn get_raw_input_data(handle: HRAWINPUT) -> Option { ) }; - if status == UINT::max_value() || status == 0 { + if status == u32::MAX || status == 0 { return None; } @@ -186,9 +185,9 @@ pub fn get_raw_input_data(handle: HRAWINPUT) -> Option { } fn button_flags_to_element_state( - button_flags: USHORT, - down_flag: USHORT, - up_flag: USHORT, + button_flags: u32, + down_flag: u32, + up_flag: u32, ) -> Option { // We assume the same button won't be simultaneously pressed and released. if util::has_flag(button_flags, down_flag) { @@ -200,22 +199,22 @@ fn button_flags_to_element_state( } } -pub fn get_raw_mouse_button_state(button_flags: USHORT) -> [Option; 3] { +pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option; 3] { [ button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_LEFT_BUTTON_DOWN, - winuser::RI_MOUSE_LEFT_BUTTON_UP, + RI_MOUSE_LEFT_BUTTON_DOWN, + RI_MOUSE_LEFT_BUTTON_UP, ), button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_MIDDLE_BUTTON_DOWN, - winuser::RI_MOUSE_MIDDLE_BUTTON_UP, + RI_MOUSE_MIDDLE_BUTTON_DOWN, + RI_MOUSE_MIDDLE_BUTTON_UP, ), button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_RIGHT_BUTTON_DOWN, - winuser::RI_MOUSE_RIGHT_BUTTON_UP, + RI_MOUSE_RIGHT_BUTTON_DOWN, + RI_MOUSE_RIGHT_BUTTON_UP, ), ] } diff --git a/src/platform_impl/windows/util.rs b/src/platform_impl/windows/util.rs index 4ca6cf9184..c92f363cc9 100644 --- a/src/platform_impl/windows/util.rs +++ b/src/platform_impl/windows/util.rs @@ -2,26 +2,34 @@ use std::{ io, mem, ops::BitAnd, os::raw::c_void, - ptr, slice, + ptr, sync::atomic::{AtomicBool, Ordering}, }; -use crate::{dpi::PhysicalSize, window::CursorIcon}; -use winapi::{ - ctypes::wchar_t, - shared::{ - minwindef::{BOOL, DWORD, UINT}, - windef::{DPI_AWARENESS_CONTEXT, HMONITOR, HWND, LPRECT, RECT}, - }, - um::{ - libloaderapi::{GetProcAddress, LoadLibraryA}, - shellscalingapi::{MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS}, - winbase::lstrlenW, - winnt::{HRESULT, LONG, LPCSTR}, - winuser, +use windows::{ + runtime::{Handle, HRESULT}, + Win32::{ + Foundation::{BOOL, HWND, PSTR, PWSTR, RECT}, + Graphics::Gdi::{ClientToScreen, InvalidateRgn, HMONITOR}, + System::LibraryLoader::{GetProcAddress, LoadLibraryA}, + UI::{ + HiDpi::{DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS}, + Input::KeyboardAndMouse::GetActiveWindow, + WindowsAndMessaging::{ + AdjustWindowRectEx, ClipCursor, GetClientRect, GetClipCursor, GetMenu, + GetSystemMetrics, GetWindowLongW, GetWindowRect, SetWindowPos, ShowCursor, + GWL_EXSTYLE, GWL_STYLE, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, + IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, + IDC_WAIT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, + SM_YVIRTUALSCREEN, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOMOVE, + SWP_NOREPOSITION, SWP_NOZORDER, WINDOW_EX_STYLE, WINDOW_STYLE, + }, + }, }, }; +use crate::{dpi::PhysicalSize, window::CursorIcon}; + pub fn has_flag(bitset: T, flag: T) -> bool where T: Copy + PartialEq + BitAnd, @@ -29,19 +37,9 @@ where bitset & flag == flag } -pub fn wchar_to_string(wchar: &[wchar_t]) -> String { - String::from_utf16_lossy(wchar) -} - -pub fn wchar_ptr_to_string(wchar: *const wchar_t) -> String { - let len = unsafe { lstrlenW(wchar) } as usize; - let wchar_slice = unsafe { slice::from_raw_parts(wchar, len) }; - wchar_to_string(wchar_slice) -} - pub unsafe fn status_map BOOL>(mut fun: F) -> Option { let mut data: T = mem::zeroed(); - if fun(&mut data) != 0 { + if fun(&mut data).as_bool() { Some(data) } else { None @@ -49,7 +47,7 @@ pub unsafe fn status_map BOOL>(mut fun: F) -> Option { } fn win_to_err BOOL>(f: F) -> Result<(), io::Error> { - if f() != 0 { + if f().as_bool() { Ok(()) } else { Err(io::Error::last_os_error()) @@ -57,7 +55,7 @@ fn win_to_err BOOL>(f: F) -> Result<(), io::Error> { } pub fn get_window_rect(hwnd: HWND) -> Option { - unsafe { status_map(|rect| winuser::GetWindowRect(hwnd, rect)) } + unsafe { status_map(|rect| GetWindowRect(hwnd, rect)) } } pub fn get_client_rect(hwnd: HWND) -> Result { @@ -65,8 +63,8 @@ pub fn get_client_rect(hwnd: HWND) -> Result { let mut rect = mem::zeroed(); let mut top_left = mem::zeroed(); - win_to_err(|| winuser::ClientToScreen(hwnd, &mut top_left))?; - win_to_err(|| winuser::GetClientRect(hwnd, &mut rect))?; + win_to_err(|| ClientToScreen(hwnd, &mut top_left))?; + win_to_err(|| GetClientRect(hwnd, &mut rect))?; rect.left += top_left.x; rect.top += top_left.y; rect.right += top_left.x; @@ -80,9 +78,9 @@ pub fn adjust_size(hwnd: HWND, size: PhysicalSize) -> PhysicalSize { let (width, height): (u32, u32) = size.into(); let rect = RECT { left: 0, - right: width as LONG, + right: width as i32, top: 0, - bottom: height as LONG, + bottom: height as i32, }; let rect = adjust_window_rect(hwnd, rect).unwrap_or(rect); PhysicalSize::new((rect.right - rect.left) as _, (rect.bottom - rect.top) as _) @@ -95,57 +93,53 @@ pub(crate) fn set_inner_size_physical(window: HWND, x: u32, y: u32) { RECT { top: 0, left: 0, - bottom: y as LONG, - right: x as LONG, + bottom: y as i32, + right: x as i32, }, ) .expect("adjust_window_rect failed"); let outer_x = (rect.right - rect.left).abs() as _; let outer_y = (rect.top - rect.bottom).abs() as _; - winuser::SetWindowPos( + SetWindowPos( window, - ptr::null_mut(), + None, 0, 0, outer_x, outer_y, - winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOREPOSITION - | winuser::SWP_NOMOVE - | winuser::SWP_NOACTIVATE, + SWP_ASYNCWINDOWPOS | SWP_NOZORDER | SWP_NOREPOSITION | SWP_NOMOVE | SWP_NOACTIVATE, ); - winuser::InvalidateRgn(window, ptr::null_mut(), 0); + InvalidateRgn(window, None, false); } } pub fn adjust_window_rect(hwnd: HWND, rect: RECT) -> Option { unsafe { - let style = winuser::GetWindowLongW(hwnd, winuser::GWL_STYLE); - let style_ex = winuser::GetWindowLongW(hwnd, winuser::GWL_EXSTYLE); - adjust_window_rect_with_styles(hwnd, style as _, style_ex as _, rect) + let style = WINDOW_STYLE(GetWindowLongW(hwnd, GWL_STYLE) as u32); + let style_ex = WINDOW_EX_STYLE(GetWindowLongW(hwnd, GWL_EXSTYLE) as u32); + adjust_window_rect_with_styles(hwnd, style, style_ex, rect) } } pub fn adjust_window_rect_with_styles( hwnd: HWND, - style: DWORD, - style_ex: DWORD, + style: WINDOW_STYLE, + style_ex: WINDOW_EX_STYLE, rect: RECT, ) -> Option { unsafe { status_map(|r| { *r = rect; - let b_menu = !winuser::GetMenu(hwnd).is_null() as BOOL; + let b_menu = !GetMenu(hwnd).is_invalid(); if let (Some(get_dpi_for_window), Some(adjust_window_rect_ex_for_dpi)) = (*GET_DPI_FOR_WINDOW, *ADJUST_WINDOW_RECT_EX_FOR_DPI) { let dpi = get_dpi_for_window(hwnd); - adjust_window_rect_ex_for_dpi(r, style as _, b_menu, style_ex as _, dpi) + adjust_window_rect_ex_for_dpi(r, style.0, b_menu.into(), style_ex.0, dpi) } else { - winuser::AdjustWindowRectEx(r, style as _, b_menu, style_ex as _) + AdjustWindowRectEx(r, style, b_menu, style_ex) } }) } @@ -155,14 +149,14 @@ pub fn set_cursor_hidden(hidden: bool) { static HIDDEN: AtomicBool = AtomicBool::new(false); let changed = HIDDEN.swap(hidden, Ordering::SeqCst) ^ hidden; if changed { - unsafe { winuser::ShowCursor(!hidden as BOOL) }; + unsafe { ShowCursor(!hidden) }; } } pub fn get_cursor_clip() -> Result { unsafe { let mut rect: RECT = mem::zeroed(); - win_to_err(|| winuser::GetClipCursor(&mut rect)).map(|_| rect) + win_to_err(|| GetClipCursor(&mut rect)).map(|_| rect) } } @@ -175,56 +169,52 @@ pub fn set_cursor_clip(rect: Option) -> Result<(), io::Error> { .as_ref() .map(|r| r as *const RECT) .unwrap_or(ptr::null()); - win_to_err(|| winuser::ClipCursor(rect_ptr)) + win_to_err(|| ClipCursor(rect_ptr)) } } pub fn get_desktop_rect() -> RECT { unsafe { - let left = winuser::GetSystemMetrics(winuser::SM_XVIRTUALSCREEN); - let top = winuser::GetSystemMetrics(winuser::SM_YVIRTUALSCREEN); + let left = GetSystemMetrics(SM_XVIRTUALSCREEN); + let top = GetSystemMetrics(SM_YVIRTUALSCREEN); RECT { left, top, - right: left + winuser::GetSystemMetrics(winuser::SM_CXVIRTUALSCREEN), - bottom: top + winuser::GetSystemMetrics(winuser::SM_CYVIRTUALSCREEN), + right: left + GetSystemMetrics(SM_CXVIRTUALSCREEN), + bottom: top + GetSystemMetrics(SM_CYVIRTUALSCREEN), } } } pub fn is_focused(window: HWND) -> bool { - window == unsafe { winuser::GetActiveWindow() } + window == unsafe { GetActiveWindow() } } impl CursorIcon { - pub(crate) fn to_windows_cursor(self) -> *const wchar_t { + pub(crate) fn to_windows_cursor(self) -> PWSTR { match self { - CursorIcon::Arrow | CursorIcon::Default => winuser::IDC_ARROW, - CursorIcon::Hand => winuser::IDC_HAND, - CursorIcon::Crosshair => winuser::IDC_CROSS, - CursorIcon::Text | CursorIcon::VerticalText => winuser::IDC_IBEAM, - CursorIcon::NotAllowed | CursorIcon::NoDrop => winuser::IDC_NO, + CursorIcon::Arrow | CursorIcon::Default => IDC_ARROW, + CursorIcon::Hand => IDC_HAND, + CursorIcon::Crosshair => IDC_CROSS, + CursorIcon::Text | CursorIcon::VerticalText => IDC_IBEAM, + CursorIcon::NotAllowed | CursorIcon::NoDrop => IDC_NO, CursorIcon::Grab | CursorIcon::Grabbing | CursorIcon::Move | CursorIcon::AllScroll => { - winuser::IDC_SIZEALL + IDC_SIZEALL } CursorIcon::EResize | CursorIcon::WResize | CursorIcon::EwResize - | CursorIcon::ColResize => winuser::IDC_SIZEWE, + | CursorIcon::ColResize => IDC_SIZEWE, CursorIcon::NResize | CursorIcon::SResize | CursorIcon::NsResize - | CursorIcon::RowResize => winuser::IDC_SIZENS, - CursorIcon::NeResize | CursorIcon::SwResize | CursorIcon::NeswResize => { - winuser::IDC_SIZENESW - } - CursorIcon::NwResize | CursorIcon::SeResize | CursorIcon::NwseResize => { - winuser::IDC_SIZENWSE - } - CursorIcon::Wait => winuser::IDC_WAIT, - CursorIcon::Progress => winuser::IDC_APPSTARTING, - CursorIcon::Help => winuser::IDC_HELP, - _ => winuser::IDC_ARROW, // use arrow for the missing cases. + | CursorIcon::RowResize => IDC_SIZENS, + CursorIcon::NeResize | CursorIcon::SwResize | CursorIcon::NeswResize => IDC_SIZENESW, + CursorIcon::NwResize | CursorIcon::SeResize | CursorIcon::NwseResize => IDC_SIZENWSE, + CursorIcon::Wait => IDC_WAIT, + CursorIcon::Progress => IDC_APPSTARTING, + CursorIcon::Help => IDC_HELP, + _ => IDC_ARROW, // use arrow for the missing cases. } } } @@ -236,17 +226,13 @@ pub(super) fn get_function_impl(library: &str, function: &str) -> Option<*const assert_eq!(function.chars().last(), Some('\0')); // Library names we will use are ASCII so we can use the A version to avoid string conversion. - let module = unsafe { LoadLibraryA(library.as_ptr() as LPCSTR) }; - if module.is_null() { - return None; - } - - let function_ptr = unsafe { GetProcAddress(module, function.as_ptr() as LPCSTR) }; - if function_ptr.is_null() { + let module = unsafe { LoadLibraryA(PSTR(library.as_ptr() as *mut u8)) }; + if module.is_invalid() { return None; } - Some(function_ptr as _) + unsafe { GetProcAddress(module, PSTR(function.as_ptr() as *mut u8)) } + .map(|function_ptr| function_ptr as _) } macro_rules! get_function { @@ -264,20 +250,20 @@ pub type SetProcessDpiAwareness = unsafe extern "system" fn(value: PROCESS_DPI_AWARENESS) -> HRESULT; pub type SetProcessDpiAwarenessContext = unsafe extern "system" fn(value: DPI_AWARENESS_CONTEXT) -> BOOL; -pub type GetDpiForWindow = unsafe extern "system" fn(hwnd: HWND) -> UINT; +pub type GetDpiForWindow = unsafe extern "system" fn(hwnd: HWND) -> u32; pub type GetDpiForMonitor = unsafe extern "system" fn( hmonitor: HMONITOR, dpi_type: MONITOR_DPI_TYPE, - dpi_x: *mut UINT, - dpi_y: *mut UINT, + dpi_x: *mut u32, + dpi_y: *mut u32, ) -> HRESULT; pub type EnableNonClientDpiScaling = unsafe extern "system" fn(hwnd: HWND) -> BOOL; pub type AdjustWindowRectExForDpi = unsafe extern "system" fn( - rect: LPRECT, - dwStyle: DWORD, + rect: *mut RECT, + dwStyle: u32, bMenu: BOOL, - dwExStyle: DWORD, - dpi: UINT, + dwExStyle: u32, + dpi: u32, ) -> BOOL; lazy_static! { diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 7e002e1644..d856279620 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -3,31 +3,64 @@ use parking_lot::Mutex; use raw_window_handle::{windows::WindowsHandle, RawWindowHandle}; use std::{ - cell::Cell, + cell::{Cell, RefCell}, ffi::OsStr, - io, mem, + io, + iter::once, + mem, os::windows::ffi::OsStrExt, panic, ptr, sync::{mpsc::channel, Arc}, }; -use winapi::{ - ctypes::c_int, - shared::{ - minwindef::{HINSTANCE, LPARAM, UINT, WPARAM}, - windef::{HWND, POINT, POINTS, RECT}, - }, - um::{ - combaseapi, dwmapi, - imm::{CFS_POINT, COMPOSITIONFORM}, - libloaderapi, - objbase::COINIT_APARTMENTTHREADED, - ole2, - oleidl::LPDROPTARGET, - shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}, - wingdi::{CreateRectRgn, DeleteObject}, - winnt::{LPCWSTR, SHORT}, - winuser, +use windows::{ + runtime::Handle, + Win32::{ + Foundation::{ + HINSTANCE, HWND, LPARAM, POINT, POINTS, PWSTR, RECT, RPC_E_CHANGED_MODE, WPARAM, + }, + Graphics::{ + Dwm::{DwmEnableBlurBehindWindow, DWM_BB_BLURREGION, DWM_BB_ENABLE, DWM_BLURBEHIND}, + Gdi::{ + ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, + InvalidateRgn, RedrawWindow, CDS_FULLSCREEN, DISP_CHANGE_BADFLAGS, + DISP_CHANGE_BADMODE, DISP_CHANGE_BADPARAM, DISP_CHANGE_FAILED, + DISP_CHANGE_SUCCESSFUL, HBRUSH, RDW_INTERNALPAINT, + }, + }, + System::{ + Com::{ + CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_ALL, + COINIT_APARTMENTTHREADED, + }, + LibraryLoader::GetModuleHandleW, + Ole::{IDropTarget, OleInitialize, RegisterDragDrop}, + }, + UI::{ + Input::{ + Ime::{ + ImmGetContext, ImmReleaseContext, ImmSetCompositionWindow, CFS_POINT, + COMPOSITIONFORM, + }, + KeyboardAndMouse::{ + GetActiveWindow, MapVirtualKeyW, ReleaseCapture, SendInput, INPUT, INPUT_0, + INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, VK_LMENU, + VK_MENU, + }, + Touch::{RegisterTouchWindow, TWF_WANTPALM}, + }, + Shell::{ITaskbarList2, TaskbarList}, + WindowsAndMessaging::{ + CreateWindowExW, FlashWindowEx, GetClientRect, GetCursorPos, GetForegroundWindow, + GetSystemMetrics, GetWindowPlacement, LoadCursorW, PeekMessageW, PostMessageW, + RegisterClassExW, SetCursor, SetCursorPos, SetForegroundWindow, SetWindowPlacement, + SetWindowPos, SetWindowTextW, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, CW_USEDEFAULT, + FLASHWINFO, FLASHW_ALL, FLASHW_STOP, FLASHW_TIMERNOFG, FLASHW_TRAY, GWLP_HINSTANCE, + HCURSOR, HICON, HMENU, HTCAPTION, MAPVK_VK_TO_VSC, NID_READY, PM_NOREMOVE, + SM_DIGITIZER, SM_IMMENABLED, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE, + SWP_NOZORDER, WM_NCLBUTTONDOWN, WNDCLASSEXW, + }, + }, }, }; @@ -74,19 +107,20 @@ impl Window { unsafe { let drag_and_drop = pl_attr.drag_and_drop; init(w_attr, pl_attr, event_loop, |win| { - let file_drop_handler = if drag_and_drop { - use winapi::shared::winerror::{OLE_E_WRONGCOMPOBJ, RPC_E_CHANGED_MODE, S_OK}; - - let ole_init_result = ole2::OleInitialize(ptr::null_mut()); + let drop_target = if drag_and_drop { + let ole_init_result = OleInitialize(ptr::null_mut()); // It is ok if the initialize result is `S_FALSE` because it might happen that // multiple windows are created on the same thread. - if ole_init_result == OLE_E_WRONGCOMPOBJ { - panic!("OleInitialize failed! Result was: `OLE_E_WRONGCOMPOBJ`"); - } else if ole_init_result == RPC_E_CHANGED_MODE { + if let Err(error) = ole_init_result { panic!( - "OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`. \ - Make sure other crates are not using multithreaded COM library \ - on the same thread or disable drag and drop support." + "OleInitialize failed! Result was: `{:?}`{}", + error.code(), + if error.code() == RPC_E_CHANGED_MODE { + ". Make sure other crates are not using multithreaded COM library \ + on the same thread or disable drag and drop support." + } else { + "" + } ); } @@ -99,14 +133,11 @@ impl Window { } }), ); - let handler_interface_ptr = - &mut (*file_drop_handler.data).interface as LPDROPTARGET; - assert_eq!( - ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), - S_OK - ); - Some(file_drop_handler) + let drop_target = IDropTarget::from(file_drop_handler); + + assert!(RegisterDragDrop(win.window.0, &drop_target).is_ok()); + Some(drop_target) } else { None }; @@ -116,7 +147,7 @@ impl Window { event_loop::WindowData { window_state: win.window_state.clone(), event_loop_runner: event_loop.runner_shared.clone(), - _file_drop_handler: file_drop_handler, + _drop_target: drop_target, userdata_removed: Cell::new(false), recurse_depth: Cell::new(0), } @@ -125,12 +156,12 @@ impl Window { } pub fn set_title(&self, text: &str) { - let text = OsStr::new(text) + let mut text = OsStr::new(text) .encode_wide() - .chain(Some(0).into_iter()) + .chain(once(0)) .collect::>(); unsafe { - winuser::SetWindowTextW(self.window.0, text.as_ptr() as LPCWSTR); + SetWindowTextW(self.hwnd(), PWSTR(text.as_mut_ptr())); } } @@ -148,18 +179,13 @@ impl Window { #[inline] pub fn request_redraw(&self) { unsafe { - winuser::RedrawWindow( - self.window.0, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT, - ); + RedrawWindow(self.hwnd(), ptr::null(), None, RDW_INTERNALPAINT); } } #[inline] pub fn outer_position(&self) -> Result, NotSupportedError> { - util::get_window_rect(self.window.0) + util::get_window_rect(self.hwnd()) .map(|rect| Ok(PhysicalPosition::new(rect.left as i32, rect.top as i32))) .expect("Unexpected GetWindowRect failure; please report this error to https://github.com/rust-windowing/winit") } @@ -167,7 +193,7 @@ impl Window { #[inline] pub fn inner_position(&self) -> Result, NotSupportedError> { let mut position: POINT = unsafe { mem::zeroed() }; - if unsafe { winuser::ClientToScreen(self.window.0, &mut position) } == 0 { + if !unsafe { ClientToScreen(self.hwnd(), &mut position) }.as_bool() { panic!("Unexpected ClientToScreen failure: please report this error to https://github.com/rust-windowing/winit") } Ok(PhysicalPosition::new(position.x as i32, position.y as i32)) @@ -186,26 +212,23 @@ impl Window { }); unsafe { - winuser::SetWindowPos( - self.window.0, - ptr::null_mut(), - x as c_int, - y as c_int, + SetWindowPos( + self.hwnd(), + None, + x, + y, 0, 0, - winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOSIZE - | winuser::SWP_NOACTIVATE, + SWP_ASYNCWINDOWPOS | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE, ); - winuser::InvalidateRgn(self.window.0, ptr::null_mut(), 0); + InvalidateRgn(self.hwnd(), None, false); } } #[inline] pub fn inner_size(&self) -> PhysicalSize { let mut rect: RECT = unsafe { mem::zeroed() }; - if unsafe { winuser::GetClientRect(self.window.0, &mut rect) } == 0 { + if !unsafe { GetClientRect(self.hwnd(), &mut rect) }.as_bool() { panic!("Unexpected GetClientRect failure: please report this error to https://github.com/rust-windowing/winit") } PhysicalSize::new( @@ -216,7 +239,7 @@ impl Window { #[inline] pub fn outer_size(&self) -> PhysicalSize { - util::get_window_rect(self.window.0) + util::get_window_rect(self.hwnd()) .map(|rect| { PhysicalSize::new( (rect.right - rect.left) as u32, @@ -239,7 +262,7 @@ impl Window { }); }); - util::set_inner_size_physical(self.window.0, width, height); + util::set_inner_size_physical(self.hwnd(), width, height); } #[inline] @@ -278,14 +301,14 @@ impl Window { #[inline] pub fn hinstance(&self) -> HINSTANCE { - unsafe { winuser::GetWindowLongPtrW(self.hwnd(), winuser::GWLP_HINSTANCE) as *mut _ } + HINSTANCE(unsafe { super::GetWindowLongPtrW(self.hwnd(), GWLP_HINSTANCE) }) } #[inline] pub fn raw_window_handle(&self) -> RawWindowHandle { let handle = WindowsHandle { - hwnd: self.window.0 as *mut _, - hinstance: self.hinstance() as *mut _, + hwnd: self.hwnd().0 as *mut _, + hinstance: self.hinstance().0 as *mut _, ..WindowsHandle::empty() }; RawWindowHandle::Windows(handle) @@ -295,8 +318,8 @@ impl Window { pub fn set_cursor_icon(&self, cursor: CursorIcon) { self.window_state.lock().mouse.cursor = cursor; self.thread_executor.execute_in_thread(move || unsafe { - let cursor = winuser::LoadCursorW(ptr::null_mut(), cursor.to_windows_cursor()); - winuser::SetCursor(cursor); + let cursor = LoadCursorW(None, cursor.to_windows_cursor()); + SetCursor(cursor); }); } @@ -346,10 +369,10 @@ impl Window { let mut point = POINT { x, y }; unsafe { - if winuser::ClientToScreen(self.window.0, &mut point) == 0 { + if !ClientToScreen(self.hwnd(), &mut point).as_bool() { return Err(ExternalError::Os(os_error!(io::Error::last_os_error()))); } - if winuser::SetCursorPos(point.x, point.y) == 0 { + if !SetCursorPos(point.x, point.y).as_bool() { return Err(ExternalError::Os(os_error!(io::Error::last_os_error()))); } } @@ -361,19 +384,19 @@ impl Window { unsafe { let points = { let mut pos = mem::zeroed(); - winuser::GetCursorPos(&mut pos); + GetCursorPos(&mut pos); pos }; let points = POINTS { - x: points.x as SHORT, - y: points.y as SHORT, + x: points.x as i16, + y: points.y as i16, }; - winuser::ReleaseCapture(); - winuser::PostMessageW( - self.window.0, - winuser::WM_NCLBUTTONDOWN, - winuser::HTCAPTION as WPARAM, - &points as *const _ as LPARAM, + ReleaseCapture(); + PostMessageW( + self.hwnd(), + WM_NCLBUTTONDOWN, + WPARAM(HTCAPTION as usize), + LPARAM(&points as *const _ as isize), ); } @@ -382,7 +405,7 @@ impl Window { #[inline] pub fn id(&self) -> WindowId { - WindowId(self.window.0) + WindowId(self.hwnd()) } #[inline] @@ -449,47 +472,44 @@ impl Window { let mut display_name = OsStr::new(&monitor.inner.native_identifier()) .encode_wide() + .chain(once(0)) .collect::>(); - // `encode_wide` does not add a null-terminator but - // `ChangeDisplaySettingsExW` requires a null-terminated - // string, so add it - display_name.push(0); - let mut native_video_mode = video_mode.video_mode.native_video_mode; + let native_video_mode = video_mode.video_mode.native_video_mode; let res = unsafe { - winuser::ChangeDisplaySettingsExW( - display_name.as_ptr(), - &mut native_video_mode, - std::ptr::null_mut(), - winuser::CDS_FULLSCREEN, + ChangeDisplaySettingsExW( + PWSTR(display_name.as_mut_ptr()), + &native_video_mode, + None, + CDS_FULLSCREEN, std::ptr::null_mut(), ) }; - debug_assert!(res != winuser::DISP_CHANGE_BADFLAGS); - debug_assert!(res != winuser::DISP_CHANGE_BADMODE); - debug_assert!(res != winuser::DISP_CHANGE_BADPARAM); - debug_assert!(res != winuser::DISP_CHANGE_FAILED); - assert_eq!(res, winuser::DISP_CHANGE_SUCCESSFUL); + debug_assert!(res != DISP_CHANGE_BADFLAGS); + debug_assert!(res != DISP_CHANGE_BADMODE); + debug_assert!(res != DISP_CHANGE_BADPARAM); + debug_assert!(res != DISP_CHANGE_FAILED); + assert_eq!(res, DISP_CHANGE_SUCCESSFUL); } (&Some(Fullscreen::Exclusive(_)), &None) | (&Some(Fullscreen::Exclusive(_)), &Some(Fullscreen::Borderless(_))) => { let res = unsafe { - winuser::ChangeDisplaySettingsExW( - std::ptr::null_mut(), + ChangeDisplaySettingsExW( + None, std::ptr::null_mut(), - std::ptr::null_mut(), - winuser::CDS_FULLSCREEN, + None, + CDS_FULLSCREEN, std::ptr::null_mut(), ) }; - debug_assert!(res != winuser::DISP_CHANGE_BADFLAGS); - debug_assert!(res != winuser::DISP_CHANGE_BADMODE); - debug_assert!(res != winuser::DISP_CHANGE_BADPARAM); - debug_assert!(res != winuser::DISP_CHANGE_FAILED); - assert_eq!(res, winuser::DISP_CHANGE_SUCCESSFUL); + debug_assert!(res != DISP_CHANGE_BADFLAGS); + debug_assert!(res != DISP_CHANGE_BADMODE); + debug_assert!(res != DISP_CHANGE_BADPARAM); + debug_assert!(res != DISP_CHANGE_FAILED); + assert_eq!(res, DISP_CHANGE_SUCCESSFUL); } _ => (), } @@ -504,7 +524,7 @@ impl Window { // fine, taking control back from the DWM and ensuring that the `SetWindowPos` call // below goes through. let mut msg = mem::zeroed(); - winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0); + PeekMessageW(&mut msg, None, 0, 0, PM_NOREMOVE); } // Update window style @@ -525,7 +545,7 @@ impl Window { // Save window bounds before entering fullscreen let placement = unsafe { let mut placement = mem::zeroed(); - winuser::GetWindowPlacement(window.0, &mut placement); + GetWindowPlacement(window.0, &mut placement); placement }; @@ -543,16 +563,16 @@ impl Window { let size: (u32, u32) = monitor.size().into(); unsafe { - winuser::SetWindowPos( + SetWindowPos( window.0, - ptr::null_mut(), + None, position.0, position.1, size.0 as i32, size.1 as i32, - winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOZORDER, + SWP_ASYNCWINDOWPOS | SWP_NOZORDER, ); - winuser::InvalidateRgn(window.0, ptr::null_mut(), 0); + InvalidateRgn(window.0, None, false); } } None => { @@ -560,8 +580,8 @@ impl Window { if let Some(SavedWindow { placement }) = window_state_lock.saved_window.take() { drop(window_state_lock); unsafe { - winuser::SetWindowPlacement(window.0, &placement); - winuser::InvalidateRgn(window.0, ptr::null_mut(), 0); + SetWindowPlacement(window.0, &placement); + InvalidateRgn(window.0, None, false); } } } @@ -600,7 +620,7 @@ impl Window { #[inline] pub fn current_monitor(&self) -> Option { Some(RootMonitorHandle { - inner: monitor::current_monitor(self.window.0), + inner: monitor::current_monitor(self.hwnd()), }) } @@ -609,9 +629,9 @@ impl Window { if let Some(ref window_icon) = window_icon { window_icon .inner - .set_for_window(self.window.0, IconType::Small); + .set_for_window(self.hwnd(), IconType::Small); } else { - icon::unset_for_window(self.window.0, IconType::Small); + icon::unset_for_window(self.hwnd(), IconType::Small); } self.window_state.lock().window_icon = window_icon; } @@ -621,24 +641,24 @@ impl Window { if let Some(ref taskbar_icon) = taskbar_icon { taskbar_icon .inner - .set_for_window(self.window.0, IconType::Big); + .set_for_window(self.hwnd(), IconType::Big); } else { - icon::unset_for_window(self.window.0, IconType::Big); + icon::unset_for_window(self.hwnd(), IconType::Big); } self.window_state.lock().taskbar_icon = taskbar_icon; } pub(crate) fn set_ime_position_physical(&self, x: i32, y: i32) { - if unsafe { winuser::GetSystemMetrics(winuser::SM_IMMENABLED) } != 0 { - let mut composition_form = COMPOSITIONFORM { + if unsafe { GetSystemMetrics(SM_IMMENABLED) } != 0 { + let composition_form = COMPOSITIONFORM { dwStyle: CFS_POINT, ptCurrentPos: POINT { x, y }, rcArea: unsafe { mem::zeroed() }, }; unsafe { - let himc = winapi::um::imm::ImmGetContext(self.window.0); - winapi::um::imm::ImmSetCompositionWindow(himc, &mut composition_form); - winapi::um::imm::ImmReleaseContext(self.window.0, himc); + let himc = ImmGetContext(self.hwnd()); + ImmSetCompositionWindow(himc, &composition_form); + ImmReleaseContext(self.hwnd(), himc); } } } @@ -652,7 +672,7 @@ impl Window { #[inline] pub fn request_user_attention(&self, request_type: Option) { let window = self.window.clone(); - let active_window_handle = unsafe { winuser::GetActiveWindow() }; + let active_window_handle = unsafe { GetActiveWindow() }; if window.0 == active_window_handle { return; } @@ -660,23 +680,19 @@ impl Window { self.thread_executor.execute_in_thread(move || unsafe { let (flags, count) = request_type .map(|ty| match ty { - UserAttentionType::Critical => { - (winuser::FLASHW_ALL | winuser::FLASHW_TIMERNOFG, u32::MAX) - } - UserAttentionType::Informational => { - (winuser::FLASHW_TRAY | winuser::FLASHW_TIMERNOFG, 0) - } + UserAttentionType::Critical => (FLASHW_ALL | FLASHW_TIMERNOFG, u32::MAX), + UserAttentionType::Informational => (FLASHW_TRAY | FLASHW_TIMERNOFG, 0), }) - .unwrap_or((winuser::FLASHW_STOP, 0)); + .unwrap_or((FLASHW_STOP, 0)); - let mut flash_info = winuser::FLASHWINFO { - cbSize: mem::size_of::() as UINT, + let flash_info = FLASHWINFO { + cbSize: mem::size_of::() as u32, hwnd: window.0, dwFlags: flags, uCount: count, dwTimeout: 0, }; - winuser::FlashWindowEx(&mut flash_info); + FlashWindowEx(&flash_info); }); } @@ -692,7 +708,7 @@ impl Window { let is_visible = window_flags.contains(WindowFlags::VISIBLE); let is_minimized = window_flags.contains(WindowFlags::MINIMIZED); - let is_foreground = window.0 == unsafe { winuser::GetForegroundWindow() }; + let is_foreground = window.0 == unsafe { GetForegroundWindow() }; if is_visible && !is_minimized && !is_foreground { unsafe { force_window_active(window.0) }; @@ -706,7 +722,7 @@ impl Drop for Window { unsafe { // The window must be destroyed from the same thread that created it, so we send a // custom message to be handled by our callback to do the actual work. - winuser::PostMessageW(self.window.0, *DESTROY_MSG_ID, 0, 0); + PostMessageW(self.hwnd(), *DESTROY_MSG_ID, None, None); } } } @@ -741,13 +757,14 @@ where T: 'static, F: Fn(&mut Window) -> WindowData, { - let title = OsStr::new(&attributes.title) + let mut title = OsStr::new(&attributes.title) .encode_wide() - .chain(Some(0).into_iter()) + .chain(once(0)) .collect::>(); // registering the window class - let class_name = register_window_class::(&attributes.window_icon, &pl_attribs.taskbar_icon); + let mut class_name = + register_window_class::(&attributes.window_icon, &pl_attribs.taskbar_icon); let mut window_flags = WindowFlags::empty(); window_flags.set(WindowFlags::DECORATIONS, attributes.decorations); @@ -795,18 +812,18 @@ where }; let (style, ex_style) = window_flags.to_window_styles(); - let handle = winuser::CreateWindowExW( + let handle = CreateWindowExW( ex_style, - class_name.as_ptr(), - title.as_ptr() as LPCWSTR, + PWSTR(class_name.as_mut_ptr()), + PWSTR(title.as_mut_ptr()), style, - winuser::CW_USEDEFAULT, - winuser::CW_USEDEFAULT, - winuser::CW_USEDEFAULT, - winuser::CW_USEDEFAULT, - parent.unwrap_or(ptr::null_mut()), - pl_attribs.menu.unwrap_or(ptr::null_mut()), - libloaderapi::GetModuleHandleW(ptr::null()), + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + parent.unwrap_or(HWND(0)), + pl_attribs.menu.unwrap_or(HMENU(0)), + GetModuleHandleW(None), &mut initdata as *mut _ as *mut _, ); @@ -815,7 +832,7 @@ where panic::resume_unwind(panic_error) } - if handle.is_null() { + if handle.is_invalid() { return Err(os_error!(io::Error::last_os_error())); } @@ -833,9 +850,9 @@ unsafe fn post_init( ) -> Window { // Register for touch events if applicable { - let digitizer = winuser::GetSystemMetrics(winuser::SM_DIGITIZER) as u32; - if digitizer & winuser::NID_READY != 0 { - winuser::RegisterTouchWindow(real_window.0, winuser::TWF_WANTPALM); + let digitizer = GetSystemMetrics(SM_DIGITIZER) as u32; + if digitizer & NID_READY != 0 { + RegisterTouchWindow(real_window.0, TWF_WANTPALM); } } @@ -847,15 +864,15 @@ unsafe fn post_init( // Empty region for the blur effect, so the window is fully transparent let region = CreateRectRgn(0, 0, -1, -1); - let bb = dwmapi::DWM_BLURBEHIND { - dwFlags: dwmapi::DWM_BB_ENABLE | dwmapi::DWM_BB_BLURREGION, - fEnable: 1, + let bb = DWM_BLURBEHIND { + dwFlags: DWM_BB_ENABLE | DWM_BB_BLURREGION, + fEnable: true.into(), hRgnBlur: region, - fTransitionOnMaximized: 0, + fTransitionOnMaximized: false.into(), }; - dwmapi::DwmEnableBlurBehindWindow(real_window.0, &bb); - DeleteObject(region as _); + let _ = DwmEnableBlurBehindWindow(real_window.0, &bb); + DeleteObject(region); } // If the system theme is dark, we need to set the window theme now @@ -920,24 +937,24 @@ unsafe fn register_window_class( let h_icon = taskbar_icon .as_ref() .map(|icon| icon.inner.as_raw_handle()) - .unwrap_or(ptr::null_mut()); + .unwrap_or(HICON(0)); let h_icon_small = window_icon .as_ref() .map(|icon| icon.inner.as_raw_handle()) - .unwrap_or(ptr::null_mut()); + .unwrap_or(HICON(0)); - let class = winuser::WNDCLASSEXW { - cbSize: mem::size_of::() as UINT, - style: winuser::CS_HREDRAW | winuser::CS_VREDRAW | winuser::CS_OWNDC, + let class = WNDCLASSEXW { + cbSize: mem::size_of::() as u32, + style: CS_HREDRAW | CS_VREDRAW | CS_OWNDC, lpfnWndProc: Some(super::event_loop::public_window_callback::), cbClsExtra: 0, cbWndExtra: 0, - hInstance: libloaderapi::GetModuleHandleW(ptr::null()), + hInstance: GetModuleHandleW(None), hIcon: h_icon, - hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly - hbrBackground: ptr::null_mut(), - lpszMenuName: ptr::null(), - lpszClassName: class_name.as_ptr(), + hCursor: HCURSOR(0), // must be null in order for cursor state to work properly + hbrBackground: HBRUSH(0), + lpszMenuName: PWSTR(ptr::null_mut()), + lpszClassName: PWSTR(class_name.as_ptr() as *mut u16), hIconSm: h_icon_small, }; @@ -945,7 +962,7 @@ unsafe fn register_window_class( // an error, and because errors here are detected during CreateWindowEx anyway. // Also since there is no weird element in the struct, there is no reason for this // call to fail. - winuser::RegisterClassExW(&class); + RegisterClassExW(&class); class_name } @@ -953,19 +970,19 @@ unsafe fn register_window_class( struct ComInitialized(*mut ()); impl Drop for ComInitialized { fn drop(&mut self) { - unsafe { combaseapi::CoUninitialize() }; + unsafe { CoUninitialize() }; } } thread_local! { static COM_INITIALIZED: ComInitialized = { unsafe { - combaseapi::CoInitializeEx(ptr::null_mut(), COINIT_APARTMENTTHREADED); + let _ = CoInitializeEx(ptr::null_mut(), COINIT_APARTMENTTHREADED); ComInitialized(ptr::null_mut()) } }; - static TASKBAR_LIST: Cell<*mut ITaskbarList2> = Cell::new(ptr::null_mut()); + static TASKBAR_LIST: RefCell> = RefCell::new(None); } pub fn com_initialized() { @@ -983,29 +1000,21 @@ pub fn com_initialized() { unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) { com_initialized(); - TASKBAR_LIST.with(|task_bar_list_ptr| { - let mut task_bar_list = task_bar_list_ptr.get(); - - if task_bar_list.is_null() { - use winapi::{shared::winerror::S_OK, Interface}; - - let hr = combaseapi::CoCreateInstance( - &CLSID_TaskbarList, - ptr::null_mut(), - combaseapi::CLSCTX_ALL, - &ITaskbarList2::uuidof(), - &mut task_bar_list as *mut _ as *mut _, - ); + TASKBAR_LIST.with(|taskbar_list_ptr| { + let no_taskbar_list = taskbar_list_ptr.borrow().is_none(); - if hr != S_OK || (*task_bar_list).HrInit() != S_OK { - // In some old windows, the taskbar object could not be created, we just ignore it + if no_taskbar_list { + if let Ok(taskbar_list) = CoCreateInstance(&TaskbarList, None, CLSCTX_ALL) { + taskbar_list_ptr.replace(Some(taskbar_list)); + } else { + // On some old windows versions, the taskbar object could not be created, we just ignore it return; } - task_bar_list_ptr.set(task_bar_list) } - task_bar_list = task_bar_list_ptr.get(); - (*task_bar_list).MarkFullscreenWindow(handle, if fullscreen { 1 } else { 0 }); + if let Some(taskbar_list) = &*taskbar_list_ptr.borrow() { + let _ = taskbar_list.MarkFullscreenWindow(handle, fullscreen); + } }) } @@ -1014,25 +1023,39 @@ unsafe fn force_window_active(handle: HWND) { // This is a little hack which can "steal" the foreground window permission // We only call this function in the window creation, so it should be fine. // See : https://stackoverflow.com/questions/10740346/setforegroundwindow-only-working-while-visual-studio-is-open - let alt_sc = winuser::MapVirtualKeyW(winuser::VK_MENU as _, winuser::MAPVK_VK_TO_VSC); - - let mut inputs: [winuser::INPUT; 2] = mem::zeroed(); - inputs[0].type_ = winuser::INPUT_KEYBOARD; - inputs[0].u.ki_mut().wVk = winuser::VK_LMENU as _; - inputs[0].u.ki_mut().wScan = alt_sc as _; - inputs[0].u.ki_mut().dwFlags = winuser::KEYEVENTF_EXTENDEDKEY; - - inputs[1].type_ = winuser::INPUT_KEYBOARD; - inputs[1].u.ki_mut().wVk = winuser::VK_LMENU as _; - inputs[1].u.ki_mut().wScan = alt_sc as _; - inputs[1].u.ki_mut().dwFlags = winuser::KEYEVENTF_EXTENDEDKEY | winuser::KEYEVENTF_KEYUP; + let alt_sc = MapVirtualKeyW(VK_MENU.0 as u32, MAPVK_VK_TO_VSC); + + let inputs = [ + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: VK_LMENU, + wScan: alt_sc as u16, + dwFlags: KEYEVENTF_EXTENDEDKEY, + ..Default::default() + }, + }, + }, + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: VK_LMENU, + wScan: alt_sc as u16, + dwFlags: KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, + ..Default::default() + }, + }, + }, + ]; // Simulate a key press and release - winuser::SendInput( - inputs.len() as _, - inputs.as_mut_ptr(), - mem::size_of::() as _, + SendInput( + inputs.len() as u32, + inputs.as_ptr(), + mem::size_of::() as i32, ); - winuser::SetForegroundWindow(handle); + SetForegroundWindow(handle); } diff --git a/src/platform_impl/windows/window_state.rs b/src/platform_impl/windows/window_state.rs index 9e41bd7925..049e376bad 100644 --- a/src/platform_impl/windows/window_state.rs +++ b/src/platform_impl/windows/window_state.rs @@ -6,13 +6,20 @@ use crate::{ window::{CursorIcon, Fullscreen, Theme, WindowAttributes}, }; use parking_lot::MutexGuard; -use std::{io, ptr}; -use winapi::{ - shared::{ - minwindef::DWORD, - windef::{HWND, RECT}, +use std::io; +use windows::Win32::{ + Foundation::{HWND, LPARAM, RECT, WPARAM}, + Graphics::Gdi::InvalidateRgn, + UI::WindowsAndMessaging::{ + SendMessageW, SetWindowLongW, SetWindowPos, ShowWindow, GWL_EXSTYLE, GWL_STYLE, + HWND_NOTOPMOST, HWND_TOPMOST, SWP_ASYNCWINDOWPOS, SWP_FRAMECHANGED, SWP_NOACTIVATE, + SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, + SW_SHOW, WINDOWPLACEMENT, WINDOW_EX_STYLE, WINDOW_STYLE, WS_BORDER, WS_CAPTION, WS_CHILD, + WS_CLIPCHILDREN, WS_CLIPSIBLINGS, WS_EX_ACCEPTFILES, WS_EX_APPWINDOW, WS_EX_LEFT, + WS_EX_NOREDIRECTIONBITMAP, WS_EX_TOPMOST, WS_EX_WINDOWEDGE, WS_MAXIMIZE, WS_MAXIMIZEBOX, + WS_MINIMIZE, WS_MINIMIZEBOX, WS_OVERLAPPED, WS_OVERLAPPEDWINDOW, WS_POPUP, WS_SIZEBOX, + WS_SYSMENU, WS_VISIBLE, }, - um::winuser, }; /// Contains information about states and the window that the callback is going to use. @@ -39,7 +46,7 @@ pub struct WindowState { #[derive(Clone)] pub struct SavedWindow { - pub placement: winuser::WINDOWPLACEMENT, + pub placement: WINDOWPLACEMENT, } #[derive(Clone)] @@ -187,10 +194,8 @@ impl WindowFlags { self } - pub fn to_window_styles(self) -> (DWORD, DWORD) { - use winapi::um::winuser::*; - - let (mut style, mut style_ex) = (0, 0); + pub fn to_window_styles(self) -> (WINDOW_STYLE, WINDOW_EX_STYLE) { + let (mut style, mut style_ex) = (WS_OVERLAPPED, WS_EX_LEFT); if self.contains(WindowFlags::RESIZABLE) { style |= WS_SIZEBOX | WS_MAXIMIZEBOX; @@ -248,43 +253,40 @@ impl WindowFlags { if diff.contains(WindowFlags::VISIBLE) { unsafe { - winuser::ShowWindow( + ShowWindow( window, match new.contains(WindowFlags::VISIBLE) { - true => winuser::SW_SHOW, - false => winuser::SW_HIDE, + true => SW_SHOW, + false => SW_HIDE, }, ); } } if diff.contains(WindowFlags::ALWAYS_ON_TOP) { unsafe { - winuser::SetWindowPos( + SetWindowPos( window, match new.contains(WindowFlags::ALWAYS_ON_TOP) { - true => winuser::HWND_TOPMOST, - false => winuser::HWND_NOTOPMOST, + true => HWND_TOPMOST, + false => HWND_NOTOPMOST, }, 0, 0, 0, 0, - winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOMOVE - | winuser::SWP_NOSIZE - | winuser::SWP_NOACTIVATE, + SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE, ); - winuser::InvalidateRgn(window, ptr::null_mut(), 0); + InvalidateRgn(window, None, false); } } if diff.contains(WindowFlags::MAXIMIZED) || new.contains(WindowFlags::MAXIMIZED) { unsafe { - winuser::ShowWindow( + ShowWindow( window, match new.contains(WindowFlags::MAXIMIZED) { - true => winuser::SW_MAXIMIZE, - false => winuser::SW_RESTORE, + true => SW_MAXIMIZE, + false => SW_RESTORE, }, ); } @@ -293,11 +295,11 @@ impl WindowFlags { // Minimize operations should execute after maximize for proper window animations if diff.contains(WindowFlags::MINIMIZED) { unsafe { - winuser::ShowWindow( + ShowWindow( window, match new.contains(WindowFlags::MINIMIZED) { - true => winuser::SW_MINIMIZE, - false => winuser::SW_RESTORE, + true => SW_MINIMIZE, + false => SW_RESTORE, }, ); } @@ -307,18 +309,20 @@ impl WindowFlags { let (style, style_ex) = new.to_window_styles(); unsafe { - winuser::SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 1, 0); + SendMessageW( + window, + *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, + WPARAM(1), + LPARAM(0), + ); // This condition is necessary to avoid having an unrestorable window if !new.contains(WindowFlags::MINIMIZED) { - winuser::SetWindowLongW(window, winuser::GWL_STYLE, style as _); - winuser::SetWindowLongW(window, winuser::GWL_EXSTYLE, style_ex as _); + SetWindowLongW(window, GWL_STYLE, style.0 as i32); + SetWindowLongW(window, GWL_EXSTYLE, style_ex.0 as i32); } - let mut flags = winuser::SWP_NOZORDER - | winuser::SWP_NOMOVE - | winuser::SWP_NOSIZE - | winuser::SWP_FRAMECHANGED; + let mut flags = SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED; // We generally don't want style changes here to affect window // focus, but for fullscreen windows they must be activated @@ -326,12 +330,17 @@ impl WindowFlags { if !new.contains(WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN) && !new.contains(WindowFlags::MARKER_BORDERLESS_FULLSCREEN) { - flags |= winuser::SWP_NOACTIVATE; + flags |= SWP_NOACTIVATE; } // Refresh the window frame - winuser::SetWindowPos(window, ptr::null_mut(), 0, 0, 0, 0, flags); - winuser::SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 0, 0); + SetWindowPos(window, None, 0, 0, 0, 0, flags); + SendMessageW( + window, + *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, + WPARAM(0), + LPARAM(0), + ); } } }