M3: ⌘G and ⇧⌘G step through matches from the find field (#2669)

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
This commit is contained in:
mtlcl410
2026-10-16 07:18:35 +08:00
co-authored by Claude Opus 5.5
parent 99941daa5a
commit bf1ce2a07c
2 changed files with 41 additions and 7 deletions
+11 -7
View File
@@ -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);
}
+30
View File
@@ -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();