mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-21 20:20:55 +03:00
123 lines
3.5 KiB
Rust
123 lines
3.5 KiB
Rust
use async_trait::async_trait;
|
|
use std::ptr;
|
|
use x11::{xlib::{self, XCloseDisplay}, xtest};
|
|
|
|
use crate::{client::ClientHandle, consumer::EventConsumer, event::{Event, PointerEvent, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK, KeyboardEvent}};
|
|
|
|
pub struct X11Consumer {
|
|
display: *mut xlib::Display,
|
|
}
|
|
|
|
unsafe impl Send for X11Consumer {}
|
|
|
|
impl X11Consumer {
|
|
pub fn new() -> Self {
|
|
let display = unsafe {
|
|
match xlib::XOpenDisplay(ptr::null()) {
|
|
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => None,
|
|
display => Some(display),
|
|
}
|
|
};
|
|
let display = display.expect("could not open display");
|
|
Self { display }
|
|
}
|
|
|
|
fn relative_motion(&self, dx: i32, dy: i32) {
|
|
unsafe {
|
|
xtest::XTestFakeRelativeMotionEvent(self.display, dx, dy, 0, 0);
|
|
}
|
|
}
|
|
|
|
fn emulate_mouse_button(&self, button: u32, state: u32) {
|
|
unsafe {
|
|
let x11_button = match button {
|
|
BTN_RIGHT => 3,
|
|
BTN_MIDDLE => 2,
|
|
BTN_BACK => 8,
|
|
BTN_FORWARD => 9,
|
|
BTN_LEFT | _ => 1,
|
|
};
|
|
xtest::XTestFakeButtonEvent(self.display, x11_button, state as i32, 0);
|
|
};
|
|
}
|
|
|
|
const SCROLL_UP: u32 = 4;
|
|
const SCROLL_DOWN: u32 = 5;
|
|
const SCROLL_LEFT: u32 = 6;
|
|
const SCROLL_RIGHT: u32 = 7;
|
|
|
|
fn emulate_scroll(&self, axis: u8, value: f64) {
|
|
let direction = match axis {
|
|
1 => if value < 0.0 { Self::SCROLL_LEFT } else { Self::SCROLL_RIGHT },
|
|
_ => if value < 0.0 { Self::SCROLL_UP } else { Self::SCROLL_DOWN },
|
|
};
|
|
|
|
unsafe {
|
|
xtest::XTestFakeButtonEvent(self.display, direction, 1, 0);
|
|
xtest::XTestFakeButtonEvent(self.display, direction, 0, 0);
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn emulate_key(&self, key: u32, state: u8) {
|
|
let _ = key;
|
|
let _ = state;
|
|
unsafe {
|
|
xtest::XTestFakeKeyEvent(self.display, key, state as i32, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for X11Consumer {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Drop for X11Consumer {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
XCloseDisplay(self.display);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl EventConsumer for X11Consumer {
|
|
async fn consume(&mut self, event: Event, _: ClientHandle) {
|
|
match event {
|
|
Event::Pointer(pointer_event) => match pointer_event {
|
|
PointerEvent::Motion {
|
|
time: _,
|
|
relative_x,
|
|
relative_y,
|
|
} => {
|
|
self.relative_motion(relative_x as i32, relative_y as i32);
|
|
}
|
|
PointerEvent::Button { time: _, button, state } => {
|
|
self.emulate_mouse_button(button, state);
|
|
}
|
|
PointerEvent::Axis { time: _, axis, value } => {
|
|
self.emulate_scroll(axis, value);
|
|
}
|
|
PointerEvent::Frame {} => {}
|
|
},
|
|
Event::Keyboard(KeyboardEvent::Key { time: _, key, state }) => {
|
|
let _ = key;
|
|
let _ = state;
|
|
// self.emulate_key(key, state);
|
|
}
|
|
_ => {}
|
|
}
|
|
unsafe {
|
|
xlib::XFlush(self.display);
|
|
}
|
|
}
|
|
|
|
async fn notify(&mut self, _: crate::client::ClientEvent) {
|
|
// for our purposes it does not matter what client sent the event
|
|
}
|
|
|
|
async fn destroy(&mut self) {}
|
|
}
|