diff --git a/Cargo.lock b/Cargo.lock index 7e679ef91..bdf981356 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,6 +1317,7 @@ dependencies = [ "log", "objc", "pkg-config", + "rdev 0.5.1", "serde 1.0.137", "serde_derive", "unicode-segmentation", @@ -3836,6 +3837,22 @@ dependencies = [ "x11", ] +[[package]] +name = "rdev" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7336f02e29f34e9a7186ccf87051f6a5697536195569012e076e18a4efddcede" +dependencies = [ + "cocoa 0.22.0", + "core-foundation 0.7.0", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "lazy_static", + "libc", + "winapi 0.3.9", + "x11", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -4076,7 +4093,7 @@ dependencies = [ "num_cpus", "objc", "parity-tokio-ipc", - "rdev", + "rdev 0.5.0", "repng", "reqwest", "rpassword 6.0.1", diff --git a/libs/enigo/Cargo.toml b/libs/enigo/Cargo.toml index 6842dab56..29d7ee87f 100644 --- a/libs/enigo/Cargo.toml +++ b/libs/enigo/Cargo.toml @@ -21,7 +21,8 @@ appveyor = { repository = "pythoneer/enigo-85xiy" } [dependencies] serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -log = "0.4" +log = "0.4.17" +rdev = "0.5.1" [features] with_serde = ["serde", "serde_derive"] diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index adfe9507c..ee27e06cf 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -3,8 +3,8 @@ use libc; use crate::{Key, KeyboardControllable, MouseButton, MouseControllable}; use self::libc::{c_char, c_int, c_void, useconds_t}; -use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc}; - +use rdev::{simulate, EventType, EventType::*, Key as RdevKey, SimulateError}; +use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc, thread, time}; const CURRENT_WINDOW: c_int = 0; const DEFAULT_DELAY: u64 = 12000; type Window = c_int; @@ -103,6 +103,30 @@ impl Enigo { pub fn reset(&mut self) { self.tx.send((PyMsg::Char('\0'), true)).ok(); } + + fn send_rdev(&mut self, key: &Key, is_press: bool) -> bool { + log::info!("{:?} {:?}", key, is_press); + + if let Key::Raw(keycode) = key { + let event_type = match is_press { + // todo: Acccodding to client type + true => Box::leak(Box::new(EventType::KeyPress(RdevKey::Unknown( + (*keycode).into(), + )))), + false => Box::leak(Box::new(EventType::KeyRelease(RdevKey::Unknown( + (*keycode).into(), + )))), + }; + + match simulate(event_type) { + Ok(()) => true, + Err(SimulateError) => false, + } + } else { + false + } + } + #[inline] fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool { if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } { @@ -111,8 +135,15 @@ impl Enigo { if let Key::Layout(c) = key { return self.tx.send((PyMsg::Char(*c), is_press)).is_ok(); } - if let Key::Raw(_) = key { - return false; + if let Key::Raw(chr) = key { + fn string_to_static_str(s: String) -> &'static str { + Box::leak(s.into_boxed_str()) + } + dbg!(chr.to_string()); + return self + .tx + .send((PyMsg::Str(string_to_static_str(chr.to_string())), is_press)) + .is_ok(); } #[allow(deprecated)] let s = match key { @@ -431,6 +462,9 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return Ok(()); } + if self.send_rdev(&key, true) { + return Ok(()); + } if self.send_pynput(&key, true) { return Ok(()); } @@ -449,6 +483,11 @@ impl KeyboardControllable for Enigo { if self.xdo.is_null() { return; } + // todo + let keyboard_mode = 1; + if keyboard_mode == 1 && self.send_rdev(&key, false) { + return; + } if self.send_pynput(&key, false) { return; } @@ -478,6 +517,21 @@ impl KeyboardControllable for Enigo { } } } + + fn key_sequence_parse(&mut self, sequence: &str) + where + Self: Sized, + { + self.key_sequence_parse_try(sequence) + .expect("Could not parse sequence"); + } + + fn key_sequence_parse_try(&mut self, sequence: &str) -> Result<(), crate::dsl::ParseError> + where + Self: Sized, + { + crate::dsl::eval(self, sequence) + } } static mut PYNPUT_EXIT: bool = false; @@ -492,7 +546,8 @@ fn start_pynput_service(rx: mpsc::Receiver<(PyMsg, bool)>) { py = "/usr/lib/rustdesk/pynput_service.py".to_owned(); if !std::path::Path::new(&py).exists() { // enigo libs, not rustdesk root project, so skip using appimage features - py = std::env::var("APPDIR").unwrap_or("".to_string()) + "/usr/lib/rustdesk/pynput_service.py"; + py = std::env::var("APPDIR").unwrap_or("".to_string()) + + "/usr/lib/rustdesk/pynput_service.py"; if !std::path::Path::new(&py).exists() { log::error!("{} not exists", py); }