diff --git a/Cargo.toml b/Cargo.toml index 569998e8..f40d5ef6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,12 @@ input-linux = { version = "0.7.1", optional = true } xkbcommon = { version = "0.8", optional = true } [target.'cfg(target_os = "windows")'.dependencies] -winapi = { version = "0.3", features = ["winuser", "errhandlingapi", "processthreadsapi"] } +windows-sys = { version = "0.61", features = [ + "Win32_Foundation", + "Win32_System_Threading", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_WindowsAndMessaging", +] } [dev-dependencies] serde_json = "1.0" diff --git a/src/windows/common.rs b/src/windows/common.rs index e61240b0..1ac064d2 100644 --- a/src/windows/common.rs +++ b/src/windows/common.rs @@ -6,16 +6,14 @@ use std::convert::TryInto; use std::os::raw::{c_int, c_short}; use std::ptr::null_mut; use std::sync::Mutex; -use winapi::shared::minwindef::{DWORD, HIWORD, LPARAM, LRESULT, WORD, WPARAM}; -use winapi::shared::ntdef::LONG; -use winapi::shared::windef::HHOOK; -use winapi::um::errhandlingapi::GetLastError; -use winapi::um::winuser::{ - KBDLLHOOKSTRUCT, MSLLHOOKSTRUCT, SetWindowsHookExA, WH_KEYBOARD_LL, WH_MOUSE_LL, WHEEL_DELTA, - WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, +use windows_sys::Win32::Foundation::{GetLastError, LPARAM, LRESULT, WPARAM}; +use windows_sys::Win32::UI::WindowsAndMessaging::{ + HHOOK, KBDLLHOOKSTRUCT, MSLLHOOKSTRUCT, SetWindowsHookExA, WH_KEYBOARD_LL, WH_MOUSE_LL, + WHEEL_DELTA, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_XBUTTONDOWN, WM_XBUTTONUP, }; + pub const TRUE: i32 = 1; pub const FALSE: i32 = 0; @@ -24,37 +22,37 @@ lazy_static! { pub(crate) static ref KEYBOARD: Mutex = Mutex::new(Keyboard::new().unwrap()); } -pub unsafe fn get_code(lpdata: LPARAM) -> DWORD { +pub unsafe fn get_code(lpdata: LPARAM) -> u32 { unsafe { let kb = *(lpdata as *const KBDLLHOOKSTRUCT); kb.vkCode } } -pub unsafe fn get_scan_code(lpdata: LPARAM) -> DWORD { +pub unsafe fn get_scan_code(lpdata: LPARAM) -> u32 { unsafe { let kb = *(lpdata as *const KBDLLHOOKSTRUCT); kb.scanCode } } -pub unsafe fn get_point(lpdata: LPARAM) -> (LONG, LONG) { +pub unsafe fn get_point(lpdata: LPARAM) -> (i32, i32) { unsafe { let mouse = *(lpdata as *const MSLLHOOKSTRUCT); (mouse.pt.x, mouse.pt.y) } } // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644986(v=vs.85) -/// confusingly, this function returns a WORD (unsigned), but may be +/// confusingly, this function returns a u16 (unsigned), but may be /// interpreted as either signed or unsigned depending on context -pub unsafe fn get_delta(lpdata: LPARAM) -> WORD { +pub unsafe fn get_delta(lpdata: LPARAM) -> u16 { unsafe { let mouse = *(lpdata as *const MSLLHOOKSTRUCT); - HIWORD(mouse.mouseData) + (mouse.mouseData >> 16) as u16 } } -pub unsafe fn get_button_code(lpdata: LPARAM) -> WORD { +pub unsafe fn get_button_code(lpdata: LPARAM) -> u16 { unsafe { let mouse = *(lpdata as *const MSLLHOOKSTRUCT); - HIWORD(mouse.mouseData) + (mouse.mouseData >> 16) as u16 } } @@ -96,13 +94,13 @@ pub unsafe fn convert(param: WPARAM, lpdata: LPARAM) -> Option { let delta = get_delta(lpdata) as c_short; Some(EventType::Wheel { delta_x: 0, - delta_y: (delta / WHEEL_DELTA) as i64, + delta_y: (delta / WHEEL_DELTA as c_short) as i64, }) } Ok(WM_MOUSEHWHEEL) => { let delta = get_delta(lpdata) as c_short; Some(EventType::Wheel { - delta_x: (delta / WHEEL_DELTA) as i64, + delta_x: (delta / WHEEL_DELTA as c_short) as i64, delta_y: 0, }) } @@ -113,8 +111,8 @@ pub unsafe fn convert(param: WPARAM, lpdata: LPARAM) -> Option { type RawCallback = unsafe extern "system" fn(code: c_int, param: WPARAM, lpdata: LPARAM) -> LRESULT; pub enum HookError { - Mouse(DWORD), - Key(DWORD), + Mouse(u32), + Key(u32), } pub unsafe fn set_key_hook(callback: RawCallback) -> Result<(), HookError> { diff --git a/src/windows/display.rs b/src/windows/display.rs index c7db82f6..3ab721c6 100644 --- a/src/windows/display.rs +++ b/src/windows/display.rs @@ -1,6 +1,6 @@ use crate::rdev::DisplayError; use std::convert::TryInto; -use winapi::um::winuser::{GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN}; +use windows_sys::Win32::UI::WindowsAndMessaging::{GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN}; pub fn display_size() -> Result<(u64, u64), DisplayError> { let w = unsafe { diff --git a/src/windows/grab.rs b/src/windows/grab.rs index 45a5664e..131d16ef 100644 --- a/src/windows/grab.rs +++ b/src/windows/grab.rs @@ -2,13 +2,13 @@ use crate::rdev::{Event, EventType, GrabError}; use crate::windows::common::{HOOK, HookError, KEYBOARD, convert, set_key_hook, set_mouse_hook}; use std::ptr::null_mut; use std::time::SystemTime; -use winapi::um::winuser::{CallNextHookEx, GetMessageA, HC_ACTION}; +use windows_sys::Win32::UI::WindowsAndMessaging::{CallNextHookEx, GetMessageA, HC_ACTION}; static mut GLOBAL_CALLBACK: Option Option>> = None; unsafe extern "system" fn raw_callback(code: i32, param: usize, lpdata: isize) -> isize { unsafe { - if code == HC_ACTION { + if code == HC_ACTION as i32 { let opt = convert(param, lpdata); if let Some(event_type) = opt { let name = match &event_type { @@ -24,14 +24,14 @@ unsafe extern "system" fn raw_callback(code: i32, param: usize, lpdata: isize) - name, }; let ptr = &raw mut GLOBAL_CALLBACK; - if let Some(callback) = &mut *ptr { - if callback(event).is_none() { - // https://stackoverflow.com/questions/42756284/blocking-windows-mouse-click-using-setwindowshookex - // https://android.developreference.com/article/14560004/Blocking+windows+mouse+click+using+SetWindowsHookEx() - // https://cboard.cprogramming.com/windows-programming/99678-setwindowshookex-wm_keyboard_ll.html - // let _result = CallNextHookEx(HOOK, code, param, lpdata); - return 1; - } + if let Some(callback) = &mut *ptr + && callback(event).is_none() + { + // https://stackoverflow.com/questions/42756284/blocking-windows-mouse-click-using-setwindowshookex + // https://android.developreference.com/article/14560004/Blocking+windows+mouse+click+using+SetWindowsHookEx() + // https://cboard.cprogramming.com/windows-programming/99678-setwindowshookex-wm_keyboard_ll.html + // let _result = CallNextHookEx(HOOK, code, param, lpdata); + return 1; } } } diff --git a/src/windows/keyboard.rs b/src/windows/keyboard.rs index 18f07abb..71671b06 100644 --- a/src/windows/keyboard.rs +++ b/src/windows/keyboard.rs @@ -2,13 +2,13 @@ use crate::rdev::{EventType, Key, KeyboardState}; use crate::windows::common::{FALSE, TRUE, get_code, get_scan_code}; use crate::windows::keycodes::code_from_key; use std::ptr::null_mut; -use winapi::shared::minwindef::{BYTE, HKL, LPARAM, UINT}; -use winapi::um::processthreadsapi::GetCurrentThreadId; -use winapi::um::winuser; -use winapi::um::winuser::{ - GetForegroundWindow, GetKeyState, GetKeyboardLayout, GetKeyboardState, - GetWindowThreadProcessId, ToUnicodeEx, VK_CAPITAL, VK_LSHIFT, VK_RSHIFT, VK_SHIFT, +use windows_sys::Win32::Foundation::LPARAM; +use windows_sys::Win32::System::Threading::{AttachThreadInput, GetCurrentThreadId}; +use windows_sys::Win32::UI::Input::KeyboardAndMouse::{ + GetKeyState, GetKeyboardLayout, GetKeyboardState, HKL, ToUnicodeEx, VK_CAPITAL, VK_LSHIFT, + VK_RSHIFT, VK_SHIFT, }; +use windows_sys::Win32::UI::WindowsAndMessaging::{GetForegroundWindow, GetWindowThreadProcessId}; const VK_SHIFT_: usize = VK_SHIFT as usize; const VK_CAPITAL_: usize = VK_CAPITAL as usize; @@ -17,9 +17,9 @@ const VK_RSHIFT_: usize = VK_RSHIFT as usize; const HIGHBIT: u8 = 0x80; pub struct Keyboard { - last_code: UINT, - last_scan_code: UINT, - last_state: [BYTE; 256], + last_code: u32, + last_scan_code: u32, + last_state: [u8; 256], last_is_dead: bool, } @@ -50,23 +50,22 @@ impl Keyboard { let mut state = [0_u8; 256]; let state_ptr = state.as_mut_ptr(); - let _shift = GetKeyState(VK_SHIFT); + let _shift = GetKeyState(VK_SHIFT as i32); let current_window_thread_id = GetWindowThreadProcessId(GetForegroundWindow(), null_mut()); let thread_id = GetCurrentThreadId(); // Attach to active thread so we can get that keyboard state - let status = - if winuser::AttachThreadInput(thread_id, current_window_thread_id, TRUE) == 1 { - // Current state of the modifiers in keyboard - let status = GetKeyboardState(state_ptr); - - // Detach - winuser::AttachThreadInput(thread_id, current_window_thread_id, FALSE); - status - } else { - // Could not attach, perhaps it is this process? - GetKeyboardState(state_ptr) - }; + let status = if AttachThreadInput(thread_id, current_window_thread_id, TRUE) == 1 { + // Current state of the modifiers in keyboard + let status = GetKeyboardState(state_ptr); + + // Detach + AttachThreadInput(thread_id, current_window_thread_id, FALSE); + status + } else { + // Could not attach, perhaps it is this process? + GetKeyboardState(state_ptr) + }; if status != 1 { return None; @@ -76,7 +75,7 @@ impl Keyboard { } } - pub(crate) unsafe fn get_code_name(&mut self, code: UINT, scan_code: UINT) -> Option { + pub(crate) unsafe fn get_code_name(&mut self, code: u32, scan_code: u32) -> Option { unsafe { let current_window_thread_id = GetWindowThreadProcessId(GetForegroundWindow(), null_mut()); @@ -122,7 +121,7 @@ impl Keyboard { } } - unsafe fn clear_keyboard_buffer(&self, code: UINT, scan_code: UINT, layout: HKL) { + unsafe fn clear_keyboard_buffer(&self, code: u32, scan_code: u32, layout: HKL) { unsafe { const BUF_LEN: i32 = 32; let mut buff = [0_u16; BUF_LEN as usize]; diff --git a/src/windows/keycodes.rs b/src/windows/keycodes.rs index caa0b3a3..15708d13 100644 --- a/src/windows/keycodes.rs +++ b/src/windows/keycodes.rs @@ -1,11 +1,10 @@ use crate::rdev::Key; use std::convert::TryInto; -use winapi::shared::minwindef::WORD; macro_rules! decl_keycodes { ($($key:ident, $code:literal),*) => { //TODO: make const when rust lang issue #49146 is fixed - pub fn code_from_key(key: Key) -> Option { + pub fn code_from_key(key: Key) -> Option { match key { $( Key::$key => Some($code), @@ -16,7 +15,7 @@ macro_rules! decl_keycodes { } //TODO: make const when rust lang issue #49146 is fixed - pub fn key_from_code(code: WORD) -> Key { + pub fn key_from_code(code: u16) -> Key { match code { $( $code => Key::$key, @@ -28,7 +27,7 @@ macro_rules! decl_keycodes { } // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes -// We redefined here for Letter and number keys which are not in winapi crate (and don't have a name either in win32) +// We redefined here for letter and number keys which do not have named Win32 constants. decl_keycodes! { Alt, 164, AltGr, 165, diff --git a/src/windows/listen.rs b/src/windows/listen.rs index f5c2e733..e2686029 100644 --- a/src/windows/listen.rs +++ b/src/windows/listen.rs @@ -3,8 +3,8 @@ use crate::windows::common::{HOOK, HookError, KEYBOARD, convert, set_key_hook, s use std::os::raw::c_int; use std::ptr::null_mut; use std::time::SystemTime; -use winapi::shared::minwindef::{LPARAM, LRESULT, WPARAM}; -use winapi::um::winuser::{CallNextHookEx, GetMessageA, HC_ACTION}; +use windows_sys::Win32::Foundation::{LPARAM, LRESULT, WPARAM}; +use windows_sys::Win32::UI::WindowsAndMessaging::{CallNextHookEx, GetMessageA, HC_ACTION}; static mut GLOBAL_CALLBACK: Option> = None; @@ -19,7 +19,7 @@ impl From for ListenError { unsafe extern "system" fn raw_callback(code: c_int, param: WPARAM, lpdata: LPARAM) -> LRESULT { unsafe { - if code == HC_ACTION { + if code == HC_ACTION as c_int { let opt = convert(param, lpdata); if let Some(event_type) = opt { let name = match &event_type { diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 8ef404f3..b58ecf0a 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -1,5 +1,3 @@ -extern crate winapi; - mod common; mod display; #[cfg(feature = "unstable_grab")] diff --git a/src/windows/simulate.rs b/src/windows/simulate.rs index 4ebcdf2d..8e96344a 100644 --- a/src/windows/simulate.rs +++ b/src/windows/simulate.rs @@ -2,38 +2,39 @@ use crate::rdev::{Button, EventType, SimulateError}; use crate::windows::keycodes::code_from_key; use std::convert::TryFrom; use std::mem::size_of; -use winapi::ctypes::{c_int, c_short}; -use winapi::shared::minwindef::{DWORD, UINT, WORD}; -use winapi::shared::ntdef::LONG; -use winapi::um::winuser::{ - GetSystemMetrics, INPUT, INPUT_KEYBOARD, INPUT_MOUSE, INPUT_u, KEYBDINPUT, KEYEVENTF_KEYUP, - MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, - MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, - MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK, MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, - MOUSEEVENTF_XUP, MOUSEINPUT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SendInput, WHEEL_DELTA, +use std::os::raw::{c_int, c_short}; +use windows_sys::Win32::UI::Input::KeyboardAndMouse::{ + INPUT, INPUT_0, INPUT_KEYBOARD, INPUT_MOUSE, KEYBDINPUT, KEYEVENTF_KEYUP, MOUSEEVENTF_ABSOLUTE, + MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, + MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, + MOUSEEVENTF_VIRTUALDESK, MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP, MOUSEINPUT, + SendInput, }; +use windows_sys::Win32::UI::WindowsAndMessaging::{ + GetSystemMetrics, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, WHEEL_DELTA, +}; + /// Not defined in win32 but define here for clarity -static KEYEVENTF_KEYDOWN: DWORD = 0; +static KEYEVENTF_KEYDOWN: u32 = 0; -fn sim_mouse_event(flags: DWORD, data: DWORD, dx: LONG, dy: LONG) -> Result<(), SimulateError> { - let mut union: INPUT_u = unsafe { std::mem::zeroed() }; - let inner_union = unsafe { union.mi_mut() }; - *inner_union = MOUSEINPUT { - dx, - dy, - mouseData: data, - dwFlags: flags, - time: 0, - dwExtraInfo: 0, - }; - let mut input = [INPUT { - type_: INPUT_MOUSE, - u: union, +fn sim_mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> Result<(), SimulateError> { + let input = [INPUT { + r#type: INPUT_MOUSE, + Anonymous: INPUT_0 { + mi: MOUSEINPUT { + dx, + dy, + mouseData: data, + dwFlags: flags, + time: 0, + dwExtraInfo: 0, + }, + }, }; 1]; let value = unsafe { SendInput( - input.len() as UINT, - input.as_mut_ptr(), + input.len() as u32, + input.as_ptr(), size_of::() as c_int, ) }; @@ -44,24 +45,23 @@ fn sim_mouse_event(flags: DWORD, data: DWORD, dx: LONG, dy: LONG) -> Result<(), } } -fn sim_keyboard_event(flags: DWORD, vk: WORD, scan: WORD) -> Result<(), SimulateError> { - let mut union: INPUT_u = unsafe { std::mem::zeroed() }; - let inner_union = unsafe { union.ki_mut() }; - *inner_union = KEYBDINPUT { - wVk: vk, - wScan: scan, - dwFlags: flags, - time: 0, - dwExtraInfo: 0, - }; - let mut input = [INPUT { - type_: INPUT_KEYBOARD, - u: union, +fn sim_keyboard_event(flags: u32, vk: u16, scan: u16) -> Result<(), SimulateError> { + let input = [INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: vk, + wScan: scan, + dwFlags: flags, + time: 0, + dwExtraInfo: 0, + }, + }, }; 1]; let value = unsafe { SendInput( - input.len() as UINT, - input.as_mut_ptr(), + input.len() as u32, + input.as_ptr(), size_of::() as c_int, ) }; @@ -98,7 +98,8 @@ pub fn simulate(event_type: &EventType) -> Result<(), SimulateError> { if *delta_x != 0 { sim_mouse_event( MOUSEEVENTF_HWHEEL, - (c_short::try_from(*delta_x).map_err(|_| SimulateError)? * WHEEL_DELTA) as u32, + (c_short::try_from(*delta_x).map_err(|_| SimulateError)? + * WHEEL_DELTA as c_short) as u32, 0, 0, )?; @@ -107,7 +108,8 @@ pub fn simulate(event_type: &EventType) -> Result<(), SimulateError> { if *delta_y != 0 { sim_mouse_event( MOUSEEVENTF_WHEEL, - (c_short::try_from(*delta_y).map_err(|_| SimulateError)? * WHEEL_DELTA) as u32, + (c_short::try_from(*delta_y).map_err(|_| SimulateError)? + * WHEEL_DELTA as c_short) as u32, 0, 0, )?;