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(absolute: bool, 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_VIRTUALDESK; if absolute { dw_flags = dw_flags | MOUSEEVENTF_ABSOLUTE; } 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::() 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::() 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::() 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!(), } } }