diff --git a/.gitignore b/.gitignore index ea8c4bf..25e41ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.gdbinit diff --git a/src/backend/consumer/libei.rs b/src/backend/consumer/libei.rs index 05a3ba3..2d94add 100644 --- a/src/backend/consumer/libei.rs +++ b/src/backend/consumer/libei.rs @@ -7,7 +7,7 @@ impl LibeiConsumer { } impl EventConsumer for LibeiConsumer { - fn consume(&self, _: crate::event::Event, _: crate::client::ClientHandle) { + fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) { log::error!("libei backend not yet implemented!"); todo!() } diff --git a/src/backend/consumer/wlroots.rs b/src/backend/consumer/wlroots.rs index 3066f03..da7b87e 100644 --- a/src/backend/consumer/wlroots.rs +++ b/src/backend/consumer/wlroots.rs @@ -1,7 +1,9 @@ use wayland_client::WEnum; +use wayland_client::backend::WaylandError; use crate::client::{ClientHandle, ClientEvent}; use crate::consumer::EventConsumer; use std::collections::HashMap; +use std::io; use std::os::fd::OwnedFd; use std::os::unix::prelude::AsRawFd; @@ -46,6 +48,7 @@ struct State { // App State, implements Dispatch event handlers pub(crate) struct WlrootsConsumer { + last_flush_failed: bool, state: State, queue: EventQueue, } @@ -89,6 +92,7 @@ impl WlrootsConsumer { let input_for_client: HashMap = HashMap::new(); let mut consumer = WlrootsConsumer { + last_flush_failed: false, state: State { keymap: None, input_for_client, @@ -137,11 +141,36 @@ impl State { } impl EventConsumer for WlrootsConsumer { - fn consume(&self, event: Event, client_handle: ClientHandle) { + fn consume(&mut self, event: Event, client_handle: ClientHandle) { if let Some(virtual_input) = self.state.input_for_client.get(&client_handle) { + if self.last_flush_failed { + if let Err(WaylandError::Io(e)) = self.queue.flush() { + if e.kind() == io::ErrorKind::WouldBlock { + /* + * outgoing buffer is full - sending more events + * will overwhelm the output buffer and leave the + * wayland connection in a broken state + */ + log::warn!("can't keep up, discarding event: ({client_handle}) - {event:?}"); + return + } + } + } virtual_input.consume_event(event).unwrap(); - if let Err(e) = self.queue.flush() { - log::error!("{}", e); + match self.queue.flush() { + Err(WaylandError::Io(e)) if e.kind() == io::ErrorKind::WouldBlock => { + self.last_flush_failed = true; + log::warn!("can't keep up, retrying ..."); + } + Err(WaylandError::Io(e)) => { + log::error!("{e}") + }, + Err(WaylandError::Protocol(e)) => { + panic!("wayland protocol violation: {e}") + } + Ok(()) => { + self.last_flush_failed = false; + }, } } } diff --git a/src/backend/consumer/x11.rs b/src/backend/consumer/x11.rs index 3c377de..c0dc83e 100644 --- a/src/backend/consumer/x11.rs +++ b/src/backend/consumer/x11.rs @@ -31,7 +31,7 @@ impl X11Consumer { } impl EventConsumer for X11Consumer { - fn consume(&self, event: Event, _: ClientHandle) { + fn consume(&mut self, event: Event, _: ClientHandle) { match event { Event::Pointer(pointer_event) => match pointer_event { crate::event::PointerEvent::Motion { diff --git a/src/backend/consumer/xdg_desktop_portal.rs b/src/backend/consumer/xdg_desktop_portal.rs index 55c385f..85df116 100644 --- a/src/backend/consumer/xdg_desktop_portal.rs +++ b/src/backend/consumer/xdg_desktop_portal.rs @@ -7,7 +7,7 @@ impl DesktopPortalConsumer { } impl EventConsumer for DesktopPortalConsumer { - fn consume(&self, _: crate::event::Event, _: crate::client::ClientHandle) { + fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) { log::error!("xdg_desktop_portal backend not yet implemented!"); } diff --git a/src/consumer.rs b/src/consumer.rs index 12e608d..07b03bc 100644 --- a/src/consumer.rs +++ b/src/consumer.rs @@ -15,7 +15,7 @@ enum Backend { pub trait EventConsumer { /// Event corresponding to an abstract `client_handle` - fn consume(&self, event: Event, client_handle: ClientHandle); + fn consume(&mut self, event: Event, client_handle: ClientHandle); /// Event corresponding to a configuration change fn notify(&mut self, client_event: ClientEvent);