mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-14 19:27:04 -04:00
Co-authored-by: Codex <[email protected]>
This commit is contained in:
1 parent
da9cefa33c
commit
03d9900990
2 files changed
+79
-3
No files matched your search
@@ -159,15 +159,17 @@ pub fn show(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
||||
.font(theme::regular(15.0))
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
// Enter runs the top hit. The field keeps focus (requested every frame), so
|
||||
// check while it is focused as well as when focus is lost.
|
||||
// Enter runs the selected hit while the field is focused or relinquishing focus.
|
||||
if (r.has_focus() || r.lost_focus())
|
||||
&& ui.input(|i| i.key_pressed(egui::Key::Enter))
|
||||
&& let Some((_, h)) = hits.get(selected)
|
||||
{
|
||||
chosen = Some((h.command, h.group));
|
||||
}
|
||||
r.request_focus();
|
||||
// Re-requesting existing focus interrupts native IME composition.
|
||||
if !r.has_focus() {
|
||||
r.request_focus();
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
for (index, (_, h)) in hits.iter().enumerate() {
|
||||
|
||||
@@ -506,3 +506,77 @@ fn command_w_still_closes_the_document_tab_on_macos() {
|
||||
h.run_steps(2);
|
||||
assert!(h.state().views.is_empty(), "⌘W closes the clean document tab");
|
||||
}
|
||||
|
||||
fn palette_ime_output_requests_interrupt(h: &Harness<'_, PdfCraftApp>, phase: &str) -> bool {
|
||||
assert!(h.state().palette_open, "palette closed during {phase}");
|
||||
let ime = h.output().platform_output.ime.as_ref().expect("focused palette advertises IME");
|
||||
eprintln!("{phase}: query={:?}; should_interrupt_composition={}", h.state().palette_query, ime.should_interrupt_composition);
|
||||
ime.should_interrupt_composition
|
||||
}
|
||||
|
||||
fn palette_ime_output_is_uninterrupted(h: &Harness<'_, PdfCraftApp>, phase: &str) {
|
||||
assert!(!palette_ime_output_requests_interrupt(h, phase), "palette interrupted composition during {phase}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn palette_ime_idle_frames_and_reopen_do_not_interrupt_composition() {
|
||||
let mut h = harness();
|
||||
for opening in 0..2 {
|
||||
h.state_mut().run_command("view.palette");
|
||||
h.run_steps(3);
|
||||
for frame in 0..3 {
|
||||
h.step();
|
||||
palette_ime_output_is_uninterrupted(&h, &format!("opening {opening}, idle {frame}"));
|
||||
}
|
||||
h.key_press(Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert!(!h.state().palette_open);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn palette_ime_chinese_preedit_commit_and_cancel_remain_uninterrupted() {
|
||||
let mut h = harness();
|
||||
let mut interruptions = Vec::new();
|
||||
h.state_mut().run_command("view.palette");
|
||||
h.run_steps(3);
|
||||
for preedit in ["ni", "nih"] {
|
||||
h.event(egui::Event::Ime(egui::ImeEvent::Preedit { text: preedit.into(), active_range_chars: Some(0..preedit.chars().count()) }));
|
||||
h.step();
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, preedit));
|
||||
h.step();
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, "preedit idle"));
|
||||
}
|
||||
h.event(egui::Event::Ime(egui::ImeEvent::Commit("你".into())));
|
||||
h.step();
|
||||
assert_eq!(h.state().palette_query, "你");
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, "Chinese commit"));
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().palette_query, "你");
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, "committed idle"));
|
||||
h.event(egui::Event::Ime(egui::ImeEvent::Preedit { text: "hao".into(), active_range_chars: Some(0..3) }));
|
||||
h.step();
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, "second preedit"));
|
||||
h.event(egui::Event::Ime(egui::ImeEvent::Preedit { text: String::new(), active_range_chars: None }));
|
||||
h.step();
|
||||
assert_eq!(h.state().palette_query, "你");
|
||||
interruptions.push(palette_ime_output_requests_interrupt(&h, "cancel preedit"));
|
||||
assert!(interruptions.iter().all(|interrupt| !interrupt), "composition interrupted: {interruptions:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn palette_ime_outside_click_closes_without_running_a_command() {
|
||||
let mut h = harness();
|
||||
h.state_mut().set_option("palette", "rotate pages clockwise").unwrap();
|
||||
h.run_steps(3);
|
||||
h.event(egui::Event::PointerButton {
|
||||
pos: egui::pos2(20.0, 850.0),
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed: true,
|
||||
modifiers: Modifiers::NONE,
|
||||
});
|
||||
h.step();
|
||||
assert!(!h.state().palette_open);
|
||||
assert!(h.state().palette_query.is_empty());
|
||||
assert_eq!(h.state().session.get(h.state().views[0].id).unwrap().info.pages[0].rotation, 0);
|
||||
}
|
||||
Reference in new issue
Block a user