Fail CI when a key is bound but not in the gesture book, or listed but not bound

The gesture book is generated from GESTURE tags, so it could not describe a
gesture nobody tagged, but nothing made anyone tag one. The arrow keys, Enter,
P, X, U, Delete, F1 and F2 all worked in the grid with no line in the help
sheet, and a tag could name a key whose handler had gone.

Key handlers now compare one canonical string, Keys.chord(event) == "Ctrl+Z",
instead of reading event.text and the modifiers themselves. keys.slint folds
the key and its modifiers into that spelling, so the literal in the handler is
the whole binding and the checker reads exactly what the handler dispatches
on. Each handler carries a KEYMAP comment naming the gesture-book section its
keys belong to, and a tag's keys field names its keys between backticks.
gestures-check now fails when a handler binds a key no tag in that section
names, when a tag names a key no handler there binds, when any .slint file
other than keys.slint reads event.text, when a compared literal is not
canonical, and when keys.slint's named keys drift from the Rust list.

Spellings are normalised in one place, chord.rs: Ctrl+z, Control+Z and
LeftArrow all mean what the handler's "Ctrl+Z" and "Left" mean. Shift and Alt
count only for letters and named keys, because on the French layout every
digit needs shift and a 6 has to be a 6 however it was typed.

A Rust keymap that both dispatched and was read by the generator was the
alternative. It would have moved the handlers' decisions away from the Slint
state they depend on, and a window that forgot to install it would have had
no working keys at all.

The keys that were already bound and undocumented are now tagged.
This commit is contained in:
2026-09-24 23:42:25 -04:00
parent 150e53e878
commit 9d1e31ffbb
15 changed files with 1696 additions and 258 deletions
+64 -8
View File
@@ -72,6 +72,14 @@ pub const GESTURES: &[Gesture] = &[
keys: "Ctrl+Shift+Z",
manual: "history-snapshots-presets",
},
Gesture {
title: "Remove a repair",
section: "Develop",
touch: "Tap it, then Delete Repair",
pointer: "Click it, then Delete Repair",
keys: "Delete or Backspace, while repairing",
manual: "",
},
Gesture {
title: "Copy the settings from this photograph",
section: "Develop",
@@ -141,7 +149,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Develop",
touch: "Tap a frame in the roll along the foot of the canvas",
pointer: "Click a frame in the roll",
keys: "Right arrow, D or space for the next; left arrow or A for the one before",
keys: "→, D or Space for the next; ← or A for the one before",
manual: "moving-between-photographs",
},
Gesture {
@@ -181,7 +189,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Develop",
touch: "Tap the ring at the head of its row",
pointer: "Click the ring at the head of its row",
keys: "H, for the selected layer history step, unlike holding \"Before\" — the layer really is off until it is switched back on.",
keys: "H, for the selected layer",
manual: "local-adjustments",
},
Gesture {
@@ -208,6 +216,14 @@ pub const GESTURES: &[Gesture] = &[
keys: "",
manual: "local-adjustments",
},
Gesture {
title: "Close what is open, or go back a step",
section: "Everywhere",
touch: "The system Back gesture, or the Back button",
pointer: "The Close or Back button on whatever is open",
keys: "Escape, or Back where the device has one",
manual: "",
},
Gesture {
title: "Pick a collection up to rearrange the tree",
section: "Collections sidebar",
@@ -237,7 +253,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Collections sidebar",
touch: "Hold the collection, then \"Rename\"",
pointer: "Double-click its name, or right-click it and choose \"Rename\"",
keys: "",
keys: "Escape while typing abandons the new name",
manual: "collections",
},
Gesture {
@@ -293,7 +309,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Library grid",
touch: "Press Done in the header",
pointer: "Press Done in the header",
keys: "Escape",
keys: "Escape, or Back; an open sheet closes first",
manual: "selecting-several",
},
Gesture {
@@ -309,7 +325,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Library grid",
touch: "While selecting, press \"Select to…\", then tap the last photograph of the run",
pointer: "Shift-click the last photograph of the run",
keys: "",
keys: "Shift with any key that walks the grid — Shift+←, Shift+→, Shift+↑, Shift+↓, Shift+Page Up, Shift+Page Down, Shift+Home, Shift+End",
manual: "selecting-several",
},
Gesture {
@@ -357,7 +373,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Library grid",
touch: "Tap a star chip in the filter bar",
pointer: "Click a star chip in the filter bar",
keys: "Hold F and tap a digit for exactly that many stars, or two digits for everything between them; tap F alone to show every rating again",
keys: "Hold F and tap a digit, 0–5, for exactly that many stars, or two digits for everything between them; tap F alone to show every rating again",
manual: "rating-and-flagging",
},
Gesture {
@@ -368,6 +384,46 @@ pub const GESTURES: &[Gesture] = &[
keys: "6 red, 7 yellow, 8 green, 9 blue, with the pointer over it or on the selection; the same key again takes the label off",
manual: "rating-and-flagging",
},
Gesture {
title: "Pick or reject a photograph",
section: "Library grid",
touch: "",
pointer: "",
keys: "P picks, X rejects and U takes the flag off, with the pointer over it or on the selection",
manual: "",
},
Gesture {
title: "Move photographs to the trash",
section: "Library grid",
touch: "Tap the bin at the start of a cell's stars",
pointer: "Hover the cell and click the bin before its stars",
keys: "Delete or Backspace, on the selection",
manual: "",
},
Gesture {
title: "Open this list",
section: "Library grid",
touch: "Press Help in the header",
pointer: "Press Help in the header",
keys: "F1",
manual: "",
},
Gesture {
title: "Rename the collection the grid is showing",
section: "Library grid",
touch: "Hold it in the sidebar, then \"Rename\"",
pointer: "Double-click it in the sidebar",
keys: "F2",
manual: "",
},
Gesture {
title: "Move through the grid",
section: "Library grid",
touch: "Scroll, and tap a photograph",
pointer: "Scroll, and click a photograph",
keys: "←, →, ↑ and ↓ move one photograph; Page Up and Page Down a screenful; Home and End to the first and the last",
manual: "",
},
Gesture {
title: "Resize the thumbnails",
section: "Library grid",
@@ -389,7 +445,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Library grid",
touch: "Tap it — a single tap, any length",
pointer: "Click it",
keys: "",
keys: "Enter, on the photograph the arrow keys have walked to",
manual: "developing-a-photograph",
},
Gesture {
@@ -397,7 +453,7 @@ pub const GESTURES: &[Gesture] = &[
section: "Library grid",
touch: "Tap a star on the cell",
pointer: "Hover the cell, then click a star",
keys: "0 to 5 with the pointer over it, or on the selection",
keys: "0–5 with the pointer over it, or on the selection",
manual: "rating-and-flagging",
},
Gesture {