diff --git a/crates/ui-egui/src/panels/appearance.rs b/crates/ui-egui/src/panels/appearance.rs index 4e39c75b7..32963ce68 100644 --- a/crates/ui-egui/src/panels/appearance.rs +++ b/crates/ui-egui/src/panels/appearance.rs @@ -398,11 +398,9 @@ pub(crate) fn row_popup(app: &mut VectorcraftApp, ctx: &egui::Context, panel: Re } last = true; } - // Fields let go of the keyboard on a click, which this press isn't yet. - let surrender = ctx.options(|o| o.input_options.surrender_focus_on); - if last { - ctx.options_mut(|o| o.input_options.surrender_focus_on = egui::SurrenderFocusOn::Presses); - } + // Fields let go of the keyboard on a click, which this press isn't yet. The app-wide option + // goes back however this function ends, a panic in the panel included. + let _surrender = last.then(|| SurrenderOnPress::set(ctx)); let screen = ctx.content_rect(); let left = panel.left() - POPUP_GAP - POPUP_W; let x = if left >= screen.left() + POPUP_GAP { left } else { (panel.right() + POPUP_GAP).min(screen.right() - POPUP_W - POPUP_GAP) }; @@ -430,11 +428,29 @@ pub(crate) fn row_popup(app: &mut VectorcraftApp, ctx: &egui::Context, panel: Re }); }); if last { - ctx.options_mut(|o| o.input_options.surrender_focus_on = surrender); close(app); } } +/// While it lives, a press anywhere makes a field let go of the keyboard, as a click does +/// otherwise; dropped, egui's previous `surrender_focus_on` is back ([`row_popup`]'s last frame). +struct SurrenderOnPress(egui::Context, egui::SurrenderFocusOn); + +impl SurrenderOnPress { + fn set(ctx: &egui::Context) -> Self { + let before = ctx.options(|o| o.input_options.surrender_focus_on); + ctx.options_mut(|o| o.input_options.surrender_focus_on = egui::SurrenderFocusOn::Presses); + Self(ctx.clone(), before) + } +} + +impl Drop for SurrenderOnPress { + fn drop(&mut self) { + let before = self.1; + self.0.options_mut(|o| o.input_options.surrender_focus_on = before); + } +} + /// A row's name that edits the row when clicked ([`link`]), with the tooltip "Click to edit". fn name_link(ui: &mut Ui, pos: egui::Pos2, id: impl std::hash::Hash + std::fmt::Debug, s: &str) -> egui::Response { link(ui, pos, id, s).on_hover_text(tl!("Click to edit")) diff --git a/crates/ui-egui/src/panels/tests_appearance.rs b/crates/ui-egui/src/panels/tests_appearance.rs index 2cf78847a..3d486dfe2 100644 --- a/crates/ui-egui/src/panels/tests_appearance.rs +++ b/crates/ui-egui/src/panels/tests_appearance.rs @@ -2016,6 +2016,8 @@ fn a_dash_typed_in_a_stroke_popup_sticks_when_a_click_outside_closes_it() { let dash = |app: &VectorcraftApp| current_stroke(app).and_then(|s| s.dash).map(|d| d.pattern); assert_eq!(dash(&app), Some(vec![10.0]), "{link}: nothing set while typing"); click(&ctx, &mut app, egui::pos2(5.0, 3000.0), show); + let surrender = ctx.options(|o| o.input_options.surrender_focus_on); + assert_eq!(surrender, egui::SurrenderFocusOn::Clicks, "{link}: fields let go of the keyboard on a click again"); frame_events(&ctx, &mut app, vec![], show); assert_eq!(dash(&app).and_then(|p| p.first().copied()), Some(4.0), "{link}: the typed dash stuck: {:?}", dash(&app)); let texts = frame_events(&ctx, &mut app, vec![], show);