Starting input system

This commit is contained in:
william 2023-05-25 13:13:06 -04:00
parent 61a7ce3904
commit 70319a98cb
7 changed files with 310 additions and 60 deletions

View File

@ -1,3 +1,4 @@
use std::fmt::{Display, Formatter};
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
pub struct KvmKeyboardEvent {
@ -9,4 +10,13 @@ impl KvmEventTrait for KvmKeyboardEvent {
fn into_kvm_event(self) -> KvmEvent {
KvmEvent::Keyboard(self)
}
}
}
impl Display for KvmKeyboardEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.state {
KvmButtonState::Pressed => write!(f, "Press {}", self.key_code),
KvmButtonState::Released => write!(f, "Press {}", self.key_code)
}
}
}

View File

@ -22,17 +22,8 @@ pub trait KvmEventTrait {
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")
KvmEvent::Pointer(e) => write!(f, "Pointer({e})"),
KvmEvent::Keyboard(e) => write!(f, "Keyboard({e})")
}
}
}
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")
}
}
}

View File

@ -1,7 +1,9 @@
use std::fmt::{Display, Formatter};
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
pub enum KvmPointerEvent {
Motion(KvmPointerMotionEvent),
MotionRelative(KvmPointerMotionRelativeEvent),
MotionAbsolute(KvmPointerMotionAbsoluteEvent),
Button(KvmPointerButtonEvent),
Scroll(KvmPointerScrollEvent),
}
@ -11,13 +13,20 @@ pub struct KvmPointerButtonEvent {
pub state: KvmButtonState,
}
pub struct KvmPointerMotionEvent {
pub struct KvmPointerMotionRelativeEvent {
pub dx: f64,
pub dx_unaccelerated: f64,
pub dy: f64,
pub dy_unaccelerated: f64,
}
pub struct KvmPointerMotionAbsoluteEvent {
pub x: f64,
pub x_mm: f64,
pub y: f64,
pub y_mm: f64,
}
pub struct KvmPointerScrollEvent {
pub horizontal_scroll_value: f64,
pub vertical_scroll_value: f64,
@ -49,6 +58,45 @@ macro_rules! kvm_event_traits {
}
}
kvm_event_traits!(Motion, KvmPointerMotionEvent);
kvm_event_traits!(MotionRelative, KvmPointerMotionRelativeEvent);
kvm_event_traits!(MotionAbsolute, KvmPointerMotionAbsoluteEvent);
kvm_event_traits!(Button, KvmPointerButtonEvent);
kvm_event_traits!(Scroll, KvmPointerScrollEvent);
kvm_event_traits!(Scroll, KvmPointerScrollEvent);
impl Display for KvmPointerEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
KvmPointerEvent::Button(e) => write!(f, "Button({e})"),
KvmPointerEvent::MotionRelative(e) => write!(f, "MotionRelative({e})"),
KvmPointerEvent::MotionAbsolute(e) => write!(f, "MotionAbsolute({e})"),
KvmPointerEvent::Scroll(e) => write!(f, "Scroll({e})")
}
}
}
impl Display for KvmPointerButtonEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.state {
KvmButtonState::Pressed => write!(f, "Press {}", self.button),
KvmButtonState::Released => write!(f, "Release {}", self.button)
}
}
}
impl Display for KvmPointerMotionRelativeEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "x: {} ({}), y: {} ({})", self.dx, self.dx_unaccelerated, self.dy, self.dy_unaccelerated)
}
}
impl Display for KvmPointerMotionAbsoluteEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "x: {} ({}), y: {} ({})", self.x, self.x_mm, self.y, self.y_mm)
}
}
impl Display for KvmPointerScrollEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "h: {}, v: {}", self.horizontal_scroll_value, self.vertical_scroll_value)
}
}

View File

