openloaf_rdev/linux/
simulate.rs1use crate::linux::common::{FALSE, TRUE};
2use crate::keycodes::linux::code_from_key;
3use crate::rdev::{Button, EventType, RawKey, SimulateError};
4use std::convert::TryInto;
5use std::os::raw::c_int;
6use std::ptr::null;
7use x11::xlib;
8use x11::xtest;
9
10unsafe fn send_native(event_type: &EventType, display: *mut xlib::Display) -> Option<()> {
11 let res = match event_type {
12 EventType::KeyPress(key) => match key {
13 crate::Key::RawKey(rawkey) => {
14 if let RawKey::LinuxXorgKeycode(keycode) = rawkey {
15 xtest::XTestFakeKeyEvent(display, *keycode as _, TRUE, 0)
16 } else {
17 return None;
18 }
19 }
20 _ => {
21 let code = code_from_key(*key)?;
22 xtest::XTestFakeKeyEvent(display, code, TRUE, 0)
23 }
24 },
25 EventType::KeyRelease(key) => match key {
26 crate::Key::RawKey(rawkey) => {
27 if let RawKey::LinuxXorgKeycode(keycode) = rawkey {
28 xtest::XTestFakeKeyEvent(display, *keycode as _, FALSE, 0)
29 } else {
30 return None;
31 }
32 }
33 _ => {
34 let code = code_from_key(*key)?;
35 xtest::XTestFakeKeyEvent(display, code, FALSE, 0)
36 }
37 },
38 EventType::ButtonPress(button) => match button {
39 Button::Left => xtest::XTestFakeButtonEvent(display, 1, TRUE, 0),
40 Button::Middle => xtest::XTestFakeButtonEvent(display, 2, TRUE, 0),
41 Button::Right => xtest::XTestFakeButtonEvent(display, 3, TRUE, 0),
42 Button::Unknown(code) => {
43 xtest::XTestFakeButtonEvent(display, (*code).try_into().ok()?, TRUE, 0)
44 }
45 },
46 EventType::ButtonRelease(button) => match button {
47 Button::Left => xtest::XTestFakeButtonEvent(display, 1, FALSE, 0),
48 Button::Middle => xtest::XTestFakeButtonEvent(display, 2, FALSE, 0),
49 Button::Right => xtest::XTestFakeButtonEvent(display, 3, FALSE, 0),
50 Button::Unknown(code) => {
51 xtest::XTestFakeButtonEvent(display, (*code).try_into().ok()?, FALSE, 0)
52 }
53 },
54 EventType::MouseMove { x, y } => {
55 let x = if x.is_finite() {
57 x.min(c_int::max_value().into())
58 .max(c_int::min_value().into())
59 .round() as c_int
60 } else {
61 0
62 };
63 let y = if y.is_finite() {
64 y.min(c_int::max_value().into())
65 .max(c_int::min_value().into())
66 .round() as c_int
67 } else {
68 0
69 };
70 xtest::XTestFakeMotionEvent(display, 0, x, y, 0)
71 }
73 EventType::Wheel { delta_y, .. } => {
74 let code = if *delta_y > 0 { 4 } else { 5 };
75 xtest::XTestFakeButtonEvent(display, code, TRUE, 0)
76 & xtest::XTestFakeButtonEvent(display, code, FALSE, 0)
77 }
78 };
79 if res == 0 {
80 None
81 } else {
82 Some(())
83 }
84}
85
86pub fn simulate(event_type: &EventType) -> Result<(), SimulateError> {
87 unsafe {
88 let dpy = xlib::XOpenDisplay(null());
89 if dpy.is_null() {
90 return Err(SimulateError);
91 }
92 match send_native(event_type, dpy) {
93 Some(_) => {
94 xlib::XFlush(dpy);
95 xlib::XSync(dpy, 0);
96 xlib::XCloseDisplay(dpy);
97 Ok(())
98 }
99 None => {
100 xlib::XCloseDisplay(dpy);
101 Err(SimulateError)
102 }
103 }
104 }
105}
106
107unsafe fn send_native_char(chr: char, pressed: bool, display: *mut xlib::Display) -> Option<()> {
108 let keycode: u32 = 194;
110
111 let ordinal: u32 = chr.into();
113 let mut keysym = if ordinal < 0x100 {
114 ordinal
115 } else {
116 ordinal | 0x01000000
117 } as libc::c_ulong;
118
119 x11::xlib::XChangeKeyboardMapping(display, keycode as _, 1, &mut keysym, 1);
121
122 let res = if pressed {
123 xtest::XTestFakeKeyEvent(display, keycode as _, TRUE, 0)
124 } else {
125 xtest::XTestFakeKeyEvent(display, keycode as _, FALSE, 0)
126 };
127
128 if res == 0 {
129 None
130 } else {
131 Some(())
132 }
133}
134
135pub fn simulate_char(chr: char, pressed: bool) -> Result<(), SimulateError> {
136 unsafe {
137 let dpy = xlib::XOpenDisplay(null());
138 if dpy.is_null() {
139 return Err(SimulateError);
140 }
141 match send_native_char(chr, pressed, dpy) {
142 Some(_) => {
143 xlib::XFlush(dpy);
144 xlib::XSync(dpy, 0);
145 xlib::XCloseDisplay(dpy);
146 Ok(())
147 }
148 None => {
149 xlib::XCloseDisplay(dpy);
150 Err(SimulateError)
151 }
152 }
153 }
154}
155
156pub fn simulate_unicode(_unicode: u16) -> Result<(), SimulateError> {
157 Err(SimulateError)
158}