Merge pull request #2595 from fufesou/keyboard3

keyboard map mode
This commit is contained in:
RustDesk 2022-12-18 16:21:26 +08:00 committed by GitHub
commit e1344f5306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 46 deletions

3
Cargo.lock generated
View File

@ -4305,7 +4305,7 @@ dependencies = [
[[package]] [[package]]
name = "rdev" name = "rdev"
version = "0.5.0-2" version = "0.5.0-2"
source = "git+https://github.com/asur4s/rdev#3d6d413a9b2ab703edc22071acea31826b0efce3" source = "git+https://github.com/asur4s/rdev#18bb9dd64563fc9761005bb39ff830e6402e326e"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"core-foundation 0.9.3", "core-foundation 0.9.3",
@ -4316,6 +4316,7 @@ dependencies = [
"inotify", "inotify",
"lazy_static", "lazy_static",
"libc", "libc",
"log",
"mio 0.8.5", "mio 0.8.5",
"strum 0.24.1", "strum 0.24.1",
"strum_macros 0.24.3", "strum_macros 0.24.3",

View File

@ -7,19 +7,19 @@ use crate::flutter::FlutterHandler;
use crate::ui::remote::SciterHandler; use crate::ui::remote::SciterHandler;
use crate::ui_session_interface::Session; use crate::ui_session_interface::Session;
use hbb_common::{log, message_proto::*}; use hbb_common::{log, message_proto::*};
#[cfg(target_os = "linux")]
use rdev::GrabError;
use rdev::{Event, EventType, Key}; use rdev::{Event, EventType, Key};
#[cfg(any(target_os = "windows", target_os = "macos"))]
use std::sync::atomic::{AtomicBool, Ordering};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
sync::{ sync::{Arc, Mutex},
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
time::SystemTime, time::SystemTime,
}; };
#[cfg(windows)]
static mut IS_ALT_GR: bool = false; static mut IS_ALT_GR: bool = false;
#[cfg(any(target_os = "windows", target_os = "macos"))]
static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false); static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false);
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]
@ -103,9 +103,10 @@ pub mod client {
if is_long_press(&event) { if is_long_press(&event) {
return; return;
} }
let key_event = event_to_key_event(&event); if let Some(key_event) = event_to_key_event(&event) {
send_key_event(&key_event); send_key_event(&key_event);
} }
}
pub fn get_modifiers_state( pub fn get_modifiers_state(
alt: bool, alt: bool,
@ -314,7 +315,7 @@ fn update_modifiers_state(event: &Event) {
}; };
} }
pub fn event_to_key_event(event: &Event) -> KeyEvent { pub fn event_to_key_event(event: &Event) -> Option<KeyEvent> {
let mut key_event = KeyEvent::new(); let mut key_event = KeyEvent::new();
update_modifiers_state(event); update_modifiers_state(event);
@ -330,22 +331,22 @@ pub fn event_to_key_event(event: &Event) -> KeyEvent {
let keyboard_mode = get_keyboard_mode_enum(); let keyboard_mode = get_keyboard_mode_enum();
key_event.mode = keyboard_mode.into(); key_event.mode = keyboard_mode.into();
match keyboard_mode { let mut key_event = match keyboard_mode {
KeyboardMode::Map => { KeyboardMode::Map => {
map_keyboard_mode(event, &mut key_event); map_keyboard_mode(event, key_event)?
} }
KeyboardMode::Translate => { KeyboardMode::Translate => {
translate_keyboard_mode(event, &mut key_event); translate_keyboard_mode(event, key_event)?
} }
_ => { _ => {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
legacy_keyboard_mode(event, &mut key_event); legacy_keyboard_mode(event, key_event)?
} }
}; };
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
add_numlock_capslock_status(&mut key_event); add_numlock_capslock_status(&mut key_event);
return key_event; return Some(key_event);
} }
pub fn event_type_to_event(event_type: EventType) -> Event { pub fn event_type_to_event(event_type: EventType) -> Event {
@ -374,13 +375,13 @@ pub fn get_peer_platform() -> String {
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn legacy_keyboard_mode(event: &Event, key_event: &mut KeyEvent) { pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
// legacy mode(0): Generate characters locally, look for keycode on other side. // legacy mode(0): Generate characters locally, look for keycode on other side.
let (mut key, down_or_up) = match event.event_type { let (mut key, down_or_up) = match event.event_type {
EventType::KeyPress(key) => (key, true), EventType::KeyPress(key) => (key, true),
EventType::KeyRelease(key) => (key, false), EventType::KeyRelease(key) => (key, false),
_ => { _ => {
return; return None;
} }
}; };
@ -422,11 +423,11 @@ pub fn legacy_keyboard_mode(event: &Event, key_event: &mut KeyEvent) {
// when pressing AltGr, an extra VK_LCONTROL with a special // when pressing AltGr, an extra VK_LCONTROL with a special
// scancode with bit 9 set is sent, let's ignore this. // scancode with bit 9 set is sent, let's ignore this.
#[cfg(windows)] #[cfg(windows)]
if event.scan_code & 0x200 != 0 { if (event.scan_code >> 8) == 0xE0 {
unsafe { unsafe {
IS_ALT_GR = true; IS_ALT_GR = true;
} }
return; return None;
} }
Some(ControlKey::Control) Some(ControlKey::Control)
} }
@ -458,7 +459,7 @@ pub fn legacy_keyboard_mode(event: &Event, key_event: &mut KeyEvent) {
Key::Delete => { Key::Delete => {
if is_win && ctrl && alt { if is_win && ctrl && alt {
client::ctrl_alt_del(); client::ctrl_alt_del();
return; return None;
} }
Some(ControlKey::Delete) Some(ControlKey::Delete)
} }
@ -496,7 +497,7 @@ pub fn legacy_keyboard_mode(event: &Event, key_event: &mut KeyEvent) {
Key::KpMinus => Some(ControlKey::Subtract), Key::KpMinus => Some(ControlKey::Subtract),
Key::KpPlus => Some(ControlKey::Add), Key::KpPlus => Some(ControlKey::Add),
Key::CapsLock | Key::NumLock | Key::ScrollLock => { Key::CapsLock | Key::NumLock | Key::ScrollLock => {
return; return None;
} }
Key::Home => Some(ControlKey::Home), Key::Home => Some(ControlKey::Home),
Key::End => Some(ControlKey::End), Key::End => Some(ControlKey::End),
@ -579,43 +580,60 @@ pub fn legacy_keyboard_mode(event: &Event, key_event: &mut KeyEvent) {
if chr != '\0' { if chr != '\0' {
if chr == 'l' && is_win && command { if chr == 'l' && is_win && command {
client::lock_screen(); client::lock_screen();
return; return None;
} }
key_event.set_chr(chr as _); key_event.set_chr(chr as _);
} else { } else {
log::error!("Unknown key {:?}", &event); log::error!("Unknown key {:?}", &event);
return; return None;
} }
} }
let (alt, ctrl, shift, command) = client::get_modifiers_state(alt, ctrl, shift, command); let (alt, ctrl, shift, command) = client::get_modifiers_state(alt, ctrl, shift, command);
client::legacy_modifiers(key_event, alt, ctrl, shift, command); client::legacy_modifiers(&mut key_event, alt, ctrl, shift, command);
if down_or_up == true { if down_or_up == true {
key_event.down = true; key_event.down = true;
} }
Some(key_event)
} }
pub fn map_keyboard_mode(event: &Event, key_event: &mut KeyEvent) { pub fn map_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
match event.event_type {
EventType::KeyPress(..) => {
key_event.down = true;
}
EventType::KeyRelease(..) => {
key_event.down = false;
}
_ => return None,
};
let mut peer = get_peer_platform().to_lowercase(); let mut peer = get_peer_platform().to_lowercase();
peer.retain(|c| !c.is_whitespace()); peer.retain(|c| !c.is_whitespace());
let key = match event.event_type { #[cfg(target_os = "windows")]
EventType::KeyPress(key) => { let keycode = match peer.as_str() {
key_event.down = true; "windows" => event.scan_code,
key "macos" => rdev::win_scancode_to_macos_code(event.scan_code)?,
} _ => rdev::win_scancode_to_linux_code(event.scan_code)?,
EventType::KeyRelease(key) => {
key_event.down = false;
key
}
_ => return,
}; };
let keycode: u32 = match peer.as_str() { #[cfg(target_os = "macos")]
"windows" => rdev::win_keycode_from_key(key).unwrap_or_default().into(), let keycode = match peer.as_str() {
"macos" => rdev::macos_keycode_from_key(key).unwrap_or_default().into(), "windows" => rdev::macos_code_to_win_scancode(event.code as _)?,
_ => rdev::linux_keycode_from_key(key).unwrap_or_default().into(), "macos" => event.code as _,
_ => rdev::macos_code_to_linux_code(event.code as _)?,
}; };
#[cfg(target_os = "linux")]
let keycode = match peer.as_str() {
"windows" => rdev::linux_code_to_win_scancode(event.code as _)?,
"macos" => rdev::linux_code_to_macos_code(event.code as _)?,
_ => event.code as _,
};
key_event.set_chr(keycode); key_event.set_chr(keycode);
Some(key_event)
} }
pub fn translate_keyboard_mode(_event: &Event, _key_event: &mut KeyEvent) {} pub fn translate_keyboard_mode(_event: &Event, mut _key_event: KeyEvent) -> Option<KeyEvent> {
None
}

View File

@ -5,7 +5,7 @@ use crate::common::IS_X11;
use dispatch::Queue; use dispatch::Queue;
use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable}; use enigo::{Enigo, Key, KeyboardControllable, MouseButton, MouseControllable};
use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown}; use hbb_common::{config::COMPRESS_LEVEL, get_time, protobuf::EnumOrUnknown};
use rdev::{simulate, EventType, Key as RdevKey}; use rdev::{self, simulate, EventType, Key as RdevKey, RawKey};
use std::time::Duration; use std::time::Duration;
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
@ -686,6 +686,20 @@ pub fn handle_key(evt: &KeyEvent) {
handle_key_(evt); handle_key_(evt);
} }
fn sim_rdev_rawkey(code: u32, down_or_up: bool) {
#[cfg(target_os = "windows")]
let rawkey = RawKey::ScanCode(code);
#[cfg(target_os = "linux")]
let rawkey = RawKey::LinuxXorgKeycode(code);
// // to-do: test android
// #[cfg(target_os = "android")]
// let rawkey = RawKey::LinuxConsoleKeycode(code);
#[cfg(target_os = "macos")]
let rawkey = RawKey::MacVirtualKeycode(code);
rdev_key_down_or_up(RdevKey::RawKey(rawkey), down_or_up);
}
fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) { fn rdev_key_down_or_up(key: RdevKey, down_or_up: bool) {
let event_type = match down_or_up { let event_type = match down_or_up {
true => EventType::KeyPress(key), true => EventType::KeyPress(key),
@ -821,8 +835,7 @@ fn map_keyboard_mode(evt: &KeyEvent) {
return; return;
} }
rdev_key_down_or_up(RdevKey::Unknown(evt.chr()), evt.down); sim_rdev_rawkey(evt.chr(), evt.down);
return;
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -850,6 +863,7 @@ fn release_unpressed_modifiers(en: &mut Enigo, key_event: &KeyEvent) {
fix_modifiers(&key_event.modifiers[..], en, ck_value); fix_modifiers(&key_event.modifiers[..], en, ck_value);
} }
#[cfg(target_os = "linux")]
fn is_altgr_pressed() -> bool { fn is_altgr_pressed() -> bool {
KEYS_DOWN KEYS_DOWN
.lock() .lock()

View File

@ -13,7 +13,6 @@ use objc::{
}; };
use sciter::{make_args, Host}; use sciter::{make_args, Host};
use std::{ffi::c_void, rc::Rc}; use std::{ffi::c_void, rc::Rc};
use dark_light;
static APP_HANDLER_IVAR: &str = "GoDeskAppHandler"; static APP_HANDLER_IVAR: &str = "GoDeskAppHandler";

View File

@ -376,7 +376,7 @@ impl<T: InvokeUiSession> Session<T> {
let scancode: u32 = scancode as u32; let scancode: u32 = scancode as u32;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let key = rdev::key_from_scancode(scancode) as rdev::Key; let key = rdev::key_from_code(keycode) as rdev::Key;
// Windows requires special handling // Windows requires special handling
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let key = rdev::get_win_key(keycode, scancode); let key = rdev::get_win_key(keycode, scancode);