mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-01-19 00:13:01 +08:00
Merge pull request #3116 from fufesou/feat/keyboard_translate_mode
feat/keyboard translate mode
This commit is contained in:
commit
993e2d9c77
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -4405,7 +4405,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/fufesou/rdev#238c9778da40056e2efda1e4264355bc89fb6358"
|
||||
source = "git+https://github.com/fufesou/rdev#4d8231f05e14c5a04cd7d2c1288e87ad52d39e4c"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-foundation 0.9.3",
|
||||
|
@ -1489,25 +1489,29 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
||||
text: translate('Ratio'),
|
||||
optionsGetter: () {
|
||||
List<MenuEntryRadioOption> list = [];
|
||||
List<String> modes = ["legacy"];
|
||||
List<KeyboardModeMenu> modes = [
|
||||
KeyboardModeMenu(key: 'legacy', menu: 'Legacy mode'),
|
||||
KeyboardModeMenu(key: 'map', menu: 'Map mode'),
|
||||
KeyboardModeMenu(key: 'translate', menu: 'Translate mode'),
|
||||
];
|
||||
|
||||
if (bind.sessionIsKeyboardModeSupported(id: widget.id, mode: "map")) {
|
||||
modes.add("map");
|
||||
}
|
||||
|
||||
for (String mode in modes) {
|
||||
if (mode == "legacy") {
|
||||
for (KeyboardModeMenu mode in modes) {
|
||||
if (bind.sessionIsKeyboardModeSupported(
|
||||
id: widget.id, mode: mode.key)) {
|
||||
if (mode.key == 'translate') {
|
||||
if (!Platform.isWindows ||
|
||||
widget.ffi.ffiModel.pi.platform != kPeerPlatformWindows) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
list.add(MenuEntryRadioOption(
|
||||
text: translate('Legacy mode'), value: 'legacy'));
|
||||
} else if (mode == "map") {
|
||||
list.add(MenuEntryRadioOption(
|
||||
text: translate('Map mode'), value: 'map'));
|
||||
text: translate(mode.menu), value: mode.key));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
},
|
||||
curOptionGetter: () async {
|
||||
return await bind.sessionGetKeyboardMode(id: widget.id) ?? "legacy";
|
||||
return await bind.sessionGetKeyboardMode(id: widget.id) ?? 'legacy';
|
||||
},
|
||||
optionSetter: (String oldValue, String newValue) async {
|
||||
await bind.sessionSetKeyboardMode(id: widget.id, value: newValue);
|
||||
@ -1796,3 +1800,10 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class KeyboardModeMenu {
|
||||
final String key;
|
||||
final String menu;
|
||||
|
||||
KeyboardModeMenu({required this.key, required this.menu});
|
||||
}
|
||||
|
@ -721,8 +721,8 @@ pub fn is_keyboard_mode_supported(keyboard_mode: &KeyboardMode, version_number:
|
||||
match keyboard_mode {
|
||||
KeyboardMode::Legacy => true,
|
||||
KeyboardMode::Map => version_number >= hbb_common::get_version_number("1.2.0"),
|
||||
KeyboardMode::Translate => false,
|
||||
KeyboardMode::Auto => false,
|
||||
KeyboardMode::Translate => version_number >= hbb_common::get_version_number("1.2.0"),
|
||||
KeyboardMode::Auto => version_number >= hbb_common::get_version_number("1.2.0"),
|
||||
}
|
||||
}
|
||||
|
||||
|
205
src/keyboard.rs
205
src/keyboard.rs
@ -88,13 +88,17 @@ pub mod client {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_event(event: &Event, lock_modes: Option<i32>) {
|
||||
pub fn process_event(event: &Event, lock_modes: Option<i32>) -> KeyboardMode {
|
||||
let keyboard_mode = get_keyboard_mode_enum();
|
||||
|
||||
if is_long_press(&event) {
|
||||
return;
|
||||
return keyboard_mode;
|
||||
}
|
||||
if let Some(key_event) = event_to_key_event(&event, lock_modes) {
|
||||
|
||||
for key_event in event_to_key_events(&event, keyboard_mode, lock_modes) {
|
||||
send_key_event(&key_event);
|
||||
}
|
||||
keyboard_mode
|
||||
}
|
||||
|
||||
pub fn get_modifiers_state(
|
||||
@ -195,6 +199,9 @@ pub fn update_grab_get_key_name() {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
static mut IS_0X021D_DOWN: bool = false;
|
||||
|
||||
pub fn start_grab_loop() {
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
std::thread::spawn(move || {
|
||||
@ -203,16 +210,43 @@ pub fn start_grab_loop() {
|
||||
if key == Key::CapsLock || key == Key::NumLock {
|
||||
return Some(event);
|
||||
}
|
||||
if KEYBOARD_HOOKED.load(Ordering::SeqCst) {
|
||||
client::process_event(&event, None);
|
||||
|
||||
let mut _keyboard_mode = KeyboardMode::Map;
|
||||
let scan_code = event.scan_code;
|
||||
let res = if KEYBOARD_HOOKED.load(Ordering::SeqCst) {
|
||||
_keyboard_mode = client::process_event(&event, None);
|
||||
if is_press {
|
||||
return None;
|
||||
None
|
||||
} else {
|
||||
return Some(event);
|
||||
Some(event)
|
||||
}
|
||||
} else {
|
||||
return Some(event);
|
||||
Some(event)
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
match scan_code {
|
||||
0x1D | 0x021D => rdev::set_modifier(Key::ControlLeft, is_press),
|
||||
0xE01D => rdev::set_modifier(Key::ControlRight, is_press),
|
||||
0x2A => rdev::set_modifier(Key::ShiftLeft, is_press),
|
||||
0x36 => rdev::set_modifier(Key::ShiftRight, is_press),
|
||||
0x38 => rdev::set_modifier(Key::Alt, is_press),
|
||||
// Right Alt
|
||||
0xE038 => rdev::set_modifier(Key::AltGr, is_press),
|
||||
0xE05B => rdev::set_modifier(Key::MetaLeft, is_press),
|
||||
0xE05C => rdev::set_modifier(Key::MetaRight, is_press),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
unsafe {
|
||||
// AltGr
|
||||
if scan_code == 0x021D {
|
||||
IS_0X021D_DOWN = is_press;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
let func = move |event: Event| match event.event_type {
|
||||
EventType::KeyPress(key) => try_handle_keyboard(event, key, true),
|
||||
@ -341,7 +375,11 @@ fn update_modifiers_state(event: &Event) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn event_to_key_event(event: &Event, lock_modes: Option<i32>) -> Option<KeyEvent> {
|
||||
pub fn event_to_key_events(
|
||||
event: &Event,
|
||||
keyboard_mode: KeyboardMode,
|
||||
lock_modes: Option<i32>,
|
||||
) -> Vec<KeyEvent> {
|
||||
let mut key_event = KeyEvent::new();
|
||||
update_modifiers_state(event);
|
||||
|
||||
@ -355,37 +393,44 @@ pub fn event_to_key_event(event: &Event, lock_modes: Option<i32>) -> Option<KeyE
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let keyboard_mode = get_keyboard_mode_enum();
|
||||
key_event.mode = keyboard_mode.into();
|
||||
let mut key_event = match keyboard_mode {
|
||||
KeyboardMode::Map => map_keyboard_mode(event, key_event)?,
|
||||
KeyboardMode::Translate => translate_keyboard_mode(event, key_event)?,
|
||||
let mut key_events = match keyboard_mode {
|
||||
KeyboardMode::Map => match map_keyboard_mode(event, key_event) {
|
||||
Some(event) => [event].to_vec(),
|
||||
None => Vec::new(),
|
||||
},
|
||||
KeyboardMode::Translate => translate_keyboard_mode(event, key_event),
|
||||
_ => {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
legacy_keyboard_mode(event, key_event)?
|
||||
legacy_keyboard_mode(event, key_event)
|
||||
}
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
{
|
||||
None?
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if let Some(lock_modes) = lock_modes {
|
||||
add_numlock_capslock_with_lock_modes(&mut key_event, lock_modes);
|
||||
} else {
|
||||
add_numlock_capslock_status(&mut key_event);
|
||||
|
||||
if keyboard_mode != KeyboardMode::Translate {
|
||||
for key_event in &mut key_events {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if let Some(lock_modes) = lock_modes {
|
||||
add_numlock_capslock_with_lock_modes(key_event, lock_modes);
|
||||
} else {
|
||||
add_numlock_capslock_status(key_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Some(key_event);
|
||||
key_events
|
||||
}
|
||||
|
||||
pub fn event_type_to_event(event_type: EventType) -> Event {
|
||||
Event {
|
||||
event_type,
|
||||
time: SystemTime::now(),
|
||||
name: None,
|
||||
unicode: None,
|
||||
code: 0,
|
||||
scan_code: 0,
|
||||
}
|
||||
@ -423,13 +468,14 @@ pub fn get_peer_platform() -> String {
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Vec<KeyEvent> {
|
||||
let mut events = Vec::new();
|
||||
// legacy mode(0): Generate characters locally, look for keycode on other side.
|
||||
let (mut key, down_or_up) = match event.event_type {
|
||||
EventType::KeyPress(key) => (key, true),
|
||||
EventType::KeyRelease(key) => (key, false),
|
||||
_ => {
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
};
|
||||
|
||||
@ -475,7 +521,7 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
unsafe {
|
||||
IS_ALT_GR = true;
|
||||
}
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
Some(ControlKey::Control)
|
||||
}
|
||||
@ -507,7 +553,7 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
Key::Delete => {
|
||||
if is_win && ctrl && alt {
|
||||
client::ctrl_alt_del();
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
Some(ControlKey::Delete)
|
||||
}
|
||||
@ -545,7 +591,7 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
Key::KpMinus => Some(ControlKey::Subtract),
|
||||
Key::KpPlus => Some(ControlKey::Add),
|
||||
Key::CapsLock | Key::NumLock | Key::ScrollLock => {
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
Key::Home => Some(ControlKey::Home),
|
||||
Key::End => Some(ControlKey::End),
|
||||
@ -558,7 +604,11 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
if let Some(k) = control_key {
|
||||
key_event.set_control_key(k);
|
||||
} else {
|
||||
let mut chr = match event.name {
|
||||
let name = event
|
||||
.unicode
|
||||
.as_ref()
|
||||
.and_then(|unicode| unicode.name.clone());
|
||||
let mut chr = match &name {
|
||||
Some(ref s) => {
|
||||
if s.len() <= 2 {
|
||||
// exclude chinese characters
|
||||
@ -628,12 +678,12 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
if chr != '\0' {
|
||||
if chr == 'l' && is_win && command {
|
||||
client::lock_screen();
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
key_event.set_chr(chr as _);
|
||||
} else {
|
||||
log::error!("Unknown key {:?}", &event);
|
||||
return None;
|
||||
return events;
|
||||
}
|
||||
}
|
||||
let (alt, ctrl, shift, command) = client::get_modifiers_state(alt, ctrl, shift, command);
|
||||
@ -642,7 +692,8 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<Ke
|
||||
if down_or_up == true {
|
||||
key_event.down = true;
|
||||
}
|
||||
Some(key_event)
|
||||
events.push(key_event);
|
||||
events
|
||||
}
|
||||
|
||||
pub fn map_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
@ -703,6 +754,94 @@ pub fn map_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEv
|
||||
Some(key_event)
|
||||
}
|
||||
|
||||
pub fn translate_keyboard_mode(_event: &Event, mut _key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
None
|
||||
fn try_fill_unicode(event: &Event, key_event: &KeyEvent, events: &mut Vec<KeyEvent>) {
|
||||
match &event.unicode {
|
||||
Some(unicode_info) => {
|
||||
if !unicode_info.is_dead {
|
||||
for code in &unicode_info.unicode {
|
||||
let mut evt = key_event.clone();
|
||||
evt.set_unicode(*code as _);
|
||||
events.push(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn is_hot_key_modifiers_down() -> bool {
|
||||
if rdev::get_modifier(Key::ControlLeft) || rdev::get_modifier(Key::ControlRight) {
|
||||
return true;
|
||||
}
|
||||
if rdev::get_modifier(Key::Alt) || rdev::get_modifier(Key::AltGr) {
|
||||
return true;
|
||||
}
|
||||
if rdev::get_modifier(Key::MetaLeft) || rdev::get_modifier(Key::MetaRight) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn translate_virtual_keycode(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();
|
||||
peer.retain(|c| !c.is_whitespace());
|
||||
|
||||
// #[cfg(target_os = "windows")]
|
||||
// let keycode = match peer.as_str() {
|
||||
// "windows" => event.code,
|
||||
// "macos" => {
|
||||
// if hbb_common::config::LocalConfig::get_kb_layout_type() == "ISO" {
|
||||
// rdev::win_scancode_to_macos_iso_code(event.scan_code)?
|
||||
// } else {
|
||||
// rdev::win_scancode_to_macos_code(event.scan_code)?
|
||||
// }
|
||||
// }
|
||||
// _ => rdev::win_scancode_to_linux_code(event.scan_code)?,
|
||||
// };
|
||||
|
||||
key_event.set_chr(event.code as _);
|
||||
Some(key_event)
|
||||
}
|
||||
|
||||
pub fn translate_keyboard_mode(event: &Event, key_event: KeyEvent) -> Vec<KeyEvent> {
|
||||
let mut events: Vec<KeyEvent> = Vec::new();
|
||||
#[cfg(target_os = "windows")]
|
||||
unsafe {
|
||||
if event.scan_code == 0x021D {
|
||||
return events;
|
||||
}
|
||||
|
||||
if IS_0X021D_DOWN {
|
||||
if event.scan_code == 0xE038 {
|
||||
return events;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
if unsafe { IS_0X021D_DOWN } || !is_hot_key_modifiers_down() {
|
||||
try_fill_unicode(event, &key_event, &mut events);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
try_fill_unicode(event, &key_event, &mut events);
|
||||
|
||||
if events.is_empty() {
|
||||
if let Some(evt) = translate_virtual_keycode(event, key_event) {
|
||||
events.push(evt);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
events
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ struct Input {
|
||||
y: i32,
|
||||
}
|
||||
|
||||
const KEY_RDEV_START: u64 = 999;
|
||||
const KEY_CHAR_START: u64 = 9999;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@ -202,11 +201,17 @@ fn run_cursor(sp: MouseCursorService, state: &mut StateCursor) -> ResultType<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
enum KeysDown {
|
||||
RdevKey(RawKey),
|
||||
EnigoKey(u64),
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ENIGO: Arc<Mutex<Enigo>> = {
|
||||
Arc::new(Mutex::new(Enigo::new()))
|
||||
};
|
||||
static ref KEYS_DOWN: Arc<Mutex<HashMap<u64, Instant>>> = Default::default();
|
||||
static ref KEYS_DOWN: Arc<Mutex<HashMap<KeysDown, Instant>>> = Default::default();
|
||||
static ref LATEST_PEER_INPUT_CURSOR: Arc<Mutex<Input>> = Default::default();
|
||||
static ref LATEST_SYS_CURSOR_POS: Arc<Mutex<(Instant, (i32, i32))>> = Arc::new(Mutex::new((Instant::now().sub(MOUSE_MOVE_PROTECTION_TIMEOUT), (0, 0))));
|
||||
}
|
||||
@ -375,12 +380,7 @@ fn record_key_is_control_key(record_key: u64) -> bool {
|
||||
|
||||
#[inline]
|
||||
fn record_key_is_chr(record_key: u64) -> bool {
|
||||
KEY_RDEV_START <= record_key && record_key < KEY_CHAR_START
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn record_key_is_rdev_layout(record_key: u64) -> bool {
|
||||
KEY_CHAR_START <= record_key
|
||||
record_key < KEY_CHAR_START
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -396,15 +396,16 @@ fn record_key_to_key(record_key: u64) -> Option<Key> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn release_record_key(record_key: u64) {
|
||||
let func = move || {
|
||||
if record_key_is_rdev_layout(record_key) {
|
||||
simulate_(&EventType::KeyRelease(RdevKey::Unknown(
|
||||
(record_key - KEY_RDEV_START) as _,
|
||||
)));
|
||||
} else if let Some(key) = record_key_to_key(record_key) {
|
||||
ENIGO.lock().unwrap().key_up(key);
|
||||
log::debug!("Fixed {:?} timeout", key);
|
||||
fn release_record_key(record_key: KeysDown) {
|
||||
let func = move || match record_key {
|
||||
KeysDown::RdevKey(raw_key) => {
|
||||
simulate_(&EventType::KeyRelease(RdevKey::RawKey(raw_key)));
|
||||
}
|
||||
KeysDown::EnigoKey(key) => {
|
||||
if let Some(key) = record_key_to_key(key) {
|
||||
ENIGO.lock().unwrap().key_up(key);
|
||||
log::debug!("Fixed {:?} timeout", key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -733,7 +734,7 @@ pub fn reset_input_ondisconn() {
|
||||
}
|
||||
}
|
||||
|
||||
fn sim_rdev_rawkey(code: u32, keydown: bool) {
|
||||
fn sim_rdev_rawkey_position(code: u32, keydown: bool) {
|
||||
#[cfg(target_os = "windows")]
|
||||
let rawkey = RawKey::ScanCode(code);
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -744,6 +745,21 @@ fn sim_rdev_rawkey(code: u32, keydown: bool) {
|
||||
#[cfg(target_os = "macos")]
|
||||
let rawkey = RawKey::MacVirtualKeycode(code);
|
||||
|
||||
// map mode(1): Send keycode according to the peer platform.
|
||||
record_pressed_key(KeysDown::RdevKey(rawkey), keydown);
|
||||
|
||||
let event_type = if keydown {
|
||||
EventType::KeyPress(RdevKey::RawKey(rawkey))
|
||||
} else {
|
||||
EventType::KeyRelease(RdevKey::RawKey(rawkey))
|
||||
};
|
||||
simulate_(&event_type);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn sim_rdev_rawkey_virtual(code: u32, keydown: bool) {
|
||||
let rawkey = RawKey::WinVirtualKeycode(code);
|
||||
record_pressed_key(KeysDown::RdevKey(rawkey), keydown);
|
||||
let event_type = if keydown {
|
||||
EventType::KeyPress(RdevKey::RawKey(rawkey))
|
||||
} else {
|
||||
@ -874,9 +890,6 @@ fn sync_numlock_capslock_status(key_event: &KeyEvent) {
|
||||
}
|
||||
|
||||
fn map_keyboard_mode(evt: &KeyEvent) {
|
||||
// map mode(1): Send keycode according to the peer platform.
|
||||
record_pressed_key(evt.chr() as u64 + KEY_CHAR_START, evt.down);
|
||||
|
||||
#[cfg(windows)]
|
||||
crate::platform::windows::try_change_desktop();
|
||||
|
||||
@ -894,7 +907,7 @@ fn map_keyboard_mode(evt: &KeyEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
sim_rdev_rawkey(evt.chr(), evt.down);
|
||||
sim_rdev_rawkey_position(evt.chr(), evt.down);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@ -924,10 +937,11 @@ fn release_unpressed_modifiers(en: &mut Enigo, key_event: &KeyEvent) {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn is_altgr_pressed() -> bool {
|
||||
let altgr_rawkey = RawKey::LinuxXorgKeycode(ControlKey::RAlt.value() as _);
|
||||
KEYS_DOWN
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&(ControlKey::RAlt.value() as _))
|
||||
.get(&KeysDown::RdevKey(altgr_rawkey))
|
||||
.is_some()
|
||||
}
|
||||
|
||||
@ -1011,7 +1025,7 @@ fn release_keys(en: &mut Enigo, to_release: &Vec<Key>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn record_pressed_key(record_key: u64, down: bool) {
|
||||
fn record_pressed_key(record_key: KeysDown, down: bool) {
|
||||
let mut key_down = KEYS_DOWN.lock().unwrap();
|
||||
if down {
|
||||
key_down.insert(record_key, Instant::now());
|
||||
@ -1050,12 +1064,12 @@ fn legacy_keyboard_mode(evt: &KeyEvent) {
|
||||
return;
|
||||
}
|
||||
let record_key = ck.value() as u64;
|
||||
record_pressed_key(record_key, down);
|
||||
record_pressed_key(KeysDown::EnigoKey(record_key), down);
|
||||
process_control_key(&mut en, &ck, down)
|
||||
}
|
||||
Some(key_event::Union::Chr(chr)) => {
|
||||
let record_key = chr as u64 + KEY_CHAR_START;
|
||||
record_pressed_key(record_key, down);
|
||||
record_pressed_key(KeysDown::EnigoKey(record_key), down);
|
||||
process_chr(&mut en, chr, down)
|
||||
}
|
||||
Some(key_event::Union::Unicode(chr)) => process_unicode(&mut en, chr),
|
||||
@ -1067,6 +1081,29 @@ fn legacy_keyboard_mode(evt: &KeyEvent) {
|
||||
release_keys(&mut en, &to_release);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn translate_process_virtual_keycode(vk: u32, down: bool) {
|
||||
crate::platform::windows::try_change_desktop();
|
||||
sim_rdev_rawkey_virtual(vk, down);
|
||||
}
|
||||
|
||||
fn translate_keyboard_mode(evt: &KeyEvent) {
|
||||
match evt.union {
|
||||
Some(key_event::Union::Unicode(_unicode)) => {
|
||||
#[cfg(target_os = "windows")]
|
||||
allow_err!(rdev::simulate_unicode(_unicode as _));
|
||||
}
|
||||
Some(key_event::Union::Chr(..)) =>
|
||||
{
|
||||
#[cfg(target_os = "windows")]
|
||||
translate_process_virtual_keycode(evt.chr(), evt.down)
|
||||
}
|
||||
_ => {
|
||||
log::debug!("Unreachable. Unexpected key event {:?}", &evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_key_(evt: &KeyEvent) {
|
||||
if EXITING.load(Ordering::SeqCst) {
|
||||
return;
|
||||
@ -1080,7 +1117,7 @@ pub fn handle_key_(evt: &KeyEvent) {
|
||||
map_keyboard_mode(evt);
|
||||
}
|
||||
KeyboardMode::Translate => {
|
||||
legacy_keyboard_mode(evt);
|
||||
translate_keyboard_mode(evt);
|
||||
}
|
||||
_ => {
|
||||
legacy_keyboard_mode(evt);
|
||||
|
@ -365,11 +365,24 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
}
|
||||
|
||||
pub fn enter(&self) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
match &self.lc.read().unwrap().keyboard_mode as _ {
|
||||
"legacy" => rdev::set_get_key_name(true),
|
||||
"translate" => rdev::set_get_key_name(true),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
IS_IN.store(true, Ordering::SeqCst);
|
||||
keyboard::client::change_grab_status(GrabState::Run);
|
||||
}
|
||||
|
||||
pub fn leave(&self) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
rdev::set_get_key_name(false);
|
||||
}
|
||||
IS_IN.store(false, Ordering::SeqCst);
|
||||
keyboard::client::change_grab_status(GrabState::Wait);
|
||||
}
|
||||
@ -407,7 +420,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
|
||||
pub fn handle_flutter_key_event(
|
||||
&self,
|
||||
name: &str,
|
||||
_name: &str,
|
||||
keycode: i32,
|
||||
scancode: i32,
|
||||
lock_modes: i32,
|
||||
@ -432,7 +445,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
};
|
||||
let event = Event {
|
||||
time: std::time::SystemTime::now(),
|
||||
name: Option::Some(name.to_owned()),
|
||||
unicode: None,
|
||||
code: keycode as _,
|
||||
scan_code: scancode as _,
|
||||
event_type: event_type,
|
||||
|
Loading…
Reference in New Issue
Block a user