diff --git a/Cargo.lock b/Cargo.lock index 3e22a9413..ca3c29392 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,21 +638,6 @@ dependencies = [ "cc", ] -[[package]] -name = "cocoa" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667fdc068627a2816b9ff831201dd9864249d6ee8d190b9532357f1fc0f61ea7" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.3", - "core-graphics 0.21.0", - "foreign-types", - "libc", - "objc", -] - [[package]] name = "cocoa" version = "0.24.0" @@ -770,18 +755,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-graphics" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a67c4378cf203eace8fb6567847eb641fd6ff933c1145a115c6ee820ebb978" -dependencies = [ - "bitflags", - "core-foundation 0.9.3", - "foreign-types", - "libc", -] - [[package]] name = "core-graphics" version = "0.22.3" @@ -1336,6 +1309,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "epoll" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "err-derive" version = "0.3.1" @@ -1370,6 +1353,29 @@ dependencies = [ "nix 0.23.1", ] +[[package]] +name = "evdev-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db51abf6b3205a6e6e8dd68d7a5414d7c50d61736a6f4c9b97df86ef5567cf" +dependencies = [ + "bitflags", + "evdev-sys", + "libc", + "log", +] + +[[package]] +name = "evdev-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "event-listener" version = "2.5.2" @@ -2342,6 +2348,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inotify" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9" +dependencies = [ + "bitflags", + "futures-core", + "inotify-sys", + "libc", + "tokio", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -3767,15 +3795,19 @@ dependencies = [ [[package]] name = "rdev" version = "0.5.0-2" -source = "git+https://github.com/asur4s/rdev#548d1194dd6863ab004d59299b995eb64cf21c3d" +source = "git+https://github.com/asur4s/rdev#d6499d2e582bf3549aa4ba33cfd3fbbdfce10947" dependencies = [ - "cocoa 0.22.0", - "core-foundation 0.7.0", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", + "cocoa", + "core-foundation 0.9.3", + "core-foundation-sys 0.8.3", + "core-graphics 0.22.3", "enum-map", + "epoll", + "evdev-rs", + "inotify", "lazy_static", "libc", + "widestring 1.0.2", "winapi 0.3.9", "x11", ] @@ -3994,7 +4026,7 @@ dependencies = [ "cfg-if 1.0.0", "clap 3.2.12", "clipboard", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "cpal", @@ -4021,6 +4053,7 @@ dependencies = [ "mouce", "num_cpus", "objc", + "once_cell", "parity-tokio-ipc", "rdev", "repng", @@ -4040,6 +4073,7 @@ dependencies = [ "sys-locale", "sysinfo", "system_shutdown", + "tfc", "tray-item", "trayicon", "uuid", @@ -4733,6 +4767,16 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +[[package]] +name = "tfc" +version = "0.6.1" +source = "git+https://github.com/asur4s/The-Fat-Controller#14d49063c8fc9a02c68c0dc842e8d6bb6c5e7713" +dependencies = [ + "core-graphics 0.22.3", + "unicode-segmentation", + "winapi 0.3.9", +] + [[package]] name = "thiserror" version = "1.0.31" @@ -4946,7 +4990,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76863575f7842ed64fda361f417a787efa82811b4617267709066969cd4ccf3b" dependencies = [ - "cocoa 0.24.0", + "cocoa", "core-graphics 0.22.3", "gtk", "libappindicator", @@ -5358,6 +5402,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.2.8" @@ -5431,7 +5481,7 @@ checksum = "0c643e10139d127d30d6d753398c8a6f0a43532e8370f6c9d29ebbff29b984ab" dependencies = [ "bitflags", "err-derive", - "widestring", + "widestring 0.4.3", "winapi 0.3.9", ] @@ -5558,7 +5608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" dependencies = [ "bitflags", - "cocoa 0.24.0", + "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", "core-video-sys", diff --git a/Cargo.toml b/Cargo.toml index 0efa224b7..4194bd51f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,8 @@ sys-locale = "0.2" enigo = { path = "libs/enigo", features = [ "with_serde" ] } clipboard = { path = "libs/clipboard" } rdev = { git = "https://github.com/asur4s/rdev" } +tfc = { git = "https://github.com/asur4s/The-Fat-Controller" } +once_cell = "1.13.0" ctrlc = "3.2" arboard = "2.0" #minreq = { version = "2.4", features = ["punycode", "https-native"] } @@ -104,6 +106,7 @@ async-process = "1.3" mouce = { git="https://github.com/fufesou/mouce.git" } evdev = { git="https://github.com/fufesou/evdev" } + [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.11" jni = "0.19" diff --git a/libs/enigo/src/linux/nix_impl.rs b/libs/enigo/src/linux/nix_impl.rs index c660bd08c..7a8f6668e 100644 --- a/libs/enigo/src/linux/nix_impl.rs +++ b/libs/enigo/src/linux/nix_impl.rs @@ -156,7 +156,6 @@ impl KeyboardControllable for Enigo { } fn key_up(&mut self, key: Key) { if self.is_x11 { - dbg!(key); if self.pynput.send_pynput(&key, false) { return; } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index c350e8d04..0154da085 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -9,6 +9,7 @@ use std::{ sync::atomic::{AtomicBool, Ordering}, time::Instant, }; +use tfc::{traits::*, Context}; #[derive(Default)] struct StateCursor { @@ -179,6 +180,7 @@ lazy_static::lazy_static! { }; static ref KEYS_DOWN: Arc>> = Default::default(); static ref LATEST_INPUT: Arc> = Default::default(); + static ref KBD_CONTEXT: Mutex = Mutex::new(Context::new().expect("kbd context error")); } static EXITING: AtomicBool = AtomicBool::new(false); @@ -819,6 +821,19 @@ fn legacy_keyboard_mode(evt: &KeyEvent) { } } +fn translate_keyboard_mode(evt: &KeyEvent) { + // Caps affects the keycode map of the peer system(Linux). + let mut en = ENIGO.lock().unwrap(); + if en.get_key_state(Key::CapsLock){ + rdev_key_click(RdevKey::CapsLock); + } + let chr = char::from_u32(evt.chr()).unwrap_or_default(); + if evt.down { + KBD_CONTEXT.lock().unwrap().unicode_char_down(chr).expect("unicode_char_down error"); + } else { + KBD_CONTEXT.lock().unwrap().unicode_char_up(chr).expect("unicode_char_up error"); + } +} fn handle_key_(evt: &KeyEvent) { if EXITING.load(Ordering::SeqCst) { @@ -832,6 +847,9 @@ fn handle_key_(evt: &KeyEvent) { KeyboardMode::Map => { map_keyboard_mode(evt); } + KeyboardMode::Translate => { + translate_keyboard_mode(evt); + } _ => { legacy_keyboard_mode(evt); } diff --git a/src/ui/header.tis b/src/ui/header.tis index 88762eec8..870167eae 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -151,6 +151,7 @@ class Header: Reactor.Component {
  • {svg_checkmark}{translate('Legacy mode')}
  • {svg_checkmark}{translate('Map mode')}
  • +
  • {svg_checkmark}{translate('Translate mode')}
  • ; } @@ -374,6 +375,8 @@ class Header: Reactor.Component { handler.save_keyboard_mode("legacy"); } else if (me.id == "map") { handler.save_keyboard_mode("map"); + } else if (me.id == "translate") { + handler.save_keyboard_mode("translate"); } toggleMenuState() } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 6f0197c87..bccd6ad79 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -39,7 +39,6 @@ use hbb_common::{ Stream, }; use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; -use rdev::{Event, EventType::*, Key as RdevKey}; use hbb_common::{ fs::{ can_enable_overwrite_detection, get_job, get_string, new_send_confirm, DigestCheckResult, @@ -47,6 +46,7 @@ use hbb_common::{ }, get_version_number, }; +use rdev::{Event, EventType::*, Key as RdevKey, Keyboard as RdevKeyboard, KeyboardState}; #[cfg(windows)] use crate::clipboard_file::*; @@ -61,6 +61,7 @@ lazy_static::lazy_static! { static ref ENIGO: Arc> = Arc::new(Mutex::new(Enigo::new())); static ref VIDEO: Arc>> = Default::default(); static ref TO_RELEASE: Arc>> = Arc::new(Mutex::new(HashSet::::new())); + static ref KEYBOARD: Arc> = Arc::new(Mutex::new(RdevKeyboard::new().unwrap())); } fn get_key_state(key: enigo::Key) -> bool { @@ -330,9 +331,6 @@ impl Handler { _ => return, }; - #[cfg(target_os = "windows")] - let _key = rdev::get_win_key(evt.code.into(), evt.scan_code); - me.key_down_or_up(down, _key, evt); }; if let Err(error) = rdev::listen(func) { @@ -793,7 +791,7 @@ impl Handler { fn leave(&mut self) { for key in TO_RELEASE.lock().unwrap().iter() { - self.map_keyboard_mode(false, *key) + self.map_keyboard_mode(false, *key, None) } #[cfg(windows)] crate::platform::windows::stop_system_key_propagate(false); @@ -1044,8 +1042,15 @@ impl Handler { } } - fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { + fn map_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, _evt: Option) { // map mode(1): Send keycode according to the peer platform. + #[cfg(target_os = "windows")] + let key = if let Some(e) = _evt { + rdev::get_win_key(e.code.into(), e.scan_code) + } else { + key + }; + let peer = self.peer_platform(); let mut key_event = KeyEvent::new(); @@ -1073,9 +1078,66 @@ impl Handler { self.send_key_event(key_event, KeyboardMode::Map); } - // fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey) { - // // translate mode(2): locally generated characters are send to the peer. - // } + fn translate_keyboard_mode(&mut self, down_or_up: bool, key: RdevKey, evt: Event) { + // translate mode(2): locally generated characters are send to the peer. + + // get char + let string = match KEYBOARD.lock() { + Ok(mut keyboard) => { + let string = keyboard.add(&evt.event_type).unwrap_or_default(); + #[cfg(target_os = "windows")] + let is_dead = keyboard.last_is_dead; + #[cfg(target_os = "linux")] + let is_dead = keyboard.is_dead(); + if is_dead && string == "" && down_or_up == true { + return; + } + string + } + Err(_) => "".to_owned(), + }; + + // maybe two string + let chars = if string == "" { + None + } else { + let chars: Vec = string.chars().collect(); + Some(chars) + }; + + if let Some(chars) = chars { + for chr in chars { + dbg!(chr); + + let mut key_event = KeyEvent::new(); + key_event.set_chr(chr as _); + key_event.down = true; + self.send_key_event(key_event, KeyboardMode::Translate); + + let mut key_event = KeyEvent::new(); + key_event.set_chr(chr as _); + key_event.down = false; + self.send_key_event(key_event, KeyboardMode::Translate); + } + } else { + if down_or_up == true { + TO_RELEASE.lock().unwrap().insert(key); + } else { + TO_RELEASE.lock().unwrap().remove(&key); + } + // algr without action + // Control left + if key == RdevKey::AltGr || evt.scan_code == 541 { + return; + } + // Caps affects the keycode map of the peer system(Linux). + if key == RdevKey::CapsLock { + return; + } + dbg!(key); + self.map_keyboard_mode(down_or_up, key, None); + } + } fn legacy_modifiers( &self, @@ -1335,6 +1397,7 @@ impl Handler { let mode = match self.get_keyboard_mode().as_str() { "map" => KeyboardMode::Map, "legacy" => KeyboardMode::Legacy, + "translate" => KeyboardMode::Translate, _ => KeyboardMode::Legacy, }; @@ -1345,9 +1408,12 @@ impl Handler { } else { TO_RELEASE.lock().unwrap().remove(&key); } - self.map_keyboard_mode(down_or_up, key); + self.map_keyboard_mode(down_or_up, key, Some(evt)); } KeyboardMode::Legacy => self.legacy_keyboard_mode(down_or_up, key, evt), + KeyboardMode::Translate => { + self.translate_keyboard_mode(down_or_up, key, evt); + } _ => self.legacy_keyboard_mode(down_or_up, key, evt), } }