From 732b2508159d66c21aa1250ef92aef4095f170e6 Mon Sep 17 00:00:00 2001 From: fufesou <13586388+fufesou@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:07:09 +0800 Subject: [PATCH] fix(keyboard): legacy mode (#14435) * fix(keyboard): legacy mode Signed-off-by: fufesou * Simple refactor Signed-off-by: fufesou * fix(keyboard): legacy mode, chr to seq Signed-off-by: fufesou * fix(keyboard): legacy mode, early return if (!hotkey)&down Signed-off-by: fufesou * fix(keyboard): legacy mode, pair down/up Signed-off-by: fufesou --------- Signed-off-by: fufesou --- libs/enigo/src/win/win_impl.rs | 15 ++++++++++++-- src/server/input_service.rs | 37 +++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index 882dba126..a6b465ea1 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -269,7 +269,7 @@ impl KeyboardControllable for Enigo { for pos in 0..mod_len { let rpos = mod_len - 1 - pos; if flag & (0x0001 << rpos) != 0 { - self.key_up(modifiers[pos]); + self.key_up(modifiers[rpos]); } } @@ -298,7 +298,18 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { - keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0); + match key { + Key::Layout(c) => { + let code = self.get_layoutdependent_keycode(c); + if code as u16 != 0xFFFF { + let vk = code & 0x00FF; + keybd_event(KEYEVENTF_KEYUP, vk, 0); + } + } + _ => { + keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0); + } + } } fn get_key_state(&mut self, key: Key) -> bool { diff --git a/src/server/input_service.rs b/src/server/input_service.rs index fb8441dde..97dc78755 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -809,7 +809,7 @@ fn record_key_is_control_key(record_key: u64) -> bool { #[inline] fn record_key_is_chr(record_key: u64) -> bool { - record_key < KEY_CHAR_START + record_key >= KEY_CHAR_START } #[inline] @@ -1513,6 +1513,27 @@ fn get_control_key_value(key_event: &KeyEvent) -> i32 { } } +#[inline] +fn has_hotkey_modifiers(key_event: &KeyEvent) -> bool { + key_event.modifiers.iter().any(|ck| { + let v = ck.value(); + v == ControlKey::Control.value() + || v == ControlKey::RControl.value() + || v == ControlKey::Meta.value() + || v == ControlKey::RWin.value() + || { + #[cfg(any(target_os = "windows", target_os = "linux"))] + { + v == ControlKey::Alt.value() || v == ControlKey::RAlt.value() + } + #[cfg(target_os = "macos")] + { + false + } + } + }) +} + fn release_unpressed_modifiers(en: &mut Enigo, key_event: &KeyEvent) { let ck_value = get_control_key_value(key_event); fix_modifiers(&key_event.modifiers[..], en, ck_value); @@ -1572,7 +1593,7 @@ fn need_to_uppercase(en: &mut Enigo) -> bool { get_modifier_state(Key::Shift, en) || get_modifier_state(Key::CapsLock, en) } -fn process_chr(en: &mut Enigo, chr: u32, down: bool) { +fn process_chr(en: &mut Enigo, chr: u32, down: bool, _hotkey: bool) { // On Wayland with uinput mode, use clipboard for character input #[cfg(target_os = "linux")] if !crate::platform::linux::is_x11() && wayland_use_uinput() { @@ -1587,6 +1608,16 @@ fn process_chr(en: &mut Enigo, chr: u32, down: bool) { } } + #[cfg(any(target_os = "macos", target_os = "windows"))] + if !_hotkey { + if down { + if let Ok(chr) = char::try_from(chr) { + en.key_sequence(&chr.to_string()); + } + } + return; + } + let key = char_value_to_key(chr); if down { @@ -1856,7 +1887,7 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { let record_key = chr as u64 + KEY_CHAR_START; record_pressed_key(KeysDown::EnigoKey(record_key), down); - process_chr(&mut en, chr, down) + process_chr(&mut en, chr, down, has_hotkey_modifiers(evt)) } Some(key_event::Union::Unicode(chr)) => { // Same as Chr: release Shift for Unicode input