use crate::linux::keyboard::Keyboard;
use crate::linux::keycodes::key_from_code;
use crate::rdev::{Button, Event, EventType, KeyboardState};
use std::convert::TryInto;
use std::os::raw::{c_int, c_uchar, c_uint};
use std::ptr::null;
use std::time::SystemTime;
use x11::xlib;
pub const TRUE: c_int = 1;
pub const FALSE: c_int = 0;
pub static mut KEYBOARD: Option<Keyboard> = None;
pub fn convert_event(code: c_uchar, type_: c_int, x: f64, y: f64) -> Option<EventType> {
match type_ {
xlib::KeyPress => {
let key = key_from_code(code.into());
Some(EventType::KeyPress(key))
}
xlib::KeyRelease => {
let key = key_from_code(code.into());
Some(EventType::KeyRelease(key))
}
xlib::ButtonPress => match code {
1 => Some(EventType::ButtonPress(Button::Left)),
2 => Some(EventType::ButtonPress(Button::Middle)),
3 => Some(EventType::ButtonPress(Button::Right)),
4 => Some(EventType::Wheel {
delta_y: 1,
delta_x: 0,
}),
5 => Some(EventType::Wheel {
delta_y: -1,
delta_x: 0,
}),
6 => Some(EventType::Wheel {
delta_y: 0,
delta_x: -1,
}),
7 => Some(EventType::Wheel {
delta_y: 0,
delta_x: 1,
}),
code => Some(EventType::ButtonPress(Button::Unknown(code))),
},
xlib::ButtonRelease => match code {
1 => Some(EventType::ButtonRelease(Button::Left)),
2 => Some(EventType::ButtonRelease(Button::Middle)),
3 => Some(EventType::ButtonRelease(Button::Right)),
4 | 5 => None,
_ => Some(EventType::ButtonRelease(Button::Unknown(code))),
},
xlib::MotionNotify => Some(EventType::MouseMove { x, y }),
_ => None,
}
}
pub fn convert(
keyboard: &mut Option<Keyboard>,
code: c_uint,
type_: c_int,
x: f64,
y: f64,
) -> Option<Event> {
let event_type = convert_event(code as c_uchar, type_, x, y)?;
let kb: &mut Keyboard = (*keyboard).as_mut()?;
let name = kb.add(&event_type);
Some(Event {
event_type,
time: SystemTime::now(),
name,
})
}
pub struct Display {
display: *mut xlib::Display,
}
impl Display {
pub fn new() -> Option<Display> {
unsafe {
let display = xlib::XOpenDisplay(null());
if display.is_null() {
return None;
}
Some(Display { display })
}
}
pub fn get_size(&self) -> Option<(u64, u64)> {
unsafe {
let screen_ptr = xlib::XDefaultScreenOfDisplay(self.display);
if screen_ptr.is_null() {
return None;
}
let screen = *screen_ptr;
Some((
screen.width.try_into().ok()?,
screen.height.try_into().ok()?,
))
}
}
#[cfg(feature = "unstable_grab")]
pub fn get_mouse_pos(&self) -> Option<(u64, u64)> {
unsafe {
let root_window = xlib::XRootWindow(self.display, 0);
let mut root_x = 0;
let mut root_y = 0;
let mut x = 0;
let mut y = 0;
let mut root = 0;
let mut child = 0;
let mut mask = 0;
let _screen_ptr = xlib::XQueryPointer(
self.display,
root_window,
&mut root,
&mut child,
&mut root_x,
&mut root_y,
&mut x,
&mut y,
&mut mask,
);
Some((root_x.try_into().ok()?, root_y.try_into().ok()?))
}
}
}
impl Drop for Display {
fn drop(&mut self) {
unsafe {
xlib::XCloseDisplay(self.display);
}
}
}