Compare commits

...

7 Commits

Author SHA1 Message Date
Ferdinand Schober
2594a83e6a formatting 2024-01-02 12:43:33 +01:00
Ferdinand Schober
b81e5806ab basic input event decoding 2024-01-02 12:43:33 +01:00
Ferdinand Schober
a129e27a26 start working on x11 producer 2024-01-02 12:43:33 +01:00
Ferdinand Schober
4561c20610 layer-shell: recreate windows, when output is removed / added (#62)
Previously, when an output was removed (e.g. laptop lid closed and opened) the windows used for input capture would not appear anymore until toggling the client off and on
2024-01-01 22:48:44 +01:00
Ferdinand Schober
6cdb607b11 Fix Error handling in layershell producer (#61)
previous error handling resulted in a softlock when the connection
to the compositor was lost
2024-01-01 22:07:21 +01:00
Ferdinand Schober
f5827bb31c fix port changing 2024-01-01 14:55:29 +01:00
Ferdinand Schober
64e3bf3ff4 release stuck keys (#53)
Keys are now released when
- A client disconnects and still has pressed keys
- A client disconnects through CTLR+ALT+SHIFT+WIN
- Lan Mouse terminates with keys still being pressed through a remote client

This is also fixes an issue caused by KDE's implementation of the remote desktop portal backend:
Keys are not correctly released when a remote desktop session is closed while keys are still pressed,
causing them to be permanently stuck until kwin is restarted.

This workaround remembers all pressed keys and releases them when lan-mouse exits or a device disconnects.

closes #15
2023-12-31 15:42:29 +01:00
13 changed files with 766 additions and 347 deletions

View File

@@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
use async_trait::async_trait; use async_trait::async_trait;
use std::ptr; use std::ptr;
use x11::{ use x11::{
xlib::{self, XCloseDisplay}, xlib::{self, XCloseDisplay, XOpenDisplay},
xtest, xtest,
}; };
@@ -23,7 +23,7 @@ unsafe impl Send for X11Consumer {}
impl X11Consumer { impl X11Consumer {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let display = unsafe { let display = unsafe {
match xlib::XOpenDisplay(ptr::null()) { match XOpenDisplay(ptr::null()) {
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => { d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => {
Err(anyhow!("could not open display")) Err(anyhow!("could not open display"))
} }

View File

@@ -24,9 +24,13 @@ impl Default for DummyProducer {
} }
impl EventProducer for DummyProducer { impl EventProducer for DummyProducer {
fn notify(&mut self, _: ClientEvent) {} fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(())
}
fn release(&mut self) {} fn release(&mut self) -> io::Result<()> {
Ok(())
}
} }
impl Stream for DummyProducer { impl Stream for DummyProducer {

View File

@@ -3,7 +3,11 @@ use std::{io, task::Poll};
use futures_core::Stream; use futures_core::Stream;
use crate::{client::ClientHandle, event::Event, producer::EventProducer}; use crate::{
client::{ClientEvent, ClientHandle},
event::Event,
producer::EventProducer,
};
pub struct LibeiProducer {} pub struct LibeiProducer {}
@@ -14,9 +18,13 @@ impl LibeiProducer {
} }
impl EventProducer for LibeiProducer { impl EventProducer for LibeiProducer {
fn notify(&mut self, _event: crate::client::ClientEvent) {} fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(())
}
fn release(&mut self) {} fn release(&mut self) -> io::Result<()> {
Ok(())
}
} }
impl Stream for LibeiProducer { impl Stream for LibeiProducer {

View File

@@ -23,7 +23,11 @@ impl Stream for MacOSProducer {
} }
impl EventProducer for MacOSProducer { impl EventProducer for MacOSProducer {
fn notify(&mut self, _event: ClientEvent) {} fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(())
}
fn release(&mut self) {} fn release(&mut self) -> io::Result<()> {
Ok(())
}
} }

View File

@@ -125,6 +125,7 @@ struct Window {
buffer: wl_buffer::WlBuffer, buffer: wl_buffer::WlBuffer,
surface: wl_surface::WlSurface, surface: wl_surface::WlSurface,
layer_surface: ZwlrLayerSurfaceV1, layer_surface: ZwlrLayerSurfaceV1,
pos: Position,
} }
impl Window { impl Window {
@@ -179,6 +180,7 @@ impl Window {
surface.set_input_region(None); surface.set_input_region(None);
surface.commit(); surface.commit();
Window { Window {
pos,
buffer, buffer,
surface, surface,
layer_surface, layer_surface,
@@ -381,6 +383,24 @@ impl WaylandEventProducer {
Ok(WaylandEventProducer(inner)) Ok(WaylandEventProducer(inner))
} }
fn add_client(&mut self, handle: ClientHandle, pos: Position) {
self.0.get_mut().state.add_client(handle, pos);
}
fn delete_client(&mut self, handle: ClientHandle) {
let inner = self.0.get_mut();
// remove all windows corresponding to this client
while let Some(i) = inner
.state
.client_for_window
.iter()
.position(|(_, c)| *c == handle)
{
inner.state.client_for_window.remove(i);
inner.state.focused = None;
}
}
} }
impl State { impl State {
@@ -475,6 +495,19 @@ impl State {
self.client_for_window.push((window, client)); self.client_for_window.push((window, client));
}); });
} }
fn update_windows(&mut self) {
log::debug!("updating windows");
log::debug!("output info: {:?}", self.output_info);
let clients: Vec<_> = self
.client_for_window
.drain(..)
.map(|(w, c)| (c, w.pos))
.collect();
for (client, pos) in clients {
self.add_client(client, pos);
}
}
} }
impl Inner { impl Inner {
@@ -527,50 +560,42 @@ impl Inner {
} }
} }
fn flush_events(&mut self) { fn flush_events(&mut self) -> io::Result<()> {
// flush outgoing events // flush outgoing events
match self.queue.flush() { match self.queue.flush() {
Ok(_) => (), Ok(_) => (),
Err(e) => match e { Err(e) => match e {
WaylandError::Io(e) => { WaylandError::Io(e) => {
log::error!("error writing to wayland socket: {e}") return Err(e);
} }
WaylandError::Protocol(e) => { WaylandError::Protocol(e) => {
panic!("wayland protocol violation: {e}") panic!("wayland protocol violation: {e}")
} }
}, },
} }
Ok(())
} }
} }
impl EventProducer for WaylandEventProducer { impl EventProducer for WaylandEventProducer {
fn notify(&mut self, client_event: ClientEvent) { fn notify(&mut self, client_event: ClientEvent) -> io::Result<()> {
match client_event { match client_event {
ClientEvent::Create(handle, pos) => { ClientEvent::Create(handle, pos) => {
self.0.get_mut().state.add_client(handle, pos); self.add_client(handle, pos);
} }
ClientEvent::Destroy(handle) => { ClientEvent::Destroy(handle) => {
let inner = self.0.get_mut(); self.delete_client(handle);
// remove all windows corresponding to this client
while let Some(i) = inner
.state
.client_for_window
.iter()
.position(|(_, c)| *c == handle)
{
inner.state.client_for_window.remove(i);
inner.state.focused = None;
}
} }
} }
let inner = self.0.get_mut(); let inner = self.0.get_mut();
inner.flush_events(); inner.flush_events()
} }
fn release(&mut self) { fn release(&mut self) -> io::Result<()> {
log::debug!("releasing pointer");
let inner = self.0.get_mut(); let inner = self.0.get_mut();
inner.state.ungrab(); inner.state.ungrab();
inner.flush_events(); inner.flush_events()
} }
} }
@@ -601,7 +626,11 @@ impl Stream for WaylandEventProducer {
inner.dispatch_events(); inner.dispatch_events();
// flush outgoing events // flush outgoing events
inner.flush_events(); if let Err(e) = inner.flush_events() {
if e.kind() != ErrorKind::WouldBlock {
return Poll::Ready(Some(Err(e)));
}
}
// prepare for the next read // prepare for the next read
match inner.prepare_read() { match inner.prepare_read() {
@@ -923,6 +952,21 @@ impl Dispatch<ZxdgOutputV1, WlOutput> for State {
} }
} }
impl Dispatch<wl_output::WlOutput, ()> for State {
fn event(
state: &mut Self,
_proxy: &wl_output::WlOutput,
event: <wl_output::WlOutput as wayland_client::Proxy>::Event,
_data: &(),
_conn: &Connection,
_qhandle: &QueueHandle<Self>,
) {
if let wl_output::Event::Done = event {
state.update_windows();
}
}
}
// don't emit any events // don't emit any events
delegate_noop!(State: wl_region::WlRegion); delegate_noop!(State: wl_region::WlRegion);
delegate_noop!(State: wl_shm_pool::WlShmPool); delegate_noop!(State: wl_shm_pool::WlShmPool);
@@ -933,7 +977,6 @@ delegate_noop!(State: ZwpKeyboardShortcutsInhibitManagerV1);
delegate_noop!(State: ZwpPointerConstraintsV1); delegate_noop!(State: ZwpPointerConstraintsV1);
// ignore events // ignore events
delegate_noop!(State: ignore wl_output::WlOutput);
delegate_noop!(State: ignore ZxdgOutputManagerV1); delegate_noop!(State: ignore ZxdgOutputManagerV1);
delegate_noop!(State: ignore wl_shm::WlShm); delegate_noop!(State: ignore wl_shm::WlShm);
delegate_noop!(State: ignore wl_buffer::WlBuffer); delegate_noop!(State: ignore wl_buffer::WlBuffer);