@ -5,7 +5,7 @@ use input::event::pointer::{Axis, ButtonState, PointerButtonEvent, PointerMotion
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::events::pointer::{KvmPointerButtonEvent, KvmPointerEvent, KvmPointerEventTrait, KvmPointerMotionAbsoluteEvent, KvmPointerMotionRelativeEvent, KvmPointerScrollEvent};
use crate::input::mappings::MappingError::{UnknownEvent, UnsupportedEvent};
#[derive(Debug)]
@ -47,8 +47,8 @@ impl FromLibinputEvent<PointerEvent> for KvmPointerEvent {
fn from_libinput(event: PointerEvent) -> Result<Self, MappingError> {
#[allow(deprecated)]
match event {
PointerEvent::Motion(event) => get_pointer_event::<PointerMotionEvent, KvmPointerMotionEvent>(event),
PointerEvent::MotionAbsolute(event) => get_pointer_event::<PointerMotionAbsoluteEvent, KvmPointerMotionEvent>(event),
PointerEvent::Motion(event) => get_pointer_event::<PointerMotionEvent, KvmPointerMotionRelativeEvent>(event),
PointerEvent::MotionAbsolute(event) => get_pointer_event::<PointerMotionAbsoluteEvent, KvmPointerMotionAbsoluteEvent>(event),
PointerEvent::Button(event) => get_pointer_event::<PointerButtonEvent, KvmPointerButtonEvent>(event),
PointerEvent::ScrollWheel(event) => get_pointer_event::<PointerScrollWheelEvent, KvmPointerScrollEvent>(event),
PointerEvent::ScrollFinger(event) => get_pointer_event::<PointerScrollFingerEvent, KvmPointerScrollEvent>(event),
@ -64,9 +64,9 @@ fn get_pointer_event<T, U>(event: T) -> Result<KvmPointerEvent, MappingError>
Ok(U::from_libinput(event)?.into_kvm_pointer_event())
}
impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionEvent {
impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionRelativeEvent {
fn from_libinput(event: PointerMotionEvent) -> Result<Self, MappingError> {
Ok(KvmPointerMotionEvent {
Ok(KvmPointerMotionRelativeEvent {
dx: event.dx(),
dx_unaccelerated: event.dx_unaccelerated(),
dy: event.dy(),
@ -75,9 +75,14 @@ impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionEvent {
}
}
impl FromLibinputEvent<PointerMotionAbsoluteEvent> for KvmPointerMotionEvent {
impl FromLibinputEvent<PointerMotionAbsoluteEvent> for KvmPointerMotionAbsoluteEvent {
fn from_libinput(event: PointerMotionAbsoluteEvent) -> Result<Self, MappingError> {
Err(UnsupportedEvent(event.into_event())) // TODO
Ok(KvmPointerMotionAbsoluteEvent {
x: event.absolute_x_transformed(1920),
x_mm: event.absolute_x(),
y: event.absolute_y_transformed(1080),
y_mm: event.absolute_y(),
})
}
}
@ -126,4 +131,4 @@ impl KvmButtonState {
ButtonState::Pressed => Self::Pressed,
}
}
}
}

View File

@ -1,25 +1,26 @@
use std::fs::{File, OpenOptions};
use std::io;
use std::os::fd::OwnedFd;
use std::os::fd::{AsRawFd, OwnedFd};
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;
use linux::epoll::{Epoll, EpollFlags};
mod events;
use crate::input::events::KvmEvent;
use crate::input::mappings::{FromLibinputEvent, MappingError};
pub mod events;
mod mappings;
const UDEV_SEAT: &str = "seat0";
const CLIENT_SWITCH_KEY_CODE: u32 = 100; // Alt Right
pub struct InputSystem<S> {
sub_system: S,
epoll: Epoll,
}
struct Interface;
@ -39,31 +40,108 @@ impl LibinputInterface for Interface {
}
}
pub fn listen_inputs() -> io::Result<()> {
let input = prepare_libinput();
read_inputs(input)
impl InputSystem<Libinput> {
pub fn new() -> Result<Self, LibinputSubsystemError> {
let mut libinput = prepare_libinput()?;
let epoll = create_epoll(&libinput)?;
Ok(Self {
sub_system: libinput,
epoll,
})
}
fn wait_for_events(&mut self) -> Result<(), LibinputSubsystemError> {
match self.epoll.wait() {
Ok(e) => self.dispatch(),
Err(e) => Err(LibinputSubsystemError::Polling(format!("Failed to wait for epoll: {}", e)))
}
}
fn dispatch(&mut self) -> Result<(), LibinputSubsystemError> {
let dispatch_result = self.sub_system.dispatch();
if dispatch_result.is_err() {
return Err(LibinputSubsystemError::Polling("Failed to dispatch libinput events".to_string()));
}
Ok(())
}
}
fn prepare_libinput() -> Libinput {
let mut input = Libinput::new_with_udev(Interface);
input.udev_assign_seat(UDEV_SEAT).unwrap();
input
}
impl Iterator for InputSystem<Libinput> {
type Item = KvmEvent;
fn read_inputs(mut input: Libinput) -> io::Result<()> {
loop {
input.dispatch().unwrap();
for event in &mut input {
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),
_ => {}
fn next(&mut self) -> Option<Self::Item> {
let mut next = self.sub_system.next();
if next.is_none() {
// Try to get more events
match self.wait_for_events() {
Ok(_) => {
next = self.sub_system.next();
}
Err(e) => {
println!("Failed to wait for events: {:?}", e);
}
}
}
match next {
Some(e) => {
match map_libinput_event(e) {
Ok(e) => Some(e),
Err(e) => {
println!("Event failed: {:?}", e);
None
}
}
}
None => None
}
}
}
}
#[derive(Debug)]
pub enum LibinputSubsystemError {
Initialization(String),
Polling(String),
Mapping(MappingError),
}
fn prepare_libinput() -> Result<Libinput, LibinputSubsystemError> {
let mut input = Libinput::new_with_udev(Interface);
match input.udev_assign_seat(UDEV_SEAT) {
Ok(_) => Ok(input),
Err(_) => Err(LibinputSubsystemError::Initialization("Failed to assign a seat to the libinput context".to_string()))
}
}
fn create_epoll(input: &Libinput) -> Result<Epoll, LibinputSubsystemError> {
match Epoll::with_flags(&[EpollFlags::In]) {
Ok(epoll) => {
let interest = epoll.add_interest(input.as_raw_fd(), 0u64, &[]);
match interest {
Ok(_) => Ok(epoll),
Err(e) => Err(LibinputSubsystemError::Initialization(format!("Failed to add epoll interest: {}", e)))
}
}
Err(e) => Err(LibinputSubsystemError::Initialization(format!("Failed to create poll context: {}", e)))
}
}
fn map_libinput_event(event: Event) -> Result<KvmEvent, LibinputSubsystemError> {
match KvmEvent::from_libinput(event) {
Err(error) => Err(LibinputSubsystemError::Mapping(error)),
Ok(mapped_event) => Ok(mapped_event)
}
}
fn intercept_client_switch_event(event: &KvmEvent) -> bool {
match event {
KvmEvent::Keyboard(event) if event.key_code == CLIENT_SWITCH_KEY_CODE => {
// Do stuff
println!("Right Alt key event");
false
}
_ => true
}
}

View File

@ -1,24 +1,46 @@
use std::collections::VecDeque;
use std::io;
use std::collections::{HashMap, VecDeque};
use std::fmt::Error;
use std::{io, thread};
use std::net::SocketAddr;
use std::sync::mpsc;
use messages::client_registration::ClientRegistration;
use messages::serialization::{DeserializeMessage, read_message_data, SerializeMessage};
use crate::input::{listen_inputs};
use crate::input::{InputSystem, LibinputSubsystemError};
use crate::input::events::KvmEvent;
use crate::multi_index_queue::MultiIndexQueue;
use crate::net::tcp_server::{NextIntent, TcpClient, TcpServer};
mod net;
mod input;
mod client;
mod multi_index_queue;
fn main() -> io::Result<()> {
// let addr = SocketAddr::from(([127, 0, 0, 1], 4433));
// let mut server: TcpServer<KvmClient> = TcpServer::new(addr)?;
//
// server.listen()?;
listen_inputs()?;
let mut input_system = InputSystem::new().expect("Failed to initialize input system");
loop {
for event in &mut input_system {
println!("Received event: {}", event);
}
}
// let mut queue = MultiIndexQueue::new(Box::new(input_system));
// let mut index = queue.create_index();
//
// loop {
// let next: Option<&KvmEvent> = queue.next(&mut index);
// if next.is_some() {
// println!("Received event: {}", next.unwrap());
// }
// }
Ok(())
}

View File

@ -0,0 +1,96 @@
use std::cmp::Ordering;
use std::collections::VecDeque;
const QUEUE_CAPACITY: usize = 1000;
pub struct MultiIndexQueue<T> {
iterator: Box<dyn Iterator<Item=T>>,
items: VecDeque<T>,
offset: usize,
}
#[derive(Eq)]
pub struct QueueIndex {
index: usize,
}
impl<T> MultiIndexQueue<T> {
pub fn new(iterator: Box<dyn Iterator<Item=T>>) -> Self {
Self {
iterator,
items: VecDeque::with_capacity(QUEUE_CAPACITY),
offset: 0,
}
}
pub fn create_index(&self) -> QueueIndex {
QueueIndex { index: self.offset }
}
pub fn next(&mut self, index: &mut QueueIndex) -> Option<&T> {
if self.items.is_empty() {
self.fill_queue();
}
let real_index = index.index - self.offset;
if real_index > QUEUE_CAPACITY {
let next = self.fill_next();
index.index += 1;
return next;
}
let real_index = index.index - self.offset;
let item = self.items.get(real_index);
index.index += 1;
item
}
fn fill_queue(&mut self) {
let mut index = 0usize;
let initial_queue_len = self.items.len();
loop {
if initial_queue_len + index >= QUEUE_CAPACITY {
break;
}
if self.fill_next().is_none() {
break;
}
index += 1;
}
}
fn fill_next(&mut self) -> Option<&T> {
let next = self.iterator.next();
match next {
Some(next) => {
self.items.pop_front();
self.items.push_back(next);
self.offset += 1;
self.items.get(QUEUE_CAPACITY)
}
None => None
}
}
}
impl PartialOrd<Self> for QueueIndex {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for QueueIndex {
fn cmp(&self, other: &Self) -> Ordering {
self.index.cmp(&other.index)
}
}
impl PartialEq<Self> for QueueIndex {
fn eq(&self, other: &Self) -> bool {
self.index == other.index
}
}