| author | |
| committer | |
| log | 5df173732775356dc2a04025c303d4e6c23890f9 |
| tree | 62d42afc20dc0fd6da58c369013df57a740b7e68 |
| parent | f837389ba02268ce5ee180e09bba96a337be406b |
| signature | Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU |
Chrome, Firefox and Safari keep Ctrl/⌘ with N, T and W for their own
windows and tabs whatever a page asks, so on the web New Page is
Ctrl+Alt+N (OneNote 2010's other New Page chord) and New Section
Ctrl+Alt+T, ⌘⌥ on a Mac, in the menus, the palette and Keyboard
options. The desktop keeps Ctrl+N and Ctrl+T. A Mac reports ⌘⌥ with a
letter as the dead key Option makes, so the glue names it by its key.
Assisted-by: claude-opus-5.54 files changed, 26 insertions(+), 6 deletions(-)
arc/platforms.md+2-1| ... | ... | @@ -174,7 +174,8 @@ keyboard, the toolbar and the macOS menu bar all run commands from it. |
| 174 | 174 | it is uncertain, as one whose answer was lost, and it goes again on top of another app's |
| 175 | 175 | write. The sync popup says the folder isn't locked. |
| 176 | 176 | - Menus are the kit's own, as on Linux, with the PC's chords and ⌘ for Ctrl on a Mac; the |
| 177 | browser keeps its own window and tab chords. Dialogs are the browser's; Insert, and Open | |
| 177 | browser keeps its own window and tab chords, so New Page and New Section add Alt to | |
| 178 | theirs. Dialogs are the browser's; Insert, and Open | |
| 178 | 179 | without a folder to give, ask for files to copy in; printing downloads the PDF. Servers and |
| 179 | 180 | recording are still to come. |
| 180 | 181 | - Spelling is Hunspell's dictionaries through `spellbook`, each fetched beside the module the |
crates/snowbound/src/commands.rs+13| ... | ... | @@ -622,9 +622,22 @@ pub fn command(id: Id) -> &'static Command { |
| 622 | 622 | .expect("Every command has a row") |
| 623 | 623 | } |
| 624 | 624 | |
| 625 | /// Commands whose chords the browser keeps for itself (Chrome, Firefox and Safari never pass | |
| 626 | /// a page Ctrl or ⌘ with N, T or W), and theirs there: Alt joins them, as Ctrl+Alt+N is | |
| 627 | /// OneNote 2010's other New Page. | |
| 628 | #[cfg(target_arch = "wasm32")] | |
| 629 | const BROWSER: [(Id, &[Chord]); 2] = [ | |
| 630 | (Id::NewSection, &[cmd('t').option()]), | |
| 631 | (Id::NewPage, &[cmd('n').option()]), | |
| 632 | ]; | |
| 633 | ||
| 625 | 634 | impl Command { |
| 626 | 635 | /// The table's chords on `platform`, which the user's may replace. |
| 627 | 636 | pub fn chords(&self, platform: Platform) -> &'static [Chord] { |
| 637 | #[cfg(target_arch = "wasm32")] | |
| 638 | if let Some((_, chords)) = BROWSER.iter().find(|(id, _)| *id == self.id) { | |
| 639 | return chords; | |
| 640 | } | |
| 628 | 641 | match platform { |
| 629 | 642 | Platform::MacOs => self.mac, |
| 630 | 643 | Platform::Gtk | Platform::Windows => self.pc, |
crates/snowbound/src/web.rs+2-1| ... | ... | @@ -1050,7 +1050,8 @@ fn queue(input: Input) { |
| 1050 | 1050 | #[wasm_bindgen] |
| 1051 | 1051 | pub fn takes(key: &str, held: u8) -> bool { |
| 1052 | 1052 | let command = held & if MAC.get() { 8 } else { 2 } != 0; |
| 1053 | if !command { | |
| 1053 | // The browser's own chords take Ctrl or ⌘ without Alt (see `commands::BROWSER`). | |
| 1054 | if !command || held & 4 != 0 { | |
| 1054 | 1055 | return true; |
| 1055 | 1056 | } |
| 1056 | 1057 | !matches!( |
crates/snowbound/web/glue.js+9-4| ... | ... | @@ -597,13 +597,18 @@ export function attach(module) { |
| 597 | 597 | ); |
| 598 | 598 | |
| 599 | 599 | input.addEventListener("keydown", (event) => { |
| 600 | if (event.isComposing || ["Process", "Dead", "Unidentified"].includes(event.key)) return; | |
| 600 | // A Mac reports ⌘⌥N as Option makes N (a dead key), where chords name the key itself. | |
| 601 | const key = | |
| 602 | event.metaKey && event.altKey && /^(Key[A-Z]|Digit\d)$/.test(event.code) | |
| 603 | ? event.code.slice(-1).toLowerCase() | |
| 604 | : event.key; | |
| 605 | if (event.isComposing || ["Process", "Dead", "Unidentified"].includes(key)) return; | |
| 601 | 606 | const bits = modifiers(event); |
| 602 | if (!wasm.takes(event.key, bits)) return; | |
| 607 | if (!wasm.takes(key, bits)) return; | |
| 603 | 608 | event.preventDefault(); |
| 604 | 609 | const shortcut = event.ctrlKey || event.metaKey; |
| 605 | const text = [...event.key].length === 1 && !shortcut ? event.key : undefined; | |
| 606 | wasm.key(event.key, text, bits); | |
| 610 | const text = [...key].length === 1 && !shortcut ? key : undefined; | |
| 611 | wasm.key(key, text, bits); | |
| 607 | 612 | }); |
| 608 | 613 | input.addEventListener("keyup", (event) => wasm.modifiers(modifiers(event))); |
| 609 | 614 | input.addEventListener("compositionupdate", (event) => wasm.compose(event.data)); |