From 2b87aca11907c76ac51f24eb7ab0f8ee1f5495c7 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sat, 14 Sep 2024 11:57:55 +0530 Subject: [PATCH] feat: better heuristic for detecting keyboard ### Changes - Heuristic value decreases when features match that of a real keyboard - A threshold, carefully chosen after some trial and error, is used to predict if a device is a keyboard --- swhkd/src/daemon.rs | 47 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/swhkd/src/daemon.rs b/swhkd/src/daemon.rs index d155b3c..e7d3280 100644 --- a/swhkd/src/daemon.rs +++ b/swhkd/src/daemon.rs @@ -418,17 +418,44 @@ pub fn check_input_group() -> Result<(), Box> { } } -pub fn check_device_is_keyboard(device: &Device) -> bool { - if device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER)) { - if device.name() == Some("swhkd virtual output") { - return false; - } - log::debug!("Keyboard: {}", device.name().unwrap(),); - true - } else { - log::trace!("Other: {}", device.name().unwrap(),); - false +fn check_device_is_keyboard(device: &Device) -> bool { + let name = device.name(); + if name == Some("swhkd virtual output") { + return false; + } + + let unique_name = device.unique_name(); + let properties = device.properties(); + let events = device.supported_events(); + + let mut heuristic = 5; + + if let Some(name) = name { + heuristic -= name.to_lowercase().contains("keyboard") as i8; } + + if let Some(name) = unique_name { + heuristic -= name.to_lowercase().contains("keyboard") as i8; + } + + // properties a keyboard generally has: + // keys + heuristic -= events.contains(evdev::EventType::KEY) as i8; + // leds (capslocks, numpads) + heuristic -= events.contains(evdev::EventType::LED) as i8; + // repeat: hold a key to spam it + heuristic -= events.contains(evdev::EventType::REPEAT) as i8; + + heuristic += events.contains(evdev::EventType::ABSOLUTE) as i8; + heuristic += events.contains(evdev::EventType::RELATIVE) as i8; + heuristic += events.contains(evdev::EventType::SWITCH) as i8; + heuristic += properties.contains(evdev::PropType::POINTER) as i8; + heuristic += properties.contains(evdev::PropType::BUTTONPAD) as i8; + + log::debug!("name: {:?}, heuristic: {}", name, heuristic); + + // Increase this threshold to be more lenient + heuristic < 3 } pub fn setup_swhkd(invoking_uid: u32, runtime_path: String) {