mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-26 11:36:58 -06:00
fix: DeckCraft upstream #93
Keep the keyboard while editing list text: Tab and the arrow keys moved egui's keyboard focus onto ordinary widgets, and that stray focus swallowed every later key, so lists could not be typed into or continued with Enter.
This commit is contained in:
@@ -607,7 +607,20 @@ impl SlideApp {
|
||||
|
||||
/// Keyboard and clipboard for the slide (when no text field has focus).
|
||||
fn keyboard(&mut self, ctx: &egui::Context) {
|
||||
if ctx.memory(|m| m.focused().is_some()) || self.dialog.as_ref().is_some_and(|d| d.modal()) || self.palette.is_some() {
|
||||
let modal = self.dialog.as_ref().is_some_and(|d| d.modal()) || self.palette.is_some();
|
||||
// While slide text is being edited, the text owns the keyboard (#93). Tab and the arrow
|
||||
// keys move egui's keyboard focus onto ordinary widgets (the window's drag handle, ribbon
|
||||
// buttons), and that stray focus would swallow every later key and end text entry. Let it
|
||||
// go; a real text field or an open menu keeps its keys.
|
||||
if !modal
|
||||
&& self.session.active().is_some_and(|d| d.selection.text.is_some())
|
||||
&& !ctx.text_edit_focused()
|
||||
&& !ctx.any_popup_open()
|
||||
&& let Some(id) = ctx.memory(|m| m.focused())
|
||||
{
|
||||
ctx.memory_mut(|m| m.surrender_focus(id));
|
||||
}
|
||||
if ctx.memory(|m| m.focused().is_some()) || modal {
|
||||
return;
|
||||
}
|
||||
let events = ctx.input(|i| i.events.clone());
|
||||
@@ -932,6 +945,39 @@ mod tests {
|
||||
assert_eq!(harness.state().session.documents().len(), 2);
|
||||
}
|
||||
|
||||
/// #93: Tab in an edited list indented the item but handed the keyboard to egui's focus
|
||||
/// cycle: the stray focus (e.g. on the window's drag handle) swallowed every later key, so the
|
||||
/// list could neither be typed into nor continued with Enter.
|
||||
#[test]
|
||||
fn tab_in_an_edited_list_keeps_the_keyboard() {
|
||||
let mut harness = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state(
|
||||
|ui, app: &mut SlideApp| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
},
|
||||
SlideApp::new(Session::with_new(), Services::default()),
|
||||
);
|
||||
harness.run_steps(2);
|
||||
let title = harness.state().session.active().unwrap().doc.slides[0].shapes[0].id.0;
|
||||
harness.state_mut().session.execute("text.edit", &json!({"id": title})).unwrap();
|
||||
harness.event(egui::Event::Text("one".into()));
|
||||
harness.run_steps(2);
|
||||
harness.key_press(egui::Key::Enter);
|
||||
harness.run_steps(2);
|
||||
harness.key_press(egui::Key::Tab); // Increase List Level
|
||||
harness.run_steps(2);
|
||||
harness.event(egui::Event::Text("sub".into()));
|
||||
harness.run_steps(2);
|
||||
harness.key_press(egui::Key::Enter); // continues the list
|
||||
harness.run_steps(2);
|
||||
harness.event(egui::Event::Text("two".into()));
|
||||
harness.run_steps(2);
|
||||
assert_eq!(title_text(harness.state()), "one\nsub\ntwo", "typing after Tab must reach the text");
|
||||
let body = harness.state().session.active().unwrap().doc.slides[0].shapes[0].text.clone().unwrap();
|
||||
let levels: Vec<u8> = body.paragraphs.iter().map(|p| p.level).collect();
|
||||
assert_eq!(levels, vec![0, 1, 1], "Tab indents one level; Enter keeps the level");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn home_needs_an_open_presentation() {
|
||||
let mut app = SlideApp::new(Session::new(), Services::default());
|
||||
|
||||
Reference in New Issue
Block a user