mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 23:31:23 +00:00
Merge pull request #5587 from dotCooCoo/fix/backtick-text-pairing
Keyboard Shortcuts: the backtick key's label ignores the next key's text on the web
This commit is contained in:
@@ -274,19 +274,18 @@ pub fn chord_from_event(key: Key, m: Modifiers) -> Option<String> {
|
||||
|
||||
ui_mirror!(fn backtick_store() -> Option<String>);
|
||||
|
||||
/// Notes what the backtick key (left of 1) typed in `events`: the one-character text whose key, a
|
||||
/// press of it without modifiers, comes right before it (egui-winit) or, when no press comes
|
||||
/// before, right after it (eframe's web build with no text field focused). egui reports that key
|
||||
/// as [`Key::Backtick`] on layouts where it types a character egui has no key for, such as `"` on
|
||||
/// Turkish Q.
|
||||
/// Notes what the backtick key (left of 1) typed in `events`: the last one-character text that
|
||||
/// [`crate::shortcuts::typing_presses`] pairs with a press of that key without modifiers, whether
|
||||
/// the press comes before its text (egui-winit) or after it (eframe's web build with no text field
|
||||
/// focused). egui reports that key as [`Key::Backtick`] on layouts where it types a character egui
|
||||
/// has no key for, such as `"` on Turkish Q.
|
||||
pub(crate) fn note_backtick_text(events: &[egui::Event]) {
|
||||
let is_press = |e: Option<&egui::Event>| matches!(e, Some(egui::Event::Key { pressed: true, .. }));
|
||||
let is_backtick =
|
||||
|e: Option<&egui::Event>| matches!(e, Some(egui::Event::Key { key: Key::Backtick, pressed: true, modifiers, .. }) if modifiers.is_none());
|
||||
let typed = events.iter().enumerate().rev().find_map(|(j, e)| match e {
|
||||
egui::Event::Text(t) if t.chars().count() == 1 && !t.chars().any(char::is_whitespace) => {
|
||||
let before = j.checked_sub(1).and_then(|j| events.get(j));
|
||||
(is_backtick(before) || (!is_press(before) && is_backtick(events.get(j + 1)))).then(|| t.clone())
|
||||
let typed_by = crate::shortcuts::typing_presses(events);
|
||||
let typed = events.iter().zip(typed_by).rev().find_map(|(e, by)| match (e, by.and_then(|k| events.get(k))) {
|
||||
(egui::Event::Text(t), Some(egui::Event::Key { key: Key::Backtick, modifiers, .. }))
|
||||
if modifiers.is_none() && t.chars().count() == 1 && !t.chars().any(char::is_whitespace) =>
|
||||
{
|
||||
Some(t.clone())
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
@@ -1322,6 +1321,13 @@ mod tests {
|
||||
assert_eq!(backtick_text().as_deref(), Some("\""));
|
||||
note_backtick_text(&[text("`"), press(Key::Backtick)]);
|
||||
assert_eq!(backtick_text(), None);
|
||||
// Several keys typed in one frame on the web: each text goes with the press after it.
|
||||
let web = [text("a"), press(Key::A), text("\""), press(Key::Backtick), text("b"), press(Key::B)];
|
||||
note_backtick_text(&web);
|
||||
assert_eq!(backtick_text().as_deref(), Some("\""));
|
||||
note_backtick_text(&[text("`"), press(Key::Backtick)]);
|
||||
note_backtick_text(&[press(Key::A), text("a"), press(Key::Backtick), text("\""), press(Key::B), text("b")]);
|
||||
assert_eq!(backtick_text().as_deref(), Some("\""));
|
||||
// Only the unshifted key types that character.
|
||||
assert_eq!(on_layout("Shift+~".into(), Some("\"")), "Shift+~");
|
||||
assert_eq!(on_layout("Cmd+~".into(), Some("\"")), "Cmd+\"");
|
||||
|
||||
@@ -929,7 +929,7 @@ fn latin(text: &str, physical: Option<Key>) -> String {
|
||||
/// 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>> {
|
||||
pub(crate) fn typing_presses(events: &[egui::Event]) -> Vec<Option<usize>> {
|
||||
let is_press = |k: usize| matches!(events.get(k), Some(egui::Event::Key { key, pressed: true, .. }) if !is_modifier(*key));
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user