mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-09-17 18:01:11 +03:00
Compare commits
3 Commits
main-b316a
...
main-6b1ed
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b1eddef7a | ||
|
|
09889cd839 | ||
|
|
c194df791d |
@@ -123,7 +123,6 @@ struct State {
|
|||||||
focused: Option<Arc<Window>>,
|
focused: Option<Arc<Window>>,
|
||||||
global_list: GlobalList,
|
global_list: GlobalList,
|
||||||
globals: Globals,
|
globals: Globals,
|
||||||
wayland_fd: RawFd,
|
|
||||||
read_guard: Option<ReadEventsGuard>,
|
read_guard: Option<ReadEventsGuard>,
|
||||||
qh: QueueHandle<Self>,
|
qh: QueueHandle<Self>,
|
||||||
pending_events: VecDeque<(Position, CaptureEvent)>,
|
pending_events: VecDeque<(Position, CaptureEvent)>,
|
||||||
@@ -138,7 +137,7 @@ struct Inner {
|
|||||||
|
|
||||||
impl AsRawFd for Inner {
|
impl AsRawFd for Inner {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.state.wayland_fd
|
self.queue.as_fd().as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +331,6 @@ impl LayerShellInputCapture {
|
|||||||
active_windows: Vec::new(),
|
active_windows: Vec::new(),
|
||||||
focused: None,
|
focused: None,
|
||||||
qh,
|
qh,
|
||||||
wayland_fd: queue.as_fd().as_raw_fd(),
|
|
||||||
read_guard: None,
|
read_guard: None,
|
||||||
pending_events: VecDeque::new(),
|
pending_events: VecDeque::new(),
|
||||||
outputs: vec![],
|
outputs: vec![],
|
||||||
@@ -548,13 +546,12 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
fn read(&mut self) -> bool {
|
fn read(&mut self) {
|
||||||
match self.state.read_guard.take().unwrap().read() {
|
match self.state.read_guard.take().unwrap().read() {
|
||||||
Ok(_) => true,
|
Ok(_) => {}
|
||||||
Err(WaylandError::Io(e)) if e.kind() == ErrorKind::WouldBlock => false,
|
Err(WaylandError::Io(e)) if e.kind() == ErrorKind::WouldBlock => {}
|
||||||
Err(WaylandError::Io(e)) => {
|
Err(WaylandError::Io(e)) => {
|
||||||
log::error!("error reading from wayland socket: {e}");
|
log::error!("error reading from wayland socket: {e}");
|
||||||
false
|
|
||||||
}
|
}
|
||||||
Err(WaylandError::Protocol(e)) => {
|
Err(WaylandError::Protocol(e)) => {
|
||||||
panic!("wayland protocol violation: {e}")
|
panic!("wayland protocol violation: {e}")
|
||||||
@@ -564,16 +561,11 @@ impl Inner {
|
|||||||
|
|
||||||
fn prepare_read(&mut self) -> io::Result<()> {
|
fn prepare_read(&mut self) -> io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
match self.queue.prepare_read() {
|
if let Some(guard) = self.queue.prepare_read() {
|
||||||
None => match self.queue.dispatch_pending(&mut self.state) {
|
self.state.read_guard = Some(guard);
|
||||||
Ok(_) => continue,
|
break Ok(());
|
||||||
Err(DispatchError::Backend(WaylandError::Io(e))) => return Err(e),
|
} else {
|
||||||
Err(e) => panic!("failed to dispatch wayland events: {e}"),
|
self.dispatch_events();
|
||||||
},
|
|
||||||
Some(r) => {
|
|
||||||
self.state.read_guard = Some(r);
|
|
||||||
break Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,13 +647,7 @@ impl Stream for LayerShellInputCapture {
|
|||||||
let inner = guard.get_inner_mut();
|
let inner = guard.get_inner_mut();
|
||||||
|
|
||||||
// read events
|
// read events
|
||||||
while inner.read() {
|
inner.read();
|
||||||
// prepare next read
|
|
||||||
match inner.prepare_read() {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => return Poll::Ready(Some(Err(e.into()))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispatch the events
|
// dispatch the events
|
||||||
inner.dispatch_events();
|
inner.dispatch_events();
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ use reis::{
|
|||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io,
|
env, io,
|
||||||
num::NonZeroU32,
|
num::NonZeroU32,
|
||||||
os::unix::net::UnixStream,
|
os::unix::net::UnixStream,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::{Arc, LazyLock},
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
@@ -50,6 +50,25 @@ use super::{
|
|||||||
* prevents receiving further events after a session has been disabled once.
|
* prevents receiving further events after a session has been disabled once.
|
||||||
* Therefore the session needs to be recreated when the barriers are updated */
|
* Therefore the session needs to be recreated when the barriers are updated */
|
||||||
|
|
||||||
|
/* mutter also kills the session whenever ei devices come and go, so there the
|
||||||
|
* whole session has to be torn down and recreated on every device change.
|
||||||
|
* Elsewhere that is pure overhead: each restart costs a CreateSession +
|
||||||
|
* ConnectToEIS round trip, and compositors that keep per-session state around
|
||||||
|
* (hyprland leaks a keymap fd per eis session, see hyprwm/Hyprland) can be
|
||||||
|
* driven out of file descriptors by the churn.
|
||||||
|
* Set LM_RESTART_SESSION_ON_DEVICE_CHANGE=1/0 to override the default. */
|
||||||
|
static RESTART_SESSION_ON_DEVICE_CHANGE: LazyLock<bool> =
|
||||||
|
LazyLock::new(restart_session_on_device_change);
|
||||||
|
|
||||||
|
fn restart_session_on_device_change() -> bool {
|
||||||
|
match env::var("LM_RESTART_SESSION_ON_DEVICE_CHANGE").as_deref() {
|
||||||
|
Ok("1") => true,
|
||||||
|
Ok("0") => false,
|
||||||
|
_ => env::var("XDG_CURRENT_DESKTOP")
|
||||||
|
.is_ok_and(|desktops| desktops.to_uppercase().split(':').any(|d| d == "GNOME")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// events that necessitate restarting the capture session
|
/// events that necessitate restarting the capture session
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum LibeiNotifyEvent {
|
enum LibeiNotifyEvent {
|
||||||
@@ -555,20 +574,32 @@ async fn handle_ei_event(
|
|||||||
s.seat.bind_capabilities(all_capabilities);
|
s.seat.bind_capabilities(all_capabilities);
|
||||||
context.flush().map_err(|e| io::Error::new(e.kind(), e))?;
|
context.flush().map_err(|e| io::Error::new(e.kind(), e))?;
|
||||||
}
|
}
|
||||||
EiEvent::SeatRemoved(_) | /* EiEvent::DeviceAdded(_) | */ EiEvent::DeviceRemoved(_) => {
|
EiEvent::SeatRemoved(_) => {
|
||||||
log::debug!("releasing session: {ei_event:?}");
|
log::debug!("releasing session: {ei_event:?}");
|
||||||
release_session.notify_waiters();
|
release_session.notify_waiters();
|
||||||
}
|
}
|
||||||
|
/* EiEvent::DeviceAdded(_) | */
|
||||||
|
EiEvent::DeviceRemoved(_) => {
|
||||||
|
if *RESTART_SESSION_ON_DEVICE_CHANGE {
|
||||||
|
log::debug!("releasing session: {ei_event:?}");
|
||||||
|
release_session.notify_waiters();
|
||||||
|
} else {
|
||||||
|
log::debug!("ignoring device change: {ei_event:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
EiEvent::DevicePaused(_) | EiEvent::DeviceResumed(_) => {}
|
EiEvent::DevicePaused(_) | EiEvent::DeviceResumed(_) => {}
|
||||||
EiEvent::DeviceStartEmulating(_) => log::debug!("START EMULATING"),
|
EiEvent::DeviceStartEmulating(_) => log::debug!("START EMULATING"),
|
||||||
EiEvent::DeviceStopEmulating(_) => log::debug!("STOP EMULATING"),
|
EiEvent::DeviceStopEmulating(_) => log::debug!("STOP EMULATING"),
|
||||||
EiEvent::Disconnected(d) => {
|
EiEvent::Disconnected(d) => {
|
||||||
return Err(CaptureError::Disconnected(format!("{:?}", d.reason)))
|
return Err(CaptureError::Disconnected(format!("{:?}", d.reason)));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(pos) = current_client {
|
if let Some(pos) = current_client {
|
||||||
for event in Event::from_ei_event(ei_event) {
|
for event in Event::from_ei_event(ei_event) {
|
||||||
event_tx.send((pos, CaptureEvent::Input(event))).await.expect("no channel");
|
event_tx
|
||||||
|
.send((pos, CaptureEvent::Input(event)))
|
||||||
|
.await
|
||||||
|
.expect("no channel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user