fix(view): check Shift-Command-G before Command-G for find navigation (#810) (#835)

* view: check Shift-Command-G before Command-G for find navigation (#810)

* Tests: the find shortcut test waits for find by a deadline

(cherry picked from commit eaf3180bd8ebb353b3d8c5ca7b9ef7548ed55c37)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
Krzysztof Cieślik
2026-10-10 15:08:55 -04:00
committed by GitHub
co-authored by Brandon Thomas
parent 7608632db1
commit 724f13cced
2 changed files with 42 additions and 4 deletions
+3 -4
View File
@@ -1612,7 +1612,9 @@ pub fn shortcuts(view: &mut DocView, ctx: &egui::Context) {
view.fit = Fit::Width;
view.goto = Some((view.current, 0.0));
}
if pressed(cmd(Key::G)) {
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)) {
@@ -1621,9 +1623,6 @@ pub fn shortcuts(view: &mut DocView, ctx: &egui::Context) {
if pressed(cmd(Key::CloseBracket)) {
view.view_history(true);
}
if pressed(KeyboardShortcut::new(Modifiers::COMMAND | Modifiers::SHIFT, Key::G)) {
view.find_step(false);
}
// ⌘C arrives as a Copy event on most platforms.
let copy = ctx.input(|i| i.events.iter().any(|e| matches!(e, egui::Event::Copy)));
if copy && let Some(text) = view.selected_text() {
+39
View File
@@ -130,6 +130,45 @@ fn view_history_select_all_and_find_options() {
assert_eq!(h.state().views[0].find.as_ref().unwrap().matches.len(), 5);
}
#[test]
fn find_shortcuts_advance_and_retreat_matches() {
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();
// Find runs in the background: wait by a deadline, not a frame count, which a loaded machine
// can use up before the last page is searched.
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);
// Surrender text edit focus so canvas shortcut handler receives key events.
h.state_mut().views[0].find.as_mut().unwrap().focus = false;
h.ctx.memory_mut(|m| m.surrender_focus(egui::Id::new("find-input")));
h.run_steps(2);
let start = h.state().views[0].find.as_ref().unwrap().current.unwrap();
// ⌘G advances to next match.
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));
// ⇧⌘G retreats to previous match.
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));
// ⇧⌘G again wraps backwards.
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 + n - 1) % n));
}
#[test]
fn layouts_fit_height_labels_and_system_theme() {
use pdfcraft_ui_egui::canvas::{Fit, PageLayout};