Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
da9cefa33c
commit
03d9900990
|
|
@ -159,15 +159,17 @@ pub fn show(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
||||||
.font(theme::regular(15.0))
|
.font(theme::regular(15.0))
|
||||||
.desired_width(f32::INFINITY),
|
.desired_width(f32::INFINITY),
|
||||||
);
|
);
|
||||||
// Enter runs the top hit. The field keeps focus (requested every frame), so
|
// Enter runs the selected hit while the field is focused or relinquishing focus.
|
||||||
// check while it is focused as well as when focus is lost.
|
|
||||||
if (r.has_focus() || r.lost_focus())
|
if (r.has_focus() || r.lost_focus())
|
||||||
&& ui.input(|i| i.key_pressed(egui::Key::Enter))
|
&& ui.input(|i| i.key_pressed(egui::Key::Enter))
|
||||||
&& let Some((_, h)) = hits.get(selected)
|
&& let Some((_, h)) = hits.get(selected)
|
||||||
{
|
{
|
||||||
chosen = Some((h.command, h.group));
|
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();
|
ui.separator();
|
||||||
for (index, (_, h)) in hits.iter().enumerate() {
|
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);
|
h.run_steps(2);
|
||||||
assert!(h.state().views.is_empty(), "⌘W closes the clean document tab");
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue