update
This commit is contained in:
		
							parent
							
								
									ea09dc582d
								
							
						
					
					
						commit
						33d06b9cf8
					
				| @ -9,7 +9,7 @@ edition = "2018" | |||||||
| [dependencies] | [dependencies] | ||||||
| serde = { version = "1.0.117", optional = true } | serde = { version = "1.0.117", optional = true } | ||||||
| serde_derive = { version = "1.0.117", optional = true } | serde_derive = { version = "1.0.117", optional = true } | ||||||
| lazy_static = "1.4.0" | once_cell = "1.5.2" | ||||||
| 
 | 
 | ||||||
| [features] | [features] | ||||||
| with_serde = ["serde", "serde_derive"] | with_serde = ["serde", "serde_derive"] | ||||||
|  | |||||||
| @ -1,280 +1,277 @@ | |||||||
| use crate::windows; | use crate::windows; | ||||||
| use crate::{Event, EventType, HookCallback, Key, Robot}; | use crate::{Event, EventType, HookCallback, Key, Robot}; | ||||||
| use lazy_static::lazy_static; | use once_cell::sync::Lazy; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| use std::convert::TryInto; |  | ||||||
| use std::mem::{size_of, transmute_copy}; | use std::mem::{size_of, transmute_copy}; | ||||||
| use std::ptr::null_mut; | use std::ptr::null_mut; | ||||||
|  | use std::sync::atomic::{AtomicPtr, Ordering}; | ||||||
| use std::time::SystemTime; | use std::time::SystemTime; | ||||||
| use winapi::ctypes::c_int; | use winapi::ctypes::c_int; | ||||||
| use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM}; | use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM}; | ||||||
| use winapi::shared::windef::HHOOK; | use winapi::shared::windef::HHOOK__; | ||||||
| use winapi::um::winuser::{ | use winapi::um::winuser::{ | ||||||
|   CallNextHookEx, GetAsyncKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT, INPUT_KEYBOARD, |   CallNextHookEx, GetAsyncKeyState, GetKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT, | ||||||
|   KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT, WH_KEYBOARD_LL, |   INPUT_KEYBOARD, KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT, | ||||||
|   WM_KEYDOWN, WM_KEYUP, |   WH_KEYBOARD_LL, WM_KEYDOWN, WM_KEYUP, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| lazy_static! { | static KEY_2_VK_MAP: Lazy<HashMap<Key, WORD>> = Lazy::new(|| { | ||||||
|   static ref KEY_2_VK_MAP: HashMap<Key, WORD> = { |   let mut m = HashMap::new(); | ||||||
|     let mut m = HashMap::new(); |   m.insert(Key::Digit0, 0x30); | ||||||
|     m.insert(Key::Digit0 , 0x30); |   m.insert(Key::Digit1, 0x31); | ||||||
|     m.insert(Key::Digit1 , 0x31); |   m.insert(Key::Digit2, 0x32); | ||||||
|     m.insert(Key::Digit2 , 0x32); |   m.insert(Key::Digit3, 0x33); | ||||||
|     m.insert(Key::Digit3 , 0x33); |   m.insert(Key::Digit4, 0x34); | ||||||
|     m.insert(Key::Digit4 , 0x34); |   m.insert(Key::Digit5, 0x35); | ||||||
|     m.insert(Key::Digit5 , 0x35); |   m.insert(Key::Digit6, 0x36); | ||||||
|     m.insert(Key::Digit6 , 0x36); |   m.insert(Key::Digit7, 0x37); | ||||||
|     m.insert(Key::Digit7 , 0x37); |   m.insert(Key::Digit8, 0x38); | ||||||
|     m.insert(Key::Digit8 , 0x38); |   m.insert(Key::Digit9, 0x39); | ||||||
|     m.insert(Key::Digit9 , 0x39); |   m.insert(Key::KeyA, 0x41); | ||||||
|     m.insert(Key::KeyA , 0x41); |   m.insert(Key::KeyB, 0x42); | ||||||
|     m.insert(Key::KeyB , 0x42); |   m.insert(Key::KeyC, 0x43); | ||||||
|     m.insert(Key::KeyC , 0x43); |   m.insert(Key::KeyD, 0x44); | ||||||
|     m.insert(Key::KeyD , 0x44); |   m.insert(Key::KeyE, 0x45); | ||||||
|     m.insert(Key::KeyE , 0x45); |   m.insert(Key::KeyF, 0x46); | ||||||
|     m.insert(Key::KeyF , 0x46); |   m.insert(Key::KeyG, 0x47); | ||||||
|     m.insert(Key::KeyG , 0x47); |   m.insert(Key::KeyH, 0x48); | ||||||
|     m.insert(Key::KeyH , 0x48); |   m.insert(Key::KeyI, 0x49); | ||||||
|     m.insert(Key::KeyI , 0x49); |   m.insert(Key::KeyJ, 0x4A); | ||||||
|     m.insert(Key::KeyJ , 0x4A); |   m.insert(Key::KeyK, 0x4B); | ||||||
|     m.insert(Key::KeyK , 0x4B); |   m.insert(Key::KeyL, 0x4C); | ||||||
|     m.insert(Key::KeyL , 0x4C); |   m.insert(Key::KeyM, 0x4D); | ||||||
|     m.insert(Key::KeyM , 0x4D); |   m.insert(Key::KeyN, 0x4E); | ||||||
|     m.insert(Key::KeyN , 0x4E); |   m.insert(Key::KeyO, 0x4F); | ||||||
|     m.insert(Key::KeyO , 0x4F); |   m.insert(Key::KeyP, 0x50); | ||||||
|     m.insert(Key::KeyP , 0x50); |   m.insert(Key::KeyQ, 0x51); | ||||||
|     m.insert(Key::KeyQ , 0x51); |   m.insert(Key::KeyR, 0x52); | ||||||
|     m.insert(Key::KeyR , 0x52); |   m.insert(Key::KeyS, 0x53); | ||||||
|     m.insert(Key::KeyS , 0x53); |   m.insert(Key::KeyT, 0x54); | ||||||
|     m.insert(Key::KeyT , 0x54); |   m.insert(Key::KeyU, 0x55); | ||||||
|     m.insert(Key::KeyU , 0x55); |   m.insert(Key::KeyV, 0x56); | ||||||
|     m.insert(Key::KeyV , 0x56); |   m.insert(Key::KeyW, 0x57); | ||||||
|     m.insert(Key::KeyW , 0x57); |   m.insert(Key::KeyX, 0x58); | ||||||
|     m.insert(Key::KeyX , 0x58); |   m.insert(Key::KeyY, 0x59); | ||||||
|     m.insert(Key::KeyY , 0x59); |   m.insert(Key::KeyZ, 0x5A); | ||||||
|     m.insert(Key::KeyZ , 0x5A); |   m.insert(Key::F1, 0x70); | ||||||
|     m.insert(Key::F1 , 0x70); |   m.insert(Key::F2, 0x71); | ||||||
|     m.insert(Key::F2 , 0x71); |   m.insert(Key::F3, 0x72); | ||||||
|     m.insert(Key::F3 , 0x72); |   m.insert(Key::F4, 0x73); | ||||||
|     m.insert(Key::F4 , 0x73); |   m.insert(Key::F5, 0x74); | ||||||
|     m.insert(Key::F5 , 0x74); |   m.insert(Key::F6, 0x75); | ||||||
|     m.insert(Key::F6 , 0x75); |   m.insert(Key::F7, 0x76); | ||||||
|     m.insert(Key::F7 , 0x76); |   m.insert(Key::F8, 0x77); | ||||||
|     m.insert(Key::F8 , 0x77); |   m.insert(Key::F9, 0x78); | ||||||
|     m.insert(Key::F9 , 0x78); |   m.insert(Key::F10, 0x79); | ||||||
|     m.insert(Key::F10 , 0x79); |   m.insert(Key::F11, 0x7A); | ||||||
|     m.insert(Key::F11 , 0x7A); |   m.insert(Key::F12, 0x7B); | ||||||
|     m.insert(Key::F12 , 0x7B); |   m.insert(Key::F13, 0x7C); | ||||||
|     m.insert(Key::F13 , 0x7C); |   m.insert(Key::F14, 0x7D); | ||||||
|     m.insert(Key::F14 , 0x7D); |   m.insert(Key::F15, 0x7E); | ||||||
|     m.insert(Key::F15 , 0x7E); |   m.insert(Key::F16, 0x7F); | ||||||
|     m.insert(Key::F16 , 0x7F); |   m.insert(Key::F17, 0x80); | ||||||
|     m.insert(Key::F17 , 0x80); |   m.insert(Key::F18, 0x81); | ||||||
|     m.insert(Key::F18 , 0x81); |   m.insert(Key::F19, 0x82); | ||||||
|     m.insert(Key::F19 , 0x82); |   m.insert(Key::F20, 0x83); | ||||||
|     m.insert(Key::F20 , 0x83); |   m.insert(Key::F21, 0x84); | ||||||
|     m.insert(Key::F21 , 0x84); |   m.insert(Key::F22, 0x85); | ||||||
|     m.insert(Key::F22 , 0x85); |   m.insert(Key::F23, 0x86); | ||||||
|     m.insert(Key::F23 , 0x86); |   m.insert(Key::F24, 0x87); | ||||||
|     m.insert(Key::F24 , 0x87); |   m.insert(Key::Numpad0, 0x60); | ||||||
|     m.insert(Key::Numpad0 , 0x60); |   m.insert(Key::Numpad1, 0x61); | ||||||
|     m.insert(Key::Numpad1 , 0x61); |   m.insert(Key::Numpad2, 0x62); | ||||||
|     m.insert(Key::Numpad2 , 0x62); |   m.insert(Key::Numpad3, 0x63); | ||||||
|     m.insert(Key::Numpad3 , 0x63); |   m.insert(Key::Numpad4, 0x64); | ||||||
|     m.insert(Key::Numpad4 , 0x64); |   m.insert(Key::Numpad5, 0x65); | ||||||
|     m.insert(Key::Numpad5 , 0x65); |   m.insert(Key::Numpad6, 0x66); | ||||||
|     m.insert(Key::Numpad6 , 0x66); |   m.insert(Key::Numpad7, 0x67); | ||||||
|     m.insert(Key::Numpad7 , 0x67); |   m.insert(Key::Numpad8, 0x68); | ||||||
|     m.insert(Key::Numpad8 , 0x68); |   m.insert(Key::Numpad9, 0x69); | ||||||
|     m.insert(Key::Numpad9 , 0x69); |   m.insert(Key::NumpadAdd, 0x6B); // Add
 | ||||||
|     m.insert(Key::NumpadAdd , 0x6B);      // Add
 |   m.insert(Key::NumpadSubtract, 0x6D); // Subtract
 | ||||||
|     m.insert(Key::NumpadSubtract , 0x6D); // Subtract
 |   m.insert(Key::NumpadMultiply, 0x6A); // Multiply
 | ||||||
|     m.insert(Key::NumpadMultiply , 0x6A); // Multiply
 |   m.insert(Key::NumpadDivide, 0x6F); // Divide
 | ||||||
|     m.insert(Key::NumpadDivide , 0x6F);   // Divide
 |   m.insert(Key::NumpadDecimal, 0x6E); // Decimal
 | ||||||
|     m.insert(Key::NumpadDecimal , 0x6E);  // Decimal
 |   m.insert(Key::NumpadEqual, '=' as u16); | ||||||
|     m.insert(Key::NumpadEqual , '=' as u16); |   m.insert(Key::NumpadComma, ',' as u16); | ||||||
|     m.insert(Key::NumpadComma , ',' as u16); |   m.insert(Key::NumpadEnter, 0x0D); | ||||||
|     m.insert(Key::NumpadEnter , 0x0D); |   m.insert(Key::NumLock, 0x90); | ||||||
|     m.insert(Key::NumLock , 0x90); |   m.insert(Key::Minus, '-' as u16); | ||||||
|     m.insert(Key::Minus , '-' as u16); |   m.insert(Key::Equal, '=' as u16); | ||||||
|     m.insert(Key::Equal , '=' as u16); |   m.insert(Key::BracketLeft, '{' as u16); | ||||||
|     m.insert(Key::BracketLeft , '{' as u16); |   m.insert(Key::BracketRight, '}' as u16); | ||||||
|     m.insert(Key::BracketRight , '}' as u16); |   m.insert(Key::Semicolon, ';' as u16); | ||||||
|     m.insert(Key::Semicolon , ';' as u16); |   m.insert(Key::Quote, '\'' as u16); | ||||||
|     m.insert(Key::Quote , '\'' as u16); |   m.insert(Key::Backquote, '`' as u16); | ||||||
|     m.insert(Key::Backquote , '`' as u16); |   m.insert(Key::Backslash, '\\' as u16); | ||||||
|     m.insert(Key::Backslash , '\\' as u16); |   m.insert(Key::Comma, ',' as u16); | ||||||
|     m.insert(Key::Comma , ',' as u16); |   m.insert(Key::Period, '~' as u16); | ||||||
|     m.insert(Key::Period , '~' as u16); |   m.insert(Key::Slash, '/' as u16); | ||||||
|     m.insert(Key::Slash , '/' as u16); |   m.insert(Key::Escape, 0x1B); | ||||||
|     m.insert(Key::Escape , 0x1B); |   m.insert(Key::Enter, 0x0D); | ||||||
|     m.insert(Key::Enter , 0x0D); |   m.insert(Key::Backspace, 0x08); | ||||||
|     m.insert(Key::Backspace , 0x08); |   m.insert(Key::Tab, 0x09); | ||||||
|     m.insert(Key::Tab , 0x09); |   m.insert(Key::Space, 0x20); | ||||||
|     m.insert(Key::Space , 0x20); |   m.insert(Key::CapsLock, 0x14); | ||||||
|     m.insert(Key::CapsLock , 0x14); |   m.insert(Key::ShiftLeft, 0xA0); | ||||||
|     m.insert(Key::ShiftLeft , 0xA0); |   m.insert(Key::ShiftRight, 0xA1); | ||||||
|     m.insert(Key::ShiftRight , 0xA1); |   m.insert(Key::ControlLeft, 0xA2); | ||||||
|     m.insert(Key::ControlLeft , 0xA2); |   m.insert(Key::ControlRight, 0xA3); | ||||||
|     m.insert(Key::ControlRight , 0xA3); |   m.insert(Key::AltLeft, 0xA4); | ||||||
|     m.insert(Key::AltLeft , 0xA4); |   m.insert(Key::AltRight, 0xA5); | ||||||
|     m.insert(Key::AltRight , 0xA5); |   m.insert(Key::Pause, 0x13); | ||||||
|     m.insert(Key::Pause , 0x13); |   m.insert(Key::ScrollLock, 0x91); | ||||||
|     m.insert(Key::ScrollLock , 0x91); |   m.insert(Key::PrintScreen, 0x2C); | ||||||
|     m.insert(Key::PrintScreen , 0x2C); |   m.insert(Key::ArrowLeft, 0x25); | ||||||
|     m.insert(Key::ArrowLeft , 0x25); |   m.insert(Key::ArrowUp, 0x26); | ||||||
|     m.insert(Key::ArrowUp , 0x26); |   m.insert(Key::ArrowRight, 0x27); | ||||||
|     m.insert(Key::ArrowRight , 0x27); |   m.insert(Key::ArrowDown, 0x28); | ||||||
|     m.insert(Key::ArrowDown , 0x28); |   m.insert(Key::PageUp, 0x21); | ||||||
|     m.insert(Key::PageUp , 0x21); |   m.insert(Key::PageDown, 0x22); | ||||||
|     m.insert(Key::PageDown , 0x22); |   m.insert(Key::Home, 0x24); | ||||||
|     m.insert(Key::Home , 0x24); |   m.insert(Key::End, 0x23); | ||||||
|     m.insert(Key::End , 0x23); |   m.insert(Key::Insert, 0x2D); | ||||||
|     m.insert(Key::Insert , 0x2D); |   m.insert(Key::Delete, 0x2E); | ||||||
|     m.insert(Key::Delete , 0x2E); |   m.insert(Key::MetaLeft, 0x5B); | ||||||
|     m.insert(Key::MetaLeft , 0x5B); |   m.insert(Key::MetaRight, 0x5C); | ||||||
|     m.insert(Key::MetaRight , 0x5C); |   m | ||||||
|     m | }); | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   static ref VK_2_KEY_MAP: HashMap<WORD, Key> = { | static VK_2_KEY_MAP: Lazy<HashMap<WORD, Key>> = Lazy::new(|| { | ||||||
|     let mut m = HashMap::new(); |   let mut m = HashMap::new(); | ||||||
|     m.insert(0x30, Key::Digit0); |   m.insert(0x30, Key::Digit0); | ||||||
|     m.insert(0x31, Key::Digit1); |   m.insert(0x31, Key::Digit1); | ||||||
|     m.insert(0x32, Key::Digit2); |   m.insert(0x32, Key::Digit2); | ||||||
|     m.insert(0x33, Key::Digit3); |   m.insert(0x33, Key::Digit3); | ||||||
|     m.insert(0x34, Key::Digit4); |   m.insert(0x34, Key::Digit4); | ||||||
|     m.insert(0x35, Key::Digit5); |   m.insert(0x35, Key::Digit5); | ||||||
|     m.insert(0x36, Key::Digit6); |   m.insert(0x36, Key::Digit6); | ||||||
|     m.insert(0x37, Key::Digit7); |   m.insert(0x37, Key::Digit7); | ||||||
|     m.insert(0x38, Key::Digit8); |   m.insert(0x38, Key::Digit8); | ||||||
|     m.insert(0x39, Key::Digit9); |   m.insert(0x39, Key::Digit9); | ||||||
|     m.insert(0x41, Key::KeyA); |   m.insert(0x41, Key::KeyA); | ||||||
|     m.insert(0x42, Key::KeyB); |   m.insert(0x42, Key::KeyB); | ||||||
|     m.insert(0x43, Key::KeyC); |   m.insert(0x43, Key::KeyC); | ||||||
|     m.insert(0x44, Key::KeyD); |   m.insert(0x44, Key::KeyD); | ||||||
|     m.insert(0x45, Key::KeyE); |   m.insert(0x45, Key::KeyE); | ||||||
|     m.insert(0x46, Key::KeyF); |   m.insert(0x46, Key::KeyF); | ||||||
|     m.insert(0x47, Key::KeyG); |   m.insert(0x47, Key::KeyG); | ||||||
|     m.insert(0x48, Key::KeyH); |   m.insert(0x48, Key::KeyH); | ||||||
|     m.insert(0x49, Key::KeyI); |   m.insert(0x49, Key::KeyI); | ||||||
|     m.insert(0x4A, Key::KeyJ); |   m.insert(0x4A, Key::KeyJ); | ||||||
|     m.insert(0x4B, Key::KeyK); |   m.insert(0x4B, Key::KeyK); | ||||||
|     m.insert(0x4C, Key::KeyL); |   m.insert(0x4C, Key::KeyL); | ||||||
|     m.insert(0x4D, Key::KeyM); |   m.insert(0x4D, Key::KeyM); | ||||||
|     m.insert(0x4E, Key::KeyN); |   m.insert(0x4E, Key::KeyN); | ||||||
|     m.insert(0x4F, Key::KeyO); |   m.insert(0x4F, Key::KeyO); | ||||||
|     m.insert(0x50, Key::KeyP); |   m.insert(0x50, Key::KeyP); | ||||||
|     m.insert(0x51, Key::KeyQ); |   m.insert(0x51, Key::KeyQ); | ||||||
|     m.insert(0x52, Key::KeyR); |   m.insert(0x52, Key::KeyR); | ||||||
|     m.insert(0x53, Key::KeyS); |   m.insert(0x53, Key::KeyS); | ||||||
|     m.insert(0x54, Key::KeyT); |   m.insert(0x54, Key::KeyT); | ||||||
|     m.insert(0x55, Key::KeyU); |   m.insert(0x55, Key::KeyU); | ||||||
|     m.insert(0x56, Key::KeyV); |   m.insert(0x56, Key::KeyV); | ||||||
|     m.insert(0x57, Key::KeyW); |   m.insert(0x57, Key::KeyW); | ||||||
|     m.insert(0x58, Key::KeyX); |   m.insert(0x58, Key::KeyX); | ||||||
|     m.insert(0x59, Key::KeyY); |   m.insert(0x59, Key::KeyY); | ||||||
|     m.insert(0x5A, Key::KeyZ); |   m.insert(0x5A, Key::KeyZ); | ||||||
|     m.insert(0x70, Key::F1); |   m.insert(0x70, Key::F1); | ||||||
|     m.insert(0x71, Key::F2); |   m.insert(0x71, Key::F2); | ||||||
|     m.insert(0x72, Key::F3); |   m.insert(0x72, Key::F3); | ||||||
|     m.insert(0x73, Key::F4); |   m.insert(0x73, Key::F4); | ||||||
|     m.insert(0x74, Key::F5); |   m.insert(0x74, Key::F5); | ||||||
|     m.insert(0x75, Key::F6); |   m.insert(0x75, Key::F6); | ||||||
|     m.insert(0x76, Key::F7); |   m.insert(0x76, Key::F7); | ||||||
|     m.insert(0x77, Key::F8); |   m.insert(0x77, Key::F8); | ||||||
|     m.insert(0x78, Key::F9); |   m.insert(0x78, Key::F9); | ||||||
|     m.insert(0x79, Key::F10); |   m.insert(0x79, Key::F10); | ||||||
|     m.insert(0x7A, Key::F11); |   m.insert(0x7A, Key::F11); | ||||||
|     m.insert(0x7B, Key::F12); |   m.insert(0x7B, Key::F12); | ||||||
|     m.insert(0x7C, Key::F13); |   m.insert(0x7C, Key::F13); | ||||||
|     m.insert(0x7D, Key::F14); |   m.insert(0x7D, Key::F14); | ||||||
|     m.insert(0x7E, Key::F15); |   m.insert(0x7E, Key::F15); | ||||||
|     m.insert(0x7F, Key::F16); |   m.insert(0x7F, Key::F16); | ||||||
|     m.insert(0x80, Key::F17); |   m.insert(0x80, Key::F17); | ||||||
|     m.insert(0x81, Key::F18); |   m.insert(0x81, Key::F18); | ||||||
|     m.insert(0x82, Key::F19); |   m.insert(0x82, Key::F19); | ||||||
|     m.insert(0x83, Key::F20); |   m.insert(0x83, Key::F20); | ||||||
|     m.insert(0x84, Key::F21); |   m.insert(0x84, Key::F21); | ||||||
|     m.insert(0x85, Key::F22); |   m.insert(0x85, Key::F22); | ||||||
|     m.insert(0x86, Key::F23); |   m.insert(0x86, Key::F23); | ||||||
|     m.insert(0x87, Key::F24); |   m.insert(0x87, Key::F24); | ||||||
|     m.insert(0x60, Key::Numpad0); |   m.insert(0x60, Key::Numpad0); | ||||||
|     m.insert(0x61, Key::Numpad1); |   m.insert(0x61, Key::Numpad1); | ||||||
|     m.insert(0x62, Key::Numpad2); |   m.insert(0x62, Key::Numpad2); | ||||||
|     m.insert(0x63, Key::Numpad3); |   m.insert(0x63, Key::Numpad3); | ||||||
|     m.insert(0x64, Key::Numpad4); |   m.insert(0x64, Key::Numpad4); | ||||||
|     m.insert(0x65, Key::Numpad5); |   m.insert(0x65, Key::Numpad5); | ||||||
|     m.insert(0x66, Key::Numpad6); |   m.insert(0x66, Key::Numpad6); | ||||||
|     m.insert(0x67, Key::Numpad7); |   m.insert(0x67, Key::Numpad7); | ||||||
|     m.insert(0x68, Key::Numpad8); |   m.insert(0x68, Key::Numpad8); | ||||||
|     m.insert(0x69, Key::Numpad9); |   m.insert(0x69, Key::Numpad9); | ||||||
|     m.insert(0x6B, Key::NumpadAdd);      // Add
 |   m.insert(0x6B, Key::NumpadAdd); // Add
 | ||||||
|     m.insert(0x6D, Key::NumpadSubtract); // Subtract
 |   m.insert(0x6D, Key::NumpadSubtract); // Subtract
 | ||||||
|     m.insert(0x6A, Key::NumpadMultiply); // Multiply
 |   m.insert(0x6A, Key::NumpadMultiply); // Multiply
 | ||||||
|     m.insert(0x6F, Key::NumpadDivide);   // Divide
 |   m.insert(0x6F, Key::NumpadDivide); // Divide
 | ||||||
|     m.insert(0x6E, Key::NumpadDecimal);  // Decimal
 |   m.insert(0x6E, Key::NumpadDecimal); // Decimal
 | ||||||
|     m.insert( 0x0D, Key::NumpadEnter); |   m.insert(0x0D, Key::NumpadEnter); | ||||||
|     m.insert( 0x90, Key::NumLock); |   m.insert(0x90, Key::NumLock); | ||||||
|     m.insert('-' as u16, Key::Minus); |   m.insert('-' as u16, Key::Minus); | ||||||
|     m.insert('=' as u16, Key::Equal); |   m.insert('=' as u16, Key::Equal); | ||||||
|     m.insert('{' as u16, Key::BracketLeft); |   m.insert('{' as u16, Key::BracketLeft); | ||||||
|     m.insert('}' as u16, Key::BracketRight); |   m.insert('}' as u16, Key::BracketRight); | ||||||
|     m.insert(';' as u16, Key::Semicolon); |   m.insert(';' as u16, Key::Semicolon); | ||||||
|     m.insert('\'' as u16, Key::Quote); |   m.insert('\'' as u16, Key::Quote); | ||||||
|     m.insert('`' as u16, Key::Backquote); |   m.insert('`' as u16, Key::Backquote); | ||||||
|     m.insert('\\' as u16, Key::Backslash); |   m.insert('\\' as u16, Key::Backslash); | ||||||
|     m.insert(',' as u16, Key::Comma); |   m.insert(',' as u16, Key::Comma); | ||||||
|     m.insert('~' as u16, Key::Period); |   m.insert('~' as u16, Key::Period); | ||||||
|     m.insert('/' as u16, Key::Slash); |   m.insert('/' as u16, Key::Slash); | ||||||
|     m.insert(0x1B, Key::Escape); |   m.insert(0x1B, Key::Escape); | ||||||
|     m.insert( 0x0D, Key::Enter); |   m.insert(0x0D, Key::Enter); | ||||||
|     m.insert( 0x08, Key::Backspace); |   m.insert(0x08, Key::Backspace); | ||||||
|     m.insert( 0x09, Key::Tab); |   m.insert(0x09, Key::Tab); | ||||||
|     m.insert( 0x20, Key::Space); |   m.insert(0x20, Key::Space); | ||||||
|     m.insert(0x14, Key::CapsLock); |   m.insert(0x14, Key::CapsLock); | ||||||
|     m.insert(0xA0, Key::ShiftLeft); |   m.insert(0xA0, Key::ShiftLeft); | ||||||
|     m.insert(0xA1, Key::ShiftRight); |   m.insert(0xA1, Key::ShiftRight); | ||||||
|     m.insert( 0xA2, Key::ControlLeft); |   m.insert(0xA2, Key::ControlLeft); | ||||||
|     m.insert( 0xA3, Key::ControlRight); |   m.insert(0xA3, Key::ControlRight); | ||||||
|     m.insert( 0xA4, Key::AltLeft); |   m.insert(0xA4, Key::AltLeft); | ||||||
|     m.insert(0xA5, Key::AltRight); |   m.insert(0xA5, Key::AltRight); | ||||||
|     m.insert(0x13, Key::Pause); |   m.insert(0x13, Key::Pause); | ||||||
|     m.insert(0x91, Key::ScrollLock); |   m.insert(0x91, Key::ScrollLock); | ||||||
|     m.insert(0x2C, Key::PrintScreen); |   m.insert(0x2C, Key::PrintScreen); | ||||||
|     m.insert(0x25, Key::ArrowLeft); |   m.insert(0x25, Key::ArrowLeft); | ||||||
|     m.insert(0x26, Key::ArrowUp); |   m.insert(0x26, Key::ArrowUp); | ||||||
|     m.insert(0x27, Key::ArrowRight); |   m.insert(0x27, Key::ArrowRight); | ||||||
|     m.insert(0x28, Key::ArrowDown); |   m.insert(0x28, Key::ArrowDown); | ||||||
|     m.insert(0x21, Key::PageUp); |   m.insert(0x21, Key::PageUp); | ||||||
|     m.insert(0x22, Key::PageDown); |   m.insert(0x22, Key::PageDown); | ||||||
|     m.insert( 0x24, Key::Home); |   m.insert(0x24, Key::Home); | ||||||
|     m.insert( 0x23, Key::End); |   m.insert(0x23, Key::End); | ||||||
|     m.insert(0x2D, Key::Insert); |   m.insert(0x2D, Key::Insert); | ||||||
|     m.insert(0x2E, Key::Delete); |   m.insert(0x2E, Key::Delete); | ||||||
|     m.insert(0x5B, Key::MetaLeft); |   m.insert(0x5B, Key::MetaLeft); | ||||||
|     m.insert(0x5C, Key::MetaRight); |   m.insert(0x5C, Key::MetaRight); | ||||||
|     m |   m | ||||||
|   }; | }); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| fn default_callback(event: Event) { | fn default_callback(event: Event) { | ||||||
|   println!("Default : Event {:?}", event); |   println!("Default : Event {:?}", event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static mut HOOK: HHOOK = null_mut(); | static KEYBOARD_HHOOK: Lazy<AtomicPtr<HHOOK__>> = Lazy::new(AtomicPtr::default); | ||||||
| static mut HOOK_CALLBACK: HookCallback = default_callback; | static mut HOOK_CALLBACK: HookCallback = default_callback; | ||||||
| 
 | 
 | ||||||
| impl Robot { | impl Robot { | ||||||
|   pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> { |   pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> { | ||||||
|     if HOOK.is_null() { |     if KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() { | ||||||
|       let r = windows::hook(WH_KEYBOARD_LL, Self::key_raw_callback); |       let r = windows::hook(WH_KEYBOARD_LL, &*KEYBOARD_HHOOK, Self::key_raw_callback); | ||||||
| 
 | 
 | ||||||
|       if r.is_err() { |       if r.is_err() { | ||||||
|         return Err(windows::HookError::Keyboard(r.err().unwrap())); |         return Err(windows::HookError::Keyboard(r.err().unwrap())); | ||||||
|       } |       } | ||||||
|       HOOK = r.ok().unwrap(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HOOK_CALLBACK = callback; |     HOOK_CALLBACK = callback; | ||||||
| @ -283,12 +280,11 @@ impl Robot { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub unsafe fn key_unlisten() -> Result<(), windows::HookError> { |   pub unsafe fn key_unlisten() -> Result<(), windows::HookError> { | ||||||
|     if !HOOK.is_null() { |     if !KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() { | ||||||
|       let r = windows::unhook(HOOK); |       let r = windows::unhook(&*KEYBOARD_HHOOK); | ||||||
|       if r.is_err() { |       if r.is_err() { | ||||||
|         return Err(windows::HookError::Keyboard(r.err().unwrap())); |         return Err(windows::HookError::Keyboard(r.err().unwrap())); | ||||||
|       } |       } | ||||||
|       HOOK = null_mut(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HOOK_CALLBACK = default_callback; |     HOOK_CALLBACK = default_callback; | ||||||
| @ -299,37 +295,13 @@ impl Robot { | |||||||
|   pub fn key_press(key: Key) { |   pub fn key_press(key: Key) { | ||||||
|     let dw_flags = KEYEVENTF_SCANCODE; |     let dw_flags = KEYEVENTF_SCANCODE; | ||||||
| 
 | 
 | ||||||
|     let mut input = INPUT { |     Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags); | ||||||
|       type_: INPUT_KEYBOARD, |  | ||||||
|       u: unsafe { |  | ||||||
|         transmute_copy(&KEYBDINPUT { |  | ||||||
|           wVk: 0, |  | ||||||
|           wScan: Self::key_to_scancode(key), |  | ||||||
|           dwFlags: dw_flags, |  | ||||||
|           time: 0, |  | ||||||
|           dwExtraInfo: 0, |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub fn key_release(key: Key) { |   pub fn key_release(key: Key) { | ||||||
|     let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; |     let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; | ||||||
| 
 | 
 | ||||||
|     let mut input = INPUT { |     Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags); | ||||||
|       type_: INPUT_KEYBOARD, |  | ||||||
|       u: unsafe { |  | ||||||
|         transmute_copy(&KEYBDINPUT { |  | ||||||
|           wVk: 0, |  | ||||||
|           wScan: Self::key_to_scancode(key), |  | ||||||
|           dwFlags: dw_flags, |  | ||||||
|           time: 0, |  | ||||||
|           dwExtraInfo: 0, |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub fn key_pressed(key: Key) -> bool { |   pub fn key_pressed(key: Key) -> bool { | ||||||
| @ -339,6 +311,29 @@ impl Robot { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   pub fn key_toggled(key: Key) -> bool { | ||||||
|  |     match Self::key_2_virtual_key(key) { | ||||||
|  |       Some(vk) => (unsafe { GetKeyState(vk as i32) & 15 != 0 }), | ||||||
|  |       None => false, | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fn keyboard_event(vk: u16, scan: u16, dw_flags: u32) { | ||||||
|  |     let mut input = INPUT { | ||||||
|  |       type_: INPUT_KEYBOARD, | ||||||
|  |       u: unsafe { | ||||||
|  |         transmute_copy(&KEYBDINPUT { | ||||||
|  |           wVk: vk, | ||||||
|  |           wScan: scan, | ||||||
|  |           dwFlags: dw_flags, | ||||||
|  |           time: 0, | ||||||
|  |           dwExtraInfo: 0, | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   fn key_to_scancode(key: Key) -> u16 { |   fn key_to_scancode(key: Key) -> u16 { | ||||||
|     match Self::key_2_virtual_key(key) { |     match Self::key_2_virtual_key(key) { | ||||||
|       Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 }, |       Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 }, | ||||||
| @ -353,11 +348,28 @@ impl Robot { | |||||||
| 
 | 
 | ||||||
|   unsafe extern "system" fn key_raw_callback( |   unsafe extern "system" fn key_raw_callback( | ||||||
|     code: c_int, |     code: c_int, | ||||||
|     param: WPARAM, |     w_param: WPARAM, | ||||||
|     lpdata: LPARAM, |     l_param: LPARAM, | ||||||
|   ) -> LRESULT { |   ) -> LRESULT { | ||||||
|     if code == HC_ACTION { |     if code == HC_ACTION { | ||||||
|       let opt = Self::key_convert(param, lpdata); |       let opt = match w_param as u32 { | ||||||
|  |         WM_KEYDOWN => { | ||||||
|  |           let code = Self::get_virtual_key(l_param); | ||||||
|  |           match Self::virtual_key_2_key(code as u16) { | ||||||
|  |             Some(k) => Some(EventType::KeyPress(k)), | ||||||
|  |             None => None, | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         WM_KEYUP => { | ||||||
|  |           let code = Self::get_virtual_key(l_param); | ||||||
|  |           match Self::virtual_key_2_key(code as u16) { | ||||||
|  |             Some(k) => Some(EventType::KeyRelease(k)), | ||||||
|  |             None => None, | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         _ => None, | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|       if let Some(event_type) = opt { |       if let Some(event_type) = opt { | ||||||
|         let event = Event { |         let event = Event { | ||||||
|           event_type, |           event_type, | ||||||
| @ -366,27 +378,7 @@ impl Robot { | |||||||
|         HOOK_CALLBACK(event); |         HOOK_CALLBACK(event); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     CallNextHookEx(HOOK, code, param, lpdata) |     CallNextHookEx(null_mut(), code, w_param, l_param) | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   unsafe fn key_convert(wparam: WPARAM, lparam: LPARAM) -> Option<EventType> { |  | ||||||
|     match wparam.try_into() { |  | ||||||
|       Ok(WM_KEYDOWN) => { |  | ||||||
|         let code = Self::get_virtual_key(lparam); |  | ||||||
|         match Self::virtual_key_2_key(code as u16) { |  | ||||||
|           Some(k) => Some(EventType::KeyPress(k)), |  | ||||||
|           None => None, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       Ok(WM_KEYUP) => { |  | ||||||
|         let code = Self::get_virtual_key(lparam); |  | ||||||
|         match Self::virtual_key_2_key(code as u16) { |  | ||||||
|           Some(k) => Some(EventType::KeyRelease(k)), |  | ||||||
|           None => None, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       _ => None, |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   fn key_2_virtual_key(key: Key) -> Option<WORD> { |   fn key_2_virtual_key(key: Key) -> Option<WORD> { | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| use std::ptr::null_mut; | use std::ptr::null_mut; | ||||||
|  | use std::sync::atomic::{AtomicPtr, Ordering}; | ||||||
| use winapi::ctypes::c_int; | use winapi::ctypes::c_int; | ||||||
| use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM}; | use winapi::shared::minwindef::{DWORD, HINSTANCE, LPARAM, LRESULT, WPARAM}; | ||||||
| use winapi::shared::windef::HHOOK; | use winapi::shared::windef::HHOOK__; | ||||||
| use winapi::um::errhandlingapi::GetLastError; | use winapi::um::errhandlingapi::GetLastError; | ||||||
| use winapi::um::winuser::{SetWindowsHookExA, UnhookWindowsHookEx}; | use winapi::um::winuser::{SetWindowsHookExW, UnhookWindowsHookEx}; | ||||||
| 
 |  | ||||||
| pub mod keyboard; | pub mod keyboard; | ||||||
| pub mod mouse; | pub mod mouse; | ||||||
| 
 | 
 | ||||||
| @ -16,22 +16,28 @@ pub enum HookError { | |||||||
|   Keyboard(DWORD), |   Keyboard(DWORD), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub unsafe fn hook(id_hook: c_int, callback: HookCallback) -> Result<HHOOK, DWORD> { | pub unsafe fn hook( | ||||||
|   let hook = SetWindowsHookExA(id_hook, Some(callback), null_mut(), 0); |   hook_id: c_int, | ||||||
|  |   hook_ptr: &AtomicPtr<HHOOK__>, | ||||||
|  |   callback: HookCallback, | ||||||
|  | ) -> Result<(), DWORD> { | ||||||
|  |   hook_ptr.store( | ||||||
|  |     SetWindowsHookExW(hook_id, Some(callback), 0 as HINSTANCE, 0), | ||||||
|  |     Ordering::Relaxed, | ||||||
|  |   ); | ||||||
| 
 | 
 | ||||||
|   if hook.is_null() { |   if hook_ptr.load(Ordering::Relaxed).is_null() { | ||||||
|     let error = GetLastError(); |     let error = GetLastError(); | ||||||
|     return Err(error); |     return Err(error); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Ok(hook) |   Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub unsafe fn unhook(hook: HHOOK) -> Result<(), DWORD> { | pub unsafe fn unhook(hook_ptr: &AtomicPtr<HHOOK__>) -> Result<(), DWORD> { | ||||||
|   if hook.is_null() { |   if !hook_ptr.load(Ordering::Relaxed).is_null() { | ||||||
|     return Ok(()); |     UnhookWindowsHookEx(hook_ptr.load(Ordering::Relaxed)); | ||||||
|   } |     hook_ptr.store(null_mut(), Ordering::Relaxed); | ||||||
| 
 |   } | ||||||
|   UnhookWindowsHookEx(hook); |  | ||||||
|   Ok(()) |   Ok(()) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,37 +1,39 @@ | |||||||
| use crate::windows; | use crate::windows; | ||||||
| use crate::{Button, Event, EventType, HookCallback, Robot}; | use crate::{Button, Event, EventType, HookCallback, Robot}; | ||||||
| use std::convert::TryInto; | use once_cell::sync::Lazy; | ||||||
| use std::mem::{size_of, transmute}; | use std::mem::{size_of, transmute}; | ||||||
| use std::ptr::null_mut; | use std::ptr::null_mut; | ||||||
|  | use std::sync::atomic::{AtomicPtr, Ordering}; | ||||||
| use std::time::SystemTime; | use std::time::SystemTime; | ||||||
| use winapi::ctypes::c_int; | use winapi::ctypes::c_int; | ||||||
| use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM}; | use winapi::shared::minwindef::{DWORD, HIWORD, LPARAM, LRESULT, WPARAM}; | ||||||
| use winapi::shared::windef::HHOOK; | use winapi::shared::windef::{HHOOK__, POINT}; | ||||||
| use winapi::um::winuser::{ | use winapi::um::winuser::{ | ||||||
|   CallNextHookEx, GetAsyncKeyState, GetSystemMetrics, SendInput, HC_ACTION, INPUT, INPUT_MOUSE, |   CallNextHookEx, GetAsyncKeyState, GetCursorPos, GetSystemMetrics, SendInput, HC_ACTION, INPUT, | ||||||
|   LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, |   INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN, | ||||||
|   MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, |   MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, | ||||||
|   MOUSEEVENTF_VIRTUALDESK, MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, |   MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK, MOUSEEVENTF_WHEEL, | ||||||
|   SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1, |   MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, | ||||||
|   VK_XBUTTON2, WH_MOUSE_LL, WM_LBUTTONDOWN, |   SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1, VK_XBUTTON2, WH_MOUSE_LL, | ||||||
|  |   WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_RBUTTONDOWN, | ||||||
|  |   WM_RBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP, XBUTTON1, XBUTTON2, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fn default_callback(event: Event) { | fn default_callback(event: Event) { | ||||||
|   println!("Default : Event {:?}", event); |   println!("Default : Event {:?}", event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static mut HOOK: HHOOK = null_mut(); | static MOUSE_HHOOK: Lazy<AtomicPtr<HHOOK__>> = Lazy::new(AtomicPtr::default); | ||||||
| static mut HOOK_CALLBACK: HookCallback = default_callback; | static mut HOOK_CALLBACK: HookCallback = default_callback; | ||||||
| 
 | 
 | ||||||
| impl Robot { | impl Robot { | ||||||
|   pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> { |   pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> { | ||||||
|     if HOOK.is_null() { |     if MOUSE_HHOOK.load(Ordering::Relaxed).is_null() { | ||||||
|       let r = windows::hook(WH_MOUSE_LL, Self::mouse_raw_callback); |       let r = windows::hook(WH_MOUSE_LL, &*MOUSE_HHOOK, Self::mouse_raw_callback); | ||||||
| 
 | 
 | ||||||
|       if r.is_err() { |       if r.is_err() { | ||||||
|         return Err(windows::HookError::Mouse(r.err().unwrap())); |         return Err(windows::HookError::Mouse(r.err().unwrap())); | ||||||
|       } |       } | ||||||
|       HOOK = r.ok().unwrap(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HOOK_CALLBACK = callback; |     HOOK_CALLBACK = callback; | ||||||
| @ -40,12 +42,11 @@ impl Robot { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> { |   pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> { | ||||||
|     if !HOOK.is_null() { |     if !MOUSE_HHOOK.load(Ordering::Relaxed).is_null() { | ||||||
|       let r = windows::unhook(HOOK); |       let r = windows::unhook(&*MOUSE_HHOOK); | ||||||
|       if r.is_err() { |       if r.is_err() { | ||||||
|         return Err(windows::HookError::Mouse(r.err().unwrap())); |         return Err(windows::HookError::Mouse(r.err().unwrap())); | ||||||
|       } |       } | ||||||
|       HOOK = null_mut(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HOOK_CALLBACK = default_callback; |     HOOK_CALLBACK = default_callback; | ||||||
| @ -53,6 +54,17 @@ impl Robot { | |||||||
|     Ok(()) |     Ok(()) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   pub fn mouse_location() -> (i32, i32) { | ||||||
|  |     let mut point = POINT { x: 0, y: 0 }; | ||||||
|  |     let result = unsafe { GetCursorPos(&mut point) }; | ||||||
|  | 
 | ||||||
|  |     if result != 0 { | ||||||
|  |       (point.x, point.y) | ||||||
|  |     } else { | ||||||
|  |       (0, 0) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   pub fn mouse_move_to(dx: i32, dy: i32) { |   pub fn mouse_move_to(dx: i32, dy: i32) { | ||||||
|     let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) }; |     let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) }; | ||||||
|     let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) }; |     let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) }; | ||||||
| @ -74,24 +86,14 @@ impl Robot { | |||||||
|       dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN; |       dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let mut input = INPUT { |     Self::mouse_event( | ||||||
|       type_: INPUT_MOUSE, |       (dx - unsafe { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 | ||||||
|       u: unsafe { |         / unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) }, | ||||||
|         transmute(MOUSEINPUT { |       (dy - unsafe { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535 | ||||||
|           dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / { |         / unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) }, | ||||||
|             GetSystemMetrics(SM_CXVIRTUALSCREEN) |       0, | ||||||
|           }, |       dw_flags, | ||||||
|           dy: (dy - { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535 / { |     ); | ||||||
|             GetSystemMetrics(SM_CYVIRTUALSCREEN) |  | ||||||
|           }, |  | ||||||
|           mouseData: 0, |  | ||||||
|           dwFlags: dw_flags, |  | ||||||
|           time: 0, |  | ||||||
|           dwExtraInfo: 0, |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub fn mouse_press(button: Button) { |   pub fn mouse_press(button: Button) { | ||||||
| @ -99,20 +101,7 @@ impl Robot { | |||||||
| 
 | 
 | ||||||
|     let dw_flags = btn; |     let dw_flags = btn; | ||||||
| 
 | 
 | ||||||
|     let mut input = INPUT { |     Self::mouse_event(0, 0, 0, dw_flags); | ||||||
|       type_: INPUT_MOUSE, |  | ||||||
|       u: unsafe { |  | ||||||
|         transmute(MOUSEINPUT { |  | ||||||
|           dx: 0, |  | ||||||
|           dy: 0, |  | ||||||
|           mouseData: 0, |  | ||||||
|           dwFlags: dw_flags, |  | ||||||
|           time: 0, |  | ||||||
|           dwExtraInfo: 0, |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub fn mouse_release(button: Button) { |   pub fn mouse_release(button: Button) { | ||||||
| @ -120,13 +109,31 @@ impl Robot { | |||||||
| 
 | 
 | ||||||
|     let dw_flags = btn; |     let dw_flags = btn; | ||||||
| 
 | 
 | ||||||
|  |     Self::mouse_event(0, 0, 0, dw_flags); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pub fn mouse_pressed(button: Button) -> bool { | ||||||
|  |     (unsafe { GetAsyncKeyState(Self::mouse_button_virtual_key(button)) } >> 15) != 0 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pub fn mouse_wheel_x(length: i32) { | ||||||
|  |     let dw_flags = MOUSEEVENTF_HWHEEL; | ||||||
|  |     Self::mouse_event(0, 0, unsafe { transmute(length * 120) }, dw_flags); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pub fn mouse_wheel_y(length: i32) { | ||||||
|  |     let dw_flags = MOUSEEVENTF_WHEEL; | ||||||
|  |     Self::mouse_event(0, 0, unsafe { transmute(length * 120) }, dw_flags); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fn mouse_event(dx: i32, dy: i32, mouse_data: u32, dw_flags: u32) { | ||||||
|     let mut input = INPUT { |     let mut input = INPUT { | ||||||
|       type_: INPUT_MOUSE, |       type_: INPUT_MOUSE, | ||||||
|       u: unsafe { |       u: unsafe { | ||||||
|         transmute(MOUSEINPUT { |         transmute(MOUSEINPUT { | ||||||
|           dx: 0, |           dx, | ||||||
|           dy: 0, |           dy, | ||||||
|           mouseData: 0, |           mouseData: mouse_data, | ||||||
|           dwFlags: dw_flags, |           dwFlags: dw_flags, | ||||||
|           time: 0, |           time: 0, | ||||||
|           dwExtraInfo: 0, |           dwExtraInfo: 0, | ||||||
| @ -136,10 +143,6 @@ impl Robot { | |||||||
|     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; |     unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pub fn mouse_pressed(button: Button) -> bool { |  | ||||||
|     (unsafe { GetAsyncKeyState(Self::mouse_button_virtual_key(button)) } >> 15) != 0 |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   fn mouse_button_event(ev: EventType) -> DWORD { |   fn mouse_button_event(ev: EventType) -> DWORD { | ||||||
|     match ev { |     match ev { | ||||||
|       EventType::MousePress(button) => match button { |       EventType::MousePress(button) => match button { | ||||||
| @ -174,13 +177,47 @@ impl Robot { | |||||||
|     (mouse.pt.x, mouse.pt.y) |     (mouse.pt.x, mouse.pt.y) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   #[allow(non_snake_case)] | ||||||
|   unsafe extern "system" fn mouse_raw_callback( |   unsafe extern "system" fn mouse_raw_callback( | ||||||
|     code: c_int, |     code: c_int, | ||||||
|     param: WPARAM, |     w_param: WPARAM, | ||||||
|     lpdata: LPARAM, |     l_param: LPARAM, | ||||||
|   ) -> LRESULT { |   ) -> LRESULT { | ||||||
|     if code == HC_ACTION { |     if code == HC_ACTION { | ||||||
|       let opt = Self::mouse_convert(param, lpdata); |       let opt = match w_param as u32 { | ||||||
|  |         WM_LBUTTONDOWN => Some(EventType::MousePress(Button::Left)), | ||||||
|  |         WM_LBUTTONUP => Some(EventType::MouseRelease(Button::Left)), | ||||||
|  |         WM_MBUTTONDOWN => Some(EventType::MousePress(Button::Middle)), | ||||||
|  |         WM_MBUTTONUP => Some(EventType::MouseRelease(Button::Middle)), | ||||||
|  |         WM_RBUTTONDOWN => Some(EventType::MousePress(Button::Right)), | ||||||
|  |         WM_RBUTTONUP => Some(EventType::MouseRelease(Button::Right)), | ||||||
|  |         WM_XBUTTONDOWN => { | ||||||
|  |           let llhs = &*(l_param as *const MSLLHOOKSTRUCT); | ||||||
|  | 
 | ||||||
|  |           match HIWORD(llhs.mouseData) { | ||||||
|  |             XBUTTON1 => Some(EventType::MousePress(Button::X1)), | ||||||
|  |             XBUTTON2 => Some(EventType::MousePress(Button::X2)), | ||||||
|  |             _ => None, | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         WM_XBUTTONUP => { | ||||||
|  |           let llhs = &*(l_param as *const MSLLHOOKSTRUCT); | ||||||
|  | 
 | ||||||
|  |           match HIWORD(llhs.mouseData) { | ||||||
|  |             XBUTTON1 => Some(EventType::MouseRelease(Button::X1)), | ||||||
|  |             XBUTTON2 => Some(EventType::MouseRelease(Button::X2)), | ||||||
|  |             _ => None, | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         WM_MOUSEMOVE => { | ||||||
|  |           let (x, y) = Self::get_mouse_point(l_param); | ||||||
|  |           Some(EventType::MouseMoveTo { | ||||||
|  |             x: x as f64, | ||||||
|  |             y: y as f64, | ||||||
|  |           }) | ||||||
|  |         } | ||||||
|  |         _ => None, | ||||||
|  |       }; | ||||||
|       if let Some(event_type) = opt { |       if let Some(event_type) = opt { | ||||||
|         let event = Event { |         let event = Event { | ||||||
|           event_type, |           event_type, | ||||||
| @ -189,25 +226,6 @@ impl Robot { | |||||||
|         HOOK_CALLBACK(event); |         HOOK_CALLBACK(event); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     CallNextHookEx(HOOK, code, param, lpdata) |     CallNextHookEx(null_mut(), code, w_param, l_param) | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   unsafe fn mouse_convert(wparam: WPARAM, lparam: LPARAM) -> Option<EventType> { |  | ||||||
|     match wparam.try_into() { |  | ||||||
|       Ok(WM_LBUTTONDOWN) => Some(EventType::MousePress(Button::Left)), |  | ||||||
|       Ok(WM_LBUTTONUP) => Some(EventType::MouseRelease(Button::Left)), |  | ||||||
|       Ok(WM_MBUTTONDOWN) => Some(EventType::MousePress(Button::Middle)), |  | ||||||
|       Ok(WM_MBUTTONUP) => Some(EventType::MouseRelease(Button::Middle)), |  | ||||||
|       Ok(WM_RBUTTONDOWN) => Some(EventType::MousePress(Button::Right)), |  | ||||||
|       Ok(WM_RBUTTONUP) => Some(EventType::MouseRelease(Button::Right)), |  | ||||||
|       Ok(WM_MOUSEMOVE) => { |  | ||||||
|         let (x, y) = Self::get_mouse_point(lparam); |  | ||||||
|         Some(EventType::MouseMoveTo { |  | ||||||
|           x: x as f64, |  | ||||||
|           y: y as f64, |  | ||||||
|         }) |  | ||||||
|       } |  | ||||||
|       _ => None, |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user