diff --git a/crates/keymap/src/egui.rs b/crates/keymap/src/egui.rs index d7d595de..52c9aff1 100644 --- a/crates/keymap/src/egui.rs +++ b/crates/keymap/src/egui.rs @@ -305,6 +305,12 @@ impl Dispatcher { } } } + // A repeat that does not run leaves its clipboard event in place with it. + Event::Key { pressed: true, repeat: true, .. } => { + if let Some((j, _)) = causes[i] { + caused_taken[j] = Some(false); + } + } Event::Text(_) if drop_text => { drop_text = false; continue; diff --git a/crates/keymap/tests/egui.rs b/crates/keymap/tests/egui.rs index 04a4ee51..b91e380f 100644 --- a/crates/keymap/tests/egui.rs +++ b/crates/keymap/tests/egui.rs @@ -218,6 +218,18 @@ fn a_web_paste_carries_its_text_and_takes_its_event() { assert_eq!(input.events, events[..2]); } +#[test] +fn a_held_web_paste_runs_once_when_repeats_are_off() { + let km = dispatch_keymap(); + let mut d = Dispatcher::new().with_clipboard_events(true); + let repeat = Event::Key { key: EguiKey::V, physical_key: Some(EguiKey::V), pressed: true, repeat: true, modifiers: CTRL }; + let paste = || Event::Paste("text".into()); + let events = vec![press(EguiKey::V, CTRL), paste(), repeat.clone(), paste()]; + let (ran, left) = run(&mut d, &km, &Active::NONE, frame(1.0, CTRL, events)); + assert_eq!(ran, ["edit.paste"]); + assert_eq!(left, [repeat, paste()], "the repeat and its event stay in egui's input"); +} + #[test] fn declined_hits_leave_their_events_in_order() { let km = dispatch_keymap();