Preferences: Interface size applies when the slider is let go (#767)

Dragging the Interface size slider set the interface scale on every
frame, which grew or shrank the slider under the pointer and ran it to
one of its ends. Keep the value pending in the dialog while the pointer
holds the slider and apply it on release; keyboard changes still apply
at once.
This commit is contained in:
Gert Pellin
2026-10-15 01:49:41 +02:00
parent ea904591a5
commit 8b08718b9a
2 changed files with 49 additions and 3 deletions
+15 -3
View File
@@ -2109,9 +2109,21 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
if ui.checkbox(&mut dark, "Dark appearance").changed() {
let _ = app.run("view.dark", json!({"on": dark}));
}
let mut scale = app.ui.ui_scale;
if ui.add(egui::Slider::new(&mut scale, 0.75..=1.75).text("Interface size")).changed() {
app.ui.ui_scale = scale;
// While the pointer holds the slider its value only waits in the dialog: applying it
// would rescale the slider under the pointer and run it to an end (#767). It applies
// on release, and at once from the keyboard.
let pending = d.fields.get("uiScale").and_then(|v| v.parse::<f32>().ok());
let mut scale = pending.unwrap_or(app.ui.ui_scale);
let r = ui.add(egui::Slider::new(&mut scale, 0.75..=1.75).text("Interface size"));
if r.is_pointer_button_down_on() {
if r.changed() || pending.is_some() {
d.fields.insert("uiScale".into(), scale.to_string());
}
} else {
if r.changed() || pending.is_some() {
app.ui.ui_scale = scale;
}
d.fields.remove("uiScale");
}
ui.label(egui::RichText::new("Editing").font(theme::bold(13.0)));
ui.checkbox(&mut app.session.prefs.smart_guides, "Show smart guides");
+34
View File
@@ -3253,4 +3253,38 @@ mod tests {
flick(&mut harness, egui::vec2(-24.0, 0.0));
assert_eq!(harness.state().show.as_ref().map(|s| s.state.slide), Some(0));
}
/// Preferences › Interface size (#767): dragging the slider leaves the interface size alone
/// until the pointer lets go, so the slider doesn't grow under the pointer mid-drag.
#[test]
fn interface_size_applies_when_the_slider_is_let_go() {
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);
harness.state_mut().run("app.preferences", json!({})).unwrap();
harness.run_steps(4);
let before = harness.state().ui.ui_scale;
let rect =
harness.query_all_by_role_and_label(egui::accesskit::Role::Slider, "Interface size").next().expect("the Interface size slider").rect();
let (from, to) = (rect.left_center() + egui::vec2(4.0, 0.0), rect.right_center() - egui::vec2(4.0, 0.0));
harness.hover_at(from);
harness.run_steps(1);
harness.drag_at(from);
harness.run_steps(1);
for k in 1..=8 {
harness.hover_at(from.lerp(to, k as f32 / 8.0));
harness.run_steps(1);
}
assert_eq!(harness.state().ui.ui_scale, before, "nothing rescales while the slider is held");
harness.drop_at(to);
harness.run_steps(2);
let after = harness.state().ui.ui_scale;
assert!(after > before + 0.3, "letting go applies the size dragged to: {before} -> {after}");
assert!(harness.state().dialog.is_some(), "Preferences stays open");
}
}