From 61a7ce3904e6692d4acbcb3e9e71cf118d39df83 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 25 Apr 2023 21:50:32 -0400 Subject: [PATCH] Input mapping --- server/src/input/events/keyboard.rs | 12 +++ server/src/input/events/mod.rs | 37 ++++++++ server/src/input/events/pointer.rs | 59 +++++++++---- server/src/input/mappings.rs | 129 ++++++++++++++++++++++++++++ server/src/input/mod.rs | 39 +++++++-- server/src/main.rs | 4 +- 6 files changed, 255 insertions(+), 25 deletions(-) create mode 100644 server/src/input/events/keyboard.rs create mode 100644 server/src/input/mappings.rs diff --git a/server/src/input/events/keyboard.rs b/server/src/input/events/keyboard.rs new file mode 100644 index 0000000..8305135 --- /dev/null +++ b/server/src/input/events/keyboard.rs @@ -0,0 +1,12 @@ +use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait}; + +pub struct KvmKeyboardEvent { + pub key_code: u32, + pub state: KvmButtonState, +} + +impl KvmEventTrait for KvmKeyboardEvent { + fn into_kvm_event(self) -> KvmEvent { + KvmEvent::Keyboard(self) + } +} \ No newline at end of file diff --git a/server/src/input/events/mod.rs b/server/src/input/events/mod.rs index 9e96c5b..477a5bf 100644 --- a/server/src/input/events/mod.rs +++ b/server/src/input/events/mod.rs @@ -1 +1,38 @@ +use std::fmt::{Display, Formatter}; +use crate::input::events::keyboard::KvmKeyboardEvent; +use crate::input::events::pointer::KvmPointerEvent; + pub mod pointer; +pub mod keyboard; + +pub enum KvmEvent { + Pointer(KvmPointerEvent), + Keyboard(KvmKeyboardEvent), +} + +pub enum KvmButtonState { + Pressed, + Released, +} + +pub trait KvmEventTrait { + fn into_kvm_event(self) -> KvmEvent; +} + +impl Display for KvmEvent { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + KvmEvent::Pointer(_) => write!(f, "Pointer"), + KvmEvent::Keyboard(_) => write!(f, "Keyboard") + } + } +} + +impl Display for KvmButtonState { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + KvmButtonState::Pressed => write!(f, "Pressed"), + KvmButtonState::Released => write!(f, "Released") + } + } +} \ No newline at end of file diff --git a/server/src/input/events/pointer.rs b/server/src/input/events/pointer.rs index 282f288..2b0e843 100644 --- a/server/src/input/events/pointer.rs +++ b/server/src/input/events/pointer.rs @@ -1,29 +1,54 @@ -pub enum PointerEvent { - Motion(PointerMotionEvent), - Button(PointerButtonEvent), - Scroll(PointerScrollEvent), +use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait}; + +pub enum KvmPointerEvent { + Motion(KvmPointerMotionEvent), + Button(KvmPointerButtonEvent), + Scroll(KvmPointerScrollEvent), } -pub enum Axis { - Horizontal = 0, - Vertical = 1, -} - -pub struct PointerButtonEvent { +pub struct KvmPointerButtonEvent { pub button: u32, - pub seat_button_count: u32, - pub button_state: u32, + pub state: KvmButtonState, } -pub struct PointerMotionEvent { +pub struct KvmPointerMotionEvent { pub dx: f64, pub dx_unaccelerated: f64, pub dy: f64, pub dy_unaccelerated: f64, } -pub struct PointerScrollEvent { - pub axis: Axis, - pub scroll_value: f64, - pub scroll_value_v120: f64, +pub struct KvmPointerScrollEvent { + pub horizontal_scroll_value: f64, + pub vertical_scroll_value: f64, } + +pub trait KvmPointerEventTrait { + fn into_kvm_pointer_event(self) -> KvmPointerEvent; +} + +impl KvmEventTrait for KvmPointerEvent { + fn into_kvm_event(self) -> KvmEvent { + KvmEvent::Pointer(self) + } +} + +macro_rules! kvm_event_traits { + ($e:ident, $s:ident) => { + impl KvmEventTrait for $s { + fn into_kvm_event(self) -> KvmEvent { + self.into_kvm_pointer_event().into_kvm_event() + } + } + + impl KvmPointerEventTrait for $s { + fn into_kvm_pointer_event(self) -> KvmPointerEvent { + KvmPointerEvent::$e(self) + } + } + } +} + +kvm_event_traits!(Motion, KvmPointerMotionEvent); +kvm_event_traits!(Button, KvmPointerButtonEvent); +kvm_event_traits!(Scroll, KvmPointerScrollEvent); \ No newline at end of file diff --git a/server/src/input/mappings.rs b/server/src/input/mappings.rs new file mode 100644 index 0000000..52eab7b --- /dev/null +++ b/server/src/input/mappings.rs @@ -0,0 +1,129 @@ +use input::{Event}; +use input::event::{EventTrait, KeyboardEvent, PointerEvent}; +use input::event::keyboard::{KeyboardEventTrait, KeyState}; +use input::event::pointer::{Axis, ButtonState, PointerButtonEvent, PointerMotionAbsoluteEvent, PointerMotionEvent, PointerScrollContinuousEvent, PointerScrollEvent, PointerScrollFingerEvent, PointerScrollWheelEvent}; + +use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait}; +use crate::input::events::keyboard::KvmKeyboardEvent; +use crate::input::events::pointer::{KvmPointerButtonEvent, KvmPointerEvent, KvmPointerEventTrait, KvmPointerMotionEvent, KvmPointerScrollEvent}; +use crate::input::mappings::MappingError::{UnknownEvent, UnsupportedEvent}; + +#[derive(Debug)] +pub enum MappingError { + UnsupportedEvent(Event), + UnknownEvent(Event), +} + +pub trait FromLibinputEvent + where Self: Sized, T: EventTrait { + fn from_libinput(t: T) -> Result; +} + +impl FromLibinputEvent for KvmEvent { + fn from_libinput(event: Event) -> Result { + match event { + Event::Keyboard(event) => get_event::(event), + Event::Pointer(event) => get_event::(event), + _ => Err(UnsupportedEvent(event)) + } + } +} + +fn get_event(event: T) -> Result + where T: EventTrait, U: FromLibinputEvent + KvmEventTrait { + Ok(U::from_libinput(event)?.into_kvm_event()) +} + +impl FromLibinputEvent for KvmKeyboardEvent { + fn from_libinput(event: KeyboardEvent) -> Result { + let key_code = event.key(); + let state = KvmButtonState::from_key_state(event.key_state()); + + Ok(KvmKeyboardEvent { key_code, state }) + } +} + +impl FromLibinputEvent for KvmPointerEvent { + fn from_libinput(event: PointerEvent) -> Result { + #[allow(deprecated)] + match event { + PointerEvent::Motion(event) => get_pointer_event::(event), + PointerEvent::MotionAbsolute(event) => get_pointer_event::(event), + PointerEvent::Button(event) => get_pointer_event::(event), + PointerEvent::ScrollWheel(event) => get_pointer_event::(event), + PointerEvent::ScrollFinger(event) => get_pointer_event::(event), + PointerEvent::ScrollContinuous(event) => get_pointer_event::(event), + PointerEvent::Axis(event) => Err(UnsupportedEvent(event.into_event())), + _ => Err(UnknownEvent(event.into_event())) + } + } +} + +fn get_pointer_event(event: T) -> Result + where T: EventTrait, U: FromLibinputEvent + KvmPointerEventTrait { + Ok(U::from_libinput(event)?.into_kvm_pointer_event()) +} + +impl FromLibinputEvent for KvmPointerMotionEvent { + fn from_libinput(event: PointerMotionEvent) -> Result { + Ok(KvmPointerMotionEvent { + dx: event.dx(), + dx_unaccelerated: event.dx_unaccelerated(), + dy: event.dy(), + dy_unaccelerated: event.dy_unaccelerated(), + }) + } +} + +impl FromLibinputEvent for KvmPointerMotionEvent { + fn from_libinput(event: PointerMotionAbsoluteEvent) -> Result { + Err(UnsupportedEvent(event.into_event())) // TODO + } +} + +impl FromLibinputEvent for KvmPointerButtonEvent { + fn from_libinput(event: PointerButtonEvent) -> Result { + let button = event.button(); + let state = KvmButtonState::from_button_state(event.button_state()); + + Ok(KvmPointerButtonEvent { button, state }) + } +} + +impl FromLibinputEvent for KvmPointerScrollEvent + where T: EventTrait + PointerScrollEvent { + fn from_libinput(event: T) -> Result { + fn get_axis_value(event: &T, axis: Axis) -> f64 + where T: PointerScrollEvent { + if event.has_axis(axis) { + return event.scroll_value(axis); + } + + 0f64 + } + + let horizontal_scroll_value = get_axis_value(&event, Axis::Horizontal); + let vertical_scroll_value = get_axis_value(&event, Axis::Vertical); + + Ok(KvmPointerScrollEvent { + horizontal_scroll_value, + vertical_scroll_value, + }) + } +} + +impl KvmButtonState { + pub fn from_key_state(state: KeyState) -> Self { + match state { + KeyState::Released => Self::Released, + KeyState::Pressed => Self::Pressed, + } + } + + pub fn from_button_state(state: ButtonState) -> Self { + match state { + ButtonState::Released => Self::Released, + ButtonState::Pressed => Self::Pressed, + } + } +} \ No newline at end of file diff --git a/server/src/input/mod.rs b/server/src/input/mod.rs index 9b6e42d..7fdab3c 100644 --- a/server/src/input/mod.rs +++ b/server/src/input/mod.rs @@ -1,5 +1,3 @@ -mod events; - use std::fs::{File, OpenOptions}; use std::io; use std::os::fd::OwnedFd; @@ -7,7 +5,19 @@ use std::os::unix::fs::OpenOptionsExt; use std::path::Path; use input::{Libinput, LibinputInterface}; +use input::Event; +use input::Event::{Keyboard, Pointer}; +use input::event::keyboard::{KeyboardEventTrait, KeyState}; +use input::event::{KeyboardEvent, PointerEvent}; +use input::event::PointerEvent::{Button, Motion}; use libc::{O_RDONLY, O_RDWR, O_WRONLY}; +use crate::input::events::keyboard::KvmKeyboardEvent; +use crate::input::events::KvmEvent; +use crate::input::events::pointer::{KvmPointerButtonEvent, KvmPointerMotionEvent}; +use crate::input::mappings::FromLibinputEvent; + +mod events; +mod mappings; const UDEV_SEAT: &str = "seat0"; @@ -29,14 +39,31 @@ impl LibinputInterface for Interface { } } -pub(crate) fn read_inputs() -> io::Result<()> { +pub fn listen_inputs() -> io::Result<()> { + let input = prepare_libinput(); + read_inputs(input) +} + +fn prepare_libinput() -> Libinput { let mut input = Libinput::new_with_udev(Interface); input.udev_assign_seat(UDEV_SEAT).unwrap(); + input +} + +fn read_inputs(mut input: Libinput) -> io::Result<()> { loop { input.dispatch().unwrap(); for event in &mut input { - // event. - println!("Got event: {:?}", event); + let mapping_result = KvmEvent::from_libinput(event); + if mapping_result.is_err() { + println!("Error: {:?}", &mapping_result.err()); + } else { + let kvm_event = mapping_result.unwrap(); + match kvm_event { + KvmEvent::Keyboard(event) => println!("Key event: {} ({})", event.key_code, event.state), + _ => {} + } + } } } -} +} \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index 28fb3d1..d7e3d6e 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,7 +5,7 @@ use std::net::SocketAddr; use messages::client_registration::ClientRegistration; use messages::serialization::{DeserializeMessage, read_message_data, SerializeMessage}; -use crate::input::read_inputs; +use crate::input::{listen_inputs}; use crate::net::tcp_server::{NextIntent, TcpClient, TcpServer}; mod net; @@ -18,7 +18,7 @@ fn main() -> io::Result<()> { // // server.listen()?; - read_inputs()?; + listen_inputs()?; Ok(()) }