View File

@@ -12,9 +12,13 @@ use crate::{
pub struct WindowsProducer {} pub struct WindowsProducer {}
impl EventProducer for WindowsProducer { impl EventProducer for WindowsProducer {
fn notify(&mut self, _: ClientEvent) {} fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(())
}
fn release(&mut self) {} fn release(&mut self) -> io::Result<()> {
Ok(())
}
} }
impl WindowsProducer { impl WindowsProducer {

View File

@@ -1,35 +1,255 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use std::io; use x11::xinput::XGrabDevice;
use std::task::Poll; use x11::xinput2::XIAllDevices;
use std::collections::VecDeque;
use std::os::fd::{AsRawFd, RawFd};
use std::task::{ready, Poll};
use std::{io, ptr};
use futures_core::Stream; use futures_core::Stream;
use crate::event::Event; use crate::event::{Event, PointerEvent};
use crate::producer::EventProducer; use crate::producer::EventProducer;
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
use tokio::io::unix::AsyncFd;
pub struct X11Producer {} use x11::xlib::{
self, ButtonPress, ButtonPressMask, ButtonRelease, ButtonReleaseMask, CWBackPixel, CWEventMask,
CWOverrideRedirect, CopyFromParent, CurrentTime, EnterNotify, EnterWindowMask, ExposureMask,
GrabModeAsync, KeyPress, KeyPressMask, KeyRelease, KeyReleaseMask, LeaveWindowMask,
MotionNotify, PointerMotionMask, VisibilityChangeMask, XClassHint, XCloseDisplay,
XCreateWindow, XDefaultScreen, XFlush, XGetInputFocus, XGrabKeyboard,
XGrabPointer, XMapRaised, XNextEvent, XOpenDisplay, XPending, XRootWindow, XSetClassHint,
XSetWindowAttributes, XWhitePixel, XDefaultRootWindow,
};
pub struct X11Producer(AsyncFd<Inner>);
struct Inner {
connection_fd: RawFd,
display: *mut xlib::Display,
pending_events: VecDeque<(ClientHandle, Event)>,
window: u64,
}
impl AsRawFd for Inner {
fn as_raw_fd(&self) -> std::os::unix::prelude::RawFd {
self.connection_fd
}
}
impl X11Producer { impl X11Producer {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
Err(anyhow!("not implemented")) let display = unsafe {
match XOpenDisplay(ptr::null()) {
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => {
Err(anyhow!("could not open display"))
}
display => Ok(display),
}
}?;
let screen = unsafe { XDefaultScreen(display) };
log::warn!("screen: {screen}");
let root_window = unsafe { XRootWindow(display, screen) };
log::warn!("root: {root_window}");
let mut attr: XSetWindowAttributes = unsafe { std::mem::zeroed() };
attr.override_redirect = true as i32;
attr.background_pixel = unsafe { XWhitePixel(display, screen) };
attr.event_mask = ExposureMask
| VisibilityChangeMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
| EnterWindowMask
| LeaveWindowMask;
let window = unsafe {
XCreateWindow(
display,
root_window,
0, /* x */
0, /* y */
2560, /* min width */
10, /* min height */
0, /* border width */
CopyFromParent, /* depth */
CopyFromParent as u32, /* class */
ptr::null_mut(), /* Visual *visual */
CWOverrideRedirect | CWBackPixel | CWEventMask,
&mut attr as *mut _,
)
};
let mut name: String = "lan-mouse".into();
let name = name.as_mut_ptr();
let mut class_hint = XClassHint {
res_name: name as *mut i8,
res_class: name as *mut i8,
};
unsafe { XSetClassHint(display, window, &mut class_hint as *mut _) };
log::warn!("window: {window}");
// unsafe { XSelectInput(display, window, event_mask as i64) };
unsafe { XMapRaised(display, window) };
unsafe { XFlush(display) };
/* can not fail */
let connection_fd = unsafe { xlib::XConnectionNumber(display) };
let pending_events = VecDeque::new();
let inner = Inner {
connection_fd,
display,
window,
pending_events,
};
let async_fd = AsyncFd::new(inner)?;
Ok(X11Producer(async_fd))
}
}
impl Inner {
fn decode(&mut self, xevent: xlib::XEvent) -> Option<(u32, Event)> {
log::info!("decoding {xevent:?}");
match xevent.get_type() {
t if t == KeyPress || t == KeyRelease => {
let key_event: xlib::XKeyEvent = unsafe { xevent.key };
let code = key_event.keycode;
let linux_code = code - 8;
let state = (xevent.get_type() == KeyPress) as u8;
return Some((
0,
Event::Keyboard(crate::event::KeyboardEvent::Key {
time: 0,
key: linux_code,
state,
}),
));
}
t if t == EnterNotify => {
let mut prev_win = 0;
unsafe {
XGetInputFocus(
self.display,
&mut self.window as *mut _,
&mut prev_win as *mut _,
);
XGrabKeyboard(
self.display,
XDefaultRootWindow(self.display),
true as i32,
GrabModeAsync,
GrabModeAsync,
CurrentTime,
);
XGrabPointer(
self.display,
self.window, /* window to grab */
true as i32, /* owner_events */
(PointerMotionMask | ButtonPressMask | ButtonReleaseMask) as u32, /* event mask */
GrabModeAsync, /* pointer_mode */
GrabModeAsync, /* keyboard_mode */
self.window, /* confine_to */
0, /* cursor */
CurrentTime,
);
};
Some((0, Event::Enter()))
}
t if t == MotionNotify => {
let pointer_event = unsafe { xevent.motion };
let (abs_x, abs_y) = (pointer_event.x, pointer_event.y);
let event = Event::Pointer(PointerEvent::Motion {
time: 0,
relative_x: abs_x as f64,
relative_y: abs_y as f64,
});
Some((0, event))
}
t if t == ButtonPress || t == ButtonRelease => {
let button_event = unsafe { xevent.button };
log::info!("{:?}", xevent);
Some((0, Event::Pointer(PointerEvent::Button {
time: 0,
button: button_event.button,
state: button_event.state,
})))
}
_ => None,
}
}
fn dispatch(&mut self) -> io::Result<bool> {
unsafe {
if XPending(self.display) > 0 {
let mut xevent: xlib::XEvent = std::mem::zeroed();
XNextEvent(self.display, &mut xevent as *mut _);
if let Some(event) = self.decode(xevent) {
self.pending_events.push_back(event);
}
Ok(true)
} else {
Ok(false)
}
}
}
}
impl Drop for Inner {
fn drop(&mut self) {
unsafe {
XCloseDisplay(self.display);
}
} }
} }
impl EventProducer for X11Producer { impl EventProducer for X11Producer {
fn notify(&mut self, _: ClientEvent) {} fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(())
}
fn release(&mut self) {} fn release(&mut self) -> io::Result<()> {
Ok(())
}
} }
impl Stream for X11Producer { impl Stream for X11Producer {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next( fn poll_next(
self: std::pin::Pin<&mut Self>, mut self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>, cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> { ) -> Poll<Option<Self::Item>> {
Poll::Pending if let Some(event) = self.0.get_mut().pending_events.pop_front() {
return Poll::Ready(Some(Ok(event)));
}
loop {
let mut guard = ready!(self.0.poll_read_ready_mut(cx))?;
{
let inner = guard.get_inner_mut();
loop {
if match inner.dispatch() {
Ok(event) => event,
Err(e) => {
guard.clear_ready();
return Poll::Ready(Some(Err(e)));
}
} == false
{
break;
}
}
}
guard.clear_ready();
match guard.get_inner_mut().pending_events.pop_front() {
Some(event) => {
return Poll::Ready(Some(Ok(event)));
}
None => continue,
}
}
} }
} }

View File

@@ -2,7 +2,6 @@ use std::{
collections::HashSet, collections::HashSet,
fmt::Display, fmt::Display,
net::{IpAddr, SocketAddr}, net::{IpAddr, SocketAddr},
time::Instant,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -57,10 +56,6 @@ pub struct Client {
/// This way any event consumer / producer backend does not /// This way any event consumer / producer backend does not
/// need to know anything about a client other than its handle. /// need to know anything about a client other than its handle.
pub handle: ClientHandle, pub handle: ClientHandle,
/// `active` address of the client, used to send data to.
/// This should generally be the socket address where data
/// was last received from.
pub active_addr: Option<SocketAddr>,
/// all socket addresses associated with a particular client /// all socket addresses associated with a particular client
/// e.g. Laptops usually have at least an ethernet and a wifi port /// e.g. Laptops usually have at least an ethernet and a wifi port
/// which have different ip addresses /// which have different ip addresses
@@ -71,7 +66,7 @@ pub struct Client {
pub pos: Position, pub pos: Position,
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug)]
pub enum ClientEvent { pub enum ClientEvent {
Create(ClientHandle, Position), Create(ClientHandle, Position),
Destroy(ClientHandle), Destroy(ClientHandle),
@@ -81,11 +76,18 @@ pub type ClientHandle = u32;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ClientState { pub struct ClientState {
/// information about the client
pub client: Client, pub client: Client,
/// events should be sent to and received from the client
pub active: bool, pub active: bool,
pub last_ping: Option<Instant>, /// `active` address of the client, used to send data to.
pub last_seen: Option<Instant>, /// This should generally be the socket address where data
pub last_replied: Option<Instant>, /// was last received from.
pub active_addr: Option<SocketAddr>,
/// tracks whether or not the client is responding to pings
pub alive: bool,
/// keys currently pressed by this client
pub pressed_keys: HashSet<u32>,
} }
pub struct ClientManager { pub struct ClientManager {
@@ -114,9 +116,6 @@ impl ClientManager {
// get a new client_handle // get a new client_handle
let handle = self.free_id(); let handle = self.free_id();
// we dont know, which IP is initially active
let active_addr = None;
// store fix ip addresses // store fix ip addresses
let fix_ips = ips.iter().cloned().collect(); let fix_ips = ips.iter().cloned().collect();
@@ -128,7 +127,6 @@ impl ClientManager {
hostname, hostname,
fix_ips, fix_ips,
handle, handle,
active_addr,
addrs, addrs,
port, port,
pos, pos,
@@ -137,10 +135,10 @@ impl ClientManager {
// client was never seen, nor pinged // client was never seen, nor pinged
let client_state = ClientState { let client_state = ClientState {
client, client,
last_ping: None,
last_seen: None,
last_replied: None,
active: false, active: false,
active_addr: None,
alive: false,
pressed_keys: HashSet::new(),
}; };
if handle as usize >= self.clients.len() { if handle as usize >= self.clients.len() {

View File

@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use std::{ use std::{
error::Error, error::Error,
fmt::{self, Display}, fmt::{self, Display},
@@ -65,6 +66,9 @@ pub enum Event {
/// response to a ping event: this event signals that a client /// response to a ping event: this event signals that a client
/// is still alive but must otherwise be ignored /// is still alive but must otherwise be ignored
Pong(), Pong(),
/// explicit disconnect request. The client will no longer
/// send events until the next Enter event. All of its keys should be released.
Disconnect(),
} }
impl Display for PointerEvent { impl Display for PointerEvent {
@@ -120,6 +124,7 @@ impl Display for Event {
Event::Leave() => write!(f, "leave"), Event::Leave() => write!(f, "leave"),
Event::Ping() => write!(f, "ping"), Event::Ping() => write!(f, "ping"),
Event::Pong() => write!(f, "pong"), Event::Pong() => write!(f, "pong"),
Event::Disconnect() => write!(f, "disconnect"),
} }
} }
} }
@@ -133,6 +138,7 @@ impl Event {
Self::Leave() => EventType::Leave, Self::Leave() => EventType::Leave,
Self::Ping() => EventType::Ping, Self::Ping() => EventType::Ping,
Self::Pong() => EventType::Pong, Self::Pong() => EventType::Pong,
Self::Disconnect() => EventType::Disconnect,
} }
} }
} }
@@ -174,18 +180,19 @@ enum EventType {
Leave, Leave,
Ping, Ping,
Pong, Pong,
Disconnect,
} }
impl TryFrom<u8> for PointerEventType { impl TryFrom<u8> for PointerEventType {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self> {
match value { match value {
x if x == Self::Motion as u8 => Ok(Self::Motion), x if x == Self::Motion as u8 => Ok(Self::Motion),
x if x == Self::Button as u8 => Ok(Self::Button), x if x == Self::Button as u8 => Ok(Self::Button),
x if x == Self::Axis as u8 => Ok(Self::Axis), x if x == Self::Axis as u8 => Ok(Self::Axis),
x if x == Self::Frame as u8 => Ok(Self::Frame), x if x == Self::Frame as u8 => Ok(Self::Frame),
_ => Err(Box::new(ProtocolError { _ => Err(anyhow!(ProtocolError {
msg: format!("invalid pointer event type {}", value), msg: format!("invalid pointer event type {}", value),
})), })),
} }
@@ -193,13 +200,13 @@ impl TryFrom<u8> for PointerEventType {
} }
impl TryFrom<u8> for KeyboardEventType { impl TryFrom<u8> for KeyboardEventType {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self> {
match value { match value {
x if x == Self::Key as u8 => Ok(Self::Key), x if x == Self::Key as u8 => Ok(Self::Key),
x if x == Self::Modifiers as u8 => Ok(Self::Modifiers), x if x == Self::Modifiers as u8 => Ok(Self::Modifiers),
_ => Err(Box::new(ProtocolError { _ => Err(anyhow!(ProtocolError {
msg: format!("invalid keyboard event type {}", value), msg: format!("invalid keyboard event type {}", value),
})), })),
} }
@@ -216,6 +223,7 @@ impl From<&Event> for Vec<u8> {
Event::Leave() => vec![], Event::Leave() => vec![],
Event::Ping() => vec![], Event::Ping() => vec![],
Event::Pong() => vec![], Event::Pong() => vec![],
Event::Disconnect() => vec![],
}; };
[event_id, event_data].concat() [event_id, event_data].concat()
} }
@@ -234,9 +242,9 @@ impl fmt::Display for ProtocolError {
impl Error for ProtocolError {} impl Error for ProtocolError {}
impl TryFrom<Vec<u8>> for Event { impl TryFrom<Vec<u8>> for Event {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(value: Vec<u8>) -> Result<Self> {
let event_id = u8::from_be_bytes(value[..1].try_into()?); let event_id = u8::from_be_bytes(value[..1].try_into()?);
match event_id { match event_id {
i if i == (EventType::Pointer as u8) => Ok(Event::Pointer(value.try_into()?)), i if i == (EventType::Pointer as u8) => Ok(Event::Pointer(value.try_into()?)),
@@ -245,7 +253,8 @@ impl TryFrom<Vec<u8>> for Event {
i if i == (EventType::Leave as u8) => Ok(Event::Leave()), i if i == (EventType::Leave as u8) => Ok(Event::Leave()),
i if i == (EventType::Ping as u8) => Ok(Event::Ping()), i if i == (EventType::Ping as u8) => Ok(Event::Ping()),
i if i == (EventType::Pong as u8) => Ok(Event::Pong()), i if i == (EventType::Pong as u8) => Ok(Event::Pong()),
_ => Err(Box::new(ProtocolError { i if i == (EventType::Disconnect as u8) => Ok(Event::Disconnect()),
_ => Err(anyhow!(ProtocolError {
msg: format!("invalid event_id {}", event_id), msg: format!("invalid event_id {}", event_id),
})), })),
} }
@@ -291,9 +300,9 @@ impl From<&PointerEvent> for Vec<u8> {
} }
impl TryFrom<Vec<u8>> for PointerEvent { impl TryFrom<Vec<u8>> for PointerEvent {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(data: Vec<u8>) -> Result<Self> {
match data.get(1) { match data.get(1) {
Some(id) => { Some(id) => {
let event_type = match id.to_owned().try_into() { let event_type = match id.to_owned().try_into() {
@@ -305,7 +314,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -313,7 +322,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let relative_x = match data.get(6..14) { let relative_x = match data.get(6..14) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 6".into(), msg: "Expected 8 Bytes at index 6".into(),
})) }))
} }
@@ -321,7 +330,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let relative_y = match data.get(14..22) { let relative_y = match data.get(14..22) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 14".into(), msg: "Expected 8 Bytes at index 14".into(),
})) }))
} }
@@ -336,7 +345,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -344,7 +353,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let button = match data.get(6..10) { let button = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -352,7 +361,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let state = match data.get(10..14) { let state = match data.get(10..14) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 14".into(), msg: "Expected 4 Bytes at index 14".into(),
})) }))
} }
@@ -367,7 +376,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -375,7 +384,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let axis = match data.get(6) { let axis = match data.get(6) {
Some(d) => *d, Some(d) => *d,
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 1 Byte at index 6".into(), msg: "Expected 1 Byte at index 6".into(),
})); }));
} }
@@ -383,7 +392,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let value = match data.get(7..15) { let value = match data.get(7..15) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 7".into(), msg: "Expected 8 Bytes at index 7".into(),
})); }));
} }
@@ -393,7 +402,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
PointerEventType::Frame => Ok(Self::Frame {}), PointerEventType::Frame => Ok(Self::Frame {}),
} }
} }
None => Err(Box::new(ProtocolError { None => Err(anyhow!(ProtocolError {
msg: "Expected an element at index 0".into(), msg: "Expected an element at index 0".into(),
})), })),
} }
@@ -434,9 +443,9 @@ impl From<&KeyboardEvent> for Vec<u8> {
} }
impl TryFrom<Vec<u8>> for KeyboardEvent { impl TryFrom<Vec<u8>> for KeyboardEvent {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(data: Vec<u8>) -> Result<Self> {
match data.get(1) { match data.get(1) {
Some(id) => { Some(id) => {
let event_type = match id.to_owned().try_into() { let event_type = match id.to_owned().try_into() {
@@ -448,7 +457,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 6".into(), msg: "Expected 4 Bytes at index 6".into(),
})) }))
} }
@@ -456,7 +465,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let key = match data.get(6..10) { let key = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -464,7 +473,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let state = match data.get(10) { let state = match data.get(10) {
Some(d) => *d, Some(d) => *d,
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 1 Bytes at index 14".into(), msg: "Expected 1 Bytes at index 14".into(),
})) }))
} }
@@ -475,7 +484,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_depressed = match data.get(2..6) { let mods_depressed = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 6".into(), msg: "Expected 4 Bytes at index 6".into(),
})) }))
} }
@@ -483,7 +492,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_latched = match data.get(6..10) { let mods_latched = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -491,7 +500,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_locked = match data.get(10..14) { let mods_locked = match data.get(10..14) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 14".into(), msg: "Expected 4 Bytes at index 14".into(),
})) }))
} }
@@ -499,7 +508,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let group = match data.get(14..18) { let group = match data.get(14..18) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 18".into(), msg: "Expected 4 Bytes at index 18".into(),
})) }))
} }
@@ -513,7 +522,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
} }
} }
} }
None => Err(Box::new(ProtocolError { None => Err(anyhow!(ProtocolError {
msg: "Expected an element at index 0".into(), msg: "Expected an element at index 0".into(),
})), })),
} }

