ing
This commit is contained in:
		
							parent
							
								
									9638e5cac6
								
							
						
					
					
						commit
						ea09dc582d
					
				@ -9,12 +9,13 @@ edition = "2018"
 | 
			
		||||
[dependencies]
 | 
			
		||||
serde = { version = "1.0.117", optional = true }
 | 
			
		||||
serde_derive = { version = "1.0.117", optional = true }
 | 
			
		||||
lazy_static = "1.4.0"
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
with_serde = ["serde", "serde_derive"]
 | 
			
		||||
 | 
			
		||||
[target.'cfg(target_os = "windows")'.dependencies]
 | 
			
		||||
winapi = { version = "0.3.9", features = ["winuser"] }
 | 
			
		||||
winapi = { version = "0.3.9", features = ["winuser", "errhandlingapi"] }
 | 
			
		||||
 | 
			
		||||
[build-dependencies]
 | 
			
		||||
pkg-config = "0.3.19"
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,5 @@
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
mod windows;
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub use crate::keyboard::windows::*;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub enum Key {
 | 
			
		||||
  Escape,
 | 
			
		||||
  Digit0,
 | 
			
		||||
@ -123,10 +119,3 @@ pub enum Key {
 | 
			
		||||
  MetaLeft,
 | 
			
		||||
  MetaRight,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum KeyboardState {
 | 
			
		||||
  Press,
 | 
			
		||||
  Release,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Keyboard;
 | 
			
		||||
@ -1,153 +0,0 @@
 | 
			
		||||
// // https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731
 | 
			
		||||
 | 
			
		||||
// pub const VK_LBUTTON: u16 = 0x01; // Left mouse button
 | 
			
		||||
// pub const VK_RBUTTON: u16 = 0x02; // Right mouse button
 | 
			
		||||
// pub const VK_CANCEL: u16 = 0x03; // Control-break processing
 | 
			
		||||
// pub const VK_MBUTTON: u16 = 0x04; // Middle mouse button (three-button mouse)
 | 
			
		||||
// pub const VK_XBUTTON1: u16 = 0x05; // X1 mouse button
 | 
			
		||||
// pub const VK_XBUTTON2: u16 = 0x06; // X2 mouse button
 | 
			
		||||
// pub const VK_BACK: u16 = 0x08; // BACKSPACE key
 | 
			
		||||
// pub const VK_TAB: u16 = 0x09; // TAB key
 | 
			
		||||
// pub const VK_CLEAR: u16 = 0x0C; // CLEAR key
 | 
			
		||||
// pub const VK_RETURN: u16 = 0x0D; // ENTER key
 | 
			
		||||
// pub const VK_SHIFT: u16 = 0x10; // SHIFT key
 | 
			
		||||
// pub const VK_CONTROL: u16 = 0x11; // CTRL key
 | 
			
		||||
// pub const VK_MENU: u16 = 0x12; // ALT key
 | 
			
		||||
// pub const VK_PAUSE: u16 = 0x13; // PAUSE key
 | 
			
		||||
// pub const VK_CAPITAL: u16 = 0x14; // CAPS LOCK key
 | 
			
		||||
// pub const VK_KANA: u16 = 0x15; // IME Kana mode
 | 
			
		||||
// pub const VK_HANGUEL: u16 = 0x15; // IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
 | 
			
		||||
// pub const VK_HANGUL: u16 = 0x15; // IME Hangul mode
 | 
			
		||||
// pub const VK_IME_ON: u16 = 0x16; // IME On
 | 
			
		||||
// pub const VK_JUNJA: u16 = 0x17; // IME Junja mode
 | 
			
		||||
// pub const VK_FINAL: u16 = 0x18; // IME final mode
 | 
			
		||||
// pub const VK_HANJA: u16 = 0x19; // IME Hanja mode
 | 
			
		||||
// pub const VK_KANJI: u16 = 0x19; // IME Kanji mode
 | 
			
		||||
// pub const VK_IME_OFF: u16 = 0x1A; // IME Off
 | 
			
		||||
// pub const VK_ESCAPE: u16 = 0x1B; // ESC key
 | 
			
		||||
// pub const VK_CONVERT: u16 = 0x1C; // IME convert
 | 
			
		||||
// pub const VK_NONCONVERT: u16 = 0x1D; // IME nonconvert
 | 
			
		||||
// pub const VK_ACCEPT: u16 = 0x1E; // IME accept
 | 
			
		||||
// pub const VK_MODECHANGE: u16 = 0x1F; // IME mode change request
 | 
			
		||||
// pub const VK_SPACE: u16 = 0x20; // SPACEBAR
 | 
			
		||||
// pub const VK_PRIOR: u16 = 0x21; // PAGE UP key
 | 
			
		||||
// pub const VK_NEXT: u16 = 0x22; // PAGE DOWN key
 | 
			
		||||
// pub const VK_END: u16 = 0x23; // END key
 | 
			
		||||
// pub const VK_HOME: u16 = 0x24; // HOME key
 | 
			
		||||
// pub const VK_LEFT: u16 = 0x25; // LEFT ARROW key
 | 
			
		||||
// pub const VK_UP: u16 = 0x26; // UP ARROW key
 | 
			
		||||
// pub const VK_RIGHT: u16 = 0x27; // RIGHT ARROW key
 | 
			
		||||
// pub const VK_DOWN: u16 = 0x28; // DOWN ARROW key
 | 
			
		||||
// pub const VK_SELECT: u16 = 0x29; // SELECT key
 | 
			
		||||
// pub const VK_PRINT: u16 = 0x2A; // PRINT key
 | 
			
		||||
// pub const VK_EXECUTE: u16 = 0x2B; // EXECUTE key
 | 
			
		||||
// pub const VK_SNAPSHOT: u16 = 0x2C; // PRINT SCREEN key
 | 
			
		||||
// pub const VK_INSERT: u16 = 0x2D; // INS key
 | 
			
		||||
// pub const VK_DELETE: u16 = 0x2E; // DEL key
 | 
			
		||||
// pub const VK_HELP: u16 = 0x2F; // HELP key
 | 
			
		||||
// pub const VK_DIGIT_0: u16 = 0x30; // 0 key
 | 
			
		||||
// pub const VK_DIGIT_1: u16 = 0x31; // 1 key
 | 
			
		||||
// pub const VK_DIGIT_2: u16 = 0x32; // 2 key
 | 
			
		||||
// pub const VK_DIGIT_3: u16 = 0x33; // 3 key
 | 
			
		||||
// pub const VK_DIGIT_4: u16 = 0x34; // 4 key
 | 
			
		||||
// pub const VK_DIGIT_5: u16 = 0x35; // 5 key
 | 
			
		||||
// pub const VK_DIGIT_6: u16 = 0x36; // 6 key
 | 
			
		||||
// pub const VK_DIGIT_7: u16 = 0x37; // 7 key
 | 
			
		||||
// pub const VK_DIGIT_8: u16 = 0x38; // 8 key
 | 
			
		||||
// pub const VK_DIGIT_9: u16 = 0x39; // 9 key
 | 
			
		||||
// pub const VK_KEY_A: u16 = 0x41; // A key
 | 
			
		||||
// pub const VK_KEY_B: u16 = 0x42; // B key
 | 
			
		||||
// pub const VK_KEY_C: u16 = 0x43; // C key
 | 
			
		||||
// pub const VK_KEY_D: u16 = 0x44; // D key
 | 
			
		||||
// pub const VK_KEY_E: u16 = 0x45; // E key
 | 
			
		||||
// pub const VK_KEY_F: u16 = 0x46; // F key
 | 
			
		||||
// pub const VK_KEY_G: u16 = 0x47; // G key
 | 
			
		||||
// pub const VK_KEY_H: u16 = 0x48; // H key
 | 
			
		||||
// pub const VK_KEY_I: u16 = 0x49; // I key
 | 
			
		||||
// pub const VK_KEY_J: u16 = 0x4A; // J key
 | 
			
		||||
// pub const VK_KEY_K: u16 = 0x4B; // K key
 | 
			
		||||
// pub const VK_KEY_L: u16 = 0x4C; // L key
 | 
			
		||||
// pub const VK_KEY_M: u16 = 0x4D; // M key
 | 
			
		||||
// pub const VK_KEY_N: u16 = 0x4E; // N key
 | 
			
		||||
// pub const VK_KEY_O: u16 = 0x4F; // O key
 | 
			
		||||
// pub const VK_KEY_P: u16 = 0x50; // P key
 | 
			
		||||
// pub const VK_KEY_Q: u16 = 0x51; // Q key
 | 
			
		||||
// pub const VK_KEY_R: u16 = 0x52; // R key
 | 
			
		||||
// pub const VK_KEY_S: u16 = 0x53; // S key
 | 
			
		||||
// pub const VK_KEY_T: u16 = 0x54; // T key
 | 
			
		||||
// pub const VK_KEY_U: u16 = 0x55; // U key
 | 
			
		||||
// pub const VK_KEY_V: u16 = 0x56; // V key
 | 
			
		||||
// pub const VK_KEY_W: u16 = 0x57; // W key
 | 
			
		||||
// pub const VK_KEY_X: u16 = 0x58; // X key
 | 
			
		||||
// pub const VK_KEY_Y: u16 = 0x59; // Y key
 | 
			
		||||
// pub const VK_KEY_Z: u16 = 0x5A; // Z key
 | 
			
		||||
// pub const VK_LWIN: u16 = 0x5B; // Left Windows key (Natural keyboard)
 | 
			
		||||
// pub const VK_RWIN: u16 = 0x5C; // Right Windows key (Natural keyboard)
 | 
			
		||||
// pub const VK_APPS: u16 = 0x5D; // Applications key (Natural keyboard)
 | 
			
		||||
// pub const VK_SLEEP: u16 = 0x5F; // Computer Sleep key
 | 
			
		||||
// pub const VK_NUMPAD0: u16 = 0x60; // Numeric keypad 0 key
 | 
			
		||||
// pub const VK_NUMPAD1: u16 = 0x61; // Numeric keypad 1 key
 | 
			
		||||
// pub const VK_NUMPAD2: u16 = 0x62; // Numeric keypad 2 key
 | 
			
		||||
// pub const VK_NUMPAD3: u16 = 0x63; // Numeric keypad 3 key
 | 
			
		||||
// pub const VK_NUMPAD4: u16 = 0x64; // Numeric keypad 4 key
 | 
			
		||||
// pub const VK_NUMPAD5: u16 = 0x65; // Numeric keypad 5 key
 | 
			
		||||
// pub const VK_NUMPAD6: u16 = 0x66; // Numeric keypad 6 key
 | 
			
		||||
// pub const VK_NUMPAD7: u16 = 0x67; // Numeric keypad 7 key
 | 
			
		||||
// pub const VK_NUMPAD8: u16 = 0x68; // Numeric keypad 8 key
 | 
			
		||||
// pub const VK_NUMPAD9: u16 = 0x69; // Numeric keypad 9 key
 | 
			
		||||
// pub const VK_MULTIPLY: u16 = 0x6A; // Multiply key
 | 
			
		||||
// pub const VK_ADD: u16 = 0x6B; // Add key
 | 
			
		||||
// pub const VK_SEPARATOR: u16 = 0x6C; // Separator key
 | 
			
		||||
// pub const VK_SUBTRACT: u16 = 0x6D; // Subtract key
 | 
			
		||||
// pub const VK_DECIMAL: u16 = 0x6E; // Decimal key
 | 
			
		||||
// pub const VK_DIVIDE: u16 = 0x6F; // Divide key
 | 
			
		||||
// pub const VK_F1: u16 = 0x70; // F1 key
 | 
			
		||||
// pub const VK_F2: u16 = 0x71; // F2 key
 | 
			
		||||
// pub const VK_F3: u16 = 0x72; // F3 key
 | 
			
		||||
// pub const VK_F4: u16 = 0x73; // F4 key
 | 
			
		||||
// pub const VK_F5: u16 = 0x74; // F5 key
 | 
			
		||||
// pub const VK_F6: u16 = 0x75; // F6 key
 | 
			
		||||
// pub const VK_F7: u16 = 0x76; // F7 key
 | 
			
		||||
// pub const VK_F8: u16 = 0x77; // F8 key
 | 
			
		||||
// pub const VK_F9: u16 = 0x78; // F9 key
 | 
			
		||||
// pub const VK_F10: u16 = 0x79; // F10 key
 | 
			
		||||
// pub const VK_F11: u16 = 0x7A; // F11 key
 | 
			
		||||
// pub const VK_F12: u16 = 0x7B; // F12 key
 | 
			
		||||
// pub const VK_F13: u16 = 0x7C; // F13 key
 | 
			
		||||
// pub const VK_F14: u16 = 0x7D; // F14 key
 | 
			
		||||
// pub const VK_F15: u16 = 0x7E; // F15 key
 | 
			
		||||
// pub const VK_F16: u16 = 0x7F; // F16 key
 | 
			
		||||
// pub const VK_F17: u16 = 0x80; // F17 key
 | 
			
		||||
// pub const VK_F18: u16 = 0x81; // F18 key
 | 
			
		||||
// pub const VK_F19: u16 = 0x82; // F19 key
 | 
			
		||||
// pub const VK_F20: u16 = 0x83; // F20 key
 | 
			
		||||
// pub const VK_F21: u16 = 0x84; // F21 key
 | 
			
		||||
// pub const VK_F22: u16 = 0x85; // F22 key
 | 
			
		||||
// pub const VK_F23: u16 = 0x86; // F23 key
 | 
			
		||||
// pub const VK_F24: u16 = 0x87; // F24 key
 | 
			
		||||
// pub const VK_NUMLOCK: u16 = 0x90; // NUM LOCK key
 | 
			
		||||
// pub const VK_SCROLL: u16 = 0x91; // SCROLL LOCK key
 | 
			
		||||
// pub const VK_LSHIFT: u16 = 0xA0; // Left SHIFT key
 | 
			
		||||
// pub const VK_RSHIFT: u16 = 0xA1; // Right SHIFT key
 | 
			
		||||
// pub const VK_LCONTROL: u16 = 0xA2; // Left CONTROL key
 | 
			
		||||
// pub const VK_RCONTROL: u16 = 0xA3; // Right CONTROL key
 | 
			
		||||
// pub const VK_LMENU: u16 = 0xA4; // Left MENU key
 | 
			
		||||
// pub const VK_RMENU: u16 = 0xA5; // Right MENU key
 | 
			
		||||
// pub const VK_BROWSER_BACK: u16 = 0xA6; // Browser Back key
 | 
			
		||||
// pub const VK_BROWSER_FORWARD: u16 = 0xA7; // Browser Forward key
 | 
			
		||||
// pub const VK_BROWSER_REFRESH: u16 = 0xA8; // Browser Refresh key
 | 
			
		||||
// pub const VK_BROWSER_STOP: u16 = 0xA9; // Browser Stop key
 | 
			
		||||
// pub const VK_BROWSER_SEARCH: u16 = 0xAA; // Browser Search key
 | 
			
		||||
// pub const VK_BROWSER_FAVORITES: u16 = 0xAB; // Browser Favorites key
 | 
			
		||||
// pub const VK_BROWSER_HOME: u16 = 0xAC; // Browser Start and Home key
 | 
			
		||||
// pub const VK_VOLUME_MUTE: u16 = 0xAD; // Volume Mute key
 | 
			
		||||
// pub const VK_VOLUME_DOWN: u16 = 0xAE; // Volume Down key
 | 
			
		||||
// pub const VK_VOLUME_UP: u16 = 0xAF; // Volume Up key
 | 
			
		||||
// pub const VK_MEDIA_NEXT_TRACK: u16 = 0xB0; // Next Track key
 | 
			
		||||
// pub const VK_MEDIA_PREV_TRACK: u16 = 0xB1; // Previous Track key
 | 
			
		||||
// pub const VK_MEDIA_STOP: u16 = 0xB2; // Stop Media key
 | 
			
		||||
// pub const VK_MEDIA_PLAY_PAUSE: u16 = 0xB3; // Play/Pause Media key
 | 
			
		||||
// pub const VK_LAUNCH_MAIL: u16 = 0xB4; // Start Mail key
 | 
			
		||||
// pub const VK_LAUNCH_MEDIA_SELECT: u16 = 0xB5; // Select Media key
 | 
			
		||||
// pub const VK_LAUNCH_APP1: u16 = 0xB6; // Start Application 1 key
 | 
			
		||||
// pub const VK_LAUNCH_APP2: u16 = 0xB7; // Start Application 2 key
 | 
			
		||||
@ -1,178 +0,0 @@
 | 
			
		||||
use std::mem::{size_of, transmute_copy};
 | 
			
		||||
use winapi::ctypes::c_int;
 | 
			
		||||
use winapi::shared::minwindef::WORD;
 | 
			
		||||
use winapi::um::winuser::{
 | 
			
		||||
  GetAsyncKeyState, MapVirtualKeyW, SendInput, INPUT, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_KEYUP,
 | 
			
		||||
  KEYEVENTF_SCANCODE, LPINPUT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::keyboard::{Key, Keyboard};
 | 
			
		||||
 | 
			
		||||
impl Keyboard {
 | 
			
		||||
  pub fn press(key: Key) {
 | 
			
		||||
    let dw_flags = KEYEVENTF_SCANCODE;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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 release(key: Key) {
 | 
			
		||||
    let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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 pressed(key: Key) -> bool {
 | 
			
		||||
    (unsafe { GetAsyncKeyState(Self::key_2_virtual_key(key) as i32) } >> 15) != 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn key_to_scancode(key: Key) -> u16 {
 | 
			
		||||
    let vk = Self::key_2_virtual_key(key);
 | 
			
		||||
    unsafe { MapVirtualKeyW(vk as u32, 0) as u16 }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn key_2_virtual_key(key: Key) -> WORD {
 | 
			
		||||
    match key {
 | 
			
		||||
      Key::Digit0 => 0x30,
 | 
			
		||||
      Key::Digit1 => 0x31,
 | 
			
		||||
      Key::Digit2 => 0x32,
 | 
			
		||||
      Key::Digit3 => 0x33,
 | 
			
		||||
      Key::Digit4 => 0x34,
 | 
			
		||||
      Key::Digit5 => 0x35,
 | 
			
		||||
      Key::Digit6 => 0x36,
 | 
			
		||||
      Key::Digit7 => 0x37,
 | 
			
		||||
      Key::Digit8 => 0x38,
 | 
			
		||||
      Key::Digit9 => 0x39,
 | 
			
		||||
      Key::KeyA => 0x41,
 | 
			
		||||
      Key::KeyB => 0x42,
 | 
			
		||||
      Key::KeyC => 0x43,
 | 
			
		||||
      Key::KeyD => 0x44,
 | 
			
		||||
      Key::KeyE => 0x45,
 | 
			
		||||
      Key::KeyF => 0x46,
 | 
			
		||||
      Key::KeyG => 0x47,
 | 
			
		||||
      Key::KeyH => 0x48,
 | 
			
		||||
      Key::KeyI => 0x49,
 | 
			
		||||
      Key::KeyJ => 0x4A,
 | 
			
		||||
      Key::KeyK => 0x4B,
 | 
			
		||||
      Key::KeyL => 0x4C,
 | 
			
		||||
      Key::KeyM => 0x4D,
 | 
			
		||||
      Key::KeyN => 0x4E,
 | 
			
		||||
      Key::KeyO => 0x4F,
 | 
			
		||||
      Key::KeyP => 0x50,
 | 
			
		||||
      Key::KeyQ => 0x51,
 | 
			
		||||
      Key::KeyR => 0x52,
 | 
			
		||||
      Key::KeyS => 0x53,
 | 
			
		||||
      Key::KeyT => 0x54,
 | 
			
		||||
      Key::KeyU => 0x55,
 | 
			
		||||
      Key::KeyV => 0x56,
 | 
			
		||||
      Key::KeyW => 0x57,
 | 
			
		||||
      Key::KeyX => 0x58,
 | 
			
		||||
      Key::KeyY => 0x59,
 | 
			
		||||
      Key::KeyZ => 0x5A,
 | 
			
		||||
      Key::F1 => 0x70,
 | 
			
		||||
      Key::F2 => 0x71,
 | 
			
		||||
      Key::F3 => 0x72,
 | 
			
		||||
      Key::F4 => 0x73,
 | 
			
		||||
      Key::F5 => 0x74,
 | 
			
		||||
      Key::F6 => 0x75,
 | 
			
		||||
      Key::F7 => 0x76,
 | 
			
		||||
      Key::F8 => 0x77,
 | 
			
		||||
      Key::F9 => 0x78,
 | 
			
		||||
      Key::F10 => 0x79,
 | 
			
		||||
      Key::F11 => 0x7A,
 | 
			
		||||
      Key::F12 => 0x7B,
 | 
			
		||||
      Key::F13 => 0x7C,
 | 
			
		||||
      Key::F14 => 0x7D,
 | 
			
		||||
      Key::F15 => 0x7E,
 | 
			
		||||
      Key::F16 => 0x7F,
 | 
			
		||||
      Key::F17 => 0x80,
 | 
			
		||||
      Key::F18 => 0x81,
 | 
			
		||||
      Key::F19 => 0x82,
 | 
			
		||||
      Key::F20 => 0x83,
 | 
			
		||||
      Key::F21 => 0x84,
 | 
			
		||||
      Key::F22 => 0x85,
 | 
			
		||||
      Key::F23 => 0x86,
 | 
			
		||||
      Key::F24 => 0x87,
 | 
			
		||||
      Key::Numpad0 => 0x60,
 | 
			
		||||
      Key::Numpad1 => 0x61,
 | 
			
		||||
      Key::Numpad2 => 0x62,
 | 
			
		||||
      Key::Numpad3 => 0x63,
 | 
			
		||||
      Key::Numpad4 => 0x64,
 | 
			
		||||
      Key::Numpad5 => 0x65,
 | 
			
		||||
      Key::Numpad6 => 0x66,
 | 
			
		||||
      Key::Numpad7 => 0x67,
 | 
			
		||||
      Key::Numpad8 => 0x68,
 | 
			
		||||
      Key::Numpad9 => 0x69,
 | 
			
		||||
      Key::NumpadAdd => 0x6B,      // Add
 | 
			
		||||
      Key::NumpadSubtract => 0x6D, // Subtract
 | 
			
		||||
      Key::NumpadMultiply => 0x6A, // Multiply
 | 
			
		||||
      Key::NumpadDivide => 0x6F,   // Divide
 | 
			
		||||
      Key::NumpadDecimal => 0x6E,  // Decimal
 | 
			
		||||
      Key::NumpadEqual => '=' as u16,
 | 
			
		||||
      Key::NumpadComma => ',' as u16,
 | 
			
		||||
      Key::NumpadEnter => 0x0D,
 | 
			
		||||
      Key::NumLock => 0x90,
 | 
			
		||||
      Key::Minus => '-' as u16,
 | 
			
		||||
      Key::Equal => '=' as u16,
 | 
			
		||||
      Key::BracketLeft => '{' as u16,
 | 
			
		||||
      Key::BracketRight => '}' as u16,
 | 
			
		||||
      Key::Semicolon => ';' as u16,
 | 
			
		||||
      Key::Quote => '\'' as u16,
 | 
			
		||||
      Key::Backquote => '`' as u16,
 | 
			
		||||
      Key::Backslash => '\\' as u16,
 | 
			
		||||
      Key::Comma => ',' as u16,
 | 
			
		||||
      Key::Period => '~' as u16,
 | 
			
		||||
      Key::Slash => '/' as u16,
 | 
			
		||||
      Key::Escape => 0x1B,
 | 
			
		||||
      Key::Enter => 0x0D,
 | 
			
		||||
      Key::Backspace => 0x08,
 | 
			
		||||
      Key::Tab => 0x09,
 | 
			
		||||
      Key::Space => 0x20,
 | 
			
		||||
      Key::CapsLock => 0x14,
 | 
			
		||||
      Key::ShiftLeft => 0xA0,
 | 
			
		||||
      Key::ShiftRight => 0xA1,
 | 
			
		||||
      Key::ControlLeft => 0xA2,
 | 
			
		||||
      Key::ControlRight => 0xA3,
 | 
			
		||||
      Key::AltLeft => 0xA4,
 | 
			
		||||
      Key::AltRight => 0xA5,
 | 
			
		||||
      Key::Pause => 0x13,
 | 
			
		||||
      Key::ScrollLock => 0x91,
 | 
			
		||||
      Key::PrintScreen => 0x2C,
 | 
			
		||||
      Key::ArrowLeft => 0x25,
 | 
			
		||||
      Key::ArrowUp => 0x26,
 | 
			
		||||
      Key::ArrowRight => 0x27,
 | 
			
		||||
      Key::ArrowDown => 0x28,
 | 
			
		||||
      Key::PageUp => 0x21,
 | 
			
		||||
      Key::PageDown => 0x22,
 | 
			
		||||
      Key::Home => 0x24,
 | 
			
		||||
      Key::End => 0x23,
 | 
			
		||||
      Key::Insert => 0x2D,
 | 
			
		||||
      Key::Delete => 0x2E,
 | 
			
		||||
      Key::MetaLeft => 0x5B,
 | 
			
		||||
      Key::MetaRight => 0x5C,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -1,2 +1,32 @@
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
mod windows;
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub use crate::windows::*;
 | 
			
		||||
 | 
			
		||||
use crate::keyboard::Key;
 | 
			
		||||
use crate::mouse::Button;
 | 
			
		||||
use std::time::SystemTime;
 | 
			
		||||
 | 
			
		||||
pub mod keyboard;
 | 
			
		||||
pub mod mouse;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub enum EventType {
 | 
			
		||||
  KeyPress(Key),
 | 
			
		||||
  KeyRelease(Key),
 | 
			
		||||
  MousePress(Button),
 | 
			
		||||
  MouseRelease(Button),
 | 
			
		||||
  MouseMoveTo { x: f64, y: f64 },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub struct Event {
 | 
			
		||||
  pub time: SystemTime,
 | 
			
		||||
  pub event_type: EventType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type HookCallback = fn(event: Event);
 | 
			
		||||
 | 
			
		||||
pub struct Robot;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/mouse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/mouse.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub enum Button {
 | 
			
		||||
  Left,
 | 
			
		||||
  Middle,
 | 
			
		||||
  Right,
 | 
			
		||||
  X1,
 | 
			
		||||
  X2,
 | 
			
		||||
  Other(u32),
 | 
			
		||||
}
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
mod windows;
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub use crate::mouse::windows::*;
 | 
			
		||||
 | 
			
		||||
pub enum Button {
 | 
			
		||||
  Left,
 | 
			
		||||
  Middle,
 | 
			
		||||
  Right,
 | 
			
		||||
  X1,
 | 
			
		||||
  X2,
 | 
			
		||||
  Other(u32),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum ButtonState {
 | 
			
		||||
  Press,
 | 
			
		||||
  Release,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Mouse;
 | 
			
		||||
@ -1,129 +0,0 @@
 | 
			
		||||
use std::mem::{size_of, transmute};
 | 
			
		||||
use winapi::ctypes::c_int;
 | 
			
		||||
use winapi::shared::minwindef::DWORD;
 | 
			
		||||
use winapi::um::winuser::{
 | 
			
		||||
  GetAsyncKeyState, GetSystemMetrics, SendInput, INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE,
 | 
			
		||||
  MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP,
 | 
			
		||||
  MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK,
 | 
			
		||||
  MOUSEINPUT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN,
 | 
			
		||||
  VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1, VK_XBUTTON2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::mouse::{Button, ButtonState, Mouse};
 | 
			
		||||
 | 
			
		||||
impl Mouse {
 | 
			
		||||
  pub fn move_to(dx: i32, dy: i32) {
 | 
			
		||||
    let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
 | 
			
		||||
    let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
 | 
			
		||||
    if width == 0 || height == 0 {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    let pressed_left = Self::pressed(Button::Left);
 | 
			
		||||
    let pressed_right = Self::pressed(Button::Right);
 | 
			
		||||
    let pressed_middle = Self::pressed(Button::Middle);
 | 
			
		||||
    let mut dw_flags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK;
 | 
			
		||||
 | 
			
		||||
    if pressed_left {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_LEFTDOWN;
 | 
			
		||||
    }
 | 
			
		||||
    if pressed_right {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_RIGHTDOWN;
 | 
			
		||||
    }
 | 
			
		||||
    if pressed_middle {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      type_: INPUT_MOUSE,
 | 
			
		||||
      u: unsafe {
 | 
			
		||||
        transmute(MOUSEINPUT {
 | 
			
		||||
          dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / {
 | 
			
		||||
            GetSystemMetrics(SM_CXVIRTUALSCREEN)
 | 
			
		||||
          },
 | 
			
		||||
          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 press(button: Button) {
 | 
			
		||||
    let btn = Self::button_event(button, ButtonState::Press);
 | 
			
		||||
 | 
			
		||||
    let dw_flags = btn;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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 release(button: Button) {
 | 
			
		||||
    let btn = Self::button_event(button, ButtonState::Release);
 | 
			
		||||
 | 
			
		||||
    let dw_flags = btn;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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 pressed(button: Button) -> bool {
 | 
			
		||||
    (unsafe { GetAsyncKeyState(Self::button_virtual_key(button)) } >> 15) != 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn button_event(button: Button, state: ButtonState) -> DWORD {
 | 
			
		||||
    match state {
 | 
			
		||||
      ButtonState::Press => match button {
 | 
			
		||||
        Button::Left => MOUSEEVENTF_LEFTDOWN,
 | 
			
		||||
        Button::Middle => MOUSEEVENTF_MIDDLEDOWN,
 | 
			
		||||
        Button::Right => MOUSEEVENTF_RIGHTDOWN,
 | 
			
		||||
        _ => unimplemented!(),
 | 
			
		||||
      },
 | 
			
		||||
      ButtonState::Release => match button {
 | 
			
		||||
        Button::Left => MOUSEEVENTF_LEFTUP,
 | 
			
		||||
        Button::Middle => MOUSEEVENTF_MIDDLEUP,
 | 
			
		||||
        Button::Right => MOUSEEVENTF_RIGHTUP,
 | 
			
		||||
        _ => unimplemented!(),
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn button_virtual_key(button: Button) -> c_int {
 | 
			
		||||
    match button {
 | 
			
		||||
      Button::Left => VK_LBUTTON,
 | 
			
		||||
      Button::Middle => VK_MBUTTON,
 | 
			
		||||
      Button::Right => VK_RBUTTON,
 | 
			
		||||
      Button::X1 => VK_XBUTTON1,
 | 
			
		||||
      Button::X2 => VK_XBUTTON2,
 | 
			
		||||
      _ => unimplemented!(),
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
use crate::mouse::Mouse;
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn mouse_moto_to() {
 | 
			
		||||
    Mouse::move_to(true, 500, 30);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										405
									
								
								src/windows/keyboard.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								src/windows/keyboard.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,405 @@
 | 
			
		||||
use crate::windows;
 | 
			
		||||
use crate::{Event, EventType, HookCallback, Key, Robot};
 | 
			
		||||
use lazy_static::lazy_static;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use std::convert::TryInto;
 | 
			
		||||
use std::mem::{size_of, transmute_copy};
 | 
			
		||||
use std::ptr::null_mut;
 | 
			
		||||
use std::time::SystemTime;
 | 
			
		||||
use winapi::ctypes::c_int;
 | 
			
		||||
use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM};
 | 
			
		||||
use winapi::shared::windef::HHOOK;
 | 
			
		||||
use winapi::um::winuser::{
 | 
			
		||||
  CallNextHookEx, GetAsyncKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT, INPUT_KEYBOARD,
 | 
			
		||||
  KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT, WH_KEYBOARD_LL,
 | 
			
		||||
  WM_KEYDOWN, WM_KEYUP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
lazy_static! {
 | 
			
		||||
  static ref KEY_2_VK_MAP: HashMap<Key, WORD> = {
 | 
			
		||||
    let mut m = HashMap::new();
 | 
			
		||||
    m.insert(Key::Digit0 , 0x30);
 | 
			
		||||
    m.insert(Key::Digit1 , 0x31);
 | 
			
		||||
    m.insert(Key::Digit2 , 0x32);
 | 
			
		||||
    m.insert(Key::Digit3 , 0x33);
 | 
			
		||||
    m.insert(Key::Digit4 , 0x34);
 | 
			
		||||
    m.insert(Key::Digit5 , 0x35);
 | 
			
		||||
    m.insert(Key::Digit6 , 0x36);
 | 
			
		||||
    m.insert(Key::Digit7 , 0x37);
 | 
			
		||||
    m.insert(Key::Digit8 , 0x38);
 | 
			
		||||
    m.insert(Key::Digit9 , 0x39);
 | 
			
		||||
    m.insert(Key::KeyA , 0x41);
 | 
			
		||||
    m.insert(Key::KeyB , 0x42);
 | 
			
		||||
    m.insert(Key::KeyC , 0x43);
 | 
			
		||||
    m.insert(Key::KeyD , 0x44);
 | 
			
		||||
    m.insert(Key::KeyE , 0x45);
 | 
			
		||||
    m.insert(Key::KeyF , 0x46);
 | 
			
		||||
    m.insert(Key::KeyG , 0x47);
 | 
			
		||||
    m.insert(Key::KeyH , 0x48);
 | 
			
		||||
    m.insert(Key::KeyI , 0x49);
 | 
			
		||||
    m.insert(Key::KeyJ , 0x4A);
 | 
			
		||||
    m.insert(Key::KeyK , 0x4B);
 | 
			
		||||
    m.insert(Key::KeyL , 0x4C);
 | 
			
		||||
    m.insert(Key::KeyM , 0x4D);
 | 
			
		||||
    m.insert(Key::KeyN , 0x4E);
 | 
			
		||||
    m.insert(Key::KeyO , 0x4F);
 | 
			
		||||
    m.insert(Key::KeyP , 0x50);
 | 
			
		||||
    m.insert(Key::KeyQ , 0x51);
 | 
			
		||||
    m.insert(Key::KeyR , 0x52);
 | 
			
		||||
    m.insert(Key::KeyS , 0x53);
 | 
			
		||||
    m.insert(Key::KeyT , 0x54);
 | 
			
		||||
    m.insert(Key::KeyU , 0x55);
 | 
			
		||||
    m.insert(Key::KeyV , 0x56);
 | 
			
		||||
    m.insert(Key::KeyW , 0x57);
 | 
			
		||||
    m.insert(Key::KeyX , 0x58);
 | 
			
		||||
    m.insert(Key::KeyY , 0x59);
 | 
			
		||||
    m.insert(Key::KeyZ , 0x5A);
 | 
			
		||||
    m.insert(Key::F1 , 0x70);
 | 
			
		||||
    m.insert(Key::F2 , 0x71);
 | 
			
		||||
    m.insert(Key::F3 , 0x72);
 | 
			
		||||
    m.insert(Key::F4 , 0x73);
 | 
			
		||||
    m.insert(Key::F5 , 0x74);
 | 
			
		||||
    m.insert(Key::F6 , 0x75);
 | 
			
		||||
    m.insert(Key::F7 , 0x76);
 | 
			
		||||
    m.insert(Key::F8 , 0x77);
 | 
			
		||||
    m.insert(Key::F9 , 0x78);
 | 
			
		||||
    m.insert(Key::F10 , 0x79);
 | 
			
		||||
    m.insert(Key::F11 , 0x7A);
 | 
			
		||||
    m.insert(Key::F12 , 0x7B);
 | 
			
		||||
    m.insert(Key::F13 , 0x7C);
 | 
			
		||||
    m.insert(Key::F14 , 0x7D);
 | 
			
		||||
    m.insert(Key::F15 , 0x7E);
 | 
			
		||||
    m.insert(Key::F16 , 0x7F);
 | 
			
		||||
    m.insert(Key::F17 , 0x80);
 | 
			
		||||
    m.insert(Key::F18 , 0x81);
 | 
			
		||||
    m.insert(Key::F19 , 0x82);
 | 
			
		||||
    m.insert(Key::F20 , 0x83);
 | 
			
		||||
    m.insert(Key::F21 , 0x84);
 | 
			
		||||
    m.insert(Key::F22 , 0x85);
 | 
			
		||||
    m.insert(Key::F23 , 0x86);
 | 
			
		||||
    m.insert(Key::F24 , 0x87);
 | 
			
		||||
    m.insert(Key::Numpad0 , 0x60);
 | 
			
		||||
    m.insert(Key::Numpad1 , 0x61);
 | 
			
		||||
    m.insert(Key::Numpad2 , 0x62);
 | 
			
		||||
    m.insert(Key::Numpad3 , 0x63);
 | 
			
		||||
    m.insert(Key::Numpad4 , 0x64);
 | 
			
		||||
    m.insert(Key::Numpad5 , 0x65);
 | 
			
		||||
    m.insert(Key::Numpad6 , 0x66);
 | 
			
		||||
    m.insert(Key::Numpad7 , 0x67);
 | 
			
		||||
    m.insert(Key::Numpad8 , 0x68);
 | 
			
		||||
    m.insert(Key::Numpad9 , 0x69);
 | 
			
		||||
    m.insert(Key::NumpadAdd , 0x6B);      // Add
 | 
			
		||||
    m.insert(Key::NumpadSubtract , 0x6D); // Subtract
 | 
			
		||||
    m.insert(Key::NumpadMultiply , 0x6A); // Multiply
 | 
			
		||||
    m.insert(Key::NumpadDivide , 0x6F);   // Divide
 | 
			
		||||
    m.insert(Key::NumpadDecimal , 0x6E);  // Decimal
 | 
			
		||||
    m.insert(Key::NumpadEqual , '=' as u16);
 | 
			
		||||
    m.insert(Key::NumpadComma , ',' as u16);
 | 
			
		||||
    m.insert(Key::NumpadEnter , 0x0D);
 | 
			
		||||
    m.insert(Key::NumLock , 0x90);
 | 
			
		||||
    m.insert(Key::Minus , '-' as u16);
 | 
			
		||||
    m.insert(Key::Equal , '=' as u16);
 | 
			
		||||
    m.insert(Key::BracketLeft , '{' as u16);
 | 
			
		||||
    m.insert(Key::BracketRight , '}' as u16);
 | 
			
		||||
    m.insert(Key::Semicolon , ';' as u16);
 | 
			
		||||
    m.insert(Key::Quote , '\'' as u16);
 | 
			
		||||
    m.insert(Key::Backquote , '`' as u16);
 | 
			
		||||
    m.insert(Key::Backslash , '\\' as u16);
 | 
			
		||||
    m.insert(Key::Comma , ',' as u16);
 | 
			
		||||
    m.insert(Key::Period , '~' as u16);
 | 
			
		||||
    m.insert(Key::Slash , '/' as u16);
 | 
			
		||||
    m.insert(Key::Escape , 0x1B);
 | 
			
		||||
    m.insert(Key::Enter , 0x0D);
 | 
			
		||||
    m.insert(Key::Backspace , 0x08);
 | 
			
		||||
    m.insert(Key::Tab , 0x09);
 | 
			
		||||
    m.insert(Key::Space , 0x20);
 | 
			
		||||
    m.insert(Key::CapsLock , 0x14);
 | 
			
		||||
    m.insert(Key::ShiftLeft , 0xA0);
 | 
			
		||||
    m.insert(Key::ShiftRight , 0xA1);
 | 
			
		||||
    m.insert(Key::ControlLeft , 0xA2);
 | 
			
		||||
    m.insert(Key::ControlRight , 0xA3);
 | 
			
		||||
    m.insert(Key::AltLeft , 0xA4);
 | 
			
		||||
    m.insert(Key::AltRight , 0xA5);
 | 
			
		||||
    m.insert(Key::Pause , 0x13);
 | 
			
		||||
    m.insert(Key::ScrollLock , 0x91);
 | 
			
		||||
    m.insert(Key::PrintScreen , 0x2C);
 | 
			
		||||
    m.insert(Key::ArrowLeft , 0x25);
 | 
			
		||||
    m.insert(Key::ArrowUp , 0x26);
 | 
			
		||||
    m.insert(Key::ArrowRight , 0x27);
 | 
			
		||||
    m.insert(Key::ArrowDown , 0x28);
 | 
			
		||||
    m.insert(Key::PageUp , 0x21);
 | 
			
		||||
    m.insert(Key::PageDown , 0x22);
 | 
			
		||||
    m.insert(Key::Home , 0x24);
 | 
			
		||||
    m.insert(Key::End , 0x23);
 | 
			
		||||
    m.insert(Key::Insert , 0x2D);
 | 
			
		||||
    m.insert(Key::Delete , 0x2E);
 | 
			
		||||
    m.insert(Key::MetaLeft , 0x5B);
 | 
			
		||||
    m.insert(Key::MetaRight , 0x5C);
 | 
			
		||||
    m
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static ref VK_2_KEY_MAP: HashMap<WORD, Key> = {
 | 
			
		||||
    let mut m = HashMap::new();
 | 
			
		||||
    m.insert(0x30, Key::Digit0);
 | 
			
		||||
    m.insert(0x31, Key::Digit1);
 | 
			
		||||
    m.insert(0x32, Key::Digit2);
 | 
			
		||||
    m.insert(0x33, Key::Digit3);
 | 
			
		||||
    m.insert(0x34, Key::Digit4);
 | 
			
		||||
    m.insert(0x35, Key::Digit5);
 | 
			
		||||
    m.insert(0x36, Key::Digit6);
 | 
			
		||||
    m.insert(0x37, Key::Digit7);
 | 
			
		||||
    m.insert(0x38, Key::Digit8);
 | 
			
		||||
    m.insert(0x39, Key::Digit9);
 | 
			
		||||
    m.insert(0x41, Key::KeyA);
 | 
			
		||||
    m.insert(0x42, Key::KeyB);
 | 
			
		||||
    m.insert(0x43, Key::KeyC);
 | 
			
		||||
    m.insert(0x44, Key::KeyD);
 | 
			
		||||
    m.insert(0x45, Key::KeyE);
 | 
			
		||||
    m.insert(0x46, Key::KeyF);
 | 
			
		||||
    m.insert(0x47, Key::KeyG);
 | 
			
		||||
    m.insert(0x48, Key::KeyH);
 | 
			
		||||
    m.insert(0x49, Key::KeyI);
 | 
			
		||||
    m.insert(0x4A, Key::KeyJ);
 | 
			
		||||
    m.insert(0x4B, Key::KeyK);
 | 
			
		||||
    m.insert(0x4C, Key::KeyL);
 | 
			
		||||
    m.insert(0x4D, Key::KeyM);
 | 
			
		||||
    m.insert(0x4E, Key::KeyN);
 | 
			
		||||
    m.insert(0x4F, Key::KeyO);
 | 
			
		||||
    m.insert(0x50, Key::KeyP);
 | 
			
		||||
    m.insert(0x51, Key::KeyQ);
 | 
			
		||||
    m.insert(0x52, Key::KeyR);
 | 
			
		||||
    m.insert(0x53, Key::KeyS);
 | 
			
		||||
    m.insert(0x54, Key::KeyT);
 | 
			
		||||
    m.insert(0x55, Key::KeyU);
 | 
			
		||||
    m.insert(0x56, Key::KeyV);
 | 
			
		||||
    m.insert(0x57, Key::KeyW);
 | 
			
		||||
    m.insert(0x58, Key::KeyX);
 | 
			
		||||
    m.insert(0x59, Key::KeyY);
 | 
			
		||||
    m.insert(0x5A, Key::KeyZ);
 | 
			
		||||
    m.insert(0x70, Key::F1);
 | 
			
		||||
    m.insert(0x71, Key::F2);
 | 
			
		||||
    m.insert(0x72, Key::F3);
 | 
			
		||||
    m.insert(0x73, Key::F4);
 | 
			
		||||
    m.insert(0x74, Key::F5);
 | 
			
		||||
    m.insert(0x75, Key::F6);
 | 
			
		||||
    m.insert(0x76, Key::F7);
 | 
			
		||||
    m.insert(0x77, Key::F8);
 | 
			
		||||
    m.insert(0x78, Key::F9);
 | 
			
		||||
    m.insert(0x79, Key::F10);
 | 
			
		||||
    m.insert(0x7A, Key::F11);
 | 
			
		||||
    m.insert(0x7B, Key::F12);
 | 
			
		||||
    m.insert(0x7C, Key::F13);
 | 
			
		||||
    m.insert(0x7D, Key::F14);
 | 
			
		||||
    m.insert(0x7E, Key::F15);
 | 
			
		||||
    m.insert(0x7F, Key::F16);
 | 
			
		||||
    m.insert(0x80, Key::F17);
 | 
			
		||||
    m.insert(0x81, Key::F18);
 | 
			
		||||
    m.insert(0x82, Key::F19);
 | 
			
		||||
    m.insert(0x83, Key::F20);
 | 
			
		||||
    m.insert(0x84, Key::F21);
 | 
			
		||||
    m.insert(0x85, Key::F22);
 | 
			
		||||
    m.insert(0x86, Key::F23);
 | 
			
		||||
    m.insert(0x87, Key::F24);
 | 
			
		||||
    m.insert(0x60, Key::Numpad0);
 | 
			
		||||
    m.insert(0x61, Key::Numpad1);
 | 
			
		||||
    m.insert(0x62, Key::Numpad2);
 | 
			
		||||
    m.insert(0x63, Key::Numpad3);
 | 
			
		||||
    m.insert(0x64, Key::Numpad4);
 | 
			
		||||
    m.insert(0x65, Key::Numpad5);
 | 
			
		||||
    m.insert(0x66, Key::Numpad6);
 | 
			
		||||
    m.insert(0x67, Key::Numpad7);
 | 
			
		||||
    m.insert(0x68, Key::Numpad8);
 | 
			
		||||
    m.insert(0x69, Key::Numpad9);
 | 
			
		||||
    m.insert(0x6B, Key::NumpadAdd);      // Add
 | 
			
		||||
    m.insert(0x6D, Key::NumpadSubtract); // Subtract
 | 
			
		||||
    m.insert(0x6A, Key::NumpadMultiply); // Multiply
 | 
			
		||||
    m.insert(0x6F, Key::NumpadDivide);   // Divide
 | 
			
		||||
    m.insert(0x6E, Key::NumpadDecimal);  // Decimal
 | 
			
		||||
    m.insert( 0x0D, Key::NumpadEnter);
 | 
			
		||||
    m.insert( 0x90, Key::NumLock);
 | 
			
		||||
    m.insert('-' as u16, Key::Minus);
 | 
			
		||||
    m.insert('=' as u16, Key::Equal);
 | 
			
		||||
    m.insert('{' as u16, Key::BracketLeft);
 | 
			
		||||
    m.insert('}' as u16, Key::BracketRight);
 | 
			
		||||
    m.insert(';' as u16, Key::Semicolon);
 | 
			
		||||
    m.insert('\'' as u16, Key::Quote);
 | 
			
		||||
    m.insert('`' as u16, Key::Backquote);
 | 
			
		||||
    m.insert('\\' as u16, Key::Backslash);
 | 
			
		||||
    m.insert(',' as u16, Key::Comma);
 | 
			
		||||
    m.insert('~' as u16, Key::Period);
 | 
			
		||||
    m.insert('/' as u16, Key::Slash);
 | 
			
		||||
    m.insert(0x1B, Key::Escape);
 | 
			
		||||
    m.insert( 0x0D, Key::Enter);
 | 
			
		||||
    m.insert( 0x08, Key::Backspace);
 | 
			
		||||
    m.insert( 0x09, Key::Tab);
 | 
			
		||||
    m.insert( 0x20, Key::Space);
 | 
			
		||||
    m.insert(0x14, Key::CapsLock);
 | 
			
		||||
    m.insert(0xA0, Key::ShiftLeft);
 | 
			
		||||
    m.insert(0xA1, Key::ShiftRight);
 | 
			
		||||
    m.insert( 0xA2, Key::ControlLeft);
 | 
			
		||||
    m.insert( 0xA3, Key::ControlRight);
 | 
			
		||||
    m.insert( 0xA4, Key::AltLeft);
 | 
			
		||||
    m.insert(0xA5, Key::AltRight);
 | 
			
		||||
    m.insert(0x13, Key::Pause);
 | 
			
		||||
    m.insert(0x91, Key::ScrollLock);
 | 
			
		||||
    m.insert(0x2C, Key::PrintScreen);
 | 
			
		||||
    m.insert(0x25, Key::ArrowLeft);
 | 
			
		||||
    m.insert(0x26, Key::ArrowUp);
 | 
			
		||||
    m.insert(0x27, Key::ArrowRight);
 | 
			
		||||
    m.insert(0x28, Key::ArrowDown);
 | 
			
		||||
    m.insert(0x21, Key::PageUp);
 | 
			
		||||
    m.insert(0x22, Key::PageDown);
 | 
			
		||||
    m.insert( 0x24, Key::Home);
 | 
			
		||||
    m.insert( 0x23, Key::End);
 | 
			
		||||
    m.insert(0x2D, Key::Insert);
 | 
			
		||||
    m.insert(0x2E, Key::Delete);
 | 
			
		||||
    m.insert(0x5B, Key::MetaLeft);
 | 
			
		||||
    m.insert(0x5C, Key::MetaRight);
 | 
			
		||||
    m
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn default_callback(event: Event) {
 | 
			
		||||
  println!("Default : Event {:?}", event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mut HOOK: HHOOK = null_mut();
 | 
			
		||||
static mut HOOK_CALLBACK: HookCallback = default_callback;
 | 
			
		||||
 | 
			
		||||
impl Robot {
 | 
			
		||||
  pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> {
 | 
			
		||||
    if HOOK.is_null() {
 | 
			
		||||
      let r = windows::hook(WH_KEYBOARD_LL, Self::key_raw_callback);
 | 
			
		||||
 | 
			
		||||
      if r.is_err() {
 | 
			
		||||
        return Err(windows::HookError::Keyboard(r.err().unwrap()));
 | 
			
		||||
      }
 | 
			
		||||
      HOOK = r.ok().unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HOOK_CALLBACK = callback;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub unsafe fn key_unlisten() -> Result<(), windows::HookError> {
 | 
			
		||||
    if !HOOK.is_null() {
 | 
			
		||||
      let r = windows::unhook(HOOK);
 | 
			
		||||
      if r.is_err() {
 | 
			
		||||
        return Err(windows::HookError::Keyboard(r.err().unwrap()));
 | 
			
		||||
      }
 | 
			
		||||
      HOOK = null_mut();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HOOK_CALLBACK = default_callback;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub fn key_press(key: Key) {
 | 
			
		||||
    let dw_flags = KEYEVENTF_SCANCODE;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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) {
 | 
			
		||||
    let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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 {
 | 
			
		||||
    match Self::key_2_virtual_key(key) {
 | 
			
		||||
      Some(vk) => (unsafe { GetAsyncKeyState(vk as i32) } >> 15) != 0,
 | 
			
		||||
      None => false,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn key_to_scancode(key: Key) -> u16 {
 | 
			
		||||
    match Self::key_2_virtual_key(key) {
 | 
			
		||||
      Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 },
 | 
			
		||||
      None => 0,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unsafe fn get_virtual_key(lpdata: isize) -> u32 {
 | 
			
		||||
    let kb = *(lpdata as *const KBDLLHOOKSTRUCT);
 | 
			
		||||
    kb.vkCode
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unsafe extern "system" fn key_raw_callback(
 | 
			
		||||
    code: c_int,
 | 
			
		||||
    param: WPARAM,
 | 
			
		||||
    lpdata: LPARAM,
 | 
			
		||||
  ) -> LRESULT {
 | 
			
		||||
    if code == HC_ACTION {
 | 
			
		||||
      let opt = Self::key_convert(param, lpdata);
 | 
			
		||||
      if let Some(event_type) = opt {
 | 
			
		||||
        let event = Event {
 | 
			
		||||
          event_type,
 | 
			
		||||
          time: SystemTime::now(),
 | 
			
		||||
        };
 | 
			
		||||
        HOOK_CALLBACK(event);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    CallNextHookEx(HOOK, code, param, lpdata)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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> {
 | 
			
		||||
    match KEY_2_VK_MAP.get(&key) {
 | 
			
		||||
      Some(v) => Some(*v),
 | 
			
		||||
      None => None,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn virtual_key_2_key(virtual_key: WORD) -> Option<Key> {
 | 
			
		||||
    match VK_2_KEY_MAP.get(&virtual_key) {
 | 
			
		||||
      Some(v) => Some(*v),
 | 
			
		||||
      None => None,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/windows/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/windows/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
use std::ptr::null_mut;
 | 
			
		||||
use winapi::ctypes::c_int;
 | 
			
		||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
 | 
			
		||||
use winapi::shared::windef::HHOOK;
 | 
			
		||||
use winapi::um::errhandlingapi::GetLastError;
 | 
			
		||||
use winapi::um::winuser::{SetWindowsHookExA, UnhookWindowsHookEx};
 | 
			
		||||
 | 
			
		||||
pub mod keyboard;
 | 
			
		||||
pub mod mouse;
 | 
			
		||||
 | 
			
		||||
pub type HookCallback =
 | 
			
		||||
  unsafe extern "system" fn(code: c_int, param: WPARAM, lpdata: LPARAM) -> LRESULT;
 | 
			
		||||
 | 
			
		||||
pub enum HookError {
 | 
			
		||||
  Mouse(DWORD),
 | 
			
		||||
  Keyboard(DWORD),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub unsafe fn hook(id_hook: c_int, callback: HookCallback) -> Result<HHOOK, DWORD> {
 | 
			
		||||
  let hook = SetWindowsHookExA(id_hook, Some(callback), null_mut(), 0);
 | 
			
		||||
 | 
			
		||||
  if hook.is_null() {
 | 
			
		||||
    let error = GetLastError();
 | 
			
		||||
    return Err(error);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Ok(hook)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub unsafe fn unhook(hook: HHOOK) -> Result<(), DWORD> {
 | 
			
		||||
  if hook.is_null() {
 | 
			
		||||
    return Ok(());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  UnhookWindowsHookEx(hook);
 | 
			
		||||
  Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										213
									
								
								src/windows/mouse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/windows/mouse.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,213 @@
 | 
			
		||||
use crate::windows;
 | 
			
		||||
use crate::{Button, Event, EventType, HookCallback, Robot};
 | 
			
		||||
use std::convert::TryInto;
 | 
			
		||||
use std::mem::{size_of, transmute};
 | 
			
		||||
use std::ptr::null_mut;
 | 
			
		||||
use std::time::SystemTime;
 | 
			
		||||
use winapi::ctypes::c_int;
 | 
			
		||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
 | 
			
		||||
use winapi::shared::windef::HHOOK;
 | 
			
		||||
use winapi::um::winuser::{
 | 
			
		||||
  CallNextHookEx, GetAsyncKeyState, GetSystemMetrics, SendInput, HC_ACTION, INPUT, INPUT_MOUSE,
 | 
			
		||||
  LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN,
 | 
			
		||||
  MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP,
 | 
			
		||||
  MOUSEEVENTF_VIRTUALDESK, MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN,
 | 
			
		||||
  SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1,
 | 
			
		||||
  VK_XBUTTON2, WH_MOUSE_LL, WM_LBUTTONDOWN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
fn default_callback(event: Event) {
 | 
			
		||||
  println!("Default : Event {:?}", event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mut HOOK: HHOOK = null_mut();
 | 
			
		||||
static mut HOOK_CALLBACK: HookCallback = default_callback;
 | 
			
		||||
 | 
			
		||||
impl Robot {
 | 
			
		||||
  pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> {
 | 
			
		||||
    if HOOK.is_null() {
 | 
			
		||||
      let r = windows::hook(WH_MOUSE_LL, Self::mouse_raw_callback);
 | 
			
		||||
 | 
			
		||||
      if r.is_err() {
 | 
			
		||||
        return Err(windows::HookError::Mouse(r.err().unwrap()));
 | 
			
		||||
      }
 | 
			
		||||
      HOOK = r.ok().unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HOOK_CALLBACK = callback;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> {
 | 
			
		||||
    if !HOOK.is_null() {
 | 
			
		||||
      let r = windows::unhook(HOOK);
 | 
			
		||||
      if r.is_err() {
 | 
			
		||||
        return Err(windows::HookError::Mouse(r.err().unwrap()));
 | 
			
		||||
      }
 | 
			
		||||
      HOOK = null_mut();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HOOK_CALLBACK = default_callback;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub fn mouse_move_to(dx: i32, dy: i32) {
 | 
			
		||||
    let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
 | 
			
		||||
    let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
 | 
			
		||||
    if width == 0 || height == 0 {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    let pressed_left = Self::mouse_pressed(Button::Left);
 | 
			
		||||
    let pressed_right = Self::mouse_pressed(Button::Right);
 | 
			
		||||
    let pressed_middle = Self::mouse_pressed(Button::Middle);
 | 
			
		||||
    let mut dw_flags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK;
 | 
			
		||||
 | 
			
		||||
    if pressed_left {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_LEFTDOWN;
 | 
			
		||||
    }
 | 
			
		||||
    if pressed_right {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_RIGHTDOWN;
 | 
			
		||||
    }
 | 
			
		||||
    if pressed_middle {
 | 
			
		||||
      dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      type_: INPUT_MOUSE,
 | 
			
		||||
      u: unsafe {
 | 
			
		||||
        transmute(MOUSEINPUT {
 | 
			
		||||
          dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / {
 | 
			
		||||
            GetSystemMetrics(SM_CXVIRTUALSCREEN)
 | 
			
		||||
          },
 | 
			
		||||
          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) {
 | 
			
		||||
    let btn = Self::mouse_button_event(EventType::MousePress(button));
 | 
			
		||||
 | 
			
		||||
    let dw_flags = btn;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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) {
 | 
			
		||||
    let btn = Self::mouse_button_event(EventType::MouseRelease(button));
 | 
			
		||||
 | 
			
		||||
    let dw_flags = btn;
 | 
			
		||||
 | 
			
		||||
    let mut input = INPUT {
 | 
			
		||||
      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_pressed(button: Button) -> bool {
 | 
			
		||||
    (unsafe { GetAsyncKeyState(Self::mouse_button_virtual_key(button)) } >> 15) != 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn mouse_button_event(ev: EventType) -> DWORD {
 | 
			
		||||
    match ev {
 | 
			
		||||
      EventType::MousePress(button) => match button {
 | 
			
		||||
        Button::Left => MOUSEEVENTF_LEFTDOWN,
 | 
			
		||||
        Button::Middle => MOUSEEVENTF_MIDDLEDOWN,
 | 
			
		||||
        Button::Right => MOUSEEVENTF_RIGHTDOWN,
 | 
			
		||||
        _ => unimplemented!(),
 | 
			
		||||
      },
 | 
			
		||||
      EventType::MouseRelease(button) => match button {
 | 
			
		||||
        Button::Left => MOUSEEVENTF_LEFTUP,
 | 
			
		||||
        Button::Middle => MOUSEEVENTF_MIDDLEUP,
 | 
			
		||||
        Button::Right => MOUSEEVENTF_RIGHTUP,
 | 
			
		||||
        _ => unimplemented!(),
 | 
			
		||||
      },
 | 
			
		||||
      _ => unimplemented!(),
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn mouse_button_virtual_key(button: Button) -> c_int {
 | 
			
		||||
    match button {
 | 
			
		||||
      Button::Left => VK_LBUTTON,
 | 
			
		||||
      Button::Middle => VK_MBUTTON,
 | 
			
		||||
      Button::Right => VK_RBUTTON,
 | 
			
		||||
      Button::X1 => VK_XBUTTON1,
 | 
			
		||||
      Button::X2 => VK_XBUTTON2,
 | 
			
		||||
      _ => unimplemented!(),
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unsafe fn get_mouse_point(lpdata: isize) -> (i32, i32) {
 | 
			
		||||
    let mouse = *(lpdata as *const MSLLHOOKSTRUCT);
 | 
			
		||||
    (mouse.pt.x, mouse.pt.y)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unsafe extern "system" fn mouse_raw_callback(
 | 
			
		||||
    code: c_int,
 | 
			
		||||
    param: WPARAM,
 | 
			
		||||
    lpdata: LPARAM,
 | 
			
		||||
  ) -> LRESULT {
 | 
			
		||||
    if code == HC_ACTION {
 | 
			
		||||
      let opt = Self::mouse_convert(param, lpdata);
 | 
			
		||||
      if let Some(event_type) = opt {
 | 
			
		||||
        let event = Event {
 | 
			
		||||
          event_type,
 | 
			
		||||
          time: SystemTime::now(),
 | 
			
		||||
        };
 | 
			
		||||
        HOOK_CALLBACK(event);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    CallNextHookEx(HOOK, code, param, lpdata)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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