fix: wayland CapsLock (#9641)

* fix: wayland CapsLock

Signed-off-by: fufesou <linlong1266@gmail.com>

* unformat for less changes

Signed-off-by: fufesou <linlong1266@gmail.com>

* refact: input, LockModes, do not check evt.down

Remove `evt.down`(revert the change) to avoid potential bugs.

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-10-14 11:46:28 +08:00 committed by GitHub
parent af610b2408
commit 498b8ba3d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 5 deletions

View File

@ -175,6 +175,22 @@ impl LockModesHandler {
}
}
#[cfg(target_os = "linux")]
fn sleep_to_ensure_locked(v: bool, k: enigo::Key, en: &mut Enigo) {
if wayland_use_uinput() {
// Sleep at most 500ms to ensure the lock state is applied.
for _ in 0..50 {
std::thread::sleep(std::time::Duration::from_millis(10));
if en.get_key_state(k) == v {
break;
}
}
} else if wayland_use_rdp_input() {
// We can't call `en.get_key_state(k)` because there's no api for this.
std::thread::sleep(std::time::Duration::from_millis(50));
}
}
#[cfg(any(target_os = "windows", target_os = "linux"))]
fn new(key_event: &KeyEvent, is_numpad_key: bool) -> Self {
let mut en = ENIGO.lock().unwrap();
@ -183,12 +199,15 @@ impl LockModesHandler {
let caps_lock_changed = event_caps_enabled != local_caps_enabled;
if caps_lock_changed {
en.key_click(enigo::Key::CapsLock);
#[cfg(target_os = "linux")]
Self::sleep_to_ensure_locked(event_caps_enabled, enigo::Key::CapsLock, &mut en);
}
let mut num_lock_changed = false;
let mut event_num_enabled = false;
if is_numpad_key {
let local_num_enabled = en.get_key_state(enigo::Key::NumLock);
let event_num_enabled = Self::is_modifier_enabled(key_event, ControlKey::NumLock);
event_num_enabled = Self::is_modifier_enabled(key_event, ControlKey::NumLock);
num_lock_changed = event_num_enabled != local_num_enabled;
} else if is_legacy_mode(key_event) {
#[cfg(target_os = "windows")]
@ -199,6 +218,8 @@ impl LockModesHandler {
}
if num_lock_changed {
en.key_click(enigo::Key::NumLock);
#[cfg(target_os = "linux")]
Self::sleep_to_ensure_locked(event_num_enabled, enigo::Key::NumLock, &mut en);
}
Self {
@ -236,6 +257,14 @@ impl LockModesHandler {
#[cfg(any(target_os = "windows", target_os = "linux"))]
impl Drop for LockModesHandler {
fn drop(&mut self) {
// Do not change led state if is Wayland uinput.
// Because there must be a delay to ensure the lock state is applied on Wayland uinput,
// which may affect the user experience.
#[cfg(target_os = "linux")]
if wayland_use_uinput() {
return;
}
let mut en = ENIGO.lock().unwrap();
if self.caps_lock_changed {
en.key_click(enigo::Key::CapsLock);
@ -1633,12 +1662,13 @@ pub fn handle_key_(evt: &KeyEvent) {
let is_numpad_key = false;
#[cfg(any(target_os = "windows", target_os = "linux"))]
let is_numpad_key = crate::keyboard::is_numpad_rdev_key(&key);
_lock_mode_handler = Some(LockModesHandler::new_handler(evt, is_numpad_key));
_lock_mode_handler =
Some(LockModesHandler::new_handler(evt, is_numpad_key));
}
}
}
_ => {}
};
}
match evt.mode.enum_value() {
Ok(KeyboardMode::Map) => {

View File

@ -431,8 +431,8 @@ pub mod service {
allow_err!(keyboard.emit(&[down_event]));
}
DataKeyboard::KeyUp(enigo::Key::Raw(code)) => {
let down_event = InputEvent::new(EventType::KEY, *code - 8, 0);
allow_err!(keyboard.emit(&[down_event]));
let up_event = InputEvent::new(EventType::KEY, *code - 8, 0);
allow_err!(keyboard.emit(&[up_event]));
}
DataKeyboard::KeyDown(key) => {
if let Ok((k, is_shift)) = map_key(key) {