mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-18 10:01:26 +03:00
Compare commits
7 Commits
v0.5.0
...
x11-event-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2594a83e6a | ||
|
|
b81e5806ab | ||
|
|
a129e27a26 | ||
|
|
4561c20610 | ||
|
|
6cdb607b11 | ||
|
|
f5827bb31c | ||
|
|
64e3bf3ff4 |
@@ -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"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
71
src/event.rs
71
src/event.rs
@@ -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(),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
|||||||
@@ -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<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
636
src/server.rs
636
src/server.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user