Starting input system
This commit is contained in:
parent
61a7ce3904
commit
70319a98cb
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
||||
|
||||
pub struct KvmKeyboardEvent {
|
||||
|
@ -10,3 +11,12 @@ impl KvmEventTrait for KvmKeyboardEvent {
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
KvmEvent::Pointer(e) => write!(f, "Pointer({e})"),
|
||||
KvmEvent::Keyboard(e) => write!(f, "Keyboard({e})")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 prepare_libinput() -> Libinput {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for InputSystem<Libinput> {
|
||||
type Item = KvmEvent;
|
||||
|
||||
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);
|
||||
input.udev_assign_seat(UDEV_SEAT).unwrap();
|
||||
input
|
||||
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 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 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
|
||||
}
|
||||
}
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue