#![allow(non_snake_case)]
use std::convert::From;
use winapi::shared::windef::*;
use winapi::shared::minwindef::*;
use winapi::um::winuser::*;
use crate::event::*;
impl KeyboardEvent {
pub unsafe fn new(wm_key_code: WPARAM, kbd_hook_struct: *const KBDLLHOOKSTRUCT) -> Self {
KeyboardEvent{
pressed: KeyPress::from(wm_key_code),
key: KeyboardKey::optionally_from(kbd_hook_struct),
is_injected: IsEventInjected::optionally_from_keyboard(kbd_hook_struct),
}
}
}
impl IsEventInjected {
unsafe fn optionally_from_keyboard(value: *const KBDLLHOOKSTRUCT) -> Option<Self> {
if value.is_null() {
None
} else {
Some(IsEventInjected::from_keyboard_flags((*value).flags))
}
}
unsafe fn optionally_from_mouse(value: *const MSLLHOOKSTRUCT) -> Option<Self> {
if value.is_null() {
None
} else {
Some(IsEventInjected::from_mouse_flags((*value).flags))
}
}
fn from_mouse_flags(value: DWORD) -> Self {
let i1 = 0 != value & LLMHF_INJECTED;
let i2 = 0 != value & LLMHF_LOWER_IL_INJECTED;
use IsEventInjected::*;
match i1 || i2 {
true => Injected,
false => NotInjected,
}
}
fn from_keyboard_flags(value: DWORD) -> Self {
let i1 = 0 != value & LLKHF_INJECTED;
let i2 = 0 != value & LLKHF_LOWER_IL_INJECTED;
use IsEventInjected::*;
match i1 || i2 {
true => Injected,
false => NotInjected,
}
}
}
impl From<WPARAM> for KeyPress {
fn from(code: WPARAM) -> Self {
use KeyPress::*;
use IsSystemKeyPress::*;
match code.try_into() {
Ok(WM_KEYDOWN) => Down(Normal),
Ok(WM_KEYUP) => Up(Normal),
Ok(WM_SYSKEYDOWN) => Down(System),
Ok(WM_SYSKEYUP) => Up(System),
_ => Other(code),
}
}
}
impl From<DWORD> for KeyboardKey {
fn from(code: DWORD) -> Self {
use KeyboardKey::*;
match code.try_into() {
Ok(sc) => {
match sc {
VK_BACK => BackSpace,
VK_TAB => Tab,
VK_RETURN => Enter,
VK_ESCAPE => Escape,
VK_SPACE => Space,
VK_PRIOR => PageUp,
VK_NEXT => PageDown,
VK_HOME => Home,
VK_LEFT => ArrowLeft,
VK_UP => ArrowUp,
VK_RIGHT => ArrowRight,
VK_DOWN => ArrowDown,
VK_PRINT => Print,
VK_SNAPSHOT => PrintScreen,
VK_INSERT => Insert,
VK_DELETE => Delete,
VK_0 => Number0,
VK_1 => Number1,
VK_2 => Number2,
VK_3 => Number3,
VK_4 => Number4,
VK_5 => Number5,
VK_6 => Number6,
VK_7 => Number7,
VK_8 => Number8,
VK_9 => Number9,
VK_A => A,
VK_B => B,
VK_C => C,
VK_D => D,
VK_E => E,
VK_F => F,
VK_G => G,
VK_H => H,
VK_I => I,
VK_J => J,
VK_K => K,
VK_L => L,
VK_M => M,
VK_N => N,
VK_O => O,
VK_P => P,
VK_Q => Q,
VK_R => R,
VK_S => S,
VK_T => T,
VK_U => U,
VK_V => V,
VK_W => W,
VK_X => X,
VK_Y => Y,
VK_Z => Z,
VK_LWIN => LeftWindows,
VK_RWIN => RightWindows,
VK_NUMPAD0 => Numpad0,
VK_NUMPAD1 => Numpad1,
VK_NUMPAD2 => Numpad2,
VK_NUMPAD3 => Numpad3,
VK_NUMPAD4 => Numpad4,
VK_NUMPAD5 => Numpad5,
VK_NUMPAD6 => Numpad6,
VK_NUMPAD7 => Numpad7,
VK_NUMPAD8 => Numpad8,
VK_NUMPAD9 => Numpad9,
VK_MULTIPLY => Multiply,
VK_ADD => Add,
VK_SEPARATOR => Separator,
VK_SUBTRACT => Subtract,
VK_DECIMAL => Decimal,
VK_DIVIDE => Divide,
VK_F1 => F1,
VK_F2 => F2,
VK_F3 => F3,
VK_F4 => F4,
VK_F5 => F5,
VK_F6 => F6,
VK_F7 => F7,
VK_F8 => F8,
VK_F9 => F9,
VK_F10 => F10,
VK_F11 => F11,
VK_F12 => F12,
VK_F13 => F13,
VK_F14 => F14,
VK_F15 => F15,
VK_F16 => F16,
VK_F17 => F17,
VK_F18 => F18,
VK_F19 => F19,
VK_F20 => F20,
VK_F21 => F21,
VK_F22 => F22,
VK_F23 => F23,
VK_F24 => F24,
VK_NUMLOCK => NumLock,
VK_SCROLL => ScrollLock,
VK_CAPITAL => CapsLock,
VK_LSHIFT => LeftShift,
VK_RSHIFT => RightShift,
VK_LCONTROL => LeftControl,
VK_RCONTROL => RightControl,
VK_LMENU => LeftAlt,
VK_RMENU => RightAlt,
VK_OEM_PERIOD => Period,
VK_OEM_COMMA => Comma,
VK_OEM_1 => SemiColon,
VK_OEM_2 => Slash,
VK_OEM_3 => Grave,
VK_OEM_4 => LeftBrace,
VK_OEM_5 => BackwardSlash,
VK_OEM_6 => RightBrace,
VK_OEM_7 => Apostrophe,
_ => Other(code),
}
}
Err(_) => Other(code),
}
}
}
impl KeyboardKey {
pub unsafe fn optionally_from(value: *const KBDLLHOOKSTRUCT) -> Option<Self> {
if value.is_null() {
None
} else {
Some(KeyboardKey::from((*value).vkCode))
}
}
}
impl MouseEvent {
pub unsafe fn new(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> Self {
use MouseEventType::*;
MouseEvent{
is_injected: IsEventInjected::optionally_from_mouse(ms_ll_hook_struct),
event: match wm_mouse_param as u32 {
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)),
WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)),
WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)),
WM_XBUTTONDOWN | WM_XBUTTONUP | WM_XBUTTONDBLCLK => Press(MousePressEvent::new(wm_mouse_param, ms_ll_hook_struct)),
WM_MOUSEMOVE => Move(MouseMoveEvent::new(ms_ll_hook_struct)),
WM_MOUSEWHEEL | WM_MOUSEHWHEEL => Wheel(MouseWheelEvent::new(wm_mouse_param, ms_ll_hook_struct)),
_ => Other(wm_mouse_param),
}
}
}
}
impl MousePressEvent {
pub unsafe fn new(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> MousePressEvent {
MousePressEvent {
pressed: MouseButtonPress::from(wm_mouse_param),
button: MouseButton::from(wm_mouse_param, ms_ll_hook_struct),
}
}
}
impl From<POINT> for Point {
fn from(value: POINT) -> Self {
Point { x: value.x, y: value.y }
}
}
impl MouseWheel {
pub fn new(wm_mouse_param: WPARAM) -> MouseWheel {
use MouseWheel::*;
match wm_mouse_param.try_into() {
Ok(param_u32) => {
match param_u32 {
WM_MOUSEWHEEL => Vertical,
WM_MOUSEHWHEEL => Horizontal,
_ => Unknown(wm_mouse_param),
}
},
_ => Unknown(wm_mouse_param),
}
}
}
impl MouseWheelEvent {
pub unsafe fn new(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> MouseWheelEvent {
MouseWheelEvent {
wheel: MouseWheel::new(wm_mouse_param),
direction: MouseWheelDirection::optionally_from(ms_ll_hook_struct)
}
}
}
impl MouseWheelDirection {
pub unsafe fn optionally_from(ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> Option<MouseWheelDirection>{
if ms_ll_hook_struct.is_null() {
None
} else {
Some(MouseWheelDirection::new(&*ms_ll_hook_struct))
}
}
fn new(ms_ll_hook_struct: &MSLLHOOKSTRUCT) -> MouseWheelDirection {
use MouseWheelDirection::*;
let delta = GET_WHEEL_DELTA_WPARAM(ms_ll_hook_struct.mouseData as WPARAM);
match delta {
_ if delta > 0 => Forward,
_ if delta < 0 => Backward,
_ => Unknown(ms_ll_hook_struct.mouseData),
}
}
}
impl MouseMoveEvent {
pub unsafe fn new(ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> MouseMoveEvent {
if ms_ll_hook_struct.is_null() {
MouseMoveEvent{ point: None }
} else {
let msll = &*ms_ll_hook_struct;
let pt = msll.pt;
MouseMoveEvent{ point: Some(pt.into()) }
}
}
}
impl From<WPARAM> for MouseButtonPress {
fn from(value: WPARAM) -> Self {
use MouseButtonPress::*;
match value.try_into() {
Ok(uv) => {
match uv {
WM_LBUTTONDOWN| WM_RBUTTONDOWN| WM_MBUTTONDOWN | WM_XBUTTONDOWN => Down,
WM_RBUTTONUP | WM_LBUTTONUP | WM_MBUTTONUP | WM_XBUTTONUP => Up,
_ => Other(value),
}
}
Err(_) => Other(value),
}
}
}
impl From<WPARAM> for MouseClick {
fn from(value: WPARAM) -> Self {
use MouseClick::*;
match value.try_into() {
Ok (uv) => {
match uv {
WM_LBUTTONDOWN | WM_RBUTTONDOWN | WM_MBUTTONDOWN | WM_XBUTTONDOWN => SingleClick,
WM_LBUTTONUP | WM_RBUTTONUP | WM_MBUTTONUP | WM_XBUTTONUP => SingleClick,
WM_LBUTTONDBLCLK | WM_RBUTTONDBLCLK | WM_MBUTTONDBLCLK | WM_XBUTTONDBLCLK => DoubleClick,
_ => Other(value as u32),
}
},
Err(_) => Other(value as u32),
}
}
}
impl MouseButton {
pub unsafe fn from(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> Self {
let click = MouseClick::from(wm_mouse_param);
use MouseButton::*;
match wm_mouse_param.try_into() {
Ok(param) => {
match param {
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK => Left(click),
WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK => Right(click),
WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK=> Middle(click),
WM_XBUTTONDOWN | WM_XBUTTONUP | WM_XBUTTONDBLCLK => {
if ms_ll_hook_struct.is_null() {
UnkownX(click)
} else {
Self::into_extra(click, &*ms_ll_hook_struct)
}
},
_ => Other(wm_mouse_param)
}
},
Err(_) => Other(wm_mouse_param),
}
}
fn into_extra(click: MouseClick, ms_ll_hook_struct: &MSLLHOOKSTRUCT) -> Self {
use MouseButton::*;
match GET_XBUTTON_WPARAM(ms_ll_hook_struct.mouseData.try_into().expect("")) {
XBUTTON1 => X1(click),
XBUTTON2 => X2(click),
_ => UnkownX(click),
}
}
}