Merge pull request #3949 from fufesou/fix/legacy_mode_win_layout_code
legacy mode, win, fix layout code simulation
This commit is contained in:
		
						commit
						30e42d8820
					
				| @ -247,15 +247,51 @@ impl KeyboardControllable for Enigo { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn key_down(&mut self, key: Key) -> crate::ResultType { |     fn key_down(&mut self, key: Key) -> crate::ResultType { | ||||||
|         let code = self.key_to_keycode(key); |         match &key { | ||||||
|         if code == 0 || code == 65535 { |             Key::Layout(c) => { | ||||||
|             return Err("".into()); |                 // to-do: dup code
 | ||||||
|         } |                 // https://github.com/rustdesk/rustdesk/blob/1bc0dd791ed8344997024dc46626bd2ca7df73d2/src/server/input_service.rs#L1348
 | ||||||
|         let res = keybd_event(0, code, 0); |                 let code = self.get_layoutdependent_keycode(*c); | ||||||
|         if res == 0 { |                 if code as u16 != 0xFFFF { | ||||||
|             let err = get_error(); |                     let vk = code & 0x00FF; | ||||||
|             if !err.is_empty() { |                     let flag = code >> 8; | ||||||
|                 return Err(err.into()); |                     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(()) |         Ok(()) | ||||||
| @ -411,30 +447,27 @@ 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
 |         // NOTE VkKeyScanW uses the current keyboard LAYOUT
 | ||||||
|         // ensure its not a multybyte char
 |         // to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout
 | ||||||
|         if let Some(chr) = string.chars().nth(0) { |         // or load one with LoadKeyboardLayoutW
 | ||||||
|             // NOTE VkKeyScanW uses the current keyboard LAYOUT
 |         let current_window_thread_id = | ||||||
|             // to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout
 |             unsafe { GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut()) }; | ||||||
|             // or load one with LoadKeyboardLayoutW
 |         unsafe { LAYOUT = GetKeyboardLayout(current_window_thread_id) }; | ||||||
|             let current_window_thread_id = |         let keycode_and_shiftstate = unsafe { VkKeyScanExW(chr as _, LAYOUT) }; | ||||||
|                 unsafe { GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut()) }; |         if keycode_and_shiftstate == (EVK_DECIMAL as i16) && chr == '.' { | ||||||
|             unsafe { LAYOUT = GetKeyboardLayout(current_window_thread_id) }; |             // a workaround of italian keyboard shift + '.' issue
 | ||||||
|             let keycode_and_shiftstate = unsafe { VkKeyScanExW(chr as _, LAYOUT) }; |             EVK_PERIOD as _ | ||||||
|             if keycode_and_shiftstate == (EVK_DECIMAL as i16) && chr == '.' { |  | ||||||
|                 // a workaround of italian keyboard shift + '.' issue
 |  | ||||||
|                 EVK_PERIOD as _ |  | ||||||
|             } else { |  | ||||||
|                 keycode_and_shiftstate as _ |  | ||||||
|             } |  | ||||||
|         } else { |         } else { | ||||||
|             0 |             keycode_and_shiftstate as _ | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -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