diff --git a/libs/enigo/src/linux/nix_impl.rs b/libs/enigo/src/linux/nix_impl.rs index f6e172677..f0e6a2166 100644 --- a/libs/enigo/src/linux/nix_impl.rs +++ b/libs/enigo/src/linux/nix_impl.rs @@ -1,5 +1,5 @@ use super::xdo::EnigoXdo; -use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; +use crate::{Key, KeyboardControllable, MouseButton, MouseControllable, ResultType}; use std::io::Read; use tfc::{traits::*, Context as TFC_Context, Key as TFC_Key}; @@ -42,6 +42,37 @@ impl Enigo { &mut self.custom_mouse } + /// Clear remapped keycodes + pub fn tfc_clear_remapped(&mut self) { + if let Some(tfc) = &mut self.tfc { + tfc.recover_remapped_keycodes(); + } + } + + fn tfc_key_click(&mut self, key: Key) -> ResultType { + if let Some(tfc) = &mut self.tfc { + let res = match key { + Key::Layout(chr) => tfc.unicode_char(chr), + key => { + let tfc_key: TFC_Key = match convert_to_tfc_key(key) { + Some(key) => key, + None => { + return Err("Failed to convert key to TFC_Key".into()); + } + }; + tfc.key_click(tfc_key) + } + }; + if res.is_err() { + Err("Failed to click char by tfc".to_string().into()) + } else { + Ok(()) + } + } else { + Err("Not Found TFC".into()) + } + } + fn tfc_key_down_or_up(&mut self, key: Key, down: bool, up: bool) -> bool { match &mut self.tfc { None => false, @@ -223,6 +254,7 @@ impl KeyboardControllable for Enigo { } } + /// Warning: Get 6^ in French. fn key_sequence(&mut self, sequence: &str) { if self.is_x11 { self.xdo.key_sequence(sequence) @@ -262,8 +294,10 @@ impl KeyboardControllable for Enigo { } } fn key_click(&mut self, key: Key) { - self.key_down(key).ok(); - self.key_up(key); + if self.tfc_key_click(key).is_err() { + self.key_down(key).ok(); + self.key_up(key); + } } } @@ -335,3 +369,10 @@ fn convert_to_tfc_key(key: Key) -> Option { }; Some(key) } + +#[test] +fn test_key_seq() { + // Get 6^ in French. + let mut en = Enigo::new(); + en.key_sequence("^^"); +} diff --git a/src/server/connection.rs b/src/server/connection.rs index b531a2add..5e6fbe50e 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -612,6 +612,8 @@ impl Connection { } } } + #[cfg(target_os = "linux")] + clear_remapped_keycode(); log::info!("Input thread exited"); } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index f205e3f02..bb9ba167c 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -413,6 +413,11 @@ pub fn fix_key_down_timeout_at_exit() { log::info!("fix_key_down_timeout_at_exit"); } +#[cfg(target_os = "linux")] +pub fn clear_remapped_keycode() { + ENIGO.lock().unwrap().tfc_clear_remapped(); +} + #[inline] fn record_key_is_control_key(record_key: u64) -> bool { record_key < KEY_CHAR_START @@ -1130,7 +1135,24 @@ fn translate_process_code(code: u32, down: bool) { fn translate_keyboard_mode(evt: &KeyEvent) { match &evt.union { Some(key_event::Union::Seq(seq)) => { - ENIGO.lock().unwrap().key_sequence(seq); + // Fr -> US + // client: Shift + & => 1(send to remote) + // remote: Shift + 1 => ! + // + // Try to release shift first. + // remote: Shift + 1 => 1 + let mut en = ENIGO.lock().unwrap(); + + #[cfg(target_os = "linux")] + { + simulate_(&EventType::KeyRelease(RdevKey::ShiftLeft)); + simulate_(&EventType::KeyRelease(RdevKey::ShiftRight)); + for chr in seq.chars() { + en.key_click(Key::Layout(chr)); + } + } + #[cfg(not(target_os = "linux"))] + en.key_sequence(seq); } Some(key_event::Union::Chr(..)) => { #[cfg(target_os = "windows")]