use std::mem::{size_of, transmute};
use winapi::ctypes::c_int;
use winapi::shared::minwindef::DWORD;
use winapi::um::winuser::{
GetAsyncKeyState, SendInput, INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE,
MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP,
MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK,
MOUSEINPUT, 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 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,
dy,
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!(),
}
}
}