mki_fork 0.2.1

Windows and Linux library for registring global input hooks and simulating keyboard and mouse events. This is a basic fork from mki to update the 'input' dependency that uses an updated libinput 1.19.1 version vs 1.19.0.
Documentation
use crate::Mouse;
use std::mem::{size_of, transmute_copy};
use winapi::um::winuser::{
    SendInput, INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_LEFTDOWN,
    MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTDOWN,
    MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP, MOUSEINPUT, XBUTTON1, XBUTTON2,
};

pub(crate) mod mimpl {
    use crate::windows::mouse::{
        button_to_event_down, button_to_mouse_data, mouse_click, mouse_interact_with, mouse_press,
        mouse_release, Pos,
    };
    use crate::Mouse;

    pub(crate) fn press(button: Mouse) {
        mouse_press(button)
    }

    pub(crate) fn click(button: Mouse) {
        mouse_click(button);
    }

    pub(crate) fn release(button: Mouse) {
        mouse_release(button);
    }

    pub(crate) fn move_to(x: i32, y: i32) {
        mouse_interact_with(0, 0, Some(Pos::absolute(x, y)));
    }

    pub(crate) fn move_by(x: i32, y: i32) {
        mouse_interact_with(0, 0, Some(Pos::relative(x, y)));
    }

    pub(crate) fn click_at(x: i32, y: i32, button: Mouse) {
        mouse_interact_with(
            button_to_event_down(button),
            button_to_mouse_data(button),
            Some(Pos::absolute(x, y)),
        )
    }
}

struct Pos {
    x: i32,
    y: i32,
    absolute: bool,
}

impl Pos {
    fn absolute(x: i32, y: i32) -> Self {
        Pos {
            x,
            y,
            absolute: true,
        }
    }

    fn relative(x: i32, y: i32) -> Self {
        Pos {
            x,
            y,
            absolute: false,
        }
    }
}

fn mouse_interact_with(mut interaction: u32, mouse_data: u16, pos: Option<Pos>) {
    let mut x = 0;
    let mut y = 0;
    if let Some(pos) = pos {
        if pos.absolute {
            interaction |= MOUSEEVENTF_ABSOLUTE;
        }
        x = pos.x;
        y = pos.y;
    }
    unsafe {
        let mut x = INPUT {
            type_: INPUT_MOUSE,
            u: transmute_copy(&MOUSEINPUT {
                dx: x,
                dy: y,
                mouseData: mouse_data.into(),
                time: 0,
                dwFlags: interaction,
                dwExtraInfo: 0,
            }),
        };

        SendInput(1, &mut x as LPINPUT, size_of::<INPUT>() as libc::c_int);
    }
}

pub fn mouse_press(button: Mouse) {
    let click = button_to_event_down(button) | button_to_event_up(button);
    mouse_interact_with(click, button_to_mouse_data(button), mouse_to_pos(button))
}

pub fn mouse_release(button: Mouse) {
    mouse_interact_with(
        button_to_event_up(button),
        button_to_mouse_data(button),
        mouse_to_pos(button),
    )
}

pub fn mouse_click(button: Mouse) {
    mouse_interact_with(
        button_to_event_down(button),
        button_to_mouse_data(button),
        mouse_to_pos(button),
    )
}

fn button_to_mouse_data(button: Mouse) -> u16 {
    match button {
        Mouse::Side | Mouse::DoubleSide => XBUTTON1,
        Mouse::Extra | Mouse::DoubleExtra => XBUTTON2,
        _ => 0,
    }
}

fn button_to_event_up(button: Mouse) -> u32 {
    use Mouse::*;
    match button {
        Left | DoubleLeft => MOUSEEVENTF_LEFTDOWN,
        Right | DoubleRight => MOUSEEVENTF_RIGHTDOWN,
        Middle | DoubleMiddle => MOUSEEVENTF_MIDDLEDOWN,
        Side | DoubleSide | Extra | DoubleExtra => MOUSEEVENTF_XDOWN,
    }
}

fn button_to_event_down(button: Mouse) -> u32 {
    use Mouse::*;
    match button {
        Left | DoubleLeft => MOUSEEVENTF_LEFTUP,
        Right | DoubleRight => MOUSEEVENTF_RIGHTUP,
        Middle | DoubleMiddle => MOUSEEVENTF_MIDDLEUP,
        Side | DoubleSide | Extra | DoubleExtra => MOUSEEVENTF_XUP,
    }
}

fn mouse_to_pos(button: Mouse) -> Option<Pos> {
    use Mouse::*;
    match button {
        Left | DoubleLeft => None,
        Right | DoubleRight => None,
        Middle | DoubleMiddle => None,
        Side | DoubleSide | Extra | DoubleExtra => None,
    }
}