fix: remove MSC_SCAN fallback, deduplicate multi-device events in non-grabbed mode

- Remove MSC_SCAN/MSC event processing that could cause double-processing
- In non-grabbed evdev mode, only process engine events from primary device
  to prevent doubled characters when multiple keyboard devices report same keys
- Add per-key diagnostic logging for non-grabbed path
This commit is contained in:
Khoa Vo 2026-07-04 17:18:29 +07:00
parent 48cd360e37
commit 63cae4765a

View file

@ -1468,50 +1468,12 @@ fn run_with_evdev(
}; };
last_event_time = std::time::Instant::now(); last_event_time = std::time::Instant::now();
// Collect all EV_KEY keycodes first so we can skip redundant MSC_SCAN events
let mut key_processed: HashSet<u16> = HashSet::new();
for event in &event_list {
if event.event_type() == evdev::EventType::KEY {
key_processed.insert(event.code());
}
}
// Cache last MSC_SCAN keycode (VM workaround: some VMs emit EV_MSC instead of EV_KEY)
let mut last_msc_code: Option<u16> = None;
for event in event_list { for event in event_list {
let ev_type = event.event_type(); if event.event_type() != evdev::EventType::KEY {
let ev_code = event.code();
let ev_value = event.value();
// Handle both EV_KEY (normal) and EV_MSC/MSC_SCAN (VM fallback)
let is_key = ev_type == evdev::EventType::KEY;
let is_msc_key = !is_key && ev_type == evdev::EventType::MISC && ev_code == 4;
if !is_key && !is_msc_key {
continue; continue;
} }
let keycode = event.code();
let (keycode_val, value) = if is_key { let value = event.value();
(ev_code, ev_value)
} else {
// MSC_SCAN contains Linux keycode in value.
// Skip if this keycode was already processed as EV_KEY.
let scan_code = ev_value as u16;
if key_processed.contains(&scan_code) {
continue;
}
let is_press = last_msc_code.map_or(true, |prev| prev != ev_code);
last_msc_code = Some(ev_code);
if !is_press {
continue;
}
let code = if ev_value >= 0 && ev_value <= KEY_MAX as i32 {
ev_value as u16
} else {
continue;
};
(code, 1i32)
};
let keycode = keycode_val;
let key = evdev::Key(keycode); let key = evdev::Key(keycode);
// Update key state dynamically // Update key state dynamically
@ -1565,6 +1527,12 @@ fn run_with_evdev(
} }
} }
// In non-grabbed mode, only process engine from primary device (i==0)
// to avoid double-processing when multiple keyboard devices report same keys
if !grabbed && i != 0 {
continue;
}
if !grabbed { if !grabbed {
if value != 1 { if value != 1 {
continue; continue;