From 0fbf9f4dc2946991e6388370403bc246c4e6db3c Mon Sep 17 00:00:00 2001 From: Ferdinand Schober Date: Sat, 16 Dec 2023 11:47:52 +0100 Subject: [PATCH] X11: Mouse emulation now fully supported --- src/backend/consumer/x11.rs | 48 ++++++++++++++++++++++++++++++++----- src/event.rs | 2 ++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/backend/consumer/x11.rs b/src/backend/consumer/x11.rs index 6e6044c..2d46a40 100644 --- a/src/backend/consumer/x11.rs +++ b/src/backend/consumer/x11.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use std::ptr; use x11::{xlib, xtest}; -use crate::{client::ClientHandle, consumer::EventConsumer, event::Event}; +use crate::{client::ClientHandle, consumer::EventConsumer, event::{Event, PointerEvent, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK}}; pub struct X11Consumer { display: *mut xlib::Display, @@ -25,7 +25,36 @@ impl X11Consumer { fn relative_motion(&self, dx: i32, dy: i32) { unsafe { xtest::XTestFakeRelativeMotionEvent(self.display, dx, dy, 0, 0); - xlib::XFlush(self.display); + } + } + + 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); } } } @@ -41,20 +70,27 @@ impl EventConsumer for X11Consumer { async fn consume(&mut self, event: Event, _: ClientHandle) { match event { Event::Pointer(pointer_event) => match pointer_event { - crate::event::PointerEvent::Motion { + PointerEvent::Motion { time: _, relative_x, relative_y, } => { self.relative_motion(relative_x as i32, relative_y as i32); } - crate::event::PointerEvent::Button { .. } => {} - crate::event::PointerEvent::Axis { .. } => {} - crate::event::PointerEvent::Frame {} => {} + 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(_) => {} _ => {} } + unsafe { + xlib::XFlush(self.display); + } } async fn notify(&mut self, _: crate::client::ClientEvent) { diff --git a/src/event.rs b/src/event.rs index 32ab695..4a65a01 100644 --- a/src/event.rs +++ b/src/event.rs @@ -7,6 +7,8 @@ use std::{ pub const BTN_LEFT: u32 = 0x110; pub const BTN_RIGHT: u32 = 0x111; pub const BTN_MIDDLE: u32 = 0x112; +pub const BTN_BACK: u32 = 0x113; +pub const BTN_FORWARD: u32 = 0x114; #[derive(Debug, Clone, Copy)] pub enum PointerEvent {