mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-10-23 20:21:24 +00:00
fix: distinguish AltGraph from ordinary Alt shortcuts
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
1 parent
f3ead7e09d
commit
558ca359b8
2 files changed
+51
-5
No files matched your search
@@ -150,10 +150,6 @@ pub fn match_normalized<'a>(key: &str, mods: &[Modifier], b: &'a Bindings) -> Op
|
||||
pub fn normalize_modifiers(alt: bool, ctrl: bool, shift: bool, command: bool) -> Vec<Modifier> {
|
||||
// iOS shares Apple's keyboard semantics with macOS — recording dialog
|
||||
// already treats iOS as `_isMac`, so the matcher must too.
|
||||
//
|
||||
// AltGr conflation: `get_modifiers_state` ORs Alt and AltGr, so an
|
||||
// AltGr+key press satisfies `Modifier::Alt`. Theoretical collision only;
|
||||
// fix at `get_modifiers_state` if a real bug surfaces.
|
||||
let mut v = Vec::new();
|
||||
if cfg!(any(target_os = "macos", target_os = "ios")) {
|
||||
if command { v.push(Modifier::Primary); }
|
||||
@@ -333,7 +329,28 @@ pub fn match_event(event: &rdev::Event) -> Option<String> {
|
||||
let (alt, ctrl, shift, command) =
|
||||
crate::keyboard::client::get_modifiers_state(false, false, false, false);
|
||||
let mods = normalize_modifiers(alt, ctrl, shift, command);
|
||||
match_normalized(&key_name, &mods, &bindings).map(str::to_owned)
|
||||
let action = match_normalized(&key_name, &mods, &bindings)?;
|
||||
// AltGraph is text input, not the ordinary Alt recorded in a shortcut.
|
||||
// Keep the shared modifier snapshot unchanged for remote key encoding.
|
||||
#[cfg(target_os = "windows")]
|
||||
if unsafe { super::IS_0X021D_DOWN }
|
||||
&& super::MODIFIERS_STATE.lock().unwrap().get(&rdev::Key::AltGr) == Some(&true)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
if super::MODIFIERS_STATE.lock().unwrap().get(&rdev::Key::AltGr) == Some(&true) {
|
||||
match crate::platform::linux::right_alt_is_level3_shift() {
|
||||
Ok(true) => return None,
|
||||
Ok(false) => {}
|
||||
Err(err) => {
|
||||
hbb_common::throttled_log!(std::time::Duration::from_secs(5), warn,
|
||||
"Cannot identify AltGraph for keyboard shortcuts: {}", err);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(action.to_owned())
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
|
||||
@@ -302,6 +302,35 @@ thread_local! {
|
||||
static DISPLAY: RefCell<*mut c_void> = RefCell::new(unsafe { XOpenDisplay(std::ptr::null())});
|
||||
}
|
||||
|
||||
pub fn right_alt_is_level3_shift() -> ResultType<bool> {
|
||||
use hbb_common::x11::{keysym, xlib};
|
||||
const XKB_USE_CORE_KBD: c_uint = 0x0100;
|
||||
// A fresh connection avoids Xlib's stale keymap cache after a layout switch.
|
||||
// This query runs only for a matched chord with physical Right Alt held.
|
||||
let display = unsafe { xlib::XOpenDisplay(std::ptr::null()) };
|
||||
if display.is_null() {
|
||||
bail!("X display unavailable");
|
||||
}
|
||||
let result = (|| {
|
||||
let code = rdev::linux_keycode_from_key(rdev::Key::AltGr)
|
||||
.ok_or_else(|| anyhow!("Right Alt has no X keycode"))?;
|
||||
let mut state: xlib::XkbStateRec = unsafe { std::mem::zeroed() };
|
||||
let status = unsafe { xlib::XkbGetState(display, XKB_USE_CORE_KBD, &mut state) };
|
||||
if status != c_int::from(xlib::Success) {
|
||||
bail!("XkbGetState failed: {}", status);
|
||||
}
|
||||
let symbol = unsafe {
|
||||
xlib::XkbKeycodeToKeysym(display, code as _, state.group.into(), 0)
|
||||
};
|
||||
// Physical Right Alt is ordinary Alt on layouts such as US English.
|
||||
Ok(matches!(symbol as u32, keysym::XK_ISO_Level3_Shift
|
||||
| keysym::XK_ISO_Level3_Latch | keysym::XK_ISO_Level3_Lock
|
||||
| keysym::XK_Mode_switch))
|
||||
})();
|
||||
unsafe { xlib::XCloseDisplay(display) };
|
||||
result
|
||||
}
|
||||
|
||||
// X11 error event structure for the custom error handler.
|
||||
// See: https://www.x.org/releases/current/doc/libX11/libX11/libX11.html#Using-the-Default-Error-Handlers
|
||||
#[repr(C)]
|
||||
|
||||
Reference in new issue
Block a user