mouse-rs 0.4.2

Library to control your mouse via rust
Documentation
use crate::types::keys::Keys;
use crate::types::Point;
use std::error::Error;

use libc;

use libc::{c_int, c_void, c_char};
use std::{ptr};

type XDO = *const c_void;
type WINDOW = c_int;
type INTPTR = *mut c_int;

fn xdo_translate_key(key: &Keys) -> c_int {
    match key {
        Keys::LEFT => 1,
        Keys::WHEEL | Keys::MIDDLE => 2,
        Keys::RIGHT => 3,
        _ => panic!("Invalid key passed: {:?}", key)
    }
}

impl From<(c_int, c_int)> for Point {
    fn from(other: (c_int, c_int)) -> Point {
        Point {
            x: other.0 as _,
            y: other.1 as _,
        }
    }
}

pub struct Mouse {
    xdo: XDO,
    current_window: c_int
}

#[link(name = "xdo")]
extern "C" {
    fn xdo_new(display: *const c_char) -> XDO;

    fn xdo_move_mouse(xdo: XDO, x: c_int, y: c_int, screen: c_int) -> c_int;
    fn xdo_mouse_down(xdo: XDO, window: WINDOW, button: c_int);
    fn xdo_mouse_up(xdo: XDO, window: WINDOW, button: c_int);
    fn xdo_click_window(xdo: XDO, window: WINDOW, button: c_int);
    fn xdo_get_mouse_location(xdo: XDO, x: INTPTR, y: INTPTR, screen_num: INTPTR);
}

impl Mouse {
    pub fn new() -> Self {
        Mouse {
            xdo: unsafe { xdo_new(ptr::null()) },
            current_window: 0
        }
    }

    pub fn move_to(&self, x: i32, y: i32) -> Result<(), Box<dyn Error>> {
        unsafe {
            xdo_move_mouse(self.xdo, x as c_int, y as c_int, 0);
        }
        Ok(())
    }

    pub fn press<'a>(&self, key: &'a Keys) -> Result<(), Box<dyn Error>> {
        unsafe {
            xdo_mouse_down(self.xdo, self.current_window, xdo_translate_key(key))
        }
        Ok(())
    }

    pub fn release<'a>(&self, key: &'a Keys) -> Result<(), Box<dyn Error>> {
        unsafe {
            xdo_mouse_up(self.xdo, self.current_window, xdo_translate_key(key))
        }
        Ok(())
    }

    pub fn get_position(&self) -> Result<Point, Box<dyn Error>> {
        let pos: Point;
        unsafe {
            let mut x: c_int = 0;
            let mut y: c_int = 0;
            let mut _screen_num: c_int = 0;
            xdo_get_mouse_location(self.xdo, &mut x as INTPTR, &mut y as INTPTR, &mut _screen_num as INTPTR);
            pos = (x, y).into();
        }

        Ok(pos)
    }

    pub fn wheel(&self, mut delta: i32) -> Result<(), Box<dyn std::error::Error>> {
        let key = if delta < 0 { 4 } else { 5 };

        if delta < 0 {
            delta = -delta;
        }

        for _ in 0..delta {
            unsafe {
                xdo_click_window(self.xdo, self.current_window, key);
            }
        }
        Ok(())
    }
}