#1298: craft-keymap 9aaf9df (craft-libs#164 review fixes)

Keymap::catalog(), Platform's non-exhaustive match, and the web
platform from craft_keymap::egui::platform.
This commit is contained in:
aiongg committed 2026-10-20 16:07:19 +00:00
1 parent 691eb35a28
commit c464072ee7
6 files changed
+28 -33

No files matched your search

Generated
+1 -1
View File
@@ -832,7 +832,7 @@ source = "git+https://github.com/storytold/craft-libs?rev=82a24b006eefa036b43c09
[[package]]
name = "craft-keymap"
version = "0.1.0"
source = "git+https://github.com/aiongg/craft-libs?rev=1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305#1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305"
source = "git+https://github.com/aiongg/craft-libs?rev=9aaf9dfd3882c12b6aab5604cc2567fc3b64127b#9aaf9dfd3882c12b6aab5604cc2567fc3b64127b"
dependencies = [
"egui",
"serde",
+1 -1
View File
@@ -14,7 +14,7 @@ repository = "https://github.com/storytold/designcraft"
# Shared writer; the immutable revision must be published before this consumer.
craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "c3487320b2d1de657b860b3c8abb44e1f2b32bd8", version = "=0.1.0", default-features = false }
# Shared keyboard bindings: chords, overrides, conflicts, egui dispatch.
craft-keymap = { git = "https://github.com/aiongg/craft-libs", rev = "1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305", version = "=0.1.0", features = ["egui"] }
craft-keymap = { git = "https://github.com/aiongg/craft-libs", rev = "9aaf9dfd3882c12b6aab5604cc2567fc3b64127b", version = "=0.1.0", features = ["egui"] }
# internal
designcraft-geom = { path = "crates/geom" }
designcraft-color = { path = "crates/color" }
+1 -1
View File
@@ -296,7 +296,7 @@ fn keyboard_shortcuts(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
// UI commands, the panels and the tools.
let mut rows: Vec<(String, String, String)> = app
.keymap
.catalogue()
.catalog()
.iter()
.filter(|b| {
let ui_command = crate::menus::UI_COMMANDS.iter().any(|c| c.0 == b.command.id);
+23 -28
View File
@@ -1,4 +1,4 @@
//! Keyboard shortcuts on `craft-keymap`: the catalogue (UI commands, engine commands, panels and
//! Keyboard shortcuts on `craft-keymap`: the catalog (UI commands, engine commands, panels and
//! tools with their default keys and menu paths), shortcut text, and the edits that
//! `window.setShortcut`, the Keyboard Shortcuts dialog and the shortcut-set importer make.
@@ -89,8 +89,8 @@ pub fn command_ref(id: &str, params: &Value) -> CommandRef {
}
}
/// The browser's operating system as [`note_os`] recorded it, by [`platform_code`]; 0 before the
/// first frame.
/// The browser's operating system as [`note_platform`] recorded it, by [`platform_code`]; 0
/// before the first frame.
static WEB_PLATFORM: AtomicU8 = AtomicU8::new(0);
fn platform_code(p: Platform) -> u8 {
@@ -98,6 +98,7 @@ fn platform_code(p: Platform) -> u8 {
Platform::Mac => 1,
Platform::Windows => 2,
Platform::Linux => 3,
_ => 0,
}
}
@@ -115,21 +116,10 @@ pub fn platform() -> Platform {
}
}
/// The platform for an operating system egui reports (on the web, guessed from the browser's user
/// agent). An iPad with a keyboard has ⌘ as on a Mac.
pub fn platform_of(os: egui::os::OperatingSystem) -> Platform {
use egui::os::OperatingSystem as Os;
match os {
Os::Mac | Os::IOS => Platform::Mac,
Os::Windows => Platform::Windows,
Os::Nix | Os::Android | Os::Unknown => Platform::Linux,
}
}
/// Records the operating system egui reports, which the web build reads from the browser.
pub fn note_os(os: egui::os::OperatingSystem) {
/// Records the platform egui reports, which the web build reads from the browser's user agent.
pub fn note_platform(ctx: &egui::Context) {
if cfg!(target_arch = "wasm32") {
WEB_PLATFORM.store(platform_code(platform_of(os)), Ordering::Relaxed);
WEB_PLATFORM.store(platform_code(craft_keymap::egui::platform(ctx)), Ordering::Relaxed);
}
}
@@ -141,7 +131,7 @@ pub fn new_keymap(overrides: Overrides) -> Keymap {
/// The keymap for `platform`: the system's own chords are reserved, so neither a user edit nor an
/// imported set can take them.
pub fn keymap_for(platform: Platform, overrides: Overrides) -> Keymap {
Keymap::new(catalogue().to_vec(), Scopes::new().with_context(TEXT_CONTEXT), platform)
Keymap::new(catalog().to_vec(), Scopes::new().with_context(TEXT_CONTEXT), platform)
.with_reserved(craft_keymap::reserved::system(platform))
.with_overrides(overrides)
}
@@ -149,12 +139,12 @@ pub fn keymap_for(platform: Platform, overrides: Overrides) -> Keymap {
/// Every bindable command, in dispatch order: where two share keys the earlier one runs. UI
/// commands come first (⌘N is the New Document dialog, not a bare `file.new`), then engine
/// commands, panels and tools.
pub fn catalogue() -> &'static [Bindable] {
static CATALOGUE: OnceLock<Vec<Bindable>> = OnceLock::new();
CATALOGUE.get_or_init(build_catalogue)
pub fn catalog() -> &'static [Bindable] {
static CATALOG: OnceLock<Vec<Bindable>> = OnceLock::new();
CATALOG.get_or_init(build_catalog)
}
fn build_catalogue() -> Vec<Bindable> {
fn build_catalog() -> Vec<Bindable> {
let paths = menu_paths();
// An engine command's own menu placement counts only where no menu row stands: a row there
// runs a UI command in its place (File › Save is the Save dialog when needed), and two
@@ -334,7 +324,7 @@ mod tests {
for p in PLATFORMS {
let km = keymap_for(p, Overrides::new());
let reserved: Vec<String> = km
.catalogue()
.catalog()
.iter()
.flat_map(|b| km.default_bindings(&b.command).into_iter().map(move |d| (b.command.key(), d)))
.filter(|(_, d)| km.is_reserved(&d.trigger.chord))
@@ -349,7 +339,7 @@ mod tests {
match p {
Platform::Mac => "Cmd+Tab",
Platform::Windows => "Alt+F4",
Platform::Linux => "Cmd+Alt+F2",
_ => "Cmd+Alt+F2",
}
}
@@ -379,11 +369,16 @@ mod tests {
assert_eq!(menus::shortcut_of(&app, "app.palette").as_deref(), Some("Cmd+Enter"));
}
/// The web build follows the operating system in the browser's user agent.
/// The web build follows the operating system in the browser's user agent; an iPad counts as a
/// Mac.
#[test]
fn browser_user_agent_picks_the_platform() {
use egui::os::OperatingSystem as Os;
let of = |ua: &str| platform_of(Os::from_user_agent(ua));
let ctx = egui::Context::default();
let of = |ua: &str| {
ctx.set_os(Os::from_user_agent(ua));
craft_keymap::egui::platform(&ctx)
};
let mac = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15";
let ipad = "Mozilla/5.0 (iPad; CPU OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1";
let windows = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
@@ -394,10 +389,10 @@ mod tests {
assert_eq!(of(windows), Platform::Windows);
assert_eq!(of(linux), Platform::Linux);
assert_eq!(of(android), Platform::Linux);
assert_eq!(platform_of(Os::Unknown), Platform::Linux);
// Native builds keep their own platform whatever egui reports.
if !cfg!(target_arch = "wasm32") {
note_os(Os::Mac);
ctx.set_os(Os::Mac);
note_platform(&ctx);
assert_eq!(platform(), Platform::current());
}
}
+1 -1
View File
@@ -1149,7 +1149,7 @@ impl DesignApp {
if self.egui_ctx.is_none() {
self.egui_ctx = Some(ctx.clone());
}
keys::note_os(ctx.os());
keys::note_platform(ctx);
self.sync_keymap();
self.window_maximized = ctx.input(|i| i.viewport().maximized.unwrap_or(false));
if !self.color_applied {
+1 -1
View File
@@ -2168,7 +2168,7 @@ pub fn tool_shortcut_label(app: &DesignApp, tool: &str) -> Option<String> {
/// commands come first: where one shares keys with an engine command (⌘N, ⌘O…) it's the one
/// with the dialog.
pub fn effective_shortcuts(app: &DesignApp) -> Vec<(String, String)> {
app.keymap.catalogue().iter().filter_map(|b| crate::keys::shortcut(&app.keymap, &b.command).map(|s| (b.command.key(), s))).collect()
app.keymap.catalog().iter().filter_map(|b| crate::keys::shortcut(&app.keymap, &b.command).map(|s| (b.command.key(), s))).collect()
}
/// A shortcut as written in this app ("Cmd+Alt+Shift+K") from a key press.