Shortcuts: outside macOS Ctrl and Cmd are one key when checking who has a shortcut

One Ctrl press runs a Ctrl and a Cmd shortcut alike on Windows and Linux, so
two commands could hold Ctrl+K and Cmd+K and only the first would ever run.
same() now compares them as one key there; macOS keeps Control apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkJ8y75DE7yLZ7utxSRDeP
This commit is contained in:
ATARYS-LAB
2026-11-03 18:45:14 +01:00
co-authored by Claude Opus 5.5
parent d23c5f0182
commit cce67d27c7
+33 -7
View File
@@ -30,8 +30,17 @@ const FIXED: &[&str] = &["copyclip", "cutclip", "pasteclip", "copybase", "pasteb
/// The dialog name in `UiState::dialog`.
pub const DIALOG: &str = "shortcuts";
/// Whether two shortcuts are one key press. Outside macOS Ctrl is the command key, and one Ctrl
/// press runs a Ctrl and a Cmd shortcut alike, so they are compared as Cmd.
fn same(a: &KeyboardShortcut, b: &KeyboardShortcut) -> bool {
a.logical_key == b.logical_key && a.modifiers == b.modifiers
let pressed = |m: Modifiers| {
if !cfg!(target_os = "macos") && (m.ctrl || m.command || m.mac_cmd) {
Modifiers { ctrl: false, command: true, mac_cmd: false, ..m }
} else {
m
}
};
a.logical_key == b.logical_key && pressed(a.modifiers) == pressed(b.modifiers)
}
/// A registry shortcut string ("Cmd+Shift+G", "Alt+4", "F3") as a shortcut; `None` when empty or
@@ -521,16 +530,20 @@ mod tests {
fn control_and_command_control_shortcuts_keep_their_control() {
let mut user = UserKeys::new();
assert_eq!(assign(&mut user, "line", "Ctrl+K"), Ok(vec![]));
assert_eq!(assign(&mut user, "circle", "Cmd+Ctrl+K"), Ok(vec![]));
assert_eq!(user.get("line").map(String::as_str), Some("Ctrl+K"));
// Outside macOS both are one Ctrl press, so Circle takes it from Line.
let lost = if cfg!(target_os = "macos") { vec![] } else { vec!["line".to_string()] };
assert_eq!(assign(&mut user, "circle", "Cmd+Ctrl+K"), Ok(lost));
assert_eq!(user.get("circle").map(String::as_str), Some("Cmd+Ctrl+K"));
let eff = effective(&user);
let of = |id: &str| eff.iter().find(|(_, i)| i == id).map(|(s, _)| s.modifiers);
assert_eq!(of("line"), Some(Modifiers::CTRL));
assert_eq!(of("circle"), Some(Modifiers { ctrl: true, command: true, mac_cmd: true, ..Modifiers::NONE }));
// Command+Control+K is tried before Control+K, which it holds too.
let at = |id: &str| eff.iter().position(|(_, i)| i == id);
assert!(at("circle") < at("line"));
if cfg!(target_os = "macos") {
assert_eq!(user.get("line").map(String::as_str), Some("Ctrl+K"));
assert_eq!(of("line"), Some(Modifiers::CTRL));
// Command+Control+K is tried before Control+K, which it holds too.
let at = |id: &str| eff.iter().position(|(_, i)| i == id);
assert!(at("circle") < at("line"));
}
}
#[test]
@@ -549,6 +562,19 @@ mod tests {
assert_eq!(assign(&mut user, "line", "Cmd+8"), Ok(vec!["ui.toggle.quickcalc".to_string()]));
}
/// On Windows and Linux one Ctrl press runs a Ctrl and a Cmd shortcut alike, so they are one
/// key: giving it takes it from the command that had it, and preferences keep it once.
#[test]
#[cfg(not(target_os = "macos"))]
fn ctrl_and_cmd_are_one_key_outside_macos() {
let mut user = UserKeys::new();
assert_eq!(assign(&mut user, "line", "Ctrl+P"), Ok(vec!["plot".to_string()]));
assert_eq!(runs(&user, "Cmd+P").as_deref(), Some("line"));
assert_eq!(assign(&mut user, "circle", "Cmd+P"), Ok(vec!["line".to_string()]));
let user = from_prefs(&json!({"circle": "Cmd+K", "line": "Ctrl+K"}));
assert_eq!(user.values().filter(|k| !k.is_empty()).count(), 1, "{user:?}");
}
#[test]
fn a_new_shortcut_replaces_the_commands_own_and_clear_removes_it() {
let mut user = UserKeys::new();