legacy mode, win, fix layout code simulation
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
1bc0dd791e
commit
ac74ed1914
@ -247,6 +247,40 @@ impl KeyboardControllable for Enigo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn key_down(&mut self, key: Key) -> crate::ResultType {
|
fn key_down(&mut self, key: Key) -> crate::ResultType {
|
||||||
|
match &key {
|
||||||
|
Key::Layout(c) => {
|
||||||
|
// to-do: dup code
|
||||||
|
// https://github.com/rustdesk/rustdesk/blob/1bc0dd791ed8344997024dc46626bd2ca7df73d2/src/server/input_service.rs#L1348
|
||||||
|
let code = self.get_layoutdependent_keycode(*c);
|
||||||
|
if code as u16 != 0xFFFF {
|
||||||
|
let vk = code & 0x00FF;
|
||||||
|
let flag = code >> 8;
|
||||||
|
let modifiers = [Key::Shift, Key::Control, Key::Alt];
|
||||||
|
let mod_len = modifiers.len();
|
||||||
|
for pos in 0..mod_len {
|
||||||
|
if flag & (0x0001 << pos) != 0 {
|
||||||
|
self.key_down(modifiers[pos])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = keybd_event(0, vk, 0);
|
||||||
|
let err = if res == 0 { get_error() } else { "".to_owned() };
|
||||||
|
|
||||||
|
for pos in 0..mod_len {
|
||||||
|
let rpos = mod_len - 1 - pos;
|
||||||
|
if flag & (0x0001 << rpos) != 0 {
|
||||||
|
self.key_up(modifiers[pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !err.is_empty() {
|
||||||
|
return Err(err.into());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(format!("Failed to get keycode of {}", c).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
let code = self.key_to_keycode(key);
|
let code = self.key_to_keycode(key);
|
||||||
if code == 0 || code == 65535 {
|
if code == 0 || code == 65535 {
|
||||||
return Err("".into());
|
return Err("".into());
|
||||||
@ -258,6 +292,8 @@ impl KeyboardControllable for Enigo {
|
|||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,15 +447,15 @@ impl Enigo {
|
|||||||
Key::RightAlt => EVK_RMENU,
|
Key::RightAlt => EVK_RMENU,
|
||||||
|
|
||||||
Key::Raw(raw_keycode) => raw_keycode,
|
Key::Raw(raw_keycode) => raw_keycode,
|
||||||
Key::Layout(c) => self.get_layoutdependent_keycode(c.to_string()),
|
|
||||||
Key::Super | Key::Command | Key::Windows | Key::Meta => EVK_LWIN,
|
Key::Super | Key::Command | Key::Windows | Key::Meta => EVK_LWIN,
|
||||||
|
Key::Layout(..) => {
|
||||||
|
// unreachable
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_layoutdependent_keycode(&self, string: String) -> u16 {
|
fn get_layoutdependent_keycode(&self, chr: char) -> u16 {
|
||||||
// get the first char from the string ignore the rest
|
|
||||||
// ensure its not a multybyte char
|
|
||||||
if let Some(chr) = string.chars().nth(0) {
|
|
||||||
// NOTE VkKeyScanW uses the current keyboard LAYOUT
|
// NOTE VkKeyScanW uses the current keyboard LAYOUT
|
||||||
// to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout
|
// to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout
|
||||||
// or load one with LoadKeyboardLayoutW
|
// or load one with LoadKeyboardLayoutW
|
||||||
@ -433,8 +469,5 @@ impl Enigo {
|
|||||||
} else {
|
} else {
|
||||||
keycode_and_shiftstate as _
|
keycode_and_shiftstate as _
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,15 @@ pub mod linux;
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub mod macos;
|
pub mod macos;
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
use crate::{config::Config, log};
|
use crate::{config::Config, log};
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
static mut GLOBAL_CALLBACK: Option<Box<dyn Fn()>> = None;
|
static mut GLOBAL_CALLBACK: Option<Box<dyn Fn()>> = None;
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
extern "C" fn breakdown_signal_handler(sig: i32) {
|
extern "C" fn breakdown_signal_handler(sig: i32) {
|
||||||
let mut stack = vec![];
|
let mut stack = vec![];
|
||||||
backtrace::trace(|frame| {
|
backtrace::trace(|frame| {
|
||||||
@ -61,13 +65,13 @@ extern "C" fn breakdown_signal_handler(sig: i32) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_breakdown_handler<T>(_callback: T)
|
#[cfg(not(debug_assertions))]
|
||||||
|
pub fn register_breakdown_handler<T>(callback: T)
|
||||||
where
|
where
|
||||||
T: Fn() + 'static,
|
T: Fn() + 'static,
|
||||||
{
|
{
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
unsafe {
|
unsafe {
|
||||||
GLOBAL_CALLBACK = Some(Box::new(_callback));
|
GLOBAL_CALLBACK = Some(Box::new(callback));
|
||||||
libc::signal(libc::SIGSEGV, breakdown_signal_handler as _);
|
libc::signal(libc::SIGSEGV, breakdown_signal_handler as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::platform::breakdown_callback;
|
use crate::platform::breakdown_callback;
|
||||||
use hbb_common::log;
|
use hbb_common::log;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use hbb_common::platform::register_breakdown_handler;
|
use hbb_common::platform::register_breakdown_handler;
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
register_breakdown_handler(breakdown_callback);
|
register_breakdown_handler(breakdown_callback);
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user