diff --git a/Cargo.toml b/Cargo.toml index 8f39742..a237ea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,12 +30,38 @@ keyboard-types = { version = "0.6.1", default-features = false } raw-window-handle = "0.5" [target.'cfg(target_os="linux")'.dependencies] -x11rb = { version = "0.13.0", features = ["cursor", "resource_manager", "allow-unsafe-code"] } +x11rb = { version = "0.13.0", features = [ + "cursor", + "resource_manager", + "allow-unsafe-code", +] } x11 = { version = "2.21", features = ["xlib", "xlib_xcb"] } nix = "0.22.0" [target.'cfg(target_os="windows")'.dependencies] -winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi", "ole2", "oleidl", "shellapi", "winerror"] } +windows = { version = "0.62.2", features = [ + "Win32_Graphics_Gdi", + "Win32_Graphics_OpenGL", + "Win32_System_Com_StructuredStorage", + "Win32_System_Ole", + "Win32_System_SystemServices", + "Win32_UI_WindowsAndMessaging", +] } +windows-sys = { version = "0.61.2", features = [ + "Win32_Graphics_Gdi", + "Win32_Graphics_OpenGL", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", +] } +windows-core = { version = "0.62.2" } uuid = { version = "0.8", features = ["v4"], optional = true } [target.'cfg(target_os="macos")'.dependencies] diff --git a/src/gl/win.rs b/src/gl/win.rs index 0b5badb..feed623 100644 --- a/src/gl/win.rs +++ b/src/gl/win.rs @@ -1,23 +1,32 @@ use std::ffi::{c_void, CString, OsStr}; use std::os::windows::ffi::OsStrExt; -use raw_window_handle::RawWindowHandle; - -use winapi::shared::minwindef::{HINSTANCE, HMODULE}; -use winapi::shared::ntdef::WCHAR; -use winapi::shared::windef::{HDC, HGLRC, HWND}; -use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryA}; -use winapi::um::wingdi::{ - wglCreateContext, wglDeleteContext, wglGetProcAddress, wglMakeCurrent, ChoosePixelFormat, - DescribePixelFormat, SetPixelFormat, SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, - PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR, -}; -use winapi::um::winnt::IMAGE_DOS_HEADER; -use winapi::um::winuser::{ - CreateWindowExW, DefWindowProcW, DestroyWindow, GetDC, RegisterClassW, ReleaseDC, - UnregisterClassW, CS_OWNDC, CW_USEDEFAULT, WNDCLASSW, +use windows_sys::{ + core::s, + Win32::{ + Foundation::{FreeLibrary, HINSTANCE, HMODULE, HWND}, + Graphics::{ + Gdi::{GetDC, ReleaseDC, HDC}, + OpenGL::{ + wglCreateContext, wglDeleteContext, wglGetProcAddress, wglMakeCurrent, + ChoosePixelFormat, DescribePixelFormat, SetPixelFormat, SwapBuffers, HGLRC, + PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL, + PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR, + }, + }, + System::{ + LibraryLoader::{GetProcAddress, LoadLibraryA}, + SystemServices::IMAGE_DOS_HEADER, + }, + UI::WindowsAndMessaging::{ + CreateWindowExW, DefWindowProcW, DestroyWindow, RegisterClassW, UnregisterClassW, + CS_OWNDC, CW_USEDEFAULT, WNDCLASSW, + }, + }, }; +use raw_window_handle::RawWindowHandle; + use super::{GlConfig, GlError, Profile}; // See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt @@ -91,7 +100,7 @@ impl GlContext { // Create temporary window and context to load function pointers let class_name_str = format!("raw-gl-context-window-{}", uuid::Uuid::new_v4().to_simple()); - let mut class_name: Vec = OsStr::new(&class_name_str).encode_wide().collect(); + let mut class_name: Vec = OsStr::new(&class_name_str).encode_wide().collect(); class_name.push(0); let hinstance = &__ImageBase as *const IMAGE_DOS_HEADER as HINSTANCE; @@ -111,7 +120,7 @@ impl GlContext { let hwnd_tmp = CreateWindowExW( 0, - class as *const WCHAR, + class as *const _, [0].as_ptr(), 0, CW_USEDEFAULT, @@ -139,7 +148,7 @@ impl GlContext { cAlphaBits: 8, cDepthBits: 24, cStencilBits: 8, - iLayerType: PFD_MAIN_PLANE, + iLayerType: PFD_MAIN_PLANE as u8, ..std::mem::zeroed() }; @@ -148,7 +157,7 @@ impl GlContext { let hglrc_tmp = wglCreateContext(hdc_tmp); if hglrc_tmp.is_null() { ReleaseDC(hwnd_tmp, hdc_tmp); - UnregisterClassW(class as *const WCHAR, hinstance); + UnregisterClassW(class as *const _, hinstance); DestroyWindow(hwnd_tmp); return Err(GlError::CreationFailed(())); } @@ -157,49 +166,28 @@ impl GlContext { #[allow(non_snake_case)] let wglCreateContextAttribsARB: Option = { - let symbol = CString::new("wglCreateContextAttribsARB").unwrap(); - let addr = wglGetProcAddress(symbol.as_ptr()); - if !addr.is_null() { - #[allow(clippy::missing_transmute_annotations)] - Some(std::mem::transmute(addr)) - } else { - None - } + wglGetProcAddress(s!("wglCreateContextAttribsARB")) + .map(|addr| std::mem::transmute(addr)) }; #[allow(non_snake_case)] let wglChoosePixelFormatARB: Option = { - let symbol = CString::new("wglChoosePixelFormatARB").unwrap(); - let addr = wglGetProcAddress(symbol.as_ptr()); - if !addr.is_null() { - #[allow(clippy::missing_transmute_annotations)] - Some(std::mem::transmute(addr)) - } else { - None - } + wglGetProcAddress(s!("wglChoosePixelFormatARB")).map(|addr| std::mem::transmute(addr)) }; #[allow(non_snake_case)] - let wglSwapIntervalEXT: Option = { - let symbol = CString::new("wglSwapIntervalEXT").unwrap(); - let addr = wglGetProcAddress(symbol.as_ptr()); - if !addr.is_null() { - #[allow(clippy::missing_transmute_annotations)] - Some(std::mem::transmute(addr)) - } else { - None - } - }; + let wglSwapIntervalEXT: Option = + { wglGetProcAddress(s!("wglSwapIntervalEXT")).map(|addr| std::mem::transmute(addr)) }; - wglMakeCurrent(hdc_tmp, std::ptr::null_mut()); + wglMakeCurrent(hdc_tmp, HGLRC::default()); wglDeleteContext(hglrc_tmp); ReleaseDC(hwnd_tmp, hdc_tmp); - UnregisterClassW(class as *const WCHAR, hinstance); + UnregisterClassW(class as *const _, hinstance); DestroyWindow(hwnd_tmp); // Create actual context - let hwnd = handle.hwnd as HWND; + let hwnd = handle.hwnd; let hdc = GetDC(hwnd); @@ -295,17 +283,16 @@ impl GlContext { ]; let hglrc = - wglCreateContextAttribsARB.unwrap()(hdc, std::ptr::null_mut(), ctx_attribs.as_ptr()); + wglCreateContextAttribsARB.unwrap()(hdc, HGLRC::default(), ctx_attribs.as_ptr()); if hglrc.is_null() { return Err(GlError::CreationFailed(())); } - let gl_library_name = CString::new("opengl32.dll").unwrap(); - let gl_library = LoadLibraryA(gl_library_name.as_ptr()); + let gl_library = LoadLibraryA(s!("opengl32.dll")); wglMakeCurrent(hdc, hglrc); wglSwapIntervalEXT.unwrap()(config.vsync as i32); - wglMakeCurrent(hdc, std::ptr::null_mut()); + wglMakeCurrent(hdc, HGLRC::default()); Ok(GlContext { hwnd, hdc, hglrc, gl_library }) } @@ -315,16 +302,20 @@ impl GlContext { } pub unsafe fn make_not_current(&self) { - wglMakeCurrent(self.hdc, std::ptr::null_mut()); + wglMakeCurrent(self.hdc, HGLRC::default()); } pub fn get_proc_address(&self, symbol: &str) -> *const c_void { let symbol = CString::new(symbol).unwrap(); - let addr = unsafe { wglGetProcAddress(symbol.as_ptr()) as *const c_void }; - if !addr.is_null() { - addr - } else { - unsafe { GetProcAddress(self.gl_library, symbol.as_ptr()) as *const c_void } + let symbol_ptr = symbol.as_ptr().cast(); + + let addr = unsafe { + wglGetProcAddress(symbol_ptr).or_else(|| GetProcAddress(self.gl_library, symbol_ptr)) + }; + + match addr { + Some(addr) => addr as *const c_void, + None => std::ptr::null(), } } @@ -338,7 +329,7 @@ impl GlContext { impl Drop for GlContext { fn drop(&mut self) { unsafe { - wglMakeCurrent(std::ptr::null_mut(), std::ptr::null_mut()); + wglMakeCurrent(HDC::default(), HGLRC::default()); wglDeleteContext(self.hglrc); ReleaseDC(self.hwnd, self.hdc); FreeLibrary(self.gl_library); diff --git a/src/win/cursor.rs b/src/win/cursor.rs index f9a04d3..69dff14 100644 --- a/src/win/cursor.rs +++ b/src/win/cursor.rs @@ -1,13 +1,13 @@ use crate::MouseCursor; -use winapi::{ - shared::ntdef::LPCWSTR, - um::winuser::{ +use windows_sys::{ + core::PCWSTR, + Win32::UI::WindowsAndMessaging::{ 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, }, }; -pub fn cursor_to_lpcwstr(cursor: MouseCursor) -> LPCWSTR { +pub fn cursor_to_lpcwstr(cursor: MouseCursor) -> PCWSTR { match cursor { MouseCursor::Default => IDC_ARROW, MouseCursor::Hand => IDC_HAND, diff --git a/src/win/drop_target.rs b/src/win/drop_target.rs index b9ba580..56b3b1d 100644 --- a/src/win/drop_target.rs +++ b/src/win/drop_target.rs @@ -1,95 +1,43 @@ +use std::cell::{Cell, RefCell}; use std::ffi::OsString; -use std::mem::transmute; use std::os::windows::prelude::OsStringExt; use std::ptr::null_mut; -use std::rc::{Rc, Weak}; - -use winapi::shared::guiddef::{IsEqualIID, REFIID}; -use winapi::shared::minwindef::{DWORD, WPARAM}; -use winapi::shared::ntdef::{HRESULT, ULONG}; -use winapi::shared::windef::{POINT, POINTL}; -use winapi::shared::winerror::{E_NOINTERFACE, E_UNEXPECTED, S_OK}; -use winapi::shared::wtypes::DVASPECT_CONTENT; -use winapi::um::objidl::{IDataObject, FORMATETC, STGMEDIUM, TYMED_HGLOBAL}; -use winapi::um::oleidl::{ - IDropTarget, IDropTargetVtbl, DROPEFFECT_COPY, DROPEFFECT_LINK, DROPEFFECT_MOVE, - DROPEFFECT_NONE, DROPEFFECT_SCROLL, +use std::rc::Weak; +use windows::core::implement; +use windows::Win32::Foundation::{E_UNEXPECTED, POINTL}; +use windows::Win32::System::Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL}; +use windows::Win32::System::Ole::*; +use windows::Win32::System::SystemServices::MODIFIERKEYS_FLAGS; +use windows_core::Ref; +use windows_sys::Win32::{ + Foundation::POINT, Graphics::Gdi::ScreenToClient, UI::Shell::DragQueryFileW, }; -use winapi::um::shellapi::{DragQueryFileW, HDROP}; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winuser::{ScreenToClient, CF_HDROP}; -use winapi::Interface; use crate::{DropData, DropEffect, Event, EventStatus, MouseEvent, PhyPoint, Point}; use super::WindowState; -// These function pointers have to be stored in a (const) variable before they can be transmuted -// Transmuting is needed because winapi has a bug where the pt parameter has an incorrect -// type `*const POINTL` -#[allow(non_snake_case)] -const DRAG_ENTER_PTR: unsafe extern "system" fn( - this: *mut IDropTarget, - pDataObj: *const IDataObject, - grfKeyState: DWORD, - pt: POINTL, - pdwEffect: *mut DWORD, -) -> HRESULT = DropTarget::drag_enter; -#[allow(non_snake_case)] -const DRAG_OVER_PTR: unsafe extern "system" fn( - this: *mut IDropTarget, - grfKeyState: DWORD, - pt: POINTL, - pdwEffect: *mut DWORD, -) -> HRESULT = DropTarget::drag_over; -#[allow(non_snake_case)] -const DROP_PTR: unsafe extern "system" fn( - this: *mut IDropTarget, - pDataObj: *const IDataObject, - grfKeyState: DWORD, - pt: POINTL, - pdwEffect: *mut DWORD, -) -> HRESULT = DropTarget::drop; - -#[allow(clippy::missing_transmute_annotations)] -const DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl { - parent: IUnknownVtbl { - QueryInterface: DropTarget::query_interface, - AddRef: DropTarget::add_ref, - Release: DropTarget::release, - }, - DragEnter: unsafe { transmute(DRAG_ENTER_PTR) }, - DragOver: unsafe { transmute(DRAG_OVER_PTR) }, - DragLeave: DropTarget::drag_leave, - Drop: unsafe { transmute(DROP_PTR) }, -}; - -#[repr(C)] +#[implement(IDropTarget)] pub(super) struct DropTarget { - base: IDropTarget, - window_state: Weak, // These are cached since DragOver and DragLeave callbacks don't provide them, // and handling drag move events gets awkward on the client end otherwise - drag_position: Point, - drop_data: DropData, + drag_position: Cell, + drop_data: RefCell, } impl DropTarget { pub(super) fn new(window_state: Weak) -> Self { Self { - base: IDropTarget { lpVtbl: &DROP_TARGET_VTBL }, - window_state, - - drag_position: Point::new(0.0, 0.0), - drop_data: DropData::None, + drag_position: Cell::new(Point::new(0.0, 0.0)), + drop_data: RefCell::new(DropData::None), } } #[allow(non_snake_case)] - fn on_event(&self, pdwEffect: Option<*mut DWORD>, event: MouseEvent) { + fn on_event(&self, pdwEffect: Option<*mut DROPEFFECT>, event: MouseEvent) { let Some(window_state) = self.window_state.upgrade() else { return; }; @@ -113,39 +61,37 @@ impl DropTarget { } } - fn parse_coordinates(&mut self, pt: POINTL) { + fn parse_coordinates(&self, pt: POINTL) { let Some(window_state) = self.window_state.upgrade() else { return; }; let mut pt = POINT { x: pt.x, y: pt.y }; - unsafe { ScreenToClient(window_state.hwnd, &mut pt as *mut POINT) }; + + unsafe { ScreenToClient(window_state.hwnd, &mut pt) }; let phy_point = PhyPoint::new(pt.x, pt.y); - self.drag_position = phy_point.to_logical(&window_state.window_info()); + self.drag_position.set(phy_point.to_logical(&window_state.window_info())); } - fn parse_drop_data(&mut self, data_object: &IDataObject) { + fn parse_drop_data(&self, data_object: &IDataObject) { let format = FORMATETC { - cfFormat: CF_HDROP as u16, + cfFormat: CF_HDROP.0, ptd: null_mut(), - dwAspect: DVASPECT_CONTENT, + dwAspect: DVASPECT_CONTENT.0, lindex: -1, - tymed: TYMED_HGLOBAL, + tymed: TYMED_HGLOBAL.0 as u32, }; - let mut medium = STGMEDIUM { tymed: 0, u: null_mut(), pUnkForRelease: null_mut() }; - unsafe { - let hresult = data_object.GetData(&format, &mut medium); - if hresult != S_OK { - self.drop_data = DropData::None; + let Ok(medium) = data_object.GetData(&format) else { + self.drop_data.replace(DropData::None); return; - } + }; - let hdrop = *(*medium.u).hGlobal() as HDROP; + let hdrop = medium.u.hGlobal.0; let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, null_mut(), 0); if item_count == 0 { - self.drop_data = DropData::None; + self.drop_data.replace(DropData::None); return; } @@ -161,122 +107,85 @@ impl DropTarget { paths.push(OsString::from_wide(&buffer[..characters as usize]).into()) } - self.drop_data = DropData::Files(paths); - } - } - - #[allow(non_snake_case)] - unsafe extern "system" fn query_interface( - this: *mut IUnknown, riid: REFIID, ppvObject: *mut *mut winapi::ctypes::c_void, - ) -> HRESULT { - if IsEqualIID(&*riid, &IUnknown::uuidof()) || IsEqualIID(&*riid, &IDropTarget::uuidof()) { - Self::add_ref(this); - *ppvObject = this as *mut winapi::ctypes::c_void; - return S_OK; + self.drop_data.replace(DropData::Files(paths)); } - - E_NOINTERFACE - } - - unsafe extern "system" fn add_ref(this: *mut IUnknown) -> ULONG { - let arc = Rc::from_raw(this); - let result = Rc::strong_count(&arc) + 1; - let _ = Rc::into_raw(arc); - - Rc::increment_strong_count(this); - - result as ULONG - } - - unsafe extern "system" fn release(this: *mut IUnknown) -> ULONG { - let arc = Rc::from_raw(this); - let result = Rc::strong_count(&arc) - 1; - let _ = Rc::into_raw(arc); - - Rc::decrement_strong_count(this); - - result as ULONG } +} - #[allow(non_snake_case)] - unsafe extern "system" fn drag_enter( - this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, - pdwEffect: *mut DWORD, - ) -> HRESULT { - let drop_target = &mut *(this as *mut DropTarget); - let Some(window_state) = drop_target.window_state.upgrade() else { - return E_UNEXPECTED; +#[allow(non_snake_case)] +impl IDropTarget_Impl for DropTarget_Impl { + fn DragEnter( + &self, pdataobj: Ref, grfkeystate: MODIFIERKEYS_FLAGS, pt: &POINTL, + pdweffect: *mut DROPEFFECT, + ) -> windows_core::Result<()> { + let Some(window_state) = self.window_state.upgrade() else { + return Err(E_UNEXPECTED.into()); }; let modifiers = - window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM); + window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfkeystate.0 as usize); - drop_target.parse_coordinates(pt); - drop_target.parse_drop_data(&*pDataObj); + self.parse_coordinates(*pt); + self.parse_drop_data(pdataobj.unwrap()); let event = MouseEvent::DragEntered { - position: drop_target.drag_position, + position: self.drag_position.get(), modifiers, - data: drop_target.drop_data.clone(), + data: self.drop_data.borrow().clone(), }; - drop_target.on_event(Some(pdwEffect), event); - S_OK + self.on_event(Some(pdweffect), event); + Ok(()) } - #[allow(non_snake_case)] - unsafe extern "system" fn drag_over( - this: *mut IDropTarget, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD, - ) -> HRESULT { - let drop_target = &mut *(this as *mut DropTarget); - let Some(window_state) = drop_target.window_state.upgrade() else { - return E_UNEXPECTED; + fn DragOver( + &self, grfkeystate: MODIFIERKEYS_FLAGS, pt: &POINTL, pdweffect: *mut DROPEFFECT, + ) -> windows_core::Result<()> { + let Some(window_state) = self.window_state.upgrade() else { + return Err(E_UNEXPECTED.into()); }; let modifiers = - window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM); + window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfkeystate.0 as usize); - drop_target.parse_coordinates(pt); + self.parse_coordinates(*pt); let event = MouseEvent::DragMoved { - position: drop_target.drag_position, + position: self.drag_position.get(), modifiers, - data: drop_target.drop_data.clone(), + data: self.drop_data.borrow().clone(), }; - drop_target.on_event(Some(pdwEffect), event); - S_OK + self.on_event(Some(pdweffect), event); + Ok(()) } - unsafe extern "system" fn drag_leave(this: *mut IDropTarget) -> HRESULT { - let drop_target = &mut *(this as *mut DropTarget); - drop_target.on_event(None, MouseEvent::DragLeft); - S_OK + fn DragLeave(&self) -> windows_core::Result<()> { + self.on_event(None, MouseEvent::DragLeft); + Ok(()) } - #[allow(non_snake_case)] - unsafe extern "system" fn drop( - this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, - pdwEffect: *mut DWORD, - ) -> HRESULT { - let drop_target = &mut *(this as *mut DropTarget); - let Some(window_state) = drop_target.window_state.upgrade() else { - return E_UNEXPECTED; + fn Drop( + &self, pdataobj: Ref, grfkeystate: MODIFIERKEYS_FLAGS, pt: &POINTL, + pdweffect: *mut DROPEFFECT, + ) -> windows_core::Result<()> { + let Some(window_state) = self.window_state.upgrade() else { + return Err(E_UNEXPECTED.into()); }; let modifiers = - window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM); + window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfkeystate.0 as usize); - drop_target.parse_coordinates(pt); - drop_target.parse_drop_data(&*pDataObj); + self.parse_coordinates(*pt); + self.parse_drop_data(pdataobj.unwrap()); let event = MouseEvent::DragDropped { - position: drop_target.drag_position, + position: self.drag_position.get(), modifiers, - data: drop_target.drop_data.clone(), + data: self.drop_data.borrow().clone(), }; - drop_target.on_event(Some(pdwEffect), event); - S_OK + self.on_event(Some(pdweffect), event); + Ok(()) } } diff --git a/src/win/hook.rs b/src/win/hook.rs index 0f6a3e8..569bfb9 100644 --- a/src/win/hook.rs +++ b/src/win/hook.rs @@ -1,23 +1,16 @@ use std::{ collections::HashSet, - ffi::c_int, ptr, sync::{LazyLock, RwLock}, }; -use winapi::{ - shared::{ - minwindef::{LPARAM, WPARAM}, - windef::{HHOOK, HWND, POINT}, - }, - um::{ - libloaderapi::GetModuleHandleW, - processthreadsapi::GetCurrentThreadId, - winuser::{ - CallNextHookEx, SetWindowsHookExW, UnhookWindowsHookEx, HC_ACTION, MSG, PM_REMOVE, - WH_GETMESSAGE, WM_CHAR, WM_KEYDOWN, WM_KEYUP, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, - WM_USER, - }, +use windows_sys::Win32::{ + Foundation::{HWND, LPARAM, LRESULT, WPARAM}, + System::{LibraryLoader::GetModuleHandleW, Threading::GetCurrentThreadId}, + UI::WindowsAndMessaging::{ + CallNextHookEx, SetWindowsHookExW, UnhookWindowsHookEx, HC_ACTION, HHOOK, MSG, PM_REMOVE, + WH_GETMESSAGE, WM_CHAR, WM_KEYDOWN, WM_KEYUP, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, + WM_USER, }, }; @@ -26,7 +19,7 @@ use crate::win::wnd_proc; // track all windows opened by this instance of baseview // we use an RwLock here since the vast majority of uses (event interceptions) // will only need to read from the HashSet -static HOOK_STATE: LazyLock> = LazyLock::new(|| RwLock::default()); +static HOOK_STATE: LazyLock> = LazyLock::new(RwLock::default); pub(crate) struct KeyboardHookHandle(HWNDWrapper); @@ -99,21 +92,15 @@ fn deinit_keyboard_hook(hwnd: HWNDWrapper) { } unsafe extern "system" fn keyboard_hook_callback( - n_code: c_int, wparam: WPARAM, lparam: LPARAM, -) -> isize { + n_code: i32, wparam: WPARAM, lparam: LPARAM, +) -> LRESULT { let msg = lparam as *mut MSG; - if n_code == HC_ACTION && wparam == PM_REMOVE as usize && offer_message_to_baseview(msg) { - *msg = MSG { - hwnd: ptr::null_mut(), - message: WM_USER, - wParam: 0, - lParam: 0, - time: 0, - pt: POINT { x: 0, y: 0 }, - }; + if n_code == HC_ACTION as i32 && wparam == PM_REMOVE as usize && offer_message_to_baseview(msg) + { + *msg = MSG { message: WM_USER, ..Default::default() }; - 0 + LRESULT::default() } else { CallNextHookEx(ptr::null_mut(), n_code, wparam, lparam) } diff --git a/src/win/keyboard.rs b/src/win/keyboard.rs index ed696cc..e2f9948 100644 --- a/src/win/keyboard.rs +++ b/src/win/keyboard.rs @@ -23,31 +23,18 @@ use std::mem; use std::ops::RangeInclusive; use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers}; - -use winapi::shared::minwindef::{HKL, INT, LPARAM, UINT, WPARAM}; -use winapi::shared::ntdef::SHORT; -use winapi::shared::windef::HWND; -use winapi::um::winuser::{ - GetKeyState, GetKeyboardLayout, MapVirtualKeyExW, PeekMessageW, ToUnicodeEx, MAPVK_VK_TO_CHAR, - MAPVK_VSC_TO_VK_EX, MK_CONTROL, MK_SHIFT, PM_NOREMOVE, VK_ACCEPT, VK_ADD, VK_APPS, VK_ATTN, - VK_BACK, VK_BROWSER_BACK, VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, VK_BROWSER_HOME, - VK_BROWSER_REFRESH, VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_CANCEL, VK_CAPITAL, VK_CLEAR, - VK_CONTROL, VK_CONVERT, VK_CRSEL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_EREOF, - VK_ESCAPE, VK_EXECUTE, VK_EXSEL, VK_F1, VK_F10, VK_F11, VK_F12, VK_F2, VK_F3, VK_F4, VK_F5, - VK_F6, VK_F7, VK_F8, VK_F9, VK_FINAL, VK_HELP, VK_HOME, VK_INSERT, VK_JUNJA, VK_KANA, VK_KANJI, - VK_LAUNCH_APP1, VK_LAUNCH_APP2, VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LCONTROL, VK_LEFT, - VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, - VK_MEDIA_STOP, VK_MENU, VK_MODECHANGE, VK_MULTIPLY, VK_NEXT, VK_NONCONVERT, VK_NUMLOCK, - VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, - VK_NUMPAD8, VK_NUMPAD9, VK_OEM_ATTN, VK_OEM_CLEAR, VK_PAUSE, VK_PLAY, VK_PRINT, VK_PRIOR, - VK_PROCESSKEY, VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN, VK_SCROLL, - VK_SELECT, VK_SHIFT, VK_SLEEP, VK_SNAPSHOT, VK_SUBTRACT, VK_TAB, VK_UP, VK_VOLUME_DOWN, - VK_VOLUME_MUTE, VK_VOLUME_UP, VK_ZOOM, WM_CHAR, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, - WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, +use windows_sys::Win32::{ + Foundation::{HWND, LPARAM, WPARAM}, + System::SystemServices::{MK_CONTROL, MK_SHIFT}, + UI::{ + Input::KeyboardAndMouse::*, + WindowsAndMessaging::{ + PeekMessageW, PM_NOREMOVE, WM_CHAR, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, + WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, + }, + }, }; -const VK_ABNT_C2: INT = 0xc2; - /// A (non-extended) virtual key code. type VkCode = u8; @@ -84,14 +71,14 @@ const PRINTABLE_VKS: &[RangeInclusive] = &[ ]; /// Bits of lparam indicating scan code, including extended bit. -const SCAN_MASK: LPARAM = 0x1ff_0000; +const SCAN_MASK: isize = 0x1ff_0000; /// Determine whether there are more messages in the queue for this key event. /// /// When this function returns `false`, there is another message in the queue /// with a matching scan code, therefore it is reasonable to stash the data /// from this message and defer til later to actually produce the event. -unsafe fn is_last_message(hwnd: HWND, msg: UINT, lparam: LPARAM) -> bool { +unsafe fn is_last_message(hwnd: HWND, msg: u32, lparam: LPARAM) -> bool { let expected_msg = match msg { WM_KEYDOWN | WM_CHAR => WM_CHAR, WM_SYSKEYDOWN | WM_SYSCHAR => WM_SYSCHAR, @@ -102,7 +89,7 @@ unsafe fn is_last_message(hwnd: HWND, msg: UINT, lparam: LPARAM) -> bool { avail == 0 || msg.lParam & SCAN_MASK != lparam & SCAN_MASK } -const MODIFIER_MAP: &[(INT, Modifiers, SHORT)] = &[ +const MODIFIER_MAP: &[(VIRTUAL_KEY, Modifiers, u16)] = &[ (VK_MENU, Modifiers::ALT, 0x80), (VK_CAPITAL, Modifiers::CAPS_LOCK, 0x1), (VK_CONTROL, Modifiers::CONTROL, 0x80), @@ -259,7 +246,7 @@ fn scan_to_code(scan_code: u32) -> Code { } fn vk_to_key(vk: VkCode) -> Option { - Some(match vk as INT { + Some(match vk as u16 { VK_CANCEL => Key::Cancel, VK_BACK => Key::Backspace, VK_TAB => Key::Tab, @@ -365,7 +352,7 @@ fn code_unit_to_key(code_unit: u32) -> Key { /// /// This logic is based on NativeKey::GetKeyLocation from Mozilla. fn vk_to_location(vk: VkCode, is_extended: bool) -> Location { - match vk as INT { + match vk as u16 { VK_LSHIFT | VK_LCONTROL | VK_LMENU | VK_LWIN => Location::Left, VK_RSHIFT | VK_RCONTROL | VK_RMENU | VK_RWIN => Location::Right, VK_RETURN if is_extended => Location::Numpad, @@ -437,7 +424,7 @@ impl KeyboardState { /// a valid `HKL` reference in the `WM_INPUTLANGCHANGE` message. Actual danger /// is likely low, though. pub(crate) unsafe fn process_message( - &mut self, hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM, + &mut self, hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> Option { match msg { WM_KEYDOWN | WM_SYSKEYDOWN => { @@ -550,11 +537,11 @@ impl KeyboardState { unsafe { let mut modifiers = Modifiers::empty(); for &(vk, modifier, mask) in MODIFIER_MAP { - if GetKeyState(vk) & mask != 0 { + if GetKeyState(vk.into()) as u16 & mask != 0 { modifiers |= modifier; } } - if self.has_altgr && GetKeyState(VK_RMENU) & 0x80 != 0 { + if self.has_altgr && GetKeyState(VK_RMENU.into()) & 0x80 != 0 { modifiers |= Modifiers::ALT_GRAPH; modifiers &= !(Modifiers::CONTROL | Modifiers::ALT); } @@ -569,16 +556,16 @@ impl KeyboardState { let mut modifiers = Modifiers::empty(); for &(vk, modifier, mask) in MODIFIER_MAP { let modifier_active = match modifier { - Modifiers::CONTROL => wparam & MK_CONTROL != 0, - Modifiers::SHIFT => wparam & MK_SHIFT != 0, - _ => GetKeyState(vk) & mask != 0, + Modifiers::CONTROL => wparam & MK_CONTROL as usize != 0, + Modifiers::SHIFT => wparam & MK_SHIFT as usize != 0, + _ => GetKeyState(vk.into()) as u16 & mask != 0, }; if modifier_active { modifiers |= modifier; } } - if self.has_altgr && GetKeyState(VK_RMENU) & 0x80 != 0 { + if self.has_altgr && GetKeyState(VK_RMENU.into()) & 0x80 != 0 { modifiers |= Modifiers::ALT_GRAPH; modifiers &= !(Modifiers::CONTROL | Modifiers::ALT); } @@ -614,7 +601,7 @@ impl KeyboardState { #[allow(clippy::iter_overeager_cloned)] for vk in PRINTABLE_VKS.iter().cloned().flatten() { let ret = ToUnicodeEx( - vk as UINT, + vk.into(), 0, key_state.as_ptr(), uni_chars.as_mut_ptr(), @@ -643,7 +630,7 @@ impl KeyboardState { // It's a dead key, press it again to reset the state. self.dead_keys.insert((vk, shift_state)); let _ = ToUnicodeEx( - vk as UINT, + vk.into(), 0, key_state.as_ptr(), uni_chars.as_mut_ptr(), @@ -691,7 +678,7 @@ impl KeyboardState { /// This only does the mapping if the original code is ambiguous, as otherwise the /// virtual key code reported in `wparam` is more reliable. fn refine_vk(&self, vk: VkCode, mut scan_code: u32) -> VkCode { - match vk as INT { + match vk.into() { 0 | VK_SHIFT | VK_CONTROL | VK_MENU => { if scan_code >= 0x100 { scan_code += 0xE000 - 0x100; diff --git a/src/win/window.rs b/src/win/window.rs index fea3f1a..6870d20 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -1,27 +1,38 @@ -use winapi::shared::guiddef::GUID; -use winapi::shared::minwindef::{ATOM, FALSE, LOWORD, LPARAM, LRESULT, UINT, WPARAM}; -use winapi::shared::windef::{HWND, RECT}; -use winapi::um::combaseapi::CoCreateGuid; -use winapi::um::ole2::{OleInitialize, RegisterDragDrop, RevokeDragDrop}; -use winapi::um::oleidl::LPDROPTARGET; -use winapi::um::winuser::{ - AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, - GetDpiForWindow, GetFocus, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, - RegisterClassW, ReleaseCapture, SetCapture, SetCursor, SetFocus, SetProcessDpiAwarenessContext, - SetTimer, SetWindowLongPtrW, SetWindowPos, TrackMouseEvent, TranslateMessage, UnregisterClassW, - CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, HTCLIENT, IDC_ARROW, MSG, SWP_NOACTIVATE, - SWP_NOMOVE, SWP_NOZORDER, TRACKMOUSEEVENT, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, - WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, - WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSELEAVE, WM_MOUSEMOVE, WM_MOUSEWHEEL, - WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, - WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, - WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, - WS_SIZEBOX, WS_VISIBLE, XBUTTON1, XBUTTON2, +use windows_core::{ComObject, Interface}; +use windows_sys::Win32::{ + Foundation::{HWND, LPARAM, LRESULT, RECT, WPARAM}, + System::{ + Com::CoCreateGuid, + Ole::{OleInitialize, RevokeDragDrop}, + }, + UI::{ + Controls::{HOVER_DEFAULT, WM_MOUSELEAVE}, + HiDpi::{ + GetDpiForWindow, SetProcessDpiAwarenessContext, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, + }, + Input::KeyboardAndMouse::{ + GetFocus, ReleaseCapture, SetCapture, SetFocus, TrackMouseEvent, TME_LEAVE, + TRACKMOUSEEVENT, + }, + WindowsAndMessaging::{ + AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, + GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, SetCursor, + SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW, + CS_OWNDC, GWLP_USERDATA, HTCLIENT, IDC_ARROW, MSG, SWP_NOACTIVATE, SWP_NOMOVE, + SWP_NOZORDER, WHEEL_DELTA, WINDOW_EX_STYLE, WINDOW_STYLE, WM_CHAR, WM_CLOSE, WM_CREATE, + WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, + WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, + WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SHOWWINDOW, WM_SIZE, + WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN, + WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, + WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, + }, + }, }; use std::cell::{Cell, Ref, RefCell, RefMut}; use std::collections::VecDeque; -use std::ffi::{c_void, OsStr}; +use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; use std::ptr::null_mut; use std::rc::Rc; @@ -30,8 +41,11 @@ use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, Win32WindowHandle, WindowsDisplayHandle, }; +use windows::Win32::System::Ole::IDropTarget; +use windows_sys::core::GUID; +use windows_sys::Win32::System::Ole::RegisterDragDrop; -const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1; +const BV_WINDOW_MUST_CLOSE: u32 = WM_USER + 1; use crate::win::hook::{self, KeyboardHookHandle}; use crate::{ @@ -51,20 +65,30 @@ unsafe fn generate_guid() -> String { CoCreateGuid(&mut guid); format!( "{:0X}-{:0X}-{:0X}-{:0X}{:0X}-{:0X}{:0X}{:0X}{:0X}{:0X}{:0X}\0", - guid.Data1, - guid.Data2, - guid.Data3, - guid.Data4[0], - guid.Data4[1], - guid.Data4[2], - guid.Data4[3], - guid.Data4[4], - guid.Data4[5], - guid.Data4[6], - guid.Data4[7] + guid.data1, + guid.data2, + guid.data3, + guid.data4[0], + guid.data4[1], + guid.data4[2], + guid.data4[3], + guid.data4[4], + guid.data4[5], + guid.data4[6], + guid.data4[7] ) } +#[allow(non_snake_case)] +fn HIWORD(wparam: WPARAM) -> u16 { + ((wparam >> 16) & 0xffff) as u16 +} + +#[allow(non_snake_case)] +fn LOWORD(lparam: LPARAM) -> u16 { + (lparam & 0xffff) as u16 +} + const WIN_FRAME_TIMER: usize = 4242; pub struct WindowHandle { @@ -90,7 +114,7 @@ unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { if let Some(hwnd) = self.hwnd { let mut handle = Win32WindowHandle::empty(); - handle.hwnd = hwnd as *mut c_void; + handle.hwnd = hwnd; RawWindowHandle::Win32(handle) } else { @@ -120,10 +144,10 @@ impl Drop for ParentHandle { } pub(crate) unsafe extern "system" fn wnd_proc( - hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM, + hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { if msg == WM_CREATE { - PostMessageW(hwnd, WM_SHOWWINDOW, 0, 0); + PostMessageW(hwnd, WM_SHOWWINDOW, WPARAM::default(), LPARAM::default()); return 0; } @@ -167,7 +191,7 @@ pub(crate) unsafe extern "system" fn wnd_proc( /// Our custom `wnd_proc` handler. If the result contains a value, then this is returned after /// handling any deferred tasks. otherwise the default window procedure is invoked. unsafe fn wnd_proc_inner( - hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM, window_state: &WindowState, + hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, window_state: &WindowState, ) -> Option { match msg { WM_MOUSEMOVE => { @@ -178,10 +202,10 @@ unsafe fn wnd_proc_inner( // this makes Windows track whether the mouse leaves the window. // When the mouse leaves it results in a `WM_MOUSELEAVE` event. let mut track_mouse = TRACKMOUSEEVENT { - cbSize: std::mem::size_of::() as u32, - dwFlags: winapi::um::winuser::TME_LEAVE, + cbSize: size_of::() as u32, + dwFlags: TME_LEAVE, hwndTrack: hwnd, - dwHoverTime: winapi::um::winuser::HOVER_DEFAULT, + dwHoverTime: HOVER_DEFAULT, }; // Couldn't find a good way to track whether the mouse enters, // but if `WM_MOUSEMOVE` happens, the mouse must have entered. @@ -250,6 +274,14 @@ unsafe fn wnd_proc_inner( let mut mouse_button_counter = window_state.mouse_button_counter.get(); + #[allow(non_snake_case)] + fn GET_XBUTTON_WPARAM(wparam: WPARAM) -> u16 { + HIWORD(wparam) + } + + const XBUTTON1: u16 = 0x1; + const XBUTTON2: u16 = 0x2; + let button = match msg { WM_LBUTTONDOWN | WM_LBUTTONUP => Some(MouseButton::Left), WM_MBUTTONDOWN | WM_MBUTTONUP => Some(MouseButton::Middle), @@ -439,15 +471,13 @@ unsafe fn wnd_proc_inner( // If WM_SETCURSOR returns `None`, WM_SETCURSOR continues to get handled by the outer window(s), // If it returns `Some(1)`, the current window decides what the cursor is WM_SETCURSOR => { - let low_word = LOWORD(lparam as u32) as isize; - let mouse_in_window = low_word == HTCLIENT; + let low_word = LOWORD(lparam) as isize; + let mouse_in_window = low_word == HTCLIENT as isize; if mouse_in_window { // Here we need to set the cursor back to what the state says, since it can have changed when outside the window let cursor = LoadCursorW(null_mut(), cursor_to_lpcwstr(window_state.cursor_icon.get())); - unsafe { - SetCursor(cursor); - } + SetCursor(cursor); Some(1) } else { // Cursor is being changed by some other window, e.g. when having mouse on the borders to resize it @@ -464,6 +494,9 @@ unsafe fn wnd_proc_inner( } } +#[allow(clippy::upper_case_acronyms)] +type ATOM = u16; + unsafe fn register_wnd_class() -> ATOM { // We generate a unique name for the new window class to prevent name collisions let class_name_str = format!("Baseview-{}", generate_guid()); @@ -473,14 +506,9 @@ unsafe fn register_wnd_class() -> ATOM { let wnd_class = WNDCLASSW { style: CS_OWNDC, lpfnWndProc: Some(wnd_proc), - hInstance: null_mut(), lpszClassName: class_name.as_ptr(), - cbClsExtra: 0, - cbWndExtra: 0, - hIcon: null_mut(), hCursor: LoadCursorW(null_mut(), IDC_ARROW), - hbrBackground: null_mut(), - lpszMenuName: null_mut(), + ..Default::default() }; RegisterClassW(&wnd_class) @@ -510,9 +538,9 @@ pub(super) struct WindowState { cursor_icon: Cell, // Initialized late so the `Window` can hold a reference to this `WindowState` handler: RefCell>>, - _drop_target: RefCell>>, + _drop_target: RefCell>>, scale_policy: WindowScalePolicy, - dw_style: u32, + dw_style: WINDOW_STYLE, // handle to the win32 keyboard hook // we don't need to read from this, just carry it around so the Drop impl can run @@ -564,6 +592,7 @@ impl WindowState { right: window_info.physical_size().width as i32, bottom: window_info.physical_size().height as i32, }; + unsafe { AdjustWindowRectEx(&mut rect, self.dw_style, 0, 0); SetWindowPos( @@ -603,7 +632,7 @@ impl Window<'_> { B: Send + 'static, { let parent = match parent.raw_window_handle() { - RawWindowHandle::Win32(h) => h.hwnd as HWND, + RawWindowHandle::Win32(h) => h.hwnd, h => panic!("unsupported parent handle {:?}", h), }; @@ -679,7 +708,7 @@ impl Window<'_> { }; if !parented { - AdjustWindowRectEx(&mut rect, flags, FALSE, 0); + AdjustWindowRectEx(&mut rect, flags, 0, 0); } let hwnd = CreateWindowExW( @@ -703,7 +732,7 @@ impl Window<'_> { #[cfg(feature = "opengl")] let gl_context: Option = options.gl_config.map(|gl_config| { let mut handle = Win32WindowHandle::empty(); - handle.hwnd = hwnd as *mut c_void; + handle.hwnd = hwnd; let handle = RawWindowHandle::Win32(handle); GlContext::create(&handle, gl_config).expect("Could not create OpenGL context") @@ -745,9 +774,7 @@ impl Window<'_> { *window_state.handler.borrow_mut() = Some(Box::new(handler)); // Only works on Windows 10 unfortunately. - SetProcessDpiAwarenessContext( - winapi::shared::windef::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, - ); + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); // Now we can get the actual dpi of the window. let new_rect = if let WindowScalePolicy::SystemScaleFactor = options.scale { @@ -776,19 +803,20 @@ impl Window<'_> { None }; - let drop_target = Rc::new(DropTarget::new(Rc::downgrade(&window_state))); + let drop_target = ComObject::new(DropTarget::new(Rc::downgrade(&window_state))); *window_state._drop_target.borrow_mut() = Some(drop_target.clone()); OleInitialize(null_mut()); - RegisterDragDrop(hwnd, Rc::as_ptr(&drop_target) as LPDROPTARGET); + + RegisterDragDrop(hwnd, drop_target.as_interface::().as_raw()); SetWindowLongPtrW(hwnd, GWLP_USERDATA, Rc::into_raw(window_state) as *const _ as _); SetTimer(hwnd, WIN_FRAME_TIMER, 15, None); if let Some(mut new_rect) = new_rect { - // Convert this desired"client rectangle" size to the actual "window rectangle" + // Convert this desired "client rectangle" size to the actual "window rectangle" // size (Because of course you have to do that). - AdjustWindowRectEx(&mut new_rect, flags, 0, 0); + AdjustWindowRectEx(&mut new_rect, flags, 0, WINDOW_EX_STYLE::default()); // Windows makes us resize the window manually. This will trigger another `WM_SIZE` event, // which we can then send the user the new scale factor. @@ -819,9 +847,7 @@ impl Window<'_> { } pub fn focus(&mut self) { - unsafe { - SetFocus(self.state.hwnd); - } + unsafe { SetFocus(self.state.hwnd) }; } pub fn resize(&mut self, size: Size) { @@ -848,7 +874,7 @@ impl Window<'_> { unsafe impl HasRawWindowHandle for Window<'_> { fn raw_window_handle(&self) -> RawWindowHandle { let mut handle = Win32WindowHandle::empty(); - handle.hwnd = self.state.hwnd as *mut c_void; + handle.hwnd = self.state.hwnd; RawWindowHandle::Win32(handle) }