refact, keyboard lock modifiers
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
afa0413957
commit
ec47c3f894
@ -46,6 +46,35 @@ lazy_static::lazy_static! {
|
|||||||
m.insert(Key::MetaRight, false);
|
m.insert(Key::MetaRight, false);
|
||||||
Mutex::new(m)
|
Mutex::new(m)
|
||||||
};
|
};
|
||||||
|
static ref NUMPAD_POSITION_CODES: Arc<Vec<u32>> = {
|
||||||
|
let numpad_keys = [
|
||||||
|
rdev::Key::KpMinus,
|
||||||
|
rdev::Key::KpPlus,
|
||||||
|
rdev::Key::KpMultiply,
|
||||||
|
rdev::Key::KpDivide,
|
||||||
|
rdev::Key::KpDecimal,
|
||||||
|
rdev::Key::KpReturn,
|
||||||
|
rdev::Key::KpEqual,
|
||||||
|
rdev::Key::KpComma,
|
||||||
|
rdev::Key::Kp0,
|
||||||
|
rdev::Key::Kp1,
|
||||||
|
rdev::Key::Kp2,
|
||||||
|
rdev::Key::Kp3,
|
||||||
|
rdev::Key::Kp4,
|
||||||
|
rdev::Key::Kp5,
|
||||||
|
rdev::Key::Kp6,
|
||||||
|
rdev::Key::Kp7,
|
||||||
|
rdev::Key::Kp8,
|
||||||
|
rdev::Key::Kp9,
|
||||||
|
];
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let codes = numpad_keys.iter().filter_map(|k| rdev::win_scancode_from_key(*k)).collect();
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let codes = numpad_keys.iter().filter_map(|k| rdev::linux_code_from_keycode(*k)).collect();
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let codes = numpad_keys.iter().filter_map(|k| rdev::macos_code_from_keycode(*k)).collect();
|
||||||
|
Arc::new(codes)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod client {
|
pub mod client {
|
||||||
@ -333,19 +362,43 @@ pub fn get_keyboard_mode_enum() -> KeyboardMode {
|
|||||||
match client::get_keyboard_mode().as_str() {
|
match client::get_keyboard_mode().as_str() {
|
||||||
"map" => KeyboardMode::Map,
|
"map" => KeyboardMode::Map,
|
||||||
"translate" => KeyboardMode::Translate,
|
"translate" => KeyboardMode::Translate,
|
||||||
_ => KeyboardMode::Legacy,
|
"legacy" => KeyboardMode::Legacy,
|
||||||
|
_ => {
|
||||||
|
// Set "map" as default mode if version > 1.2.0.
|
||||||
|
let mut is_peer_version_gt_1_2_0 = false;
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "flutter", feature = "cli")))]
|
||||||
|
if let Some(session) = CUR_SESSION.lock().unwrap().as_ref() {
|
||||||
|
is_peer_version_gt_1_2_0 =
|
||||||
|
session.get_peer_version() > hbb_common::get_version_number("1.2.0");
|
||||||
|
}
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
if let Some(session) = SESSIONS
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get(&*CUR_SESSION_ID.read().unwrap())
|
||||||
|
{
|
||||||
|
is_peer_version_gt_1_2_0 =
|
||||||
|
session.get_peer_version() > hbb_common::get_version_number("1.2.0");
|
||||||
|
}
|
||||||
|
if is_peer_version_gt_1_2_0 {
|
||||||
|
KeyboardMode::Map
|
||||||
|
} else {
|
||||||
|
KeyboardMode::Legacy
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
fn add_numlock_capslock_with_lock_modes(key_event: &mut KeyEvent, lock_modes: i32) {
|
fn parse_add_lock_modes_modifiers(key_event: &mut KeyEvent, lock_modes: i32, is_numpad_key: bool) {
|
||||||
const CAPS_LOCK: i32 = 1;
|
const CAPS_LOCK: i32 = 1;
|
||||||
const NUM_LOCK: i32 = 2;
|
const NUM_LOCK: i32 = 2;
|
||||||
// const SCROLL_LOCK: i32 = 3;
|
// const SCROLL_LOCK: i32 = 3;
|
||||||
if lock_modes & (1 << CAPS_LOCK) != 0 {
|
if !is_numpad_key && (lock_modes & (1 << CAPS_LOCK) != 0) {
|
||||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||||
}
|
}
|
||||||
if lock_modes & (1 << NUM_LOCK) != 0 {
|
if is_numpad_key && (lock_modes & (1 << NUM_LOCK) != 0) {
|
||||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||||
}
|
}
|
||||||
// if lock_modes & (1 << SCROLL_LOCK) != 0 {
|
// if lock_modes & (1 << SCROLL_LOCK) != 0 {
|
||||||
@ -354,11 +407,11 @@ fn add_numlock_capslock_with_lock_modes(key_event: &mut KeyEvent, lock_modes: i3
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
fn add_numlock_capslock_status(key_event: &mut KeyEvent) {
|
fn add_lock_modes_modifiers(key_event: &mut KeyEvent, is_numpad_key: bool) {
|
||||||
if get_key_state(enigo::Key::CapsLock) {
|
if !is_numpad_key && get_key_state(enigo::Key::CapsLock) {
|
||||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||||
}
|
}
|
||||||
if get_key_state(enigo::Key::NumLock) {
|
if is_numpad_key && get_key_state(enigo::Key::NumLock) {
|
||||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,12 +496,13 @@ pub fn event_to_key_events(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if keyboard_mode != KeyboardMode::Translate {
|
if keyboard_mode != KeyboardMode::Translate {
|
||||||
|
let is_numpad_key = NUMPAD_POSITION_CODES.contains(&event.position_code);
|
||||||
for key_event in &mut key_events {
|
for key_event in &mut key_events {
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
if let Some(lock_modes) = lock_modes {
|
if let Some(lock_modes) = lock_modes {
|
||||||
add_numlock_capslock_with_lock_modes(key_event, lock_modes);
|
parse_add_lock_modes_modifiers(key_event, lock_modes, is_numpad_key);
|
||||||
} else {
|
} else {
|
||||||
add_numlock_capslock_status(key_event);
|
add_lock_modes_modifiers(key_event, is_numpad_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,52 @@ impl Subscriber for MouseCursorSub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LockModesHandler {
|
||||||
|
caps_lock_changed: bool,
|
||||||
|
num_lock_changed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LockModesHandler {
|
||||||
|
fn new(key_event: &KeyEvent) -> Self {
|
||||||
|
let mut en = ENIGO.lock().unwrap();
|
||||||
|
|
||||||
|
let event_caps_enabled = key_event.modifiers.contains(&ControlKey::CapsLock.into());
|
||||||
|
let local_caps_enabled = en.get_key_state(enigo::Key::CapsLock);
|
||||||
|
let caps_lock_changed = event_caps_enabled != local_caps_enabled;
|
||||||
|
if caps_lock_changed {
|
||||||
|
click_capslock(&mut en);
|
||||||
|
}
|
||||||
|
|
||||||
|
let event_num_enabled = key_event.modifiers.contains(&ControlKey::NumLock.into());
|
||||||
|
let local_num_enabled = en.get_key_state(enigo::Key::NumLock);
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let disable_numlock = false;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let disable_numlock = is_numlock_disabled(key_event);
|
||||||
|
let num_lock_changed = event_num_enabled != local_num_enabled && !disable_numlock;
|
||||||
|
if num_lock_changed {
|
||||||
|
click_numlock(&mut en);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
caps_lock_changed,
|
||||||
|
num_lock_changed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LockModesHandler {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let mut en = ENIGO.lock().unwrap();
|
||||||
|
if self.caps_lock_changed {
|
||||||
|
click_capslock(&mut en);
|
||||||
|
}
|
||||||
|
if self.num_lock_changed {
|
||||||
|
click_numlock(&mut en);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const NAME_CURSOR: &'static str = "mouse_cursor";
|
pub const NAME_CURSOR: &'static str = "mouse_cursor";
|
||||||
pub const NAME_POS: &'static str = "mouse_pos";
|
pub const NAME_POS: &'static str = "mouse_pos";
|
||||||
pub type MouseCursorService = ServiceTmpl<MouseCursorSub>;
|
pub type MouseCursorService = ServiceTmpl<MouseCursorSub>;
|
||||||
@ -850,10 +896,6 @@ fn char_value_to_key(value: u32) -> Key {
|
|||||||
Key::Layout(std::char::from_u32(value).unwrap_or('\0'))
|
Key::Layout(std::char::from_u32(value).unwrap_or('\0'))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_not_same_status(client_locking: bool, remote_locking: bool) -> bool {
|
|
||||||
client_locking != remote_locking
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn has_numpad_key(key_event: &KeyEvent) -> bool {
|
fn has_numpad_key(key_event: &KeyEvent) -> bool {
|
||||||
key_event
|
key_event
|
||||||
@ -900,37 +942,13 @@ fn click_capslock(en: &mut Enigo) {
|
|||||||
let _ = en.key_down(enigo::Key::CapsLock);
|
let _ = en.key_down(enigo::Key::CapsLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn click_numlock(_en: &mut Enigo) {
|
fn click_numlock(_en: &mut Enigo) {
|
||||||
// without numlock in macos
|
// without numlock in macos
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
_en.key_click(enigo::Key::NumLock);
|
_en.key_click(enigo::Key::NumLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_numlock_capslock_status(key_event: &KeyEvent) {
|
|
||||||
let mut en = ENIGO.lock().unwrap();
|
|
||||||
|
|
||||||
let client_caps_locking = is_modifier_in_key_event(ControlKey::CapsLock, key_event);
|
|
||||||
let client_num_locking = is_modifier_in_key_event(ControlKey::NumLock, key_event);
|
|
||||||
let remote_caps_locking = en.get_key_state(enigo::Key::CapsLock);
|
|
||||||
let remote_num_locking = en.get_key_state(enigo::Key::NumLock);
|
|
||||||
|
|
||||||
let need_click_capslock = is_not_same_status(client_caps_locking, remote_caps_locking);
|
|
||||||
let need_click_numlock = is_not_same_status(client_num_locking, remote_num_locking);
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
let disable_numlock = false;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
let disable_numlock = is_numlock_disabled(key_event);
|
|
||||||
|
|
||||||
if need_click_capslock {
|
|
||||||
click_capslock(&mut en);
|
|
||||||
}
|
|
||||||
|
|
||||||
if need_click_numlock && !disable_numlock {
|
|
||||||
click_numlock(&mut en);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_keyboard_mode(evt: &KeyEvent) {
|
fn map_keyboard_mode(evt: &KeyEvent) {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
crate::platform::windows::try_change_desktop();
|
crate::platform::windows::try_change_desktop();
|
||||||
@ -1174,9 +1192,12 @@ pub fn handle_key_(evt: &KeyEvent) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if evt.down {
|
let lock_mode_handler = if evt.down {
|
||||||
sync_numlock_capslock_status(evt)
|
Some(LockModesHandler::new(&evt))
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
match evt.mode.unwrap() {
|
match evt.mode.unwrap() {
|
||||||
KeyboardMode::Map => {
|
KeyboardMode::Map => {
|
||||||
map_keyboard_mode(evt);
|
map_keyboard_mode(evt);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user