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

View File

@@ -24,9 +24,13 @@ impl Default 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 {

View File

@@ -3,7 +3,11 @@ use std::{io, task::Poll};
use futures_core::Stream;
use crate::{client::ClientHandle, event::Event, producer::EventProducer};
use crate::{
client::{ClientEvent, ClientHandle},
event::Event,
producer::EventProducer,
};
pub struct LibeiProducer {}
@@ -14,9 +18,13 @@ impl 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 {

View File

@@ -23,7 +23,11 @@ impl Stream 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,
surface: wl_surface::WlSurface,
layer_surface: ZwlrLayerSurfaceV1,
pos: Position,
}
impl Window {
@@ -179,6 +180,7 @@ impl Window {
surface.set_input_region(None);
surface.commit();
Window {
pos,
buffer,
surface,
layer_surface,
@@ -381,6 +383,24 @@ impl WaylandEventProducer {
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 {
@@ -475,6 +495,19 @@ impl State {
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 {
@@ -527,50 +560,42 @@ impl Inner {
}
}
fn flush_events(&mut self) {
fn flush_events(&mut self) -> io::Result<()> {
// flush outgoing events
match self.queue.flush() {
Ok(_) => (),
Err(e) => match e {
WaylandError::Io(e) => {
log::error!("error writing to wayland socket: {e}")
return Err(e);
}
WaylandError::Protocol(e) => {
panic!("wayland protocol violation: {e}")
}
},
}
Ok(())
}
}
impl EventProducer for WaylandEventProducer {
fn notify(&mut self, client_event: ClientEvent) {
fn notify(&mut self, client_event: ClientEvent) -> io::Result<()> {
match client_event {
ClientEvent::Create(handle, pos) => {
self.0.get_mut().state.add_client(handle, pos);
self.add_client(handle, pos);
}
ClientEvent::Destroy(handle) => {
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;
}
self.delete_client(handle);
}
}
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();
inner.state.ungrab();
inner.flush_events();
inner.flush_events()
}
}
@@ -601,7 +626,11 @@ impl Stream for WaylandEventProducer {
inner.dispatch_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
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
delegate_noop!(State: wl_region::WlRegion);
delegate_noop!(State: wl_shm_pool::WlShmPool);
@@ -933,7 +977,6 @@ delegate_noop!(State: ZwpKeyboardShortcutsInhibitManagerV1);
delegate_noop!(State: ZwpPointerConstraintsV1);
// ignore events
delegate_noop!(State: ignore wl_output::WlOutput);
delegate_noop!(State: ignore ZxdgOutputManagerV1);
delegate_noop!(State: ignore wl_shm::WlShm);
delegate_noop!(State: ignore wl_buffer::WlBuffer);

View File

@@ -12,9 +12,13 @@ use crate::{
pub struct 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 {

View File

@@ -1,35 +1,255 @@
use anyhow::{anyhow, Result};
use std::io;
use std::task::Poll;
use x11::xinput::XGrabDevice;
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 crate::event::Event;
use crate::event::{Event, PointerEvent};
use crate::producer::EventProducer;
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 {
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 {
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 {
type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(
self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
Poll::Pending
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Self::Item>> {
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,
fmt::Display,
net::{IpAddr, SocketAddr},
time::Instant,
};
use serde::{Deserialize, Serialize};
@@ -57,10 +56,6 @@ pub struct Client {
/// This way any event consumer / producer backend does not
/// need to know anything about a client other than its handle.
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
/// e.g. Laptops usually have at least an ethernet and a wifi port
/// which have different ip addresses
@@ -71,7 +66,7 @@ pub struct Client {
pub pos: Position,
}
#[derive(Debug)]
#[derive(Clone, Copy, Debug)]
pub enum ClientEvent {
Create(ClientHandle, Position),
Destroy(ClientHandle),
@@ -81,11 +76,18 @@ pub type ClientHandle = u32;
#[derive(Debug, Clone)]
pub struct ClientState {
/// information about the client
pub client: Client,
/// events should be sent to and received from the client
pub active: bool,
pub last_ping: Option<Instant>,
pub last_seen: Option<Instant>,
pub last_replied: Option<Instant>,
/// `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>,
/// 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 {
@@ -114,9 +116,6 @@ impl ClientManager {
// get a new client_handle
let handle = self.free_id();
// we dont know, which IP is initially active
let active_addr = None;
// store fix ip addresses
let fix_ips = ips.iter().cloned().collect();
@@ -128,7 +127,6 @@ impl ClientManager {
hostname,
fix_ips,
handle,
active_addr,
addrs,
port,
pos,
@@ -137,10 +135,10 @@ impl ClientManager {
// client was never seen, nor pinged
let client_state = ClientState {
client,
last_ping: None,
last_seen: None,
last_replied: None,
active: false,
active_addr: None,
alive: false,
pressed_keys: HashSet::new(),
};
if handle as usize >= self.clients.len() {

View File

@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use std::{
error::Error,
fmt::{self, Display},
@@ -65,6 +66,9 @@ pub enum Event {
/// response to a ping event: this event signals that a client
/// is still alive but must otherwise be ignored
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 {
@@ -120,6 +124,7 @@ impl Display for Event {
Event::Leave() => write!(f, "leave"),
Event::Ping() => write!(f, "ping"),
Event::Pong() => write!(f, "pong"),
Event::Disconnect() => write!(f, "disconnect"),
}
}
}
@@ -133,6 +138,7 @@ impl Event {
Self::Leave() => EventType::Leave,
Self::Ping() => EventType::Ping,
Self::Pong() => EventType::Pong,
Self::Disconnect() => EventType::Disconnect,
}
}
}
@@ -174,18 +180,19 @@ enum EventType {
Leave,
Ping,
Pong,
Disconnect,
}
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 {
x if x == Self::Motion as u8 => Ok(Self::Motion),
x if x == Self::Button as u8 => Ok(Self::Button),
x if x == Self::Axis as u8 => Ok(Self::Axis),
x if x == Self::Frame as u8 => Ok(Self::Frame),
_ => Err(Box::new(ProtocolError {
_ => Err(anyhow!(ProtocolError {
msg: format!("invalid pointer event type {}", value),
})),
}
@@ -193,13 +200,13 @@ impl TryFrom<u8> for PointerEventType {
}
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 {
x if x == Self::Key as u8 => Ok(Self::Key),
x if x == Self::Modifiers as u8 => Ok(Self::Modifiers),
_ => Err(Box::new(ProtocolError {
_ => Err(anyhow!(ProtocolError {
msg: format!("invalid keyboard event type {}", value),
})),
}
@@ -216,6 +223,7 @@ impl From<&Event> for Vec<u8> {
Event::Leave() => vec![],
Event::Ping() => vec![],
Event::Pong() => vec![],
Event::Disconnect() => vec![],
};
[event_id, event_data].concat()
}
@@ -234,9 +242,9 @@ impl fmt::Display for ProtocolError {
impl Error for ProtocolError {}
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()?);
match event_id {
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::Ping as u8) => Ok(Event::Ping()),
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),
})),
}
@@ -291,9 +300,9 @@ impl From<&PointerEvent> for Vec<u8> {
}
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) {
Some(id) => {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => f64::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => f64::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(),
}))
}
@@ -375,7 +384,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let axis = match data.get(6) {
Some(d) => *d,
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => f64::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 7".into(),
}));
}
@@ -393,7 +402,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
PointerEventType::Frame => Ok(Self::Frame {}),
}
}
None => Err(Box::new(ProtocolError {
None => Err(anyhow!(ProtocolError {
msg: "Expected an element at index 0".into(),
})),
}
@@ -434,9 +443,9 @@ impl From<&KeyboardEvent> for Vec<u8> {
}
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) {
Some(id) => {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(),
}))
}
@@ -464,7 +473,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let state = match data.get(10) {
Some(d) => *d,
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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) {
Some(d) => u32::from_be_bytes(d.try_into()?),
None => {
return Err(Box::new(ProtocolError {
return Err(anyhow!(ProtocolError {
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(),
})),
}

View File

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

View File

@@ -65,7 +65,9 @@ fn run_service(config: &Config) -> Result<()> {
runtime.block_on(LocalSet::new().run_until(async {
// run main loop
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");
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 {
/// notify event producer of configuration changes
fn notify(&mut self, event: ClientEvent);
fn notify(&mut self, event: ClientEvent) -> io::Result<()>;
/// release mouse
fn release(&mut self);
fn release(&mut self) -> io::Result<()>;
}

File diff suppressed because it is too large Load Diff