1use crate::{common::*, linux::inputs::*, public::*};
2use input::{
3 event::{
4 keyboard::{
5 KeyState, {KeyboardEvent, KeyboardEventTrait},
6 },
7 pointer::{ButtonState, PointerEvent::*},
8 Event::{self, *},
9 },
10 Libinput, LibinputInterface,
11};
12use nix::{
13 fcntl::{open, OFlag},
14 sys::stat::Mode,
15 unistd::close,
16};
17use once_cell::sync::Lazy;
18use std::{
19 mem::MaybeUninit, os::unix::io::RawFd, path::Path, ptr::null, sync::Mutex, thread::sleep,
20 time::Duration,
21};
22use uinput::event::{
23 controller::{Controller, Mouse},
24 relative::Position,
25 Event as UinputEvent,
26};
27use x11::xlib::*;
28
29mod inputs;
30
31type ButtonStatesMap = HashMap<MouseButton, bool>;
32type KeyStatesMap = HashMap<KeybdKey, bool>;
33
34static BUTTON_STATES: Lazy<Mutex<ButtonStatesMap>> =
35 Lazy::new(|| Mutex::new(ButtonStatesMap::new()));
36static KEY_STATES: Lazy<Mutex<KeyStatesMap>> = Lazy::new(|| Mutex::new(KeyStatesMap::new()));
37static SEND_DISPLAY: Lazy<AtomicPtr<Display>> = Lazy::new(|| {
38 unsafe { XInitThreads() };
39 AtomicPtr::new(unsafe { XOpenDisplay(null()) })
40});
41static FAKE_DEVICE: Lazy<Mutex<uinput::Device>> = Lazy::new(|| {
42 Mutex::new(
43 uinput::default()
44 .unwrap()
45 .name("inputbot")
46 .unwrap()
47 .event(uinput::event::Keyboard::All)
48 .unwrap()
49 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Left)))
50 .unwrap()
51 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Right)))
52 .unwrap()
53 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Middle)))
54 .unwrap()
55 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Side)))
56 .unwrap()
57 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Extra)))
58 .unwrap()
59 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Forward)))
60 .unwrap()
61 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Back)))
62 .unwrap()
63 .event(UinputEvent::Controller(Controller::Mouse(Mouse::Task)))
64 .unwrap()
65 .event(Position::X)
66 .unwrap()
67 .event(Position::Y)
68 .unwrap()
69 .create()
70 .unwrap(),
71 )
72});
73
74pub fn init_device() {
79 FAKE_DEVICE.lock().unwrap();
80}
81
82impl KeybdKey {
83 pub fn is_pressed(self) -> bool {
85 *KEY_STATES.lock().unwrap().entry(self).or_insert(false)
86 }
87
88 pub fn press(self) {
91 let mut device = FAKE_DEVICE.lock().unwrap();
92
93 device.write(0x01, key_to_scan_code(self), 1).unwrap();
94 device.synchronize().unwrap();
95 }
96
97 pub fn release(self) {
99 let mut device = FAKE_DEVICE.lock().unwrap();
100
101 device.write(0x01, key_to_scan_code(self), 0).unwrap();
102 device.synchronize().unwrap();
103 }
104
105 pub fn is_toggled(self) -> bool {
108 if let Some(key) = match self {
109 KeybdKey::ScrollLockKey => Some(4),
110 KeybdKey::NumLockKey => Some(2),
111 KeybdKey::CapsLockKey => Some(1),
112 _ => None,
113 } {
114 let mut state: XKeyboardState = unsafe { MaybeUninit::zeroed().assume_init() };
115 SEND_DISPLAY.with(|display| unsafe {
116 XGetKeyboardControl(display, &mut state);
117 });
118 state.led_mask & key != 0
119 } else {
120 false
121 }
122 }
123}
124
125impl MouseButton {
126 pub fn is_pressed(self) -> bool {
128 *BUTTON_STATES.lock().unwrap().entry(self).or_insert(false)
129 }
130
131 pub fn press(self) {
134 let mut device = FAKE_DEVICE.lock().unwrap();
135 device.press(&Controller::Mouse(Mouse::from(self))).unwrap();
136 device.synchronize().unwrap();
137 }
138
139 pub fn release(self) {
141 let mut device = FAKE_DEVICE.lock().unwrap();
142 device
143 .release(&Controller::Mouse(Mouse::from(self)))
144 .unwrap();
145 device.synchronize().unwrap();
146 }
147}
148
149impl MouseCursor {
150 pub fn move_rel(x: i32, y: i32) {
152 let mut device = FAKE_DEVICE.lock().unwrap();
153
154 device.position(&Position::X, x).unwrap();
155 device.position(&Position::Y, y).unwrap();
156
157 SEND_DISPLAY.with(|display| unsafe {
158 XWarpPointer(display, 0, 0, 0, 0, 0, 0, x, y);
159 });
160 device.synchronize().unwrap();
161 }
162
163 pub fn move_abs(x: i32, y: i32) {
166 let mut device = FAKE_DEVICE.lock().unwrap();
167
168 SEND_DISPLAY.with(|display| unsafe {
169 XWarpPointer(
170 display,
171 0,
172 XRootWindow(display, XDefaultScreen(display)),
173 0,
174 0,
175 0,
176 0,
177 x,
178 y,
179 );
180 });
181 device.synchronize().unwrap();
182 }
183}
184
185impl MouseWheel {
186 pub fn scroll_ver(y: i32) {
188 if y < 0 {
189 MouseButton::OtherButton(4).press();
190 MouseButton::OtherButton(4).release();
191 } else {
192 MouseButton::OtherButton(5).press();
193 MouseButton::OtherButton(5).release();
194 }
195 }
196
197 pub fn scroll_hor(x: i32) {
199 if x < 0 {
200 MouseButton::OtherButton(6).press();
201 MouseButton::OtherButton(6).release();
202 } else {
203 MouseButton::OtherButton(7).press();
204 MouseButton::OtherButton(7).release();
205 }
206 }
207}
208
209struct LibinputInterfaceRaw;
210
211impl LibinputInterfaceRaw {
212 fn seat(&self) -> String {
213 String::from("seat0")
214 }
215}
216
217impl LibinputInterface for LibinputInterfaceRaw {
218 fn open_restricted(&mut self, path: &Path, flags: i32) -> std::result::Result<RawFd, i32> {
219 if let Ok(fd) = open(path, OFlag::from_bits_truncate(flags), Mode::empty()) {
220 Ok(fd)
221 } else {
222 Err(1)
223 }
224 }
225
226 fn close_restricted(&mut self, fd: RawFd) {
227 let _ = close(fd);
228 }
229}
230
231pub fn handle_input_events() {
233 let mut libinput_context = Libinput::new_with_udev(LibinputInterfaceRaw);
234 libinput_context
235 .udev_assign_seat(&LibinputInterfaceRaw.seat())
236 .unwrap();
237
238 while !MOUSE_BINDS.lock().unwrap().is_empty() || !KEYBD_BINDS.lock().unwrap().is_empty() {
239 libinput_context.dispatch().unwrap();
240
241 for event in libinput_context.by_ref() {
242 handle_input_event(event);
243 }
244
245 sleep(Duration::from_millis(10));
246 }
247}
248
249fn handle_input_event(event: Event) {
250 match event {
251 Keyboard(KeyboardEvent::Key(keyboard_key_event)) => {
252 let key = keyboard_key_event.key();
253 if let Some(keybd_key) = scan_code_to_key(key) {
254 if keyboard_key_event.key_state() == KeyState::Pressed {
255 KEY_STATES.lock().unwrap().insert(keybd_key, true);
256
257 if let Some(Bind::NormalBind(cb)) = KEYBD_BINDS.lock().unwrap().get(&keybd_key)
258 {
259 let cb = Arc::clone(cb);
260 spawn(move || cb());
261 }
262 } else {
263 KEY_STATES.lock().unwrap().insert(keybd_key, false);
264 }
265 }
266 }
267 Pointer(Button(button_event)) => {
268 let button = button_event.button();
269 if let Some(mouse_button) = match button {
270 272 => Some(MouseButton::LeftButton),
271 273 => Some(MouseButton::RightButton),
272 274 => Some(MouseButton::MiddleButton),
273 275 => Some(MouseButton::X1Button),
274 276 => Some(MouseButton::X2Button),
275 _ => None,
276 } {
277 if button_event.button_state() == ButtonState::Pressed {
278 BUTTON_STATES.lock().unwrap().insert(mouse_button, true);
279 if let Some(Bind::NormalBind(cb)) =
280 MOUSE_BINDS.lock().unwrap().get(&mouse_button)
281 {
282 let cb = Arc::clone(cb);
283 spawn(move || cb());
284 };
285 } else {
286 BUTTON_STATES.lock().unwrap().insert(mouse_button, false);
287 }
288 }
289 }
290 _ => {}
291 }
292}
293
294trait DisplayAcquirable {
295 fn with<F, Z>(&self, cb: F) -> Z
296 where
297 F: FnOnce(*mut Display) -> Z;
298}
299
300impl DisplayAcquirable for AtomicPtr<Display> {
301 fn with<F, Z>(&self, cb: F) -> Z
302 where
303 F: FnOnce(*mut Display) -> Z,
304 {
305 let display = self.load(Ordering::Relaxed);
306 unsafe {
307 XLockDisplay(display);
308 };
309 let cb_result = cb(display);
310 unsafe {
311 XFlush(display);
312 XUnlockDisplay(display);
313 };
314 cb_result
315 }
316}