Merge #757: Cmd/Ctrl + the + key zooms the canvas, not the whole window

# Conflicts:
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/menus.rs
This commit is contained in:
aiongg
2026-10-13 19:58:26 +00:00
3 changed files with 53 additions and 2 deletions
+3
View File
@@ -32,6 +32,9 @@ display_name = "insanityxoff"
[people.moppeeer]
sync_github_name = true
[people.PiMinusMax]
display_name = "PiMinusMax"
[people.thaynej]
real_name = "Jeffrey Thayne"
+3
View File
@@ -1034,6 +1034,9 @@ impl DesignApp {
ctx.set_zoom_factor(scale);
}
if !self.styled {
// The UI scale is a preference (applied above); egui's own Cmd+Plus/Minus/0 would rescale the
// whole window instead of the canvas, only to be reset next frame.
ctx.options_mut(|o| o.zoom_with_keyboard = false);
self.fonts_system = theme::install_fonts(ctx, &self.ui.language);
self.fonts_lang = self.ui.language.clone();
self.styled = true;
+47 -2
View File
@@ -2643,10 +2643,12 @@ pub fn shortcuts(app: &mut DesignApp, ctx: &egui::Context) {
let all = effective_shortcuts(app);
for (id, sc) in &all {
let id = id.as_str();
// On layouts with a dedicated + key (German) or Shift+= (US), Cmd+= arrives as Plus.
let plus_for_equals = key == egui::Key::Plus;
if let Some((m, k)) = parse_shortcut(sc)
&& k == key
&& (k == key || (plus_for_equals && k == egui::Key::Equals))
&& m.command == modifiers.command
&& m.shift == modifiers.shift
&& (m.shift == modifiers.shift || (plus_for_equals && !m.shift))
&& m.alt == modifiers.alt
&& (m.command || m.alt || !typing)
&& !(id == "edit.clear" && typing)
@@ -3704,6 +3706,49 @@ mod tests {
assert_eq!(app.session.tool_id(), "selection");
}
#[test]
fn cmd_plus_zooms_the_canvas_not_the_window() {
// A German keyboard has its own + key, so Cmd+= arrives as Plus; it must zoom the canvas like
// Cmd+- does, not hand the key to egui's whole-window zoom.
let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
app.session.execute("file.new", &json!({})).unwrap();
let ctx = egui::Context::default();
let frame = |app: &mut crate::DesignApp, events: Vec<egui::Event>| {
let input = egui::RawInput {
screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1400.0, 900.0))),
events,
..Default::default()
};
let mut out = ctx.run_ui(input, |ui| {
app.logic(&ui.ctx().clone());
app.ui(ui);
});
out.textures_delta.clear();
};
let key = |k: egui::Key, modifiers: egui::Modifiers| {
vec![
egui::Event::Key { key: k, physical_key: None, pressed: true, repeat: false, modifiers },
egui::Event::Key { key: k, physical_key: None, pressed: false, repeat: false, modifiers },
]
};
frame(&mut app, vec![]);
frame(&mut app, vec![]);
let scale = ctx.zoom_factor();
for (k, m, zooms_in) in [
(egui::Key::Plus, egui::Modifiers::COMMAND, true),
(egui::Key::Plus, egui::Modifiers::COMMAND | egui::Modifiers::SHIFT, true),
(egui::Key::Equals, egui::Modifiers::COMMAND, true),
(egui::Key::Minus, egui::Modifiers::COMMAND, false),
] {
let z0 = app.view().unwrap().zoom;
frame(&mut app, key(k, m));
frame(&mut app, vec![]);
let z = app.view().unwrap().zoom;
assert!(if zooms_in { z > z0 } else { z < z0 }, "{k:?} {m:?}: {z0} -> {z}");
assert_eq!(ctx.zoom_factor(), scale, "{k:?} {m:?} leaves the UI scale alone");
}
}
#[test]
fn the_quick_apply_shortcut_opens_it_without_running_an_entry() {
let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());