From e679fa500a775d1bbf092e7cec88b466f36335bb Mon Sep 17 00:00:00 2001 From: aiongg Date: Sat, 24 Oct 2026 09:17:30 +0000 Subject: [PATCH] Integration: right-clicking a control handle in Edit Points keeps the picked point and its menu --- crates/engine/src/tests.rs | 20 ++++++++++++++++++++ crates/engine/src/tools.rs | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 0de23b69..fc5cd2c9 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2289,6 +2289,26 @@ fn edit_points_right_click_picks_the_point_or_the_segment() { assert_eq!((s.tool.edit_segment, s.tool.edit_vertex), (None, None)); } +/// A right-click on a control handle keeps the point menu: the vertex stays picked. +#[test] +fn edit_points_right_click_on_a_handle_keeps_the_picked_vertex() { + let mut s = Session::with_new(); + s.execute("slide.new", &json!({"layout": "blank"})).unwrap(); + s.execute("shape.insert", &json!({"preset": "ellipse", "rect": [100, 100, 200, 100]})).unwrap(); + s.execute("shape.editPoints", &json!({"on": true})).unwrap(); + // The right-most point of the ellipse. + right_click(&mut s, 300.0, 150.0); + let (path, index) = s.tool.edit_vertex.expect("the point is picked"); + let st = s.doc().unwrap(); + let id = s.tool.editing_points(st).unwrap(); + let handle = cmd::points::slide_handles(&st.doc, &st.selection, st.shape(id).unwrap(), path, index) + .and_then(|(hin, hout, _)| hout.or(hin)) + .expect("a smooth point has a handle"); + let r = right_click(&mut s, handle.x, handle.y); + assert_eq!(r["hit"]["kind"], "handle", "{r}"); + assert_eq!((s.tool.edit_segment, s.tool.edit_vertex), (None, Some((path, index)))); +} + /// #392: a `.deckcraft` whose embedded picture is damaged opens as an untitled "(Repaired)" /// copy with a message, so Save can't overwrite the original with the empty media. #[test] diff --git a/crates/engine/src/tools.rs b/crates/engine/src/tools.rs index 41fc7d4c..50853838 100644 --- a/crates/engine/src/tools.rs +++ b/crates/engine/src/tools.rs @@ -1254,6 +1254,7 @@ impl Session { // Edit Points: the point or else the segment under the pointer picks the menu. let picked = self.tool.editing_points(st).and_then(|eid| st.shape(eid)).map(|sh| match &hit { Some(Hit::Vertex { path, index, .. }) => (Some((*path, *index)), None), + Some(Hit::Handle { .. }) => (None, None), _ => (None, cmd::points::segment_at(&st.doc, &st.selection, sh, p, tol * 1.6).map(|(path, seg, _)| (path, seg))), }); if !id.is_some_and(|id| st.selection.shapes.contains(&id)) { @@ -1264,7 +1265,10 @@ impl Session { })?; } if let Some((vertex, segment)) = picked { - self.tool.edit_vertex = vertex; + // A control handle belongs to the picked point: its menu stays. + if !matches!(hit, Some(Hit::Handle { .. })) { + self.tool.edit_vertex = vertex; + } self.tool.edit_segment = segment; } let st = self.doc()?;