Files
galaxy/app/src/terminal/meta_shortcuts.rs
T

73 lines
2.9 KiB
Rust

use galaxyui::keymap::Keystroke;
/// Whether this keystroke should dispatch an action in Warp despite the
/// [`galaxyui::event::Event::KeyDown::is_composing`] being true.
///
/// Generally, we ignore all `KeyDown` events if the `is_composing` field is true. However it's
/// possible to have keybinding conflicts between terminal apps which use the meta key and MacOS
/// "dead keys". Dead keys are used to add diacritical marks to other characters. They are
/// triggered by ⌥ and another letter. On the US layout, the dead keys are ⌥e, ⌥u, ⌥i, ⌥n, and ⌥`.
/// They are different for other layouts, e.g. the Croatian layout has ⌥k. Ideally, we could check
/// if a specific keystroke is a dead key. AFAICT the OS doesn't expose this, and it would be too
/// difficult to maintain a map of layouts to lists of dead keys. Therefore, this function just
/// checks if the keystroke is meta + one letter.
///
/// https://support.apple.com/guide/mac-help/enter-characters-with-accent-marks-on-mac-mh27474/mac#mchl45cdda7f
///
/// This function is intended to be used when handling [`galaxyui::event::Event::KeyDown`] when its
/// `is_composing` is true. Returning true _does not_ mean the keystroke is a dead key necessarily.
/// Interpreting it that way would result in false-positives. Rather, it means the app may dispatch
/// an action for the keystroke _despite_ the fact that `is_composing` is true.
/// Note that this is only relevant with [`crate::settings::ExtraMetaKeys`] enabled.
pub(super) fn handle_keystroke_despite_composing(keystroke: &Keystroke) -> bool {
// This conflict only occurs on MacOS.
if !cfg!(target_os = "macos") {
return false;
}
if keystroke.cmd || keystroke.ctrl || keystroke.shift || keystroke.alt || !keystroke.meta {
return false;
}
if keystroke.key.len() != 1 {
return false;
}
true
}
#[cfg(all(test, target_os = "macos"))]
mod tests {
use std::error;
use super::*;
#[test]
fn test_handle_keystroke_despite_composing() -> Result<(), Box<dyn error::Error>> {
assert!(handle_keystroke_despite_composing(&Keystroke::parse(
"meta-i"
)?));
assert!(handle_keystroke_despite_composing(&Keystroke::parse(
"meta-u"
)?));
assert!(handle_keystroke_despite_composing(&Keystroke::parse(
"meta-`"
)?));
assert!(handle_keystroke_despite_composing(&Keystroke::parse(
"meta-n"
)?));
assert!(handle_keystroke_despite_composing(&Keystroke::parse(
"meta-e"
)?));
assert!(!handle_keystroke_despite_composing(&Keystroke::parse(
"alt-i"
)?));
assert!(!handle_keystroke_despite_composing(&Keystroke::parse(
"ctrl-i"
)?));
assert!(!handle_keystroke_despite_composing(&Keystroke::parse(
"meta-shift-I"
)?));
Ok(())
}
}