View File

@@ -108,6 +108,7 @@ pub enum FrontendNotify {
NotifyClientDelete(ClientHandle), NotifyClientDelete(ClientHandle),
/// new port, reason of failure (if failed) /// new port, reason of failure (if failed)
NotifyPortChange(u16, Option<String>), NotifyPortChange(u16, Option<String>),
/// Client State, active
Enumerate(Vec<(Client, bool)>), Enumerate(Vec<(Client, bool)>),
NotifyError(String), NotifyError(String),
} }

View File

@@ -65,7 +65,9 @@ fn run_service(config: &Config) -> Result<()> {
runtime.block_on(LocalSet::new().run_until(async { runtime.block_on(LocalSet::new().run_until(async {
// run main loop // run main loop
log::info!("Press Ctrl+Alt+Shift+Super to release the mouse"); log::info!("Press Ctrl+Alt+Shift+Super to release the mouse");
Server::run(config).await?;
let server = Server::new(config);
server.run().await?;
log::debug!("service exiting"); log::debug!("service exiting");
anyhow::Ok(()) anyhow::Ok(())

View File

@@ -54,8 +54,8 @@ pub async fn create() -> Box<dyn EventProducer> {
pub trait EventProducer: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin { pub trait EventProducer: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin {
/// notify event producer of configuration changes /// notify event producer of configuration changes
fn notify(&mut self, event: ClientEvent); fn notify(&mut self, event: ClientEvent) -> io::Result<()>;
/// release mouse /// release mouse
fn release(&mut self); fn release(&mut self) -> io::Result<()>;
} }

File diff suppressed because it is too large Load Diff