diff --git a/client/src/input/inputs.rs b/client/src/input/inputs.rs index 7f75226..6c27110 100644 --- a/client/src/input/inputs.rs +++ b/client/src/input/inputs.rs @@ -4,7 +4,9 @@ use anyhow::bail; use anyhow::{Context, Result}; 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))] use std::path::{Path, PathBuf}; use std::sync::{ @@ -43,7 +45,7 @@ pub struct InputAggregator { selected_keyboard_path: Option, selected_mouse_path: Option, #[cfg(not(coverage))] - known_input_paths: HashSet, + known_input_paths: HashMap, capture_remote_boot: bool, quick_toggle_key: Option, quick_toggle_down: bool, @@ -116,7 +118,7 @@ impl InputAggregator { selected_keyboard_path: input_device_override_from_env("LESAVKA_KEYBOARD_DEVICE"), selected_mouse_path: input_device_override_from_env("LESAVKA_MOUSE_DEVICE"), #[cfg(not(coverage))] - known_input_paths: HashSet::new(), + known_input_paths: HashMap::new(), capture_remote_boot, quick_toggle_key, quick_toggle_down: false, @@ -238,7 +240,12 @@ impl InputAggregator { { 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; } @@ -257,7 +264,7 @@ impl InputAggregator { DeviceKind::Keyboard => { 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; } if remote_active { @@ -290,13 +297,13 @@ impl InputAggregator { if !remote_active { kbd_agg.set_grab(false); } - self.known_input_paths.insert(path); + self.known_input_paths.insert(path, identity); self.keyboards.push(kbd_agg); found_any = true; } DeviceKind::Mouse => { 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; } if remote_active { @@ -322,7 +329,7 @@ impl InputAggregator { if !remote_active { mouse_agg.set_grab(false); } - self.known_input_paths.insert(path); + self.known_input_paths.insert(path, identity); self.mice.push(mouse_agg); found_any = true; } @@ -331,7 +338,7 @@ impl InputAggregator { "Skipping non-kbd/mouse device: {:?}", 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 { + std::fs::metadata(path) + .ok() + .map(|metadata| metadata.ino() ^ metadata.rdev()) +} + #[cfg(not(coverage))] fn focus_launcher_on_local_if_enabled() { if std::env::var("LESAVKA_FOCUS_LAUNCHER_ON_LOCAL")