mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-01 16:24:51 +00:00
keymap: learn nothing from presses while right Alt is held
egui-winit reports AltGr with neither Ctrl nor Alt, so AltGr text read as plain typing: German AltGr+M (µ) marked the layout as not Latin and Ctrl+Z resolved by position as Ctrl+Y. µ, ª and º no longer count as a sign of another script.
This commit is contained in:
1 parent
9c75eda598
commit
1a0e7e7bbf
4 files changed
+37
-3
No files matched your search
@@ -199,6 +199,9 @@ pub struct Dispatcher {
|
||||
/// web build sends them.
|
||||
text_first: bool,
|
||||
layout: Layout,
|
||||
/// Whether right Alt is held. egui-winit reports AltGr with neither Ctrl nor Alt, so its
|
||||
/// presses would otherwise teach the layout as plain ones.
|
||||
right_alt: bool,
|
||||
}
|
||||
|
||||
/// eframe's web build sends a press's Text event first when no text field has focus.
|
||||
@@ -206,7 +209,7 @@ const TEXT_FIRST: bool = cfg!(target_arch = "wasm32");
|
||||
|
||||
impl Default for Dispatcher {
|
||||
fn default() -> Dispatcher {
|
||||
Dispatcher { last: None, repeat: false, clipboard: false, text_first: TEXT_FIRST, layout: Layout::new() }
|
||||
Dispatcher { last: None, repeat: false, clipboard: false, text_first: TEXT_FIRST, layout: Layout::new(), right_alt: false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,6 +353,14 @@ impl Dispatcher {
|
||||
/// Teaches the layout what this frame's presses typed.
|
||||
fn learn(&mut self, events: &[Event], text_of: &[Option<usize>], platform: Platform) {
|
||||
for (event, text) in events.iter().zip(text_of) {
|
||||
match event {
|
||||
Event::Key { physical_key: Some(EguiKey::AltRight), pressed, .. } => self.right_alt = *pressed,
|
||||
Event::WindowFocused(false) => self.right_alt = false,
|
||||
_ => {}
|
||||
}
|
||||
if self.right_alt {
|
||||
continue;
|
||||
}
|
||||
let Some(Event::Text(text)) = text.and_then(|j| events.get(j)) else { continue };
|
||||
if let Some(KeyInput { mods, physical: Some(physical), .. }) = KeyInput::from_egui(event, platform) {
|
||||
self.layout.observe(physical, mods, text);
|
||||
|
||||
@@ -179,7 +179,8 @@ impl Layout {
|
||||
return;
|
||||
}
|
||||
if physical.is_letter() {
|
||||
if c.is_alphabetic() {
|
||||
// ª, µ and º are Latin-1 symbols on Latin layouts, no sign of another script.
|
||||
if c.is_alphabetic() && !matches!(c, 'ª' | 'µ' | 'º') {
|
||||
self.seen_latin = Some(is_latin_letter(c));
|
||||
}
|
||||
if !c.is_control() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![cfg(feature = "egui")]
|
||||
|
||||
use craft_keymap::egui::{Dispatcher, Hit, matches, platform};
|
||||
use craft_keymap::{Active, Bindable, Binding, Chord, CommandRef, Key, Keymap, Kind, Layout, Mods, Platform, Scope, Scopes, Trigger};
|
||||
use craft_keymap::{Active, Bindable, Binding, Chord, CommandRef, Key, KeyInput, Keymap, Kind, Layout, Mods, Platform, Scope, Scopes, Trigger};
|
||||
use egui::{Event, InputState, Key as EguiKey, Modifiers};
|
||||
|
||||
fn chord(text: &str) -> Chord {
|
||||
@@ -482,6 +482,26 @@ fn the_dispatcher_reads_presses_by_the_layout() {
|
||||
let (ran, _) = run(&mut d, &km, &Active::NONE, frame(2.0, ctrl_shift, vec![at(EguiKey::Slash, EguiKey::Num7, ctrl_shift)]));
|
||||
assert_eq!(ran, ["edit.comment"]);
|
||||
|
||||
// German on egui-winit: AltGr+M types µ and AltGr+] types ~ with no modifiers reported, so
|
||||
// presses while right Alt is held teach nothing and Ctrl+Z stays Ctrl+Z on the Y position.
|
||||
let mut d = Dispatcher::new();
|
||||
let typed = vec![at(EguiKey::Plus, EguiKey::CloseBracket, Modifiers::NONE), Event::Text("+".into())];
|
||||
run(&mut d, &km, &Active::NONE, frame(1.0, Modifiers::NONE, typed));
|
||||
let right_alt =
|
||||
|pressed| Event::Key { key: EguiKey::AltRight, physical_key: Some(EguiKey::AltRight), pressed, repeat: false, modifiers: Modifiers::NONE };
|
||||
run(&mut d, &km, &Active::NONE, frame(2.0, Modifiers::NONE, vec![right_alt(true)]));
|
||||
let alt_graph = vec![
|
||||
at(EguiKey::M, EguiKey::M, Modifiers::NONE),
|
||||
Event::Text("µ".into()),
|
||||
at(EguiKey::CloseBracket, EguiKey::CloseBracket, Modifiers::NONE),
|
||||
Event::Text("~".into()),
|
||||
right_alt(false),
|
||||
];
|
||||
run(&mut d, &km, &Active::NONE, frame(3.0, Modifiers::NONE, alt_graph));
|
||||
assert!(d.layout().is_latin());
|
||||
assert_eq!(d.layout().char_at(Key::CloseBracket), Some('+'));
|
||||
assert_eq!(d.layout().resolve(&KeyInput::new(Mods::CMD).with_typed(Key::Z).with_physical(Key::Y)), Some(chord("Cmd+Z")));
|
||||
|
||||
// A layout the platform reports applies from the first press.
|
||||
let mut d = Dispatcher::new().with_layout(Layout::new().with_latin(false));
|
||||
let (ran, _) = run(&mut d, &km, &Active::NONE, frame(1.0, ctrl_shift, vec![at(EguiKey::CloseBracket, EguiKey::D, ctrl_shift)]));
|
||||
|
||||
@@ -127,6 +127,8 @@ fn typing_decides_whether_the_layout_is_latin() {
|
||||
assert!(!layout.is_latin(), "a command chord teaches nothing");
|
||||
layout.observe(Key::S, Mods::NONE, "š");
|
||||
assert!(layout.is_latin(), "Latin letters beyond ASCII count as Latin");
|
||||
layout.observe(Key::M, Mods::NONE, "µ");
|
||||
assert!(layout.is_latin(), "Latin-1 symbols that count as letters say nothing");
|
||||
|
||||
// What the platform reports wins.
|
||||
let mut reported = Layout::new().with_latin(false);
|
||||
|
||||
Reference in new issue
Block a user