From bf1ce2a07cf78d0df29a7b39b5607c574839ab0b Mon Sep 17 00:00:00 2001 From: mtlcl410 Date: Fri, 16 Oct 2026 07:18:35 +0800 Subject: [PATCH] =?UTF-8?q?M3:=20=E2=8C=98G=20and=20=E2=87=A7=E2=8C=98G=20?= =?UTF-8?q?step=20through=20matches=20from=20the=20find=20field=20(#2669)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The find-step shortcuts sat after the canvas's "egui wants keyboard input" check, so they did nothing while the find field had the focus (Enter worked). They now run before it, while a search is open, as in Acrobat and Preview. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz --- crates/ui-egui/src/canvas.rs | 18 +++++++++++------- crates/ui-egui/tests/viewer.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 989b731b7..360d317bd 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -2072,11 +2072,20 @@ pub fn shortcuts(view: &mut DocView, ctx: &egui::Context, speed: crate::scroll_s if ctx.input_mut(|i| i.consume_shortcut(&KeyboardShortcut::new(Modifiers::COMMAND, Key::F))) { view.open_find(); } + let cmd = |k| KeyboardShortcut::new(Modifiers::COMMAND, k); + let pressed = |s: KeyboardShortcut| ctx.input_mut(|i| i.consume_shortcut(&s)); + // ⌘G / ⇧⌘G step through the matches from the find field too, as in Acrobat and Preview + // (#2669): ahead of the text-input check, but only while there is a search to step. + if view.find.is_some() { + if pressed(KeyboardShortcut::new(Modifiers::COMMAND | Modifiers::SHIFT, Key::G)) { + view.find_step(false); + } else if pressed(cmd(Key::G)) { + view.find_step(true); + } + } if ctx.egui_wants_keyboard_input() { return; } - let cmd = |k| KeyboardShortcut::new(Modifiers::COMMAND, k); - let pressed = |s: KeyboardShortcut| ctx.input_mut(|i| i.consume_shortcut(&s)); // Rotation first: egui matches ⌘+ loosely with respect to Shift. if pressed(KeyboardShortcut::new(Modifiers::COMMAND | Modifiers::SHIFT, Key::Plus)) || pressed(KeyboardShortcut::new(Modifiers::COMMAND | Modifiers::SHIFT, Key::Equals)) @@ -2117,11 +2126,6 @@ pub fn shortcuts(view: &mut DocView, ctx: &egui::Context, speed: crate::scroll_s view.fit = Fit::Width; view.goto = Some((view.current, 0.0)); } - if pressed(KeyboardShortcut::new(Modifiers::COMMAND | Modifiers::SHIFT, Key::G)) { - view.find_step(false); - } else if pressed(cmd(Key::G)) { - view.find_step(true); - } if pressed(cmd(Key::OpenBracket)) { view.view_history(false); } diff --git a/crates/ui-egui/tests/viewer.rs b/crates/ui-egui/tests/viewer.rs index 077553c71..36c1f07db 100644 --- a/crates/ui-egui/tests/viewer.rs +++ b/crates/ui-egui/tests/viewer.rs @@ -175,6 +175,36 @@ fn find_shortcuts_advance_and_retreat_matches() { assert_eq!(h.state().views[0].find.as_ref().unwrap().current, Some((start + n - 1) % n)); } +/// #2669: ⌘G and ⇧⌘G step through the matches while the find field still has the focus. +#[test] +fn find_shortcuts_work_from_the_find_field() { + let mut h = harness(); + h.state_mut().active = Some(0); + h.run_steps(2); + h.state_mut().views[0].open_find(); + h.state_mut().views[0].find.as_mut().unwrap().query = "page".into(); + h.state_mut().views[0].rerun_find(); + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(20); + while std::time::Instant::now() < deadline { + h.run_steps(2); + std::thread::sleep(std::time::Duration::from_millis(5)); + if h.state().views[0].find.as_ref().unwrap().matches.len() >= 15 { + break; + } + } + let n = h.state().views[0].find.as_ref().unwrap().matches.len(); + assert_eq!(n, 15); + assert!(h.ctx.egui_wants_keyboard_input(), "the find field has the focus"); + let start = h.state().views[0].find.as_ref().unwrap().current.unwrap(); + h.key_press_modifiers(egui::Modifiers::COMMAND, egui::Key::G); + h.run_steps(2); + assert_eq!(h.state().views[0].find.as_ref().unwrap().current, Some((start + 1) % n)); + h.key_press_modifiers(egui::Modifiers::COMMAND | egui::Modifiers::SHIFT, egui::Key::G); + h.run_steps(2); + assert_eq!(h.state().views[0].find.as_ref().unwrap().current, Some(start)); + assert!(h.ctx.egui_wants_keyboard_input(), "and keeps it"); +} + #[test] fn marking_while_searching_does_not_jitter_or_reset_search_state() { let mut h = harness();