fix(input): detect reattached devices during all capture

This commit is contained in:
Brad Stein 2026-04-21 12:48:57 -03:00
parent e3f9fd2610
commit b8e43cac6f

View File

@ -4,7 +4,9 @@
use anyhow::bail; use anyhow::bail;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use evdev::{AbsoluteAxisCode, Device, EventType, KeyCode, RelativeAxisCode}; use evdev::{AbsoluteAxisCode, Device, EventType, KeyCode, RelativeAxisCode};
use std::collections::HashSet; use std::collections::{HashMap, HashSet};
#[cfg(not(coverage))]
use std::os::unix::fs::MetadataExt;
#[cfg(not(coverage))] #[cfg(not(coverage))]
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{ use std::sync::{
@ -43,7 +45,7 @@ pub struct InputAggregator {
selected_keyboard_path: Option<String>, selected_keyboard_path: Option<String>,
selected_mouse_path: Option<String>, selected_mouse_path: Option<String>,
#[cfg(not(coverage))] #[cfg(not(coverage))]
known_input_paths: HashSet<PathBuf>, known_input_paths: HashMap<PathBuf, u64>,
capture_remote_boot: bool, capture_remote_boot: bool,
quick_toggle_key: Option<KeyCode>, quick_toggle_key: Option<KeyCode>,
quick_toggle_down: bool, quick_toggle_down: bool,
@ -116,7 +118,7 @@ impl InputAggregator {
selected_keyboard_path: input_device_override_from_env("LESAVKA_KEYBOARD_DEVICE"), selected_keyboard_path: input_device_override_from_env("LESAVKA_KEYBOARD_DEVICE"),
selected_mouse_path: input_device_override_from_env("LESAVKA_MOUSE_DEVICE"), selected_mouse_path: input_device_override_from_env("LESAVKA_MOUSE_DEVICE"),
#[cfg(not(coverage))] #[cfg(not(coverage))]
known_input_paths: HashSet::new(), known_input_paths: HashMap::new(),
capture_remote_boot, capture_remote_boot,
quick_toggle_key, quick_toggle_key,
quick_toggle_down: false, quick_toggle_down: false,
@ -238,7 +240,12 @@ impl InputAggregator {
{ {
continue; continue;
} }
if self.known_input_paths.contains(&path) { let identity = input_device_identity(&path).unwrap_or_default();
if self
.known_input_paths
.get(&path)
.is_some_and(|known| *known == identity)
{
continue; continue;
} }
@ -257,7 +264,7 @@ impl InputAggregator {
DeviceKind::Keyboard => { DeviceKind::Keyboard => {
if !matches_selected_input_device(&path, self.selected_keyboard_path.as_deref()) if !matches_selected_input_device(&path, self.selected_keyboard_path.as_deref())
{ {
self.known_input_paths.insert(path); self.known_input_paths.insert(path, identity);
continue; continue;
} }
if remote_active { if remote_active {
@ -290,13 +297,13 @@ impl InputAggregator {
if !remote_active { if !remote_active {
kbd_agg.set_grab(false); kbd_agg.set_grab(false);
} }
self.known_input_paths.insert(path); self.known_input_paths.insert(path, identity);
self.keyboards.push(kbd_agg); self.keyboards.push(kbd_agg);
found_any = true; found_any = true;
} }
DeviceKind::Mouse => { DeviceKind::Mouse => {
if !matches_selected_input_device(&path, self.selected_mouse_path.as_deref()) { if !matches_selected_input_device(&path, self.selected_mouse_path.as_deref()) {
self.known_input_paths.insert(path); self.known_input_paths.insert(path, identity);
continue; continue;
} }
if remote_active { if remote_active {
@ -322,7 +329,7 @@ impl InputAggregator {
if !remote_active { if !remote_active {
mouse_agg.set_grab(false); mouse_agg.set_grab(false);
} }
self.known_input_paths.insert(path); self.known_input_paths.insert(path, identity);
self.mice.push(mouse_agg); self.mice.push(mouse_agg);
found_any = true; found_any = true;
} }
@ -331,7 +338,7 @@ impl InputAggregator {
"Skipping non-kbd/mouse device: {:?}", "Skipping non-kbd/mouse device: {:?}",
dev.name().unwrap_or("UNKNOWN") dev.name().unwrap_or("UNKNOWN")
); );
self.known_input_paths.insert(path); self.known_input_paths.insert(path, identity);
} }
} }
} }
@ -1037,6 +1044,13 @@ fn input_rescan_interval_from_env() -> Duration {
} }
} }
#[cfg(not(coverage))]
fn input_device_identity(path: &Path) -> Option<u64> {
std::fs::metadata(path)
.ok()
.map(|metadata| metadata.ino() ^ metadata.rdev())
}
#[cfg(not(coverage))] #[cfg(not(coverage))]
fn focus_launcher_on_local_if_enabled() { fn focus_launcher_on_local_if_enabled() {
if std::env::var("LESAVKA_FOCUS_LAUNCHER_ON_LOCAL") if std::env::var("LESAVKA_FOCUS_LAUNCHER_ON_LOCAL")