diff --git a/libs/enigo/src/win/win_impl.rs b/libs/enigo/src/win/win_impl.rs index 115cb9789..068f3463a 100644 --- a/libs/enigo/src/win/win_impl.rs +++ b/libs/enigo/src/win/win_impl.rs @@ -156,7 +156,7 @@ impl MouseControllable for Enigo { match button { MouseButton::Back => XBUTTON1 as _, MouseButton::Forward => XBUTTON2 as _, - _ => 0, + _ => 0, }, 0, 0, @@ -186,7 +186,7 @@ impl MouseControllable for Enigo { match button { MouseButton::Back => XBUTTON1 as _, MouseButton::Forward => XBUTTON2 as _, - _ => 0, + _ => 0, }, 0, 0, @@ -215,7 +215,7 @@ impl KeyboardControllable for Enigo { fn as_mut_any(&mut self) -> &mut dyn std::any::Any { self } - + fn key_sequence(&mut self, sequence: &str) { let mut buffer = [0; 2]; @@ -247,15 +247,51 @@ impl KeyboardControllable for Enigo { } fn key_down(&mut self, key: Key) -> crate::ResultType { - let code = self.key_to_keycode(key); - if code == 0 || code == 65535 { - return Err("".into()); - } - let res = keybd_event(0, code, 0); - if res == 0 { - let err = get_error(); - if !err.is_empty() { - return Err(err.into()); + 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); + if code == 0 || code == 65535 { + return Err("".into()); + } + let res = keybd_event(0, code, 0); + if res == 0 { + let err = get_error(); + if !err.is_empty() { + return Err(err.into()); + } + } } } Ok(()) @@ -411,30 +447,27 @@ impl Enigo { Key::RightAlt => EVK_RMENU, 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::Layout(..) => { + // unreachable + 0 + } } } - fn get_layoutdependent_keycode(&self, string: String) -> 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 - // to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout - // or load one with LoadKeyboardLayoutW - let current_window_thread_id = - unsafe { GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut()) }; - unsafe { LAYOUT = GetKeyboardLayout(current_window_thread_id) }; - let keycode_and_shiftstate = unsafe { VkKeyScanExW(chr as _, LAYOUT) }; - if keycode_and_shiftstate == (EVK_DECIMAL as i16) && chr == '.' { - // a workaround of italian keyboard shift + '.' issue - EVK_PERIOD as _ - } else { - keycode_and_shiftstate as _ - } + fn get_layoutdependent_keycode(&self, chr: char) -> u16 { + // NOTE VkKeyScanW uses the current keyboard LAYOUT + // to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout + // or load one with LoadKeyboardLayoutW + let current_window_thread_id = + unsafe { GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut()) }; + unsafe { LAYOUT = GetKeyboardLayout(current_window_thread_id) }; + let keycode_and_shiftstate = unsafe { VkKeyScanExW(chr as _, LAYOUT) }; + if keycode_and_shiftstate == (EVK_DECIMAL as i16) && chr == '.' { + // a workaround of italian keyboard shift + '.' issue + EVK_PERIOD as _ } else { - 0 + keycode_and_shiftstate as _ } } } diff --git a/libs/hbb_common/src/platform/mod.rs b/libs/hbb_common/src/platform/mod.rs index fd57476c0..137868e12 100644 --- a/libs/hbb_common/src/platform/mod.rs +++ b/libs/hbb_common/src/platform/mod.rs @@ -4,11 +4,15 @@ pub mod linux; #[cfg(target_os = "macos")] pub mod macos; +#[cfg(not(debug_assertions))] use crate::{config::Config, log}; +#[cfg(not(debug_assertions))] use std::process::exit; +#[cfg(not(debug_assertions))] static mut GLOBAL_CALLBACK: Option> = None; +#[cfg(not(debug_assertions))] extern "C" fn breakdown_signal_handler(sig: i32) { let mut stack = vec![]; backtrace::trace(|frame| { @@ -61,13 +65,13 @@ extern "C" fn breakdown_signal_handler(sig: i32) { exit(0); } -pub fn register_breakdown_handler(_callback: T) +#[cfg(not(debug_assertions))] +pub fn register_breakdown_handler(callback: T) where T: Fn() + 'static, { - #[cfg(not(debug_assertions))] unsafe { - GLOBAL_CALLBACK = Some(Box::new(_callback)); + GLOBAL_CALLBACK = Some(Box::new(callback)); libc::signal(libc::SIGSEGV, breakdown_signal_handler as _); } } diff --git a/src/core_main.rs b/src/core_main.rs index 05a5ad769..a3e11a49e 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -1,5 +1,6 @@ use crate::platform::breakdown_callback; use hbb_common::log; +#[cfg(not(debug_assertions))] #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::platform::register_breakdown_handler; @@ -39,6 +40,7 @@ pub fn core_main() -> Option> { } i += 1; } + #[cfg(not(debug_assertions))] #[cfg(not(any(target_os = "android", target_os = "ios")))] register_breakdown_handler(breakdown_callback); #[cfg(target_os = "linux")]