use crate::core::keyboard::get_keymap_key;
use crate::errors::AutoGuiError;
use std::{collections::HashMap, mem::size_of, thread::sleep, time::Duration};
use winapi::um::wingdi::SRCAND;
use winapi::um::winuser::{MapVirtualKeyW, MAPVK_VK_TO_VSC};
use winapi::um::winuser::{
SendInput, INPUT, INPUT_KEYBOARD, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, VK_CONTROL, VK_MENU,
VK_SHIFT,
};
#[derive(Debug)]
pub struct Keyboard {
pub keymap: HashMap<String, (u16, bool)>,
}
impl Keyboard {
pub fn new() -> Keyboard {
let keyset = Keyboard::create_keymap();
Keyboard { keymap: keyset }
}
unsafe fn press_key(scan_code: &u16) {
let mut input: INPUT = std::mem::zeroed();
input.type_ = INPUT_KEYBOARD;
{
let scan_code = *scan_code;
let ki = input.u.ki_mut();
if scan_code == VK_SHIFT as u16
|| scan_code == VK_CONTROL as u16
|| scan_code == VK_MENU as u16
{
ki.wVk = scan_code; ki.wScan = 0;
ki.dwFlags = 0; } else {
let scan_code = MapVirtualKeyW(scan_code as u32, MAPVK_VK_TO_VSC) as u16;
ki.wVk = 0;
ki.wScan = scan_code;
ki.dwFlags = KEYEVENTF_SCANCODE;
}
ki.time = 0;
ki.dwExtraInfo = 0;
}
SendInput(1, &mut input, size_of::<INPUT>() as i32);
}
unsafe fn release_key(scan_code: &u16) {
let mut input: INPUT = std::mem::zeroed();
input.type_ = INPUT_KEYBOARD;
{
let scan_code = *scan_code;
let ki = input.u.ki_mut();
if scan_code == VK_SHIFT as u16
|| scan_code == VK_CONTROL as u16
|| scan_code == VK_MENU as u16
{
ki.wVk = scan_code; ki.wScan = 0;
ki.dwFlags = KEYEVENTF_KEYUP; } else {
let scan_code = MapVirtualKeyW(scan_code as u32, MAPVK_VK_TO_VSC) as u16;
ki.wVk = 0;
ki.wScan = scan_code;
ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
}
ki.time = 0;
ki.dwExtraInfo = 0;
}
SendInput(1, &mut input, size_of::<INPUT>() as i32);
}
pub fn key_down(&self, key: &str) -> Result<(), AutoGuiError> {
let (value, _) = get_keymap_key(self, key)?;
unsafe {
Keyboard::press_key(value);
}
Ok(())
}
pub fn key_up(&self, key: &str) -> Result<(), AutoGuiError> {
let (value, _) = get_keymap_key(self, key)?;
unsafe {
Keyboard::release_key(value);
}
Ok(())
}
pub fn send_key(scan_code: &u16) {
unsafe {
Keyboard::press_key(scan_code);
Keyboard::release_key(scan_code);
}
}
pub fn send_shifted_key(scan_code: &u16) {
unsafe {
Keyboard::press_key(&0x10); sleep(Duration::from_micros(50));
Keyboard::send_key(scan_code);
sleep(Duration::from_micros(50));
Keyboard::release_key(&0x10); sleep(Duration::from_micros(50));
}
}
pub fn send_char(&self, key: &char) -> Result<(), AutoGuiError> {
let char_string = String::from(*key);
let (value, shifted) = get_keymap_key(self, &char_string)?;
if *shifted {
Keyboard::send_shifted_key(value);
} else {
Keyboard::send_key(value);
}
Ok(())
}
pub fn send_command(&self, key: &str) -> Result<(), AutoGuiError> {
let (value, _) = get_keymap_key(self, key)?;
Keyboard::send_key(value);
Ok(())
}
pub fn send_multi_key(
&self,
key_1: &str,
key_2: &str,
key_3: Option<String>,
) -> Result<(), AutoGuiError> {
let (value_1, _) = get_keymap_key(self, key_1)?;
let (value_2, _) = get_keymap_key(self, key_2)?;
let mut third_key = false;
let value_3 = match key_3 {
Some(value) => {
third_key = true;
let (value_, _) = get_keymap_key(self, &value)?;
value_
}
None => &0,
};
unsafe {
Keyboard::press_key(value_1);
Keyboard::press_key(value_2);
if third_key {
Keyboard::press_key(value_3);
Keyboard::release_key(value_3);
}
Keyboard::release_key(value_2);
Keyboard::release_key(value_1);
}
Ok(())
}
pub fn create_keymap() -> HashMap<String, (u16, bool)> {
let mut key_map: HashMap<String, (u16, bool)> = HashMap::new();
key_map.insert(String::from("backspace"), (0x08, false)); key_map.insert(String::from("super"), (0x5B, false)); key_map.insert(String::from("tab"), (0x09, false)); key_map.insert(String::from("clear"), (0x0c, false)); key_map.insert(String::from("enter"), (0x0d, false)); key_map.insert(String::from("return"), (0x0d, false)); key_map.insert(String::from("shift_l"), (0x10, false)); key_map.insert(String::from("ctrl"), (0x11, false)); key_map.insert(String::from("alt"), (0x12, false)); key_map.insert(String::from("pause"), (0x13, false)); key_map.insert(String::from("caps_lock"), (0x14, false)); key_map.insert(String::from("kana"), (0x15, false)); key_map.insert(String::from("hanguel"), (0x15, false)); key_map.insert(String::from("hangul"), (0x15, false)); key_map.insert(String::from("junja"), (0x17, false)); key_map.insert(String::from("final"), (0x18, false)); key_map.insert(String::from("hanja"), (0x19, false)); key_map.insert(String::from("kanji"), (0x19, false)); key_map.insert(String::from("esc"), (0x1b, false)); key_map.insert(String::from("escape"), (0x1b, false)); key_map.insert(String::from("convert"), (0x1c, false)); key_map.insert(String::from("nonconvert"), (0x1d, false)); key_map.insert(String::from("accept"), (0x1e, false)); key_map.insert(String::from("modechange"), (0x1f, false)); key_map.insert(String::from(" "), (0x20, false)); key_map.insert(String::from("space"), (0x20, false)); key_map.insert(String::from("pgup"), (0x21, false)); key_map.insert(String::from("pgdn"), (0x22, false)); key_map.insert(String::from("page_up"), (0x21, false)); key_map.insert(String::from("page_down"), (0x22, false)); key_map.insert(String::from("end"), (0x23, false)); key_map.insert(String::from("home"), (0x24, false)); key_map.insert(String::from("left_arrow"), (0x25, false)); key_map.insert(String::from("up_arrow"), (0x26, false)); key_map.insert(String::from("right_arrow"), (0x27, false)); key_map.insert(String::from("down_arrow"), (0x28, false));
key_map.insert(String::from("left"), (0x25, false)); key_map.insert(String::from("up"), (0x26, false)); key_map.insert(String::from("right"), (0x27, false)); key_map.insert(String::from("down"), (0x28, false));
key_map.insert(String::from("select"), (0x29, false)); key_map.insert(String::from("print"), (0x2a, false)); key_map.insert(String::from("execute"), (0x2b, false)); key_map.insert(String::from("prtsc"), (0x2c, false)); key_map.insert(String::from("prtscr"), (0x2c, false)); key_map.insert(String::from("prntscrn"), (0x2c, false)); key_map.insert(String::from("printscreen"), (0x2c, false)); key_map.insert(String::from("insert"), (0x2d, false)); key_map.insert(String::from("del"), (0x2e, false)); key_map.insert(String::from("delete"), (0x2e, false)); key_map.insert(String::from("help"), (0x2f, false)); key_map.insert(String::from("win"), (0x5b, false)); key_map.insert(String::from("winleft"), (0x5b, false)); key_map.insert(String::from("win_l"), (0x5b, false)); key_map.insert(String::from("super"), (0x5b, false)); key_map.insert(String::from("super_l"), (0x5b, false)); key_map.insert(String::from("winright"), (0x5c, false)); key_map.insert(String::from("win_r"), (0x5c, false)); key_map.insert(String::from("super_r"), (0x5c, false)); key_map.insert(String::from("apps"), (0x5d, false)); key_map.insert(String::from("sleep"), (0x5f, false)); key_map.insert(String::from("num0"), (0x60, false)); key_map.insert(String::from("num1"), (0x61, false)); key_map.insert(String::from("num2"), (0x62, false)); key_map.insert(String::from("num3"), (0x63, false)); key_map.insert(String::from("num4"), (0x64, false)); key_map.insert(String::from("num5"), (0x65, false)); key_map.insert(String::from("num6"), (0x66, false)); key_map.insert(String::from("num7"), (0x67, false)); key_map.insert(String::from("num8"), (0x68, false)); key_map.insert(String::from("num9"), (0x69, false)); key_map.insert(String::from("*"), (0x6a, false)); key_map.insert(String::from("+"), (0x6b, false)); key_map.insert(String::from("="), (0xBB, false));
key_map.insert(String::from("separator"), (0x6c, true)); key_map.insert(String::from("-"), (0xBD, false)); key_map.insert(String::from("_"), (0xBD, true)); key_map.insert(String::from("."), (0xBE, false)); key_map.insert(String::from(","), (0xBC, false)); key_map.insert(String::from(">"), (0xBE, true)); key_map.insert(String::from("<"), (0xBC, true)); key_map.insert(String::from("/"), (0x6f, false)); key_map.insert(String::from("?"), (0x6f, true)); key_map.insert(String::from("f1"), (0x70, false)); key_map.insert(String::from("f2"), (0x71, false)); key_map.insert(String::from("f3"), (0x72, false)); key_map.insert(String::from("f4"), (0x73, false)); key_map.insert(String::from("f5"), (0x74, false)); key_map.insert(String::from("f6"), (0x75, false)); key_map.insert(String::from("f7"), (0x76, false)); key_map.insert(String::from("f8"), (0x77, false)); key_map.insert(String::from("f9"), (0x78, false)); key_map.insert(String::from("f10"), (0x79, false)); key_map.insert(String::from("f11"), (0x7a, false)); key_map.insert(String::from("f12"), (0x7b, false)); key_map.insert(String::from("f13"), (0x7c, false)); key_map.insert(String::from("f14"), (0x7d, false)); key_map.insert(String::from("f15"), (0x7e, false)); key_map.insert(String::from("f16"), (0x7f, false)); key_map.insert(String::from("f17"), (0x80, false)); key_map.insert(String::from("f18"), (0x81, false)); key_map.insert(String::from("f19"), (0x82, false)); key_map.insert(String::from("f20"), (0x83, false)); key_map.insert(String::from("f21"), (0x84, false)); key_map.insert(String::from("f22"), (0x85, false)); key_map.insert(String::from("f23"), (0x86, false)); key_map.insert(String::from("f24"), (0x87, false)); key_map.insert(String::from("numlock"), (0x90, false)); key_map.insert(String::from("scrolllock"), (0x91, false)); key_map.insert(String::from("shift_l"), (0xa0, false)); key_map.insert(String::from("shift"), (0xa0, false)); key_map.insert(String::from("shift_r"), (0xa1, false)); key_map.insert(String::from("control_l"), (0xa2, false)); key_map.insert(String::from("control"), (0xa2, false)); key_map.insert(String::from("ctrl"), (0xa2, false)); key_map.insert(String::from("control_r"), (0xa3, false)); key_map.insert(String::from("alt_l"), (0xa4, false)); key_map.insert(String::from("alt"), (0xa4, false)); key_map.insert(String::from("alt_r"), (0xa5, false)); key_map.insert(String::from("browserback"), (0xa6, false)); key_map.insert(String::from("browserforward"), (0xa7, false)); key_map.insert(String::from("browserrefresh"), (0xa8, false)); key_map.insert(String::from("browserstop"), (0xa9, false)); key_map.insert(String::from("browsersearch"), (0xaa, false)); key_map.insert(String::from("browserfavorites"), (0xab, false)); key_map.insert(String::from("browserhome"), (0xac, false)); key_map.insert(String::from("volumemute"), (0xad, false)); key_map.insert(String::from("volumedown"), (0xae, false)); key_map.insert(String::from("volumeup"), (0xaf, false)); key_map.insert(String::from("nexttrack"), (0xb0, false)); key_map.insert(String::from("prevtrack"), (0xb1, false)); key_map.insert(String::from("stop"), (0xb2, false)); key_map.insert(String::from("playpause"), (0xb3, false)); key_map.insert(String::from("launchmail"), (0xb4, false)); key_map.insert(String::from("launchmediaselect"), (0xb5, false)); key_map.insert(String::from("launchapp1"), (0xb6, false)); key_map.insert(String::from("launchapp2"), (0xb7, false)); key_map.insert(String::from("a"), (0x41, false)); key_map.insert(String::from("b"), (0x42, false)); key_map.insert(String::from("c"), (0x43, false)); key_map.insert(String::from("d"), (0x44, false)); key_map.insert(String::from("e"), (0x45, false)); key_map.insert(String::from("f"), (0x46, false)); key_map.insert(String::from("g"), (0x47, false)); key_map.insert(String::from("h"), (0x48, false)); key_map.insert(String::from("i"), (0x49, false)); key_map.insert(String::from("j"), (0x4A, false)); key_map.insert(String::from("k"), (0x4B, false)); key_map.insert(String::from("l"), (0x4C, false)); key_map.insert(String::from("m"), (0x4D, false)); key_map.insert(String::from("n"), (0x4E, false)); key_map.insert(String::from("o"), (0x4F, false)); key_map.insert(String::from("p"), (0x50, false)); key_map.insert(String::from("q"), (0x51, false)); key_map.insert(String::from("r"), (0x52, false)); key_map.insert(String::from("s"), (0x53, false)); key_map.insert(String::from("t"), (0x54, false)); key_map.insert(String::from("u"), (0x55, false)); key_map.insert(String::from("v"), (0x56, false)); key_map.insert(String::from("w"), (0x57, false)); key_map.insert(String::from("x"), (0x58, false)); key_map.insert(String::from("y"), (0x59, false)); key_map.insert(String::from("z"), (0x5A, false)); key_map.insert(String::from("A"), (0x41, true)); key_map.insert(String::from("B"), (0x42, true)); key_map.insert(String::from("C"), (0x43, true)); key_map.insert(String::from("D"), (0x44, true)); key_map.insert(String::from("E"), (0x45, true)); key_map.insert(String::from("F"), (0x46, true)); key_map.insert(String::from("G"), (0x47, true)); key_map.insert(String::from("H"), (0x48, true)); key_map.insert(String::from("I"), (0x49, true)); key_map.insert(String::from("J"), (0x4A, true)); key_map.insert(String::from("K"), (0x4B, true)); key_map.insert(String::from("L"), (0x4C, true)); key_map.insert(String::from("M"), (0x4D, true)); key_map.insert(String::from("N"), (0x4E, true)); key_map.insert(String::from("O"), (0x4F, true)); key_map.insert(String::from("P"), (0x50, true)); key_map.insert(String::from("Q"), (0x51, true)); key_map.insert(String::from("R"), (0x52, true)); key_map.insert(String::from("S"), (0x53, true)); key_map.insert(String::from("T"), (0x54, true)); key_map.insert(String::from("U"), (0x55, true)); key_map.insert(String::from("V"), (0x56, true)); key_map.insert(String::from("W"), (0x57, true)); key_map.insert(String::from("X"), (0x58, true)); key_map.insert(String::from("Y"), (0x59, true)); key_map.insert(String::from("Z"), (0x5A, true)); key_map.insert(String::from("0"), (0x30, false)); key_map.insert(String::from("1"), (0x31, false)); key_map.insert(String::from("2"), (0x32, false)); key_map.insert(String::from("3"), (0x33, false)); key_map.insert(String::from("4"), (0x34, false)); key_map.insert(String::from("5"), (0x35, false)); key_map.insert(String::from("6"), (0x36, false)); key_map.insert(String::from("7"), (0x37, false)); key_map.insert(String::from("8"), (0x38, false)); key_map.insert(String::from("9"), (0x39, false)); key_map.insert(String::from("0"), (0x30, false)); key_map.insert(String::from("!"), (0x31, true)); key_map.insert(String::from("@"), (0x32, true)); key_map.insert(String::from("#"), (0x33, true)); key_map.insert(String::from("$"), (0x34, true)); key_map.insert(String::from("%"), (0x35, true)); key_map.insert(String::from("^"), (0x36, true)); key_map.insert(String::from("&"), (0x37, true)); key_map.insert(String::from("*"), (0x38, true)); key_map.insert(String::from("("), (0x39, true)); key_map.insert(String::from(")"), (0x30, true)); key_map.insert(String::from(";"), (0xBA, false)); key_map.insert(String::from(":"), (0xBA, true)); key_map.insert(String::from("["), (0xDB, false)); key_map.insert(String::from("]"), (0xDD, false)); key_map.insert(String::from("\\"), (0xDC, false)); key_map.insert(String::from("'"), (0xDE, false)); key_map.insert(String::from("{"), (0xDB, true)); key_map.insert(String::from("}"), (0xDD, true)); key_map.insert(String::from("|"), (0xDC, true)); key_map.insert(String::from("\""), (0xDE, true)); key_map
}
}