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
13pub 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}