keymap: a layout switch forgets what letter positions typed, and Layout::forget_letters does so on request

This commit is contained in:
aiongg committed 2026-10-23 08:03:27 +00:00
1 parent 5050d5dead
commit 135981286f
3 files changed
+41 -3

No files matched your search

+3 -1
View File
@@ -99,7 +99,9 @@ macOS it folds into `cmd` (`Chord::effective`).
5. With Shift held on a Latin layout, a press that egui reports as the letter at its own
position, because the character typed has no key (Dvorak's ⇧, types `<`), runs nothing when
that position has been seen typing something other than its letter: once a `,` has been
typed, Ctrl+Shift+, never runs Ctrl+Shift+W.
typed, Ctrl+Shift+, never runs Ctrl+Shift+W. A change in the reported Latin status clears
what the positions typed; an app that learns of a layout switch itself calls
`Layout::forget_letters`.
6. Labels show letters and digits by name, and a punctuation key as the character the layout
types at its position when that character has no key of its own (`Ctrl+Ü` for Ctrl+[ on
German).
+15 -2
View File
@@ -22,7 +22,8 @@
//! that has no key (Dvorak's ⇧, types `<`) as the key's position, W. With Shift held on a
//! Latin layout, such a press at a letter position that has been seen typing something other
//! than its letter resolves to nothing, so Ctrl+Shift+, never runs Ctrl+Shift+W once a `,`
//! has been typed.
//! has been typed. A change in the reported Latin status, or [`Layout::forget_letters`],
//! clears what the positions typed.
//! 6. **Labels** show letters and digits by name, and a punctuation key as the character the
//! layout types at its position when that character has no key of its own: Ctrl+[ is `Ctrl+Ü`
//! on German and `Ctrl+Х` on Russian.
@@ -143,11 +144,23 @@ impl Layout {
}
/// Whether the layout is Latin, as the platform reports it; `None` when it cannot tell, so
/// that typing decides. Call again when the user switches layouts.
/// that typing decides. Call again when the user switches layouts. A report that differs
/// from the last one means another layout, so what letter positions typed is forgotten
/// ([`forget_letters`](Self::forget_letters)).
pub fn set_latin(&mut self, latin: Option<bool>) {
if latin != self.reported_latin {
self.forget_letters();
}
self.reported_latin = latin;
}
/// Forgets what each letter position has been seen typing, for an app that learns of a
/// layout switch the platform does not report: until typing shows the new layout, Shift
/// presses at letter positions resolve as their letters again (rule 5).
pub fn forget_letters(&mut self) {
self.letters.clear();
}
/// Whether letters are read as typed (rule 1): what the platform reported, else what a letter
/// key typed last, else true.
pub fn is_latin(&self) -> bool {
+23
View File
@@ -182,6 +182,29 @@ fn dvorak_shift_punctuation_never_runs_its_position() {
assert_eq!(qwerty.resolve(&at("Cmd+Shift+E", Key::E)), Some(chord("Cmd+Shift+E")));
}
#[test]
fn a_layout_switch_forgets_what_letter_positions_typed() {
// On Dvorak the W position types `,`; after a switch to QWERTY, Ctrl+Shift+W is W again.
let ctrl_shift_w = at("Cmd+Shift+W", Key::W);
let mut layout = Layout::new().with_latin(true);
layout.observe(Key::W, Mods::NONE, ",");
assert_eq!(layout.resolve(&ctrl_shift_w), None);
layout.set_latin(Some(true));
assert_eq!(layout.resolve(&ctrl_shift_w), None, "the same report is the same layout");
// Dvorak, then Russian, then QWERTY, as the platform reports them.
layout.set_latin(Some(false));
layout.set_latin(Some(true));
assert_eq!(layout.resolve(&ctrl_shift_w), Some(chord("Cmd+Shift+W")));
// An app that learns of a switch itself.
let mut unreported = Layout::new();
unreported.observe(Key::W, Mods::NONE, ",");
assert_eq!(unreported.resolve(&ctrl_shift_w), None);
unreported.forget_letters();
assert_eq!(unreported.resolve(&ctrl_shift_w), Some(chord("Cmd+Shift+W")));
}
#[test]
fn labels_show_the_layouts_own_punctuation() {
let mut german = Layout::new().with_char(Key::OpenBracket, 'ü').with_char(Key::Slash, '-').with_char(Key::CloseBracket, '+');