mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-28 04:26:51 -06:00
shortcuts: keep Cmd+Ctrl apart from Cmd on macOS; detect the Mac at runtime
On macOS a held Cmd made the Ctrl state ignored, so Cmd+Ctrl+X ran Cut instead of Cut Clip Gain. Ask egui for the OS so the web build in a Mac browser uses Mac modifiers too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,14 +41,11 @@ pub fn parse(s: &str) -> Option<(Modifiers, Key)> {
|
||||
key.map(|k| (m, k))
|
||||
}
|
||||
|
||||
/// Cmd and Ctrl are separate keys only on macOS.
|
||||
const MAC: bool = cfg!(target_os = "macos");
|
||||
|
||||
/// Whether the held modifiers `got` fire a shortcut that asks for `want`.
|
||||
fn mods_match(want: Modifiers, got: Modifiers, mac: bool) -> bool {
|
||||
// Off macOS egui reports Ctrl as both `ctrl` and `command`: Ctrl is the shortcut's Cmd, and a shortcut's
|
||||
// Ctrl (the Mac Control key) has no key of its own there, so Ctrl+X is Cut, not Cmd+Ctrl+X.
|
||||
let ctrl = if mac { want.ctrl == got.ctrl || got.mac_cmd } else { !want.ctrl };
|
||||
let ctrl = if mac { want.ctrl == got.ctrl } else { !want.ctrl };
|
||||
want.command == got.command && want.shift == got.shift && want.alt == got.alt && ctrl
|
||||
}
|
||||
|
||||
@@ -70,12 +67,14 @@ pub fn handle(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
// Cmd and Ctrl are separate keys only on macOS (asked at runtime so the web build in a Mac browser agrees).
|
||||
let mac = ctx.os() == egui::os::OperatingSystem::Mac;
|
||||
for (key, mods) in events {
|
||||
if fixed(app, key, mods) {
|
||||
if fixed(app, key, mods, mac) {
|
||||
continue;
|
||||
}
|
||||
let hit =
|
||||
soundcraft_engine::command_specs().iter().find(|c| c.shortcut.and_then(parse).is_some_and(|(m, k)| k == key && mods_match(m, mods, MAC)));
|
||||
soundcraft_engine::command_specs().iter().find(|c| c.shortcut.and_then(parse).is_some_and(|(m, k)| k == key && mods_match(m, mods, mac)));
|
||||
if let Some(c) = hit {
|
||||
let id = c.id;
|
||||
if crate::menus::invoke_shortcut_dialog(app, id) {
|
||||
@@ -87,7 +86,7 @@ pub fn handle(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
}
|
||||
|
||||
/// Keys with context-dependent meaning. Returns true when handled.
|
||||
fn fixed(app: &mut SoundApp, key: Key, m: Modifiers) -> bool {
|
||||
fn fixed(app: &mut SoundApp, key: Key, m: Modifiers, mac: bool) -> bool {
|
||||
let plain = !m.command && !m.alt && !m.ctrl && !m.shift;
|
||||
match key {
|
||||
Key::Space if !m.command && !m.alt => {
|
||||
@@ -99,7 +98,7 @@ fn fixed(app: &mut SoundApp, key: Key, m: Modifiers) -> bool {
|
||||
let _ = app.run("transport.record", json!({}));
|
||||
true
|
||||
}
|
||||
Key::S if search_chord(m, MAC) => {
|
||||
Key::S if search_chord(m, mac) => {
|
||||
let _ = app.run("window.search", json!({}));
|
||||
true
|
||||
}
|
||||
@@ -269,6 +268,7 @@ mod tests {
|
||||
assert!(mods_match(want("Cmd+S"), MAC_CMD, true));
|
||||
assert!(!mods_match(want("Cmd+S"), Modifiers::CTRL, true));
|
||||
assert!(mods_match(want("Cmd+Ctrl+X"), Modifiers { ctrl: true, ..MAC_CMD }, true));
|
||||
assert!(!mods_match(want("Cmd+X"), Modifiers { ctrl: true, ..MAC_CMD }, true), "Cmd+Ctrl+X is not Cut");
|
||||
assert!(!search_chord(MAC_CMD, true));
|
||||
assert!(search_chord(Modifiers { ctrl: true, ..MAC_CMD }, true));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user