From 9b1d47b3006fc1cd04ab56da6272dbaebdefa0ec Mon Sep 17 00:00:00 2001 From: Clemens Wasser Date: Fri, 5 Nov 2021 23:29:53 +0100 Subject: [PATCH 1/2] Adopt windows-sys --- Cargo.toml | 54 +- src/platform/windows.rs | 39 +- src/platform_impl/windows/dark_mode.rs | 88 +-- src/platform_impl/windows/definitions.rs | 140 ++++ src/platform_impl/windows/dpi.rs | 40 +- src/platform_impl/windows/drop_handler.rs | 98 +-- src/platform_impl/windows/event.rs | 451 +++++------ src/platform_impl/windows/event_loop.rs | 698 +++++++++--------- .../windows/event_loop/runner.rs | 39 +- src/platform_impl/windows/icon.rs | 110 ++- src/platform_impl/windows/mod.rs | 59 +- src/platform_impl/windows/monitor.rs | 86 ++- src/platform_impl/windows/raw_input.rs | 104 +-- src/platform_impl/windows/util.rs | 178 +++-- src/platform_impl/windows/window.rs | 408 +++++----- src/platform_impl/windows/window_state.rs | 75 +- 16 files changed, 1425 insertions(+), 1242 deletions(-) create mode 100644 src/platform_impl/windows/definitions.rs diff --git a/Cargo.toml b/Cargo.toml index 239be28533..9e08fb46bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,33 +55,35 @@ default_features = false features = ["display_link"] [target.'cfg(target_os = "windows")'.dependencies] -parking_lot = "0.11" +parking_lot = "0.12" -[target.'cfg(target_os = "windows")'.dependencies.winapi] -version = "0.3.9" +[target.'cfg(target_os = "windows")'.dependencies.windows-sys] +version = "0.33" features = [ - "combaseapi", - "commctrl", - "dwmapi", - "errhandlingapi", - "imm", - "hidusage", - "libloaderapi", - "objbase", - "ole2", - "processthreadsapi", - "shellapi", - "shellscalingapi", - "shobjidl_core", - "unknwnbase", - "winbase", - "windowsx", - "winerror", - "wingdi", - "winnt", - "winuser", - "mmsystem", - "timeapi" + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "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] @@ -91,7 +93,7 @@ sctk = { package = "smithay-client-toolkit", version = "0.15.1", default_feature mio = { version = "0.8", features = ["os-ext"], optional = true } x11-dl = { version = "2.18.5", optional = true } percent-encoding = { version = "2.0", optional = true } -parking_lot = { version = "0.11.0", optional = true } +parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 3cd7c5c319..0f5902c961 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1,11 +1,7 @@ #![cfg(target_os = "windows")] -use std::os::raw::c_void; use std::path::Path; -use winapi::shared::minwindef::WORD; -use winapi::shared::windef::{HMENU, HWND}; - use crate::{ dpi::PhysicalSize, event::DeviceId, @@ -15,6 +11,15 @@ use crate::{ window::{BadIcon, Icon, Theme, Window, WindowBuilder}, }; +/// Window Handle type used by Win32 API +pub type HWND = isize; +/// Menu Handle type used by Win32 API +pub type HMENU = isize; +/// Monitor Handle type used by Win32 API +pub type HMONITOR = isize; +/// Instance Handle type used by Win32 API +pub type HINSTANCE = isize; + /// Additional methods on `EventLoop` that are specific to Windows. pub trait EventLoopBuilderExtWindows { /// Whether to allow the event loop to be created off of the main thread. @@ -70,11 +75,11 @@ impl EventLoopBuilderExtWindows for EventLoopBuilder { /// Additional methods on `Window` that are specific to Windows. pub trait WindowExtWindows { /// Returns the HINSTANCE of the window - fn hinstance(&self) -> *mut c_void; + fn hinstance(&self) -> HINSTANCE; /// Returns the native handle that is used by this window. /// /// The pointer will become invalid when the native window was destroyed. - fn hwnd(&self) -> *mut c_void; + fn hwnd(&self) -> HWND; /// Enables or disables mouse and keyboard input to the specified window. /// @@ -100,13 +105,13 @@ pub trait WindowExtWindows { impl WindowExtWindows for Window { #[inline] - fn hinstance(&self) -> *mut c_void { - self.window.hinstance() as *mut _ + fn hinstance(&self) -> HINSTANCE { + self.window.hinstance() } #[inline] - fn hwnd(&self) -> *mut c_void { - self.window.hwnd() as *mut _ + fn hwnd(&self) -> HWND { + self.window.hwnd() } #[inline] @@ -150,10 +155,12 @@ pub trait WindowBuilderExtWindows { /// /// Parent and menu are mutually exclusive; a child window cannot have a menu! /// - /// The menu must have been manually created beforehand with [`winapi::um::winuser::CreateMenu`] or similar. + /// The menu must have been manually created beforehand with [`CreateMenu`] or similar. /// /// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how the menus look. /// If you use this, it is recommended that you combine it with `with_theme(Some(Theme::Light))` to avoid a jarring effect. + /// + /// [`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu fn with_menu(self, menu: HMENU) -> WindowBuilder; /// This sets `ICON_BIG`. A good ceiling here is 256x256. @@ -224,7 +231,7 @@ pub trait MonitorHandleExtWindows { fn native_id(&self) -> String; /// Returns the handle of the monitor - `HMONITOR`. - fn hmonitor(&self) -> *mut c_void; + fn hmonitor(&self) -> HMONITOR; } impl MonitorHandleExtWindows for MonitorHandle { @@ -234,8 +241,8 @@ impl MonitorHandleExtWindows for MonitorHandle { } #[inline] - fn hmonitor(&self) -> *mut c_void { - self.inner.hmonitor() as *mut _ + fn hmonitor(&self) -> HMONITOR { + self.inner.hmonitor() } } @@ -273,7 +280,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 { @@ -285,7 +292,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..8e1deac3ae 100644 --- a/src/platform_impl/windows/dark_mode.rs +++ b/src/platform_impl/windows/dark_mode.rs @@ -1,29 +1,35 @@ /// 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::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, +use std::{ffi::c_void, ptr}; + +use windows_sys::{ + core::PCSTR, + Win32::{ + Foundation::{BOOL, HWND, NTSTATUS, S_OK}, + System::{ + LibraryLoader::{GetProcAddress, LoadLibraryA}, + SystemInformation::OSVERSIONINFOW, + }, + UI::{ + Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTA}, + Controls::SetWindowTheme, + WindowsAndMessaging::{SystemParametersInfoA, SPI_GETHIGHCONTRAST}, + }, }, - um::{libloaderapi, uxtheme, winnt, winuser}, }; use crate::window::Theme; +use super::util; + 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, @@ -32,9 +38,9 @@ lazy_static! { szCSDVersion: [0; 128], }; - let status = (rtl_get_version)(&mut vi as _); + let status = (rtl_get_version)(&mut vi); - if NT_SUCCESS(status) && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 { + if status >= 0 && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 { Some(vi.dwBuildNumber) } else { None @@ -54,8 +60,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 = util::encode_wide("DarkMode_Explorer"); + static ref LIGHT_THEME_NAME: Vec = util::encode_wide(""); } /// Attempt to set a theme on a window, if necessary. @@ -77,7 +83,7 @@ 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, theme_name, ptr::null()) }; if status == S_OK && set_dark_mode_for_window(hwnd, is_dark_mode) { return theme; @@ -103,8 +109,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 +121,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 = BOOL::from(is_dark_mode); let mut data = WINDOWCOMPOSITIONATTRIBDATA { Attrib: WCA_USEDARKMODECOLORS, @@ -123,9 +129,9 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool { cbData: std::mem::size_of_val(&is_dark_mode_bigbool) as _, }; - let status = set_window_composition_attribute(hwnd, &mut data as *mut _); + let status = set_window_composition_attribute(hwnd, &mut data); - status != FALSE + status != false.into() } } else { false @@ -141,24 +147,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: PCSTR = 132 as PCSTR; - let module = libloaderapi::LoadLibraryA("uxtheme.dll\0".as_ptr() as _); + let module = LoadLibraryA("uxtheme.dll\0".as_ptr()); - if module.is_null() { + if module == 0 { 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 +168,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(), + lpszDefaultScheme: 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, ) }; - 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 != false.into() && util::has_flag(hc.dwFlags, HCF_HIGHCONTRASTON) } diff --git a/src/platform_impl/windows/definitions.rs b/src/platform_impl/windows/definitions.rs new file mode 100644 index 0000000000..66818f3dc5 --- /dev/null +++ b/src/platform_impl/windows/definitions.rs @@ -0,0 +1,140 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] + +use std::ffi::c_void; + +use windows_sys::{ + core::{IUnknown, GUID, HRESULT}, + Win32::{ + Foundation::{BOOL, HWND, POINTL}, + System::Com::{ + IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM, + }, + UI::Shell::ITaskbarList, + }, +}; + +#[repr(C)] +pub struct IUnknownVtbl { + pub QueryInterface: unsafe extern "system" fn( + This: *mut IUnknown, + riid: *const GUID, + ppvObject: *mut *mut c_void, + ) -> HRESULT, + pub AddRef: unsafe extern "system" fn(This: *mut IUnknown) -> u32, + pub Release: unsafe extern "system" fn(This: *mut IUnknown) -> u32, +} + +#[repr(C)] +pub struct IDataObjectVtbl { + pub parent: IUnknownVtbl, + pub GetData: unsafe extern "system" fn( + This: *mut IDataObject, + pformatetcIn: *const FORMATETC, + pmedium: *mut STGMEDIUM, + ) -> HRESULT, + pub GetDataHere: unsafe extern "system" fn( + This: *mut IDataObject, + pformatetc: *const FORMATETC, + pmedium: *mut STGMEDIUM, + ) -> HRESULT, + QueryGetData: + unsafe extern "system" fn(This: *mut IDataObject, pformatetc: *const FORMATETC) -> HRESULT, + pub GetCanonicalFormatEtc: unsafe extern "system" fn( + This: *mut IDataObject, + pformatetcIn: *const FORMATETC, + pformatetcOut: *mut FORMATETC, + ) -> HRESULT, + pub SetData: unsafe extern "system" fn( + This: *mut IDataObject, + pformatetc: *const FORMATETC, + pformatetcOut: *const FORMATETC, + fRelease: BOOL, + ) -> HRESULT, + pub EnumFormatEtc: unsafe extern "system" fn( + This: *mut IDataObject, + dwDirection: u32, + ppenumFormatEtc: *mut *mut IEnumFORMATETC, + ) -> HRESULT, + pub DAdvise: unsafe extern "system" fn( + This: *mut IDataObject, + pformatetc: *const FORMATETC, + advf: u32, + pAdvSInk: *const IAdviseSink, + pdwConnection: *mut u32, + ) -> HRESULT, + pub DUnadvise: unsafe extern "system" fn(This: *mut IDataObject, dwConnection: u32) -> HRESULT, + pub EnumDAdvise: unsafe extern "system" fn( + This: *mut IDataObject, + ppenumAdvise: *const *const IEnumSTATDATA, + ) -> HRESULT, +} + +#[repr(C)] +pub struct IDropTargetVtbl { + pub parent: IUnknownVtbl, + pub DragEnter: unsafe extern "system" fn( + This: *mut IDropTarget, + pDataObj: *const IDataObject, + grfKeyState: u32, + pt: *const POINTL, + pdwEffect: *mut u32, + ) -> HRESULT, + pub DragOver: unsafe extern "system" fn( + This: *mut IDropTarget, + grfKeyState: u32, + pt: *const POINTL, + pdwEffect: *mut u32, + ) -> HRESULT, + pub DragLeave: unsafe extern "system" fn(This: *mut IDropTarget) -> HRESULT, + pub Drop: unsafe extern "system" fn( + This: *mut IDropTarget, + pDataObj: *const IDataObject, + grfKeyState: u32, + pt: *const POINTL, + pdwEffect: *mut u32, + ) -> HRESULT, +} + +#[repr(C)] +pub struct IDropTarget { + pub lpVtbl: *const IDropTargetVtbl, +} + +#[repr(C)] +pub struct ITaskbarListVtbl { + pub parent: IUnknownVtbl, + pub HrInit: unsafe extern "system" fn(This: *mut ITaskbarList) -> HRESULT, + pub AddTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT, + pub DeleteTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT, + pub ActivateTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT, + pub SetActiveAlt: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT, +} + +#[repr(C)] +pub struct ITaskbarList2Vtbl { + pub parent: ITaskbarListVtbl, + pub MarkFullscreenWindow: unsafe extern "system" fn( + This: *mut ITaskbarList2, + hwnd: HWND, + fFullscreen: BOOL, + ) -> HRESULT, +} +#[repr(C)] +pub struct ITaskbarList2 { + pub lpVtbl: *const ITaskbarList2Vtbl, +} + +pub const CLSID_TaskbarList: GUID = GUID { + data1: 0x56fdf344, + data2: 0xfd6d, + data3: 0x11d0, + data4: [0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90], +}; + +pub const IID_ITaskbarList2: GUID = GUID { + data1: 0x602d4995, + data2: 0xb13a, + data3: 0x429b, + data4: [0xa6, 0x6e, 0x19, 0x35, 0xe4, 0x4f, 0x43, 0x17], +}; diff --git a/src/platform_impl/windows/dpi.rs b/src/platform_impl/windows/dpi.rs index f7ec439135..1a0bf69285 100644 --- a/src/platform_impl/windows/dpi.rs +++ b/src/platform_impl/windows/dpi.rs @@ -2,24 +2,26 @@ use std::sync::Once; +use windows_sys::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 = -4; pub fn become_dpi_aware() { static ENABLE_DPI_AWARENESS: Once = Once::new(); @@ -28,7 +30,7 @@ pub fn become_dpi_aware() { 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 + == false.into() { // V2 only works with Windows 10 Creators Update (1703). Try using the older // V1 if we can't set V2. @@ -76,8 +78,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 == 0 { panic!("[winit] `GetDC` returned null!"); } if let Some(GetDpiForWindow) = *GET_DPI_FOR_WINDOW { @@ -88,8 +90,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 == 0 { return BASE_DPI; } @@ -102,7 +104,7 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 { } } else { // We are on Vista or later. - if winuser::IsProcessDPIAware() != FALSE { + if IsProcessDPIAware() != false.into() { // 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..fc048c8622 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -1,29 +1,28 @@ use std::{ - ffi::OsString, + ffi::{c_void, OsString}, os::windows::ffi::OsStringExt, path::PathBuf, ptr, sync::atomic::{AtomicUsize, Ordering}, }; -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_sys::{ + core::{IUnknown, GUID, HRESULT}, + Win32::{ + Foundation::{DV_E_FORMATETC, HWND, POINTL, S_OK}, + System::{ + Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL}, + Ole::{DROPEFFECT_COPY, DROPEFFECT_NONE}, + SystemServices::CF_HDROP, + }, + UI::Shell::{DragFinish, DragQueryFileW, HDROP}, }, }; -use crate::platform_impl::platform::WindowId; - +use crate::platform_impl::platform::{ + definitions::{IDataObjectVtbl, IDropTarget, IDropTargetVtbl, IUnknownVtbl}, + WindowId, +}; use crate::{event::Event, window::WindowId as SuperWindowId}; #[repr(C)] @@ -32,7 +31,7 @@ pub struct FileDropHandlerData { refcount: AtomicUsize, 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 */ } @@ -60,8 +59,8 @@ impl FileDropHandler { // Implement IUnknown pub unsafe extern "system" fn QueryInterface( - _this: *mut unknwnbase::IUnknown, - _riid: REFIID, + _this: *mut IUnknown, + _riid: *const GUID, _ppvObject: *mut *mut c_void, ) -> HRESULT { // This function doesn't appear to be required for an `IDropTarget`. @@ -69,28 +68,28 @@ impl FileDropHandler { unimplemented!(); } - pub unsafe extern "system" fn AddRef(this: *mut unknwnbase::IUnknown) -> ULONG { + pub unsafe extern "system" fn AddRef(this: *mut IUnknown) -> u32 { let drop_handler_data = Self::from_interface(this); let count = drop_handler_data.refcount.fetch_add(1, Ordering::Release) + 1; - count as ULONG + count as u32 } - pub unsafe extern "system" fn Release(this: *mut unknwnbase::IUnknown) -> ULONG { + pub unsafe extern "system" fn Release(this: *mut IUnknown) -> u32 { 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 + count as u32 } pub unsafe extern "system" fn DragEnter( this: *mut IDropTarget, pDataObj: *const IDataObject, - _grfKeyState: DWORD, + _grfKeyState: u32, _pt: *const POINTL, - pdwEffect: *mut DWORD, + pdwEffect: *mut u32, ) -> HRESULT { use crate::event::WindowEvent::HoveredFile; let drop_handler = Self::from_interface(this); @@ -113,9 +112,9 @@ impl FileDropHandler { pub unsafe extern "system" fn DragOver( this: *mut IDropTarget, - _grfKeyState: DWORD, + _grfKeyState: u32, _pt: *const POINTL, - pdwEffect: *mut DWORD, + pdwEffect: *mut u32, ) -> HRESULT { let drop_handler = Self::from_interface(this); *pdwEffect = drop_handler.cursor_effect; @@ -139,9 +138,9 @@ impl FileDropHandler { pub unsafe extern "system" fn Drop( this: *mut IDropTarget, pDataObj: *const IDataObject, - _grfKeyState: DWORD, + _grfKeyState: u32, _pt: *const POINTL, - _pdwEffect: *mut DWORD, + _pdwEffect: *mut u32, ) -> HRESULT { use crate::event::WindowEvent::DroppedFile; let drop_handler = Self::from_interface(this); @@ -152,7 +151,7 @@ impl FileDropHandler { }); }); if let Some(hdrop) = hdrop { - shellapi::DragFinish(hdrop); + DragFinish(hdrop); } S_OK @@ -162,38 +161,23 @@ impl FileDropHandler { &mut *(this as *mut _) } - unsafe fn iterate_filenames( - data_obj: *const IDataObject, - callback: F, - ) -> Option + unsafe fn iterate_filenames(data_obj: *const IDataObject, 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, + cfFormat: CF_HDROP as u16, + ptd: ptr::null_mut(), + dwAspect: DVASPECT_CONTENT as u32, lindex: -1, - tymed: TYMED_HGLOBAL, + tymed: TYMED_HGLOBAL as u32, }; 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; + let get_data_fn = (*(*data_obj).cast::()).GetData; + let get_data_result = get_data_fn(data_obj as *mut _, &drop_format, &mut medium); + if get_data_result >= 0 { + let hdrop = medium.Anonymous.hGlobal; // The second parameter (0xFFFFFFFF) instructs the function to return the item count let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, ptr::null_mut(), 0); @@ -207,7 +191,7 @@ impl FileDropHandler { // 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); + DragQueryFileW(hdrop, i, 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()); @@ -235,13 +219,13 @@ impl FileDropHandlerData { impl Drop for FileDropHandler { fn drop(&mut self) { unsafe { - FileDropHandler::Release(self.data as *mut unknwnbase::IUnknown); + FileDropHandler::Release(self.data as *mut IUnknown); } } } static DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl { - parent: unknwnbase::IUnknownVtbl { + parent: IUnknownVtbl { QueryInterface: FileDropHandler::QueryInterface, AddRef: FileDropHandler::AddRef, Release: FileDropHandler::Release, diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index 77bd31d2ae..fba3d5ae4c 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -1,37 +1,60 @@ use std::{ char, - os::raw::c_int, - ptr, - sync::atomic::{AtomicBool, AtomicPtr, Ordering}, + sync::atomic::{AtomicBool, AtomicIsize, Ordering}, +}; + +use windows_sys::Win32::{ + Foundation::{LPARAM, WPARAM}, + UI::{ + Input::KeyboardAndMouse::{ + GetKeyState, GetKeyboardLayout, GetKeyboardState, MapVirtualKeyA, ToUnicodeEx, + VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_A, VK_ADD, + VK_APPS, VK_B, VK_BACK, VK_BROWSER_BACK, VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, + VK_BROWSER_HOME, VK_BROWSER_REFRESH, VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_C, + VK_CAPITAL, VK_CONTROL, VK_CONVERT, VK_D, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, + VK_E, VK_END, VK_ESCAPE, VK_F, 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_G, VK_H, VK_HOME, VK_I, VK_INSERT, VK_J, + VK_K, VK_KANA, VK_KANJI, VK_L, VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LCONTROL, + VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_M, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, + VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP, VK_MENU, VK_MULTIPLY, VK_N, 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_O, 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_P, VK_PAUSE, VK_PRIOR, VK_Q, VK_R, VK_RCONTROL, + VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN, VK_S, VK_SCROLL, VK_SHIFT, VK_SLEEP, + VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_T, VK_TAB, VK_U, VK_UP, VK_V, VK_VOLUME_DOWN, + VK_VOLUME_MUTE, VK_VOLUME_UP, VK_W, VK_X, VK_Y, VK_Z, + }, + TextServices::HKL, + WindowsAndMessaging::{MAPVK_VK_TO_CHAR, MAPVK_VSC_TO_VK_EX}, + }, }; use crate::event::{ModifiersState, ScanCode, VirtualKeyCode}; -use winapi::{ - shared::minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM}, - um::winuser, -}; +use super::util::has_flag; -fn key_pressed(vkey: c_int) -> bool { - unsafe { (winuser::GetKeyState(vkey) & (1 << 15)) == (1 << 15) } +fn key_pressed(vkey: VIRTUAL_KEY) -> bool { + unsafe { has_flag(GetKeyState(vkey as i32), 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,19 +108,19 @@ 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, _)| 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(), @@ -126,10 +149,10 @@ 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 hkl = GetKeyboardLayout(0); let old_hkl = ACTIVE_LAYOUT.swap(hkl, Ordering::SeqCst); if hkl == old_hkl { @@ -139,8 +162,8 @@ fn layout_uses_altgr() -> bool { 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 as usize] = 0x80; + keyboard_state_altgr[VK_CONTROL as usize] = 0x80; let keyboard_state_empty = [0u8; 256]; @@ -160,206 +183,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), + VK_0 => Some(VirtualKeyCode::Key0), + VK_1 => Some(VirtualKeyCode::Key1), + VK_2 => Some(VirtualKeyCode::Key2), + VK_3 => Some(VirtualKeyCode::Key3), + VK_4 => Some(VirtualKeyCode::Key4), + VK_5 => Some(VirtualKeyCode::Key5), + VK_6 => Some(VirtualKeyCode::Key6), + VK_7 => Some(VirtualKeyCode::Key7), + VK_8 => Some(VirtualKeyCode::Key8), + VK_9 => Some(VirtualKeyCode::Key9), + VK_A => Some(VirtualKeyCode::A), + VK_B => Some(VirtualKeyCode::B), + VK_C => Some(VirtualKeyCode::C), + VK_D => Some(VirtualKeyCode::D), + VK_E => Some(VirtualKeyCode::E), + VK_F => Some(VirtualKeyCode::F), + VK_G => Some(VirtualKeyCode::G), + VK_H => Some(VirtualKeyCode::H), + VK_I => Some(VirtualKeyCode::I), + VK_J => Some(VirtualKeyCode::J), + VK_K => Some(VirtualKeyCode::K), + VK_L => Some(VirtualKeyCode::L), + VK_M => Some(VirtualKeyCode::M), + VK_N => Some(VirtualKeyCode::N), + VK_O => Some(VirtualKeyCode::O), + VK_P => Some(VirtualKeyCode::P), + VK_Q => Some(VirtualKeyCode::Q), + VK_R => Some(VirtualKeyCode::R), + VK_S => Some(VirtualKeyCode::S), + VK_T => Some(VirtualKeyCode::T), + VK_U => Some(VirtualKeyCode::U), + VK_V => Some(VirtualKeyCode::V), + VK_W => Some(VirtualKeyCode::W), + VK_X => Some(VirtualKeyCode::X), + VK_Y => Some(VirtualKeyCode::Y), + VK_Z => 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 => (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 +388,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 == 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 +413,16 @@ pub fn process_key_params( wparam: WPARAM, lparam: LPARAM, ) -> Option<(ScanCode, Option)> { - let scancode = ((lparam >> 16) & 0xff) as UINT; + let scancode = ((lparam >> 16) & 0xff) as u32; let extended = (lparam & 0x01000000) != 0; - handle_extended_keys(wparam as _, scancode, extended) + handle_extended_keys(wparam 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 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 fd738dde07..7cb36f9515 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -17,17 +17,56 @@ 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, +use windows_sys::Win32::{ + Devices::HumanInterfaceDevice::MOUSE_MOVE_RELATIVE, + Foundation::{BOOL, HANDLE, HWND, LPARAM, LRESULT, POINT, RECT, WAIT_TIMEOUT, WPARAM}, + Graphics::Gdi::{ + ClientToScreen, GetMonitorInfoW, GetUpdateRect, MonitorFromRect, MonitorFromWindow, + RedrawWindow, ScreenToClient, ValidateRect, MONITORINFO, MONITOR_DEFAULTTONULL, + RDW_INTERNALPAINT, SC_SCREENSAVE, }, - um::{ - libloaderapi, mmsystem, ole2, processthreadsapi, timeapi, winbase, - winnt::{HANDLE, LONG, LPCSTR, SHORT}, - winuser, + Media::{timeBeginPeriod, timeEndPeriod, timeGetDevCaps, TIMECAPS, TIMERR_NOERROR}, + System::{ + LibraryLoader::GetModuleHandleW, Ole::RevokeDragDrop, Threading::GetCurrentThreadId, + WindowsProgramming::INFINITE, + }, + UI::{ + Controls::{HOVER_DEFAULT, WM_MOUSELEAVE}, + Input::{ + KeyboardAndMouse::{ + MapVirtualKeyA, ReleaseCapture, SetCapture, TrackMouseEvent, TME_LEAVE, + TRACKMOUSEEVENT, VK_F4, + }, + Pointer::{ + POINTER_FLAG_DOWN, POINTER_FLAG_UP, POINTER_FLAG_UPDATE, POINTER_INFO, + POINTER_PEN_INFO, POINTER_TOUCH_INFO, + }, + Touch::{ + CloseTouchInputHandle, GetTouchInputInfo, TOUCHEVENTF_DOWN, TOUCHEVENTF_MOVE, + TOUCHEVENTF_UP, TOUCHINPUT, + }, + RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + }, + WindowsAndMessaging::{ + CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, GetClientRect, + GetCursorPos, GetMessageW, GetWindowLongW, LoadCursorW, MsgWaitForMultipleObjectsEx, + PeekMessageW, PostMessageW, PostThreadMessageW, RegisterClassExW, + RegisterWindowMessageA, SetCursor, SetWindowPos, TranslateMessage, CREATESTRUCTW, + GIDC_ARRIVAL, GIDC_REMOVAL, GWL_EXSTYLE, GWL_STYLE, GWL_USERDATA, HTCAPTION, HTCLIENT, + MAPVK_VK_TO_VSC, MINMAXINFO, MSG, MWMO_INPUTAVAILABLE, 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, 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, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, + WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, + }, }, }; @@ -52,13 +91,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 +105,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 = @@ -129,14 +168,14 @@ impl Default for PlatformSpecificEventLoopAttributes { } pub struct EventLoopWindowTarget { - thread_id: DWORD, + thread_id: u32, thread_msg_target: HWND, pub(crate) runner_shared: EventLoopRunnerShared, } impl EventLoop { pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Self { - let thread_id = unsafe { processthreadsapi::GetCurrentThreadId() }; + let thread_id = unsafe { GetCurrentThreadId() }; if !attributes.any_thread && thread_id != main_thread_id() { panic!( @@ -153,8 +192,7 @@ impl EventLoop { 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)); @@ -210,11 +248,11 @@ impl EventLoop { runner.poll(); 'main: loop { - if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) { + if GetMessageW(&mut msg, 0, 0, 0) == false.into() { break 'main 0; } - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); + TranslateMessage(&msg); + DispatchMessageW(&msg); if let Err(payload) = runner.take_panic_error() { runner.reset_runner(); @@ -283,8 +321,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 +336,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,12 +344,12 @@ 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 _, + -1, *SEND_WAIT_THREAD_ID_MSG_ID, *SEND_WAIT_THREAD_ID_MSG_ID, ); @@ -320,19 +358,17 @@ fn get_wait_thread_id() -> DWORD { "this shouldn't be possible. please open an issue with Winit. error code: {}", result ); - msg.lParam as DWORD + msg.lParam 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,12 +376,12 @@ 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, @@ -360,17 +396,15 @@ 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, 0, 0, 0, PM_REMOVE) != false.into() { + TranslateMessage(&msg); + DispatchMessageW(&msg); } + } else if GetMessageW(&mut msg, 0, 0, 0) == false.into() { + 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 { @@ -386,28 +420,28 @@ 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 resume_reason == WAIT_TIMEOUT { + PostMessageW(msg_window_id, *PROCESS_NEW_EVENTS_MSG_ID, 0, 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, 0, 0); wait_until_opt = None; } } @@ -416,7 +450,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 +469,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 +497,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 } @@ -489,18 +523,15 @@ impl EventLoopThreadExecutor { function(); } else { // We double-box because the first box is a fat pointer. - let boxed = Box::new(function) as Box; - let boxed2: ThreadExecFn = Box::new(boxed); + let boxed2: ThreadExecFn = Box::new(Box::new(function)); let raw = Box::into_raw(boxed2); - let res = winuser::PostMessageW( - self.target_window, - *EXEC_MSG_ID, - raw as *mut () as usize as WPARAM, - 0, + let res = PostMessageW(self.target_window, *EXEC_MSG_ID, raw as usize, 0); + assert!( + res != false.into(), + "PostMessage failed; is the messages queue full?" ); - assert!(res != 0, "PostMessage failed ; is the messages queue full?"); } } } @@ -526,7 +557,7 @@ 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, 0, 0) != false.into() { self.event_send.send(event).ok(); Ok(()) } else { @@ -543,7 +574,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("Winit::WakeupMsg\0".as_ptr()) } }; // Message sent when we want to execute a closure in the thread. @@ -551,80 +582,72 @@ lazy_static! { // and LPARAM is unused. static ref EXEC_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr() as *const i8) + RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr()) } }; static ref PROCESS_NEW_EVENTS_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::ProcessNewEvents\0".as_ptr() as *const i8) + RegisterWindowMessageA("Winit::ProcessNewEvents\0".as_ptr()) } }; /// 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("Winit::SendWaitThreadId\0".as_ptr()) } }; /// 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("Winit::WaitUntil\0".as_ptr()) } }; static ref CANCEL_WAIT_UNTIL_MSG_ID: u32 = { unsafe { - winuser::RegisterWindowMessageA("Winit::CancelWaitUntil\0".as_ptr() as *const i8) + RegisterWindowMessageA("Winit::CancelWaitUntil\0".as_ptr()) } }; // 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("Winit::DestroyMsg\0".as_ptr()) } }; // 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) - }; - static ref THREAD_EVENT_TARGET_WINDOW_CLASS: Vec = { - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - - OsStr::new("Winit Thread Event Target") - .encode_wide() - .chain(Some(0).into_iter()) - .collect() + RegisterWindowMessageA("Winit::SetRetainMaximized\0".as_ptr()) }; + static ref THREAD_EVENT_TARGET_WINDOW_CLASS: Vec = util::encode_wide("Winit Thread Event Target"); } fn create_event_target_window() -> HWND { unsafe { - let class = winuser::WNDCLASSEXW { - cbSize: mem::size_of::() as UINT, + let class = WNDCLASSEXW { + cbSize: mem::size_of::() as u32, style: 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(), + hInstance: GetModuleHandleW(ptr::null()), + hIcon: 0, + hCursor: 0, // must be null in order for cursor state to work properly + hbrBackground: 0, lpszMenuName: ptr::null(), lpszClassName: THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr(), - hIconSm: ptr::null_mut(), + hIconSm: 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 +655,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, + | WS_EX_TOOLWINDOW, THREAD_EVENT_TARGET_WINDOW_CLASS.as_ptr(), - ptr::null_mut(), + ptr::null(), + WS_OVERLAPPED, 0, 0, 0, 0, 0, - ptr::null_mut(), - ptr::null_mut(), - libloaderapi::GetModuleHandleW(ptr::null()), - ptr::null_mut(), + 0, + GetModuleHandleW(ptr::null()), + ptr::null(), ); - winuser::SetWindowLongPtrW( + + super::set_window_long( 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) as isize, ); window } @@ -669,13 +693,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::set_window_long(thread_msg_target, GWL_USERDATA, input_ptr as isize) }; tx } @@ -684,7 +702,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 +712,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 +748,19 @@ 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, + ) == false.into() + { return; } - winuser::TranslateMessage(&msg); - winuser::DispatchMessageW(&msg); + TranslateMessage(&msg); + DispatchMessageW(&msg); }); true } else { @@ -752,15 +771,15 @@ 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, 0, 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, + Box::into_raw(WaitUntilInstantBox::new(until)) as isize, ); } ControlFlow::ExitWithCode(_) => (), @@ -788,11 +807,6 @@ fn update_modifiers(window: HWND, userdata: &WindowData) { } } -#[cfg(target_arch = "x86_64")] -pub(crate) type WindowLongPtr = LONG_PTR; -#[cfg(target_arch = "x86")] -pub(crate) 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,21 +816,21 @@ pub(crate) 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::get_window_long(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; - let initdata = &mut *(initdata as *mut InitData<'_, T>); + (0, WM_NCCREATE) => { + let createstruct = &mut *(lparam as *mut CREATESTRUCTW); + let initdata = &mut *(createstruct.lpCreateParams as *mut InitData<'_, T>); let result = match initdata.on_nccreate(window) { Some(userdata) => { - winuser::SetWindowLongPtrW(window, winuser::GWL_USERDATA, userdata as _); - winuser::DefWindowProcW(window, msg, wparam, lparam) + super::set_window_long(window, GWL_USERDATA, userdata as _); + DefWindowProcW(window, msg, wparam, lparam) } None => -1, // failed to create the window }; @@ -825,16 +839,16 @@ pub(super) unsafe extern "system" fn public_window_callback( } // Getting here should quite frankly be impossible, // but we'll make window creation fail here just in case. - (0, winuser::WM_CREATE) => return -1, - (_, winuser::WM_CREATE) => { - let createstruct = &mut *(lparam as *mut winuser::CREATESTRUCTW); - let initdata = createstruct.lpCreateParams as LONG_PTR; + (0, WM_CREATE) => return -1, + (_, WM_CREATE) => { + let createstruct = &mut *(lparam as *mut CREATESTRUCTW); + let initdata = createstruct.lpCreateParams; let initdata = &mut *(initdata as *mut InitData<'_, T>); initdata.on_create(); - return winuser::DefWindowProcW(window, msg, wparam, lparam); + return DefWindowProcW(window, msg, wparam, lparam); } - (0, _) => return winuser::DefWindowProcW(window, msg, wparam, lparam), + (0, _) => return DefWindowProcW(window, msg, wparam, lparam), _ => userdata as *mut WindowData, }; @@ -843,7 +857,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; @@ -861,23 +875,23 @@ 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, + 0, + 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() @@ -885,7 +899,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_EXITSIZEMOVE => { + WM_EXITSIZEMOVE => { userdata .window_state .lock() @@ -893,14 +907,14 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_NCLBUTTONDOWN => { - if wparam == winuser::HTCAPTION as _ { - winuser::PostMessageW(window, winuser::WM_MOUSEMOVE, 0, lparam); + WM_NCLBUTTONDOWN => { + if wparam == HTCAPTION as _ { + PostMessageW(window, WM_MOUSEMOVE, 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)), @@ -909,9 +923,9 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_DESTROY => { + WM_DESTROY => { use crate::event::WindowEvent::Destroyed; - ole2::RevokeDragDrop(window); + RevokeDragDrop(window); userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: Destroyed, @@ -920,22 +934,17 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_NCDESTROY => { - winuser::SetWindowLongPtrW(window, winuser::GWL_USERDATA, 0); + WM_NCDESTROY => { + super::set_window_long(window, GWL_USERDATA, 0); userdata.userdata_removed.set(true); 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(), 0, RDW_INTERNALPAINT); } else { let managing_redraw = flush_paint_messages(Some(window), &userdata.event_loop_runner); @@ -946,31 +955,30 @@ 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 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 != 0 && 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.monitorInfo.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; @@ -984,7 +992,7 @@ 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.monitorInfo.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; @@ -998,11 +1006,11 @@ unsafe fn public_window_callback_inner( } // 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 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 { @@ -1012,13 +1020,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 = super::loword(lparam as u32) as u32; + let h = super::hiword(lparam as u32) as u32; let physical_size = PhysicalSize::new(w, h); let event = Event::WindowEvent { @@ -1033,7 +1041,7 @@ unsafe fn public_window_callback_inner( .window_flags() .contains(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE) { - let maximized = wparam == winuser::SIZE_MAXIMIZED; + let maximized = wparam == SIZE_MAXIMIZED as usize; w.set_window_flags_in_place(|f| f.set(WindowFlags::MAXIMIZED, maximized)); } } @@ -1042,7 +1050,7 @@ unsafe fn public_window_callback_inner( 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); @@ -1076,28 +1084,28 @@ unsafe fn public_window_callback_inner( } // this is necessary for us to maintain minimize/restore state - winuser::WM_SYSCOMMAND => { - if wparam == winuser::SC_RESTORE { + WM_SYSCOMMAND => { + if wparam == 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 == 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 == SC_SCREENSAVE as usize { let window_state = userdata.window_state.lock(); if window_state.fullscreen.is_some() { return 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(); @@ -1118,16 +1126,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 = super::get_x_lparam(lparam as u32) as f64; + let y = super::get_y_lparam(lparam as u32) as f64; let position = PhysicalPosition::new(x, y); let cursor_moved; { @@ -1154,7 +1162,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_MOUSELEAVE => { + WM_MOUSELEAVE => { use crate::event::WindowEvent::CursorLeft; { let mut w = userdata.window_state.lock(); @@ -1173,12 +1181,12 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_MOUSEWHEEL => { + WM_MOUSEWHEEL => { use crate::event::MouseScrollDelta::LineDelta; let value = (wparam >> 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); @@ -1195,12 +1203,12 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_MOUSEHWHEEL => { + WM_MOUSEHWHEEL => { use crate::event::MouseScrollDelta::LineDelta; let value = (wparam >> 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); @@ -1217,10 +1225,10 @@ unsafe fn public_window_callback_inner( 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 == VK_F4 as usize { + DefWindowProcW(window, msg, wparam, lparam) } else { if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { update_modifiers(window, userdata); @@ -1252,7 +1260,7 @@ unsafe fn public_window_callback_inner( } } - 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); @@ -1275,7 +1283,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_LBUTTONDOWN => { + WM_LBUTTONDOWN => { use crate::event::{ElementState::Pressed, MouseButton::Left, WindowEvent::MouseInput}; capture_mouse(window, &mut *userdata.window_state.lock()); @@ -1294,7 +1302,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_LBUTTONUP => { + WM_LBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Left, WindowEvent::MouseInput, }; @@ -1315,7 +1323,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_RBUTTONDOWN => { + WM_RBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Right, WindowEvent::MouseInput, }; @@ -1336,7 +1344,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_RBUTTONUP => { + WM_RBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Right, WindowEvent::MouseInput, }; @@ -1357,7 +1365,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_MBUTTONDOWN => { + WM_MBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Middle, WindowEvent::MouseInput, }; @@ -1378,7 +1386,7 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_MBUTTONUP => { + WM_MBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Middle, WindowEvent::MouseInput, }; @@ -1399,11 +1407,11 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_XBUTTONDOWN => { + WM_XBUTTONDOWN => { use crate::event::{ ElementState::Pressed, MouseButton::Other, WindowEvent::MouseInput, }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + let xbutton = super::get_xbutton_wparam(wparam as u32); capture_mouse(window, &mut *userdata.window_state.lock()); @@ -1421,11 +1429,11 @@ unsafe fn public_window_callback_inner( 0 } - winuser::WM_XBUTTONUP => { + WM_XBUTTONUP => { use crate::event::{ ElementState::Released, MouseButton::Other, WindowEvent::MouseInput, }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + let xbutton = super::get_xbutton_wparam(wparam as u32); release_mouse(userdata.window_state.lock()); @@ -1443,36 +1451,36 @@ unsafe fn public_window_callback_inner( 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 != window { userdata.window_state.lock().mouse.capture_count = 0; } 0 } - winuser::WM_TOUCH => { - let pcount = LOWORD(wparam as DWORD) as usize; + WM_TOUCH => { + let pcount = super::loword(wparam as u32) as usize; let mut inputs = Vec::with_capacity(pcount); - inputs.set_len(pcount); - let htouch = lparam as winuser::HTOUCHINPUT; - if winuser::GetTouchInputInfo( + let htouch = lparam; + if GetTouchInputInfo( htouch, - pcount as UINT, + pcount as u32, inputs.as_mut_ptr(), - mem::size_of::() as INT, + mem::size_of::() as i32, ) > 0 { + inputs.set_len(pcount); for input in &inputs { let mut location = POINT { x: input.x / 100, y: input.y / 100, }; - if winuser::ScreenToClient(window, &mut location as *mut _) == 0 { + if ScreenToClient(window, &mut location) == false.into() { continue; } @@ -1482,11 +1490,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 util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) { TouchPhase::Started - } else if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { + } else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) { TouchPhase::Ended - } else if input.dwFlags & winuser::TOUCHEVENTF_MOVE != 0 { + } else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) { TouchPhase::Moved } else { continue; @@ -1499,11 +1507,11 @@ unsafe fn public_window_callback_inner( }); } } - winuser::CloseTouchInputHandle(htouch); + CloseTouchInputHandle(htouch); 0 } - winuser::WM_POINTERDOWN | winuser::WM_POINTERUPDATE | winuser::WM_POINTERUP => { + WM_POINTERDOWN | WM_POINTERUPDATE | WM_POINTERUP => { if let ( Some(GetPointerFrameInfoHistory), Some(SkipPointerFrameMessages), @@ -1513,31 +1521,31 @@ 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; + let pointer_id = super::loword(wparam as u32) as u32; + let mut entries_count = 0u32; + let mut pointers_count = 0u32; if GetPointerFrameInfoHistory( pointer_id, - &mut entries_count as *mut _, - &mut pointers_count as *mut _, - std::ptr::null_mut(), - ) == 0 + &mut entries_count, + &mut pointers_count, + ptr::null_mut(), + ) == false.into() { return 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( pointer_id, - &mut entries_count as *mut _, - &mut pointers_count as *mut _, + &mut entries_count, + &mut pointers_count, pointer_infos.as_mut_ptr(), - ) == 0 + ) == false.into() { return 0; } + pointer_infos.set_len(pointer_info_count); // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory // The information retrieved appears in reverse chronological order, with the most recent entry in the first @@ -1546,11 +1554,11 @@ 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 + ) == false.into() { continue; } @@ -1578,12 +1586,12 @@ 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) == false.into() { 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( @@ -1597,7 +1605,7 @@ unsafe fn public_window_callback_inner( } }) } - winuser::PT_PEN => { + PT_PEN => { let mut pen_info = mem::MaybeUninit::uninit(); GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| { match GetPointerPenInfo( @@ -1620,11 +1628,11 @@ 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 util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) { TouchPhase::Started - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { + } else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) { TouchPhase::Ended - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UPDATE != 0 + } else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE) { TouchPhase::Moved } else { @@ -1643,11 +1651,10 @@ unsafe fn public_window_callback_inner( 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 as u32, MAPVK_VK_TO_VSC); let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); update_modifiers(window, userdata); @@ -1676,15 +1683,14 @@ unsafe fn public_window_callback_inner( 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 as u32, MAPVK_VK_TO_VSC); let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); #[allow(deprecated)] @@ -1716,13 +1722,13 @@ unsafe fn public_window_callback_inner( 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 = super::loword(lparam as u32) as u32 == HTCLIENT; if in_client_area { Some(window_state.mouse.cursor) } else { @@ -1732,21 +1738,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); + let cursor = LoadCursorW(0, cursor.to_windows_cursor()); + SetCursor(cursor); 0 } - None => winuser::DefWindowProcW(window, msg, wparam, lparam), + None => DefWindowProcW(window, msg, wparam, lparam), } } - winuser::WM_DROPFILES => { + WM_DROPFILES => { // See `FileDropHandler` for implementation. 0 } - winuser::WM_GETMINMAXINFO => { - let mmi = lparam as *mut winuser::MINMAXINFO; + WM_GETMINMAXINFO => { + let mmi = lparam as *mut MINMAXINFO; let window_state = userdata.window_state.lock(); @@ -1774,14 +1780,14 @@ unsafe fn public_window_callback_inner( // 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 = super::loword(wparam as u32) as u32; let new_scale_factor = dpi_to_scale_factor(new_dpi_x); let old_scale_factor: f64; @@ -1798,8 +1804,8 @@ unsafe fn public_window_callback_inner( && !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 = GetWindowLongW(window, GWL_STYLE) as u32; + let style_ex = GetWindowLongW(window, GWL_EXSTYLE) as u32; // New size as suggested by Windows. let suggested_rect = *(lparam as *const RECT); @@ -1824,9 +1830,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; @@ -1884,8 +1890,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( @@ -1902,7 +1908,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) @@ -1912,7 +1918,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; @@ -1921,17 +1927,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; @@ -1967,7 +1974,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; } } @@ -1976,20 +1985,20 @@ unsafe fn public_window_callback_inner( }; } - winuser::SetWindowPos( + SetWindowPos( window, - ptr::null_mut(), + 0, 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 } - winuser::WM_SETTINGCHANGE => { + WM_SETTINGCHANGE => { use crate::event::WindowEvent::ThemeChanged; let preferred_theme = userdata.window_state.lock().preferred_theme; @@ -2008,12 +2017,12 @@ 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); + DestroyWindow(window); 0 } else if msg == *SET_RETAIN_STATE_ON_SIZE_MSG_ID { let mut window_state = userdata.window_state.lock(); @@ -2022,7 +2031,7 @@ unsafe fn public_window_callback_inner( }); 0 } else { - winuser::DefWindowProcW(window, msg, wparam, lparam) + DefWindowProcW(window, msg, wparam, lparam) } } }; @@ -2035,26 +2044,20 @@ unsafe fn public_window_callback_inner( 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; + let userdata_ptr = super::get_window_long(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(), 0, RDW_INTERNALPAINT); } let mut userdata_removed = false; @@ -2063,15 +2066,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::set_window_long(window, GWL_USERDATA, 0); userdata_removed = true; 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. @@ -2079,12 +2082,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(), 0, 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). @@ -2095,38 +2093,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 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 as u32), event, }); 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(lparam) { + let device_id = wrap_device_id(data.header.hDevice as u32); - if data.header.dwType == winuser::RIM_TYPEMOUSE { - let mouse = data.data.mouse(); + if data.header.dwType == RIM_TYPEMOUSE { + 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; @@ -2152,9 +2150,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 i16 as f32 / WHEEL_DELTA as f32; userdata.send_event(Event::DeviceEvent { device_id, event: MouseWheel { @@ -2163,37 +2162,37 @@ 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 { + 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) + handle_extended_keys(keyboard.VKey, scancode as u32, extended) { let virtual_keycode = vkey_to_winit_vkey(vkey); @@ -2212,7 +2211,7 @@ 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 => { @@ -2227,7 +2226,7 @@ unsafe extern "system" fn thread_event_target_callback( 0 } _ if msg == *PROCESS_NEW_EVENTS_MSG_ID => { - winuser::PostThreadMessageW( + PostThreadMessageW( userdata.event_loop_runner.wait_thread_id(), *CANCEL_WAIT_UNTIL_MSG_ID, 0, @@ -2239,22 +2238,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, 0, 0, 0, PM_NOREMOVE) != false.into() { // 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.into()) == false.into() { + RedrawWindow(msg.hwnd, ptr::null(), 0, RDW_INTERNALPAINT); } } @@ -2265,7 +2259,7 @@ unsafe extern "system" fn thread_event_target_callback( userdata.event_loop_runner.poll(); 0 } - _ => winuser::DefWindowProcW(window, msg, wparam, lparam), + _ => DefWindowProcW(window, msg, wparam, lparam), }; let result = userdata diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index a82c57a60f..43b458bf51 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_sys::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, @@ -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 } @@ -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(); } } @@ -394,12 +392,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(), 0, 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..e09aa8cabe 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -1,18 +1,22 @@ -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}, +use std::{fmt, io, mem, path::Path, ptr, sync::Arc}; + +use windows_sys::{ + core::PCWSTR, + Win32::{ + Foundation::HWND, + System::LibraryLoader::GetModuleHandleW, + UI::WindowsAndMessaging::{ + CreateIcon, DestroyIcon, LoadImageW, SendMessageW, HICON, ICON_BIG, ICON_SMALL, + IMAGE_ICON, LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_SETICON, + }, }, - um::libloaderapi, - um::winuser, }; use crate::dpi::PhysicalSize; use crate::icon::*; +use super::util; + impl Pixel { fn to_bgra(&mut self) { mem::swap(&mut self.r, &mut self.b); @@ -21,28 +25,28 @@ impl Pixel { impl RgbaIcon { fn into_windows_icon(self) -> Result { - let mut rgba = self.rgba; + let rgba = self.rgba; let pixel_count = rgba.len() / PIXEL_SIZE; let mut and_mask = Vec::with_capacity(pixel_count); let pixels = - unsafe { std::slice::from_raw_parts_mut(rgba.as_mut_ptr() as *mut Pixel, pixel_count) }; + unsafe { std::slice::from_raw_parts_mut(rgba.as_ptr() as *mut Pixel, pixel_count) }; for pixel in pixels { and_mask.push(pixel.a.wrapping_sub(std::u8::MAX)); // invert alpha channel pixel.to_bgra(); } 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( + 0, + 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(), + rgba.as_ptr(), + ) }; - if !handle.is_null() { + if handle != 0 { Ok(WinIcon::from_handle(handle)) } else { Err(BadIcon::OsError(io::Error::last_os_error())) @@ -52,8 +56,8 @@ impl RgbaIcon { #[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)] @@ -77,51 +81,46 @@ impl WinIcon { path: P, size: Option>, ) -> Result { - let wide_path: Vec = path - .as_ref() - .as_os_str() - .encode_wide() - .chain(once(0)) - .collect(); - // 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 wide_path = util::encode_wide(path.as_ref()); + 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( + 0, + wide_path.as_ptr(), + IMAGE_ICON, + width as i32, + height as i32, + LR_DEFAULTSIZE | LR_LOADFROMFILE, + ) }; - if !handle.is_null() { - Ok(WinIcon::from_handle(handle)) + if handle != 0 { + Ok(WinIcon::from_handle(handle as HICON)) } else { Err(BadIcon::OsError(io::Error::last_os_error())) } } 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(ptr::null()), + resource_id as PCWSTR, + IMAGE_ICON, + width as i32, + height as i32, + LR_DEFAULTSIZE, + ) }; - if !handle.is_null() { - Ok(WinIcon::from_handle(handle)) + if handle != 0 { + Ok(WinIcon::from_handle(handle as HICON)) } else { Err(BadIcon::OsError(io::Error::last_os_error())) } @@ -134,12 +133,7 @@ impl WinIcon { pub fn set_for_window(&self, hwnd: HWND, icon_type: IconType) { unsafe { - winuser::SendMessageW( - hwnd, - winuser::WM_SETICON, - icon_type as WPARAM, - self.as_raw_handle() as LPARAM, - ); + SendMessageW(hwnd, WM_SETICON, icon_type as usize, self.as_raw_handle()); } } @@ -152,7 +146,7 @@ impl WinIcon { impl Drop for RaiiIcon { fn drop(&mut self) { - unsafe { winuser::DestroyIcon(self.handle) }; + unsafe { DestroyIcon(self.handle) }; } } @@ -164,6 +158,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, icon_type as usize, 0); } } diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index ad6236c63c..67fc7a7666 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -1,6 +1,9 @@ #![cfg(target_os = "windows")] -use winapi::{self, shared::windef::HMENU, shared::windef::HWND}; +use windows_sys::Win32::{ + Foundation::{HANDLE, HWND}, + UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX}, +}; pub(crate) use self::{ event_loop::{ @@ -52,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 {} @@ -68,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(self.0 as HANDLE) } else { None } @@ -91,15 +94,59 @@ unsafe impl Sync for WindowId {} impl WindowId { pub const unsafe fn dummy() -> Self { - use std::ptr::null_mut; - - WindowId(null_mut()) + WindowId(0) } } +#[inline(always)] +const fn get_xbutton_wparam(x: u32) -> u16 { + loword(x) +} + +#[inline(always)] +const fn get_x_lparam(x: u32) -> u16 { + loword(x) +} + +#[inline(always)] +const fn get_y_lparam(x: u32) -> u16 { + hiword(x) +} + +#[inline(always)] +const fn loword(x: u32) -> u16 { + (x & 0xFFFF) as u16 +} + +#[inline(always)] +const fn hiword(x: u32) -> u16 { + ((x >> 16) & 0xFFFF) as u16 +} + +#[inline(always)] +unsafe fn get_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize { + #[cfg(target_pointer_width = "64")] + return windows_sys::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW(hwnd, nindex); + #[cfg(target_pointer_width = "32")] + return windows_sys::Win32::UI::WindowsAndMessaging::GetWindowLongW(hwnd, nindex) as isize; +} + +#[inline(always)] +unsafe fn set_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX, dwnewlong: isize) -> isize { + #[cfg(target_pointer_width = "64")] + return windows_sys::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW(hwnd, nindex, dwnewlong); + #[cfg(target_pointer_width = "32")] + return windows_sys::Win32::UI::WindowsAndMessaging::SetWindowLongW( + hwnd, + nindex, + dwnewlong as i32, + ) as isize; +} + #[macro_use] mod util; mod dark_mode; +mod definitions; mod dpi; mod drop_handler; mod event; diff --git a/src/platform_impl/windows/monitor.rs b/src/platform_impl/windows/monitor.rs index ff88d102db..1aacd58305 100644 --- a/src/platform_impl/windows/monitor.rs +++ b/src/platform_impl/windows/monitor.rs @@ -1,22 +1,28 @@ -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_sys::Win32::{ + Foundation::{BOOL, HWND, LPARAM, POINT, RECT}, + Graphics::Gdi::{ + EnumDisplayMonitors, EnumDisplaySettingsExW, GetMonitorInfoW, MonitorFromPoint, + MonitorFromWindow, DEVMODEW, DM_BITSPERPEL, DM_DISPLAYFREQUENCY, DM_PELSHEIGHT, + DM_PELSWIDTH, HDC, HMONITOR, MONITORINFO, MONITORINFOEXW, MONITOR_DEFAULTTONEAREST, + MONITOR_DEFAULTTOPRIMARY, + }, }; -use super::util; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode}, platform_impl::platform::{ dpi::{dpi_to_scale_factor, get_monitor_dpi}, + util::has_flag, window::Window, }, }; @@ -27,7 +33,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 { @@ -94,20 +100,20 @@ unsafe impl Send for MonitorHandle {} 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; (*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( + 0, + ptr::null(), Some(monitor_enum_proc), &mut monitors as *mut _ as LPARAM, ); @@ -117,12 +123,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 +143,16 @@ 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.monitorInfo.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 == false.into() { Err(io::Error::last_os_error()) } else { Ok(monitor_info) @@ -161,7 +167,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] @@ -176,19 +186,19 @@ impl MonitorHandle { #[inline] pub fn size(&self) -> PhysicalSize { - let monitor_info = get_monitor_info(self.0).unwrap(); + let rc_monitor = get_monitor_info(self.0).unwrap().monitorInfo.rcMonitor; PhysicalSize { - width: (monitor_info.rcMonitor.right - monitor_info.rcMonitor.left) as u32, - height: (monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top) as u32, + width: (rc_monitor.right - rc_monitor.left) as u32, + height: (rc_monitor.bottom - rc_monitor.top) as u32, } } #[inline] pub fn position(&self) -> PhysicalPosition { - let monitor_info = get_monitor_info(self.0).unwrap(); + let rc_monitor = get_monitor_info(self.0).unwrap().monitorInfo.rcMonitor; PhysicalPosition { - x: monitor_info.rcMonitor.left, - y: monitor_info.rcMonitor.top, + x: rc_monitor.left, + y: rc_monitor.top, } } @@ -209,18 +219,16 @@ 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(device_name, i, &mut mode, 0) == false.into() { break; } i += 1; - const REQUIRED_FIELDS: DWORD = wingdi::DM_BITSPERPEL - | wingdi::DM_PELSWIDTH - | wingdi::DM_PELSHEIGHT - | wingdi::DM_DISPLAYFREQUENCY; - assert!(mode.dmFields & REQUIRED_FIELDS == REQUIRED_FIELDS); + const REQUIRED_FIELDS: u32 = + (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY) as u32; + assert!(has_flag(mode.dmFields, REQUIRED_FIELDS)); modes.insert(RootVideoMode { video_mode: VideoMode { diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index 73b136a82f..46a6683044 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_sys::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,17 +103,17 @@ 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 _, @@ -119,7 +121,7 @@ pub fn get_raw_input_device_name(handle: HANDLE) -> Option { ) }; - if status == UINT::max_value() || status == 0 { + if status == u32::MAX || status == 0 { return None; } @@ -127,17 +129,15 @@ pub fn get_raw_input_device_name(handle: HANDLE) -> Option { unsafe { name.set_len(minimum_size as _) }; - Some(util::wchar_to_string(&name)) + OsString::from_wide(&name).into_string().ok() } pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool { - let device_size = size_of::() as UINT; + let device_size = size_of::() as u32; - let success = unsafe { - winuser::RegisterRawInputDevices(devices.as_ptr() as _, devices.len() as _, device_size) - }; - - success == TRUE + unsafe { + RegisterRawInputDevices(devices.as_ptr(), devices.len() as u32, device_size) == true.into() + } } pub fn register_all_mice_and_keyboards_for_raw_input(window_handle: HWND) -> bool { @@ -165,11 +165,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 +178,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 +186,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 +200,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..fb84243acc 100644 --- a/src/platform_impl/windows/util.rs +++ b/src/platform_impl/windows/util.rs @@ -1,27 +1,42 @@ use std::{ - io, mem, + ffi::{c_void, OsStr}, + io, + iter::once, + mem, ops::BitAnd, - os::raw::c_void, - ptr, slice, + os::windows::prelude::OsStrExt, + 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_sys::{ + core::{HRESULT, PCWSTR}, + Win32::{ + Foundation::{BOOL, HWND, 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 encode_wide(string: impl AsRef) -> Vec { + string.as_ref().encode_wide().chain(once(0)).collect() +} + pub fn has_flag(bitset: T, flag: T) -> bool where T: Copy + PartialEq + BitAnd, @@ -29,19 +44,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) != false.into() { Some(data) } else { None @@ -49,7 +54,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() != false.into() { Ok(()) } else { Err(io::Error::last_os_error()) @@ -57,7 +62,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 +70,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 +85,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 +100,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(), + 0, 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, 0, false.into()); } } 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 = GetWindowLongW(hwnd, GWL_STYLE) as u32; + let style_ex = 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) != 0; 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, b_menu.into(), style_ex, dpi) } else { - winuser::AdjustWindowRectEx(r, style as _, b_menu, style_ex as _) + AdjustWindowRectEx(r, style, b_menu.into(), style_ex) } }) } @@ -155,14 +156,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(BOOL::from(!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 +176,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) -> PCWSTR { 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 +233,12 @@ 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(library.as_ptr()) }; + if module == 0 { return None; } - Some(function_ptr as _) + unsafe { GetProcAddress(module, function.as_ptr()) }.map(|function_ptr| function_ptr as _) } macro_rules! get_function { @@ -264,20 +256,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 39dd31357a..3f632968a8 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -4,31 +4,54 @@ use parking_lot::Mutex; use raw_window_handle::{RawWindowHandle, Win32Handle}; use std::{ cell::Cell, - ffi::OsStr, - io, mem, - os::windows::ffi::OsStrExt, - panic, ptr, + ffi::c_void, + io, mem, panic, ptr, sync::{mpsc::channel, Arc}, }; -use winapi::{ - ctypes::c_int, - shared::{ - minwindef::{HINSTANCE, LPARAM, UINT, WPARAM}, - windef::{HWND, POINT, POINTS, RECT}, - winerror::SUCCEEDED, +use windows_sys::Win32::{ + Foundation::{ + HINSTANCE, HWND, LPARAM, OLE_E_WRONGCOMPOBJ, POINT, POINTS, RECT, RPC_E_CHANGED_MODE, S_OK, + WPARAM, }, - 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, + 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, RDW_INTERNALPAINT, + }, + }, + System::{ + Com::{ + CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_ALL, COINIT_APARTMENTTHREADED, + }, + LibraryLoader::GetModuleHandleW, + Ole::{OleInitialize, RegisterDragDrop}, + }, + UI::{ + Input::{ + Ime::{ + ImmGetContext, ImmReleaseContext, ImmSetCompositionWindow, CFS_POINT, + COMPOSITIONFORM, + }, + KeyboardAndMouse::{ + EnableWindow, GetActiveWindow, MapVirtualKeyW, ReleaseCapture, SendInput, INPUT, + INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, + VK_LMENU, VK_MENU, + }, + Touch::{RegisterTouchWindow, TWF_WANTPALM}, + }, + WindowsAndMessaging::{ + CreateWindowExW, FlashWindowEx, GetClientRect, GetCursorPos, GetForegroundWindow, + GetSystemMetrics, GetWindowPlacement, IsWindowVisible, 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, HTCAPTION, MAPVK_VK_TO_VSC, NID_READY, PM_NOREMOVE, SM_DIGITIZER, + SM_IMMENABLED, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE, SWP_NOZORDER, + WM_NCLBUTTONDOWN, WNDCLASSEXW, + }, }, }; @@ -39,9 +62,11 @@ use crate::{ monitor::MonitorHandle as RootMonitorHandle, platform_impl::platform::{ dark_mode::try_theme, + definitions::ITaskbarList2, + definitions::{CLSID_TaskbarList, IID_ITaskbarList2}, dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi}, drop_handler::FileDropHandler, - event_loop::{self, EventLoopWindowTarget, WindowLongPtr, DESTROY_MSG_ID}, + event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID}, icon::{self, IconType}, monitor, util, window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState}, @@ -76,12 +101,9 @@ impl Window { } pub fn set_title(&self, text: &str) { - let text = OsStr::new(text) - .encode_wide() - .chain(Some(0).into_iter()) - .collect::>(); + let wide_text = util::encode_wide(text); unsafe { - winuser::SetWindowTextW(self.window.0, text.as_ptr() as LPCWSTR); + SetWindowTextW(self.hwnd(), wide_text.as_ptr()); } } @@ -99,24 +121,19 @@ impl Window { #[inline] pub fn is_visible(&self) -> Option { - Some(unsafe { winuser::IsWindowVisible(self.window.0) == 1 }) + Some(unsafe { IsWindowVisible(self.window.0) == 1 }) } #[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(), 0, 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") } @@ -124,7 +141,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) } == false.into() { 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)) @@ -144,26 +161,23 @@ impl Window { }); unsafe { - winuser::SetWindowPos( - self.window.0, - ptr::null_mut(), - x as c_int, - y as c_int, + SetWindowPos( + self.hwnd(), + 0, + 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(), 0, false.into()); } } #[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) } == false.into() { panic!("Unexpected GetClientRect failure: please report this error to https://github.com/rust-windowing/winit") } PhysicalSize::new( @@ -174,7 +188,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, @@ -198,7 +212,7 @@ impl Window { }); }); - util::set_inner_size_physical(self.window.0, width, height); + util::set_inner_size_physical(self.hwnd(), width, height); } #[inline] @@ -244,7 +258,7 @@ impl Window { #[inline] pub fn hinstance(&self) -> HINSTANCE { - unsafe { winuser::GetWindowLongPtrW(self.hwnd(), winuser::GWLP_HINSTANCE) as *mut _ } + unsafe { super::get_window_long(self.hwnd(), GWLP_HINSTANCE) } } #[inline] @@ -259,8 +273,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(0, cursor.to_windows_cursor()); + SetCursor(cursor); }); } @@ -312,10 +326,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) == false.into() { 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) == false.into() { return Err(ExternalError::Os(os_error!(io::Error::last_os_error()))); } } @@ -327,18 +341,18 @@ 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, + ReleaseCapture(); + PostMessageW( + self.hwnd(), + WM_NCLBUTTONDOWN, + HTCAPTION as WPARAM, &points as *const _ as LPARAM, ); } @@ -348,7 +362,7 @@ impl Window { #[inline] pub fn id(&self) -> WindowId { - WindowId(self.window.0) + WindowId(self.hwnd()) } #[inline] @@ -415,50 +429,43 @@ impl Window { | (&Some(Fullscreen::Exclusive(_)), &Some(Fullscreen::Exclusive(ref video_mode))) => { let monitor = video_mode.monitor(); + let monitor_info = monitor::get_monitor_info(monitor.inner.hmonitor()).unwrap(); - let mut display_name = OsStr::new(&monitor.inner.native_identifier()) - .encode_wide() - .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, - std::ptr::null_mut(), + ChangeDisplaySettingsExW( + monitor_info.szDevice.as_ptr(), + &native_video_mode, + 0, + CDS_FULLSCREEN, + ptr::null(), ) }; - 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(), - std::ptr::null_mut(), - std::ptr::null_mut(), - winuser::CDS_FULLSCREEN, - std::ptr::null_mut(), + ChangeDisplaySettingsExW( + ptr::null(), + ptr::null(), + 0, + CDS_FULLSCREEN, + ptr::null(), ) }; - 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); } _ => (), } @@ -473,7 +480,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, 0, 0, 0, PM_NOREMOVE); } // Update window style @@ -494,7 +501,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 }; @@ -512,16 +519,16 @@ impl Window { let size: (u32, u32) = monitor.size().into(); unsafe { - winuser::SetWindowPos( + SetWindowPos( window.0, - ptr::null_mut(), + 0, 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, 0, false.into()); } } None => { @@ -529,8 +536,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, 0, false.into()); } } } @@ -577,7 +584,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()), }) } @@ -586,16 +593,16 @@ 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; } #[inline] pub fn set_enable(&self, enabled: bool) { - unsafe { winuser::EnableWindow(self.hwnd() as _, enabled as _) }; + unsafe { EnableWindow(self.hwnd(), enabled.into()) }; } #[inline] @@ -603,24 +610,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); } } } @@ -634,7 +641,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; } @@ -643,23 +650,19 @@ impl Window { let _ = &window; 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); }); } @@ -675,7 +678,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) }; @@ -689,7 +692,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, 0, 0); } } } @@ -720,9 +723,9 @@ impl<'a, T: 'static> InitData<'a, T> { unsafe fn create_window(&self, window: HWND) -> Window { // Register for touch events if applicable { - let digitizer = winuser::GetSystemMetrics(winuser::SM_DIGITIZER) as u32; - if digitizer & winuser::NID_READY != 0 { - winuser::RegisterTouchWindow(window, winuser::TWF_WANTPALM); + let digitizer = GetSystemMetrics(SM_DIGITIZER) as u32; + if digitizer & NID_READY != 0 { + RegisterTouchWindow(window, TWF_WANTPALM); } } @@ -758,9 +761,7 @@ impl<'a, T: 'static> InitData<'a, T> { unsafe fn create_window_data(&self, win: &Window) -> event_loop::WindowData { let file_drop_handler = if self.pl_attribs.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 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 { @@ -782,12 +783,11 @@ impl<'a, T: 'static> InitData<'a, T> { } }), ); - let handler_interface_ptr = &mut (*file_drop_handler.data).interface as LPDROPTARGET; - assert_eq!( - ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), - S_OK - ); + let handler_interface_ptr = + &mut (*file_drop_handler.data).interface as *mut _ as *mut c_void; + + assert_eq!(RegisterDragDrop(win.window.0, handler_interface_ptr), S_OK); Some(file_drop_handler) } else { None @@ -806,7 +806,7 @@ impl<'a, T: 'static> InitData<'a, T> { // Returns a pointer to window user data on success. // The user data will be registered for the window and can be accessed within the window event callback. - pub unsafe fn on_nccreate(&mut self, window: HWND) -> Option { + pub unsafe fn on_nccreate(&mut self, window: HWND) -> Option { let runner = self.event_loop.runner_shared.clone(); let result = runner.catch_unwind(|| { let mut window = self.create_window(window); @@ -829,20 +829,20 @@ impl<'a, T: 'static> InitData<'a, T> { // 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(), }; - let hr = dwmapi::DwmEnableBlurBehindWindow(win.hwnd(), &bb); - if !SUCCEEDED(hr) { + let hr = DwmEnableBlurBehindWindow(win.hwnd(), &bb); + if hr < 0 { warn!( "Setting transparent window is failed. HRESULT Code: 0x{:X}", hr ); } - DeleteObject(region as _); + DeleteObject(region); } let attributes = self.attributes.clone(); @@ -879,12 +879,8 @@ unsafe fn init( where T: 'static, { - let title = OsStr::new(&attributes.title) - .encode_wide() - .chain(Some(0).into_iter()) - .collect::>(); + let title = util::encode_wide(&attributes.title); - // registering the window class let class_name = register_window_class::(&attributes.window_icon, &pl_attribs.taskbar_icon); let mut window_flags = WindowFlags::empty(); @@ -925,18 +921,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, + title.as_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(0), + pl_attribs.menu.unwrap_or(0), + GetModuleHandleW(ptr::null()), &mut initdata as *mut _ as *mut _, ); @@ -945,7 +941,7 @@ where panic::resume_unwind(panic_error) } - if handle.is_null() { + if handle == 0 { return Err(os_error!(io::Error::last_os_error())); } @@ -958,30 +954,27 @@ unsafe fn register_window_class( window_icon: &Option, taskbar_icon: &Option, ) -> Vec { - let class_name: Vec<_> = OsStr::new("Window Class") - .encode_wide() - .chain(Some(0).into_iter()) - .collect(); + let class_name = util::encode_wide("Window Class"); let h_icon = taskbar_icon .as_ref() .map(|icon| icon.inner.as_raw_handle()) - .unwrap_or(ptr::null_mut()); + .unwrap_or(0); let h_icon_small = window_icon .as_ref() .map(|icon| icon.inner.as_raw_handle()) - .unwrap_or(ptr::null_mut()); + .unwrap_or(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(ptr::null()), hIcon: h_icon, - hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly - hbrBackground: ptr::null_mut(), + hCursor: 0, // must be null in order for cursor state to work properly + hbrBackground: 0, lpszMenuName: ptr::null(), lpszClassName: class_name.as_ptr(), hIconSm: h_icon_small, @@ -991,7 +984,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 } @@ -999,14 +992,14 @@ 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); + CoInitializeEx(ptr::null(), COINIT_APARTMENTTHREADED); ComInitialized(ptr::null_mut()) } }; @@ -1033,17 +1026,17 @@ unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) { 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( + let hr = CoCreateInstance( &CLSID_TaskbarList, ptr::null_mut(), - combaseapi::CLSCTX_ALL, - &ITaskbarList2::uuidof(), + CLSCTX_ALL, + &IID_ITaskbarList2, &mut task_bar_list as *mut _ as *mut _, ); - if hr != S_OK || (*task_bar_list).HrInit() != S_OK { + let hr_init = (*(*task_bar_list).lpVtbl).parent.HrInit; + + if hr != S_OK || hr_init(task_bar_list.cast()) != S_OK { // In some old windows, the taskbar object could not be created, we just ignore it return; } @@ -1051,7 +1044,8 @@ unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) { } task_bar_list = task_bar_list_ptr.get(); - (*task_bar_list).MarkFullscreenWindow(handle, if fullscreen { 1 } else { 0 }); + let mark_fullscreen_window = (*(*task_bar_list).lpVtbl).MarkFullscreenWindow; + mark_fullscreen_window(task_bar_list, handle, if fullscreen { 1 } else { 0 }); }) } @@ -1060,25 +1054,41 @@ 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 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, + dwExtraInfo: 0, + time: 0, + }, + }, + }, + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: VK_LMENU, + wScan: alt_sc as u16, + dwFlags: KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, + dwExtraInfo: 0, + time: 0, + }, + }, + }, + ]; // 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..d545e1efe6 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_sys::Win32::{ + Foundation::{HWND, RECT}, + 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, 0, false.into()); } } 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,15 @@ 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, 1, 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 as i32); + SetWindowLongW(window, GWL_EXSTYLE, style_ex 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 +325,12 @@ 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, 0, 0, 0, 0, 0, flags); + SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 0, 0); } } } From a48c1e77ebca784d97f7c1b47cbe8c29fe17fb77 Mon Sep 17 00:00:00 2001 From: Clemens Wasser Date: Thu, 13 Jan 2022 20:35:30 +0100 Subject: [PATCH 2/2] Add changelog entries --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54f5a13bc8..26afa2ed0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ And please only add new entries to the top of this list, right below the `# Unre - **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods). - **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods). - **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods). +- **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies. +- The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings. # 0.26.1 (2022-01-05)