mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 13:47:21 -06:00
Shortcuts: a text with no key press of its own leaves the next keystroke's press to that keystroke's text
A text-only event right before a desktop keystroke in the same frame ([text, key, text]) took the key press as the press after it, which left the keystroke's own text with no key. A text now takes the press after it only when every later text in the same run of alternating texts and presses has a press after it too, as in the web build's [text, key] order; otherwise the press goes to the text after it.
This commit is contained in:
@@ -848,9 +848,24 @@ fn latin(text: &str, physical: Option<Key>) -> String {
|
||||
|
||||
/// For each event, the index of the key press that typed it when it is text: the press right
|
||||
/// before it (egui-winit) unless an earlier text took that press, or else the press right after it
|
||||
/// (eframe's web build with no text field focused). Each press types at most one text.
|
||||
/// (eframe's web build with no text field focused). Each press types at most one text. A text
|
||||
/// takes the press after it only when every later text in the same run of alternating texts and
|
||||
/// presses has a press after it too; otherwise the text after that press takes it as the press
|
||||
/// before it, and this text has none.
|
||||
fn typing_presses(events: &[egui::Event]) -> Vec<Option<usize>> {
|
||||
let is_press = |k: usize| matches!(events.get(k), Some(egui::Event::Key { pressed: true, .. }));
|
||||
let is_text = |k: usize| matches!(events.get(k), Some(egui::Event::Text(_)));
|
||||
// Whether the run of alternating texts and presses that starts with the text at `j` ends
|
||||
// with a press.
|
||||
let ends_with_press = |mut j: usize| loop {
|
||||
if !is_press(j + 1) {
|
||||
break false;
|
||||
}
|
||||
if !is_text(j + 2) {
|
||||
break true;
|
||||
}
|
||||
j += 2;
|
||||
};
|
||||
let mut taken = None;
|
||||
events
|
||||
.iter()
|
||||
@@ -860,7 +875,7 @@ fn typing_presses(events: &[egui::Event]) -> Vec<Option<usize>> {
|
||||
return None;
|
||||
}
|
||||
let before = j.checked_sub(1).filter(|&k| is_press(k) && taken != Some(k));
|
||||
let by = before.or_else(|| Some(j + 1).filter(|&k| is_press(k)));
|
||||
let by = before.or_else(|| ends_with_press(j).then_some(j + 1));
|
||||
taken = by.or(taken);
|
||||
by
|
||||
})
|
||||
|
||||
@@ -1486,6 +1486,11 @@ fn one_key_shortcuts_use_the_key_of_the_same_keystroke_in_either_order() {
|
||||
app.select_tool("pen");
|
||||
frame(&mut app, vec![press(Key::P), text("з"), press(Key::V), text("м")]);
|
||||
assert_eq!(app.session.tool_id(), "selection", "key before its text");
|
||||
// A text with no key press of its own right before a desktop keystroke leaves that press to
|
||||
// the keystroke's text.
|
||||
assert_eq!(typing_presses(&[text("p"), press(Key::V), text("м")]), [None, None, Some(1)]);
|
||||
frame(&mut app, vec![text("p"), press(Key::V), text("м")]);
|
||||
assert_eq!(app.session.tool_id(), "selection", "the text after the key uses it");
|
||||
let names = |events: &[egui::Event]| -> Vec<String> {
|
||||
shortcut_presses(events, Modifiers::NONE).into_iter().filter_map(|(n, _)| n.into_iter().next()).collect()
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user