rdev/linux/
common.rs

1use crate::linux::keyboard::Keyboard;
2use crate::linux::keycodes::key_from_code;
3use crate::rdev::{Button, Event, EventType, KeyboardState};
4use std::convert::TryInto;
5use std::os::raw::{c_int, c_uchar, c_uint};
6use std::ptr::null;
7use std::time::SystemTime;
8use x11::xlib;
9
10pub const TRUE: c_int = 1;
11pub const FALSE: c_int = 0;
12
13// A global for the callbacks.
14pub static mut KEYBOARD: Option<Keyboard> = None;
15
16pub fn convert_event(code: c_uchar, type_: c_int, x: f64, y: f64) -> Option<EventType> {
17    match type_ {
18        xlib::KeyPress => {
19            let key = key_from_code(code.into());
20            Some(EventType::KeyPress(key))
21        }
22        xlib::KeyRelease => {
23            let key = key_from_code(code.into());
24            Some(EventType::KeyRelease(key))
25        }
26        xlib::ButtonPress => match code {
27            1 => Some(EventType::ButtonPress(Button::Left)),
28            2 => Some(EventType::ButtonPress(Button::Middle)),
29            3 => Some(EventType::ButtonPress(Button::Right)),
30            4 => Some(EventType::Wheel {
31                delta_y: 1,
32                delta_x: 0,
33            }),
34            5 => Some(EventType::Wheel {
35                delta_y: -1,
36                delta_x: 0,
37            }),
38            6 => Some(EventType::Wheel {
39                delta_y: 0,
40                delta_x: -1,
41            }),
42            7 => Some(EventType::Wheel {
43                delta_y: 0,
44                delta_x: 1,
45            }),
46            code => Some(EventType::ButtonPress(Button::Unknown(code))),
47        },
48        xlib::ButtonRelease => match code {
49            1 => Some(EventType::ButtonRelease(Button::Left)),
50            2 => Some(EventType::ButtonRelease(Button::Middle)),
51            3 => Some(EventType::ButtonRelease(Button::Right)),
52            4 | 5 => None,
53            _ => Some(EventType::ButtonRelease(Button::Unknown(code))),
54        },
55        xlib::MotionNotify => Some(EventType::MouseMove { x, y }),
56        _ => None,
57    }
58}
59
60pub fn convert(
61    keyboard: &mut Option<Keyboard>,
62    code: c_uint,
63    type_: c_int,
64    x: f64,
65    y: f64,
66) -> Option<Event> {
67    let event_type = convert_event(code as c_uchar, type_, x, y)?;
68    let kb: &mut Keyboard = (*keyboard).as_mut()?;
69    let name = kb.add(&event_type);
70    Some(Event {
71        event_type,
72        time: SystemTime::now(),
73        name,
74    })
75}
76
77pub struct Display {
78    display: *mut xlib::Display,
79}
80
81impl Display {
82    pub fn new() -> Option<Display> {
83        unsafe {
84            let display = xlib::XOpenDisplay(null());
85            if display.is_null() {
86                return None;
87            }
88            Some(Display { display })
89        }
90    }
91
92    pub fn get_size(&self) -> Option<(u64, u64)> {
93        unsafe {
94            let screen_ptr = xlib::XDefaultScreenOfDisplay(self.display);
95            if screen_ptr.is_null() {
96                return None;
97            }
98            let screen = *screen_ptr;
99            Some((
100                screen.width.try_into().ok()?,
101                screen.height.try_into().ok()?,
102            ))
103        }
104    }
105
106    #[cfg(feature = "unstable_grab")]
107    pub fn get_mouse_pos(&self) -> Option<(u64, u64)> {
108        unsafe {
109            let root_window = xlib::XRootWindow(self.display, 0);
110            let mut root_x = 0;
111            let mut root_y = 0;
112            let mut x = 0;
113            let mut y = 0;
114            let mut root = 0;
115            let mut child = 0;
116            let mut mask = 0;
117            let _screen_ptr = xlib::XQueryPointer(
118                self.display,
119                root_window,
120                &mut root,
121                &mut child,
122                &mut root_x,
123                &mut root_y,
124                &mut x,
125                &mut y,
126                &mut mask,
127            );
128            Some((root_x.try_into().ok()?, root_y.try_into().ok()?))
129        }
130    }
131}
132impl Drop for Display {
133    fn drop(&mut self) {
134        unsafe {
135            xlib::XCloseDisplay(self.display);
136        }
137    }
138}