From 708c30831c305d6b1ffe749121ebd637721a70c5 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Wed, 2 Sep 2026 15:21:57 +0300 Subject: [PATCH 1/2] Capture pointer input during grip edits --- src/app/update/viewport.rs | 22 ++++++++++++++++++---- src/scene/pick/selection_state.rs | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/app/update/viewport.rs b/src/app/update/viewport.rs index 55164a91b..f4abdd528 100644 --- a/src/app/update/viewport.rs +++ b/src/app/update/viewport.rs @@ -2784,6 +2784,18 @@ impl OpenCADStudio { height: vh, }; + // An engaged grip owns the next left press (click-move-click placement + // or the release of a press-drag). Do not let the same press arm the + // normal box/lasso state; the release path below will commit the grip. + if self.tabs[i].active_grip.is_some() { + self.tabs[i] + .scene + .selection + .borrow_mut() + .clear_left_selection_gesture(); + return Task::none(); + } + if self.tabs[i].active_cmd.is_none() && self.tabs[i].active_grip.is_none() && !self.tabs[i].selected_grips.is_empty() @@ -2879,6 +2891,11 @@ impl OpenCADStudio { )); self.grip_hover = None; self.grip_popup = None; + self.tabs[i] + .scene + .selection + .borrow_mut() + .clear_left_selection_gesture(); // A grip edit is not a CAD command, so explicitly seed the shared // dynamic-input fields for the newly engaged grip. @@ -2956,10 +2973,7 @@ impl OpenCADStudio { // click doesn't read as an in-progress drag on later moves. { let mut sel = self.tabs[i].scene.selection.borrow_mut(); - sel.left_down = false; - sel.left_press_pos = None; - sel.left_press_time = None; - sel.left_dragging = false; + sel.clear_left_selection_gesture(); } let moved = grip.last_world != grip.origin_world; if is_click && !moved { diff --git a/src/scene/pick/selection_state.rs b/src/scene/pick/selection_state.rs index 677b98618..21599ab0d 100644 --- a/src/scene/pick/selection_state.rs +++ b/src/scene/pick/selection_state.rs @@ -56,3 +56,24 @@ pub struct SelectionState { pub middle_last_pos: Option, pub middle_last_press_time: Option, } + +impl SelectionState { + /// End every left-button selection gesture without disturbing the previous + /// completed-window record or command-owned preview marquee. Grip editing + /// owns the left button while engaged and calls this before/after placement + /// so a small pointer move cannot also arm a box or lasso selection. + pub fn clear_left_selection_gesture(&mut self) { + self.left_down = false; + self.left_press_pos = None; + self.left_press_time = None; + self.left_dragging = false; + self.box_anchor = None; + self.box_anchor_world = None; + self.box_current = None; + self.box_crossing = false; + self.box_crossing_locked = false; + self.poly_active = false; + self.poly_points.clear(); + self.poly_crossing = false; + } +} From 2bb491d8749733f52a4b33bb03bbe248de680cb4 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 2 Sep 2026 17:46:49 +0300 Subject: [PATCH 2/2] fix(grips): capture placement clicks first --- src/app/update/viewport.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app/update/viewport.rs b/src/app/update/viewport.rs index f4abdd528..697400e7e 100644 --- a/src/app/update/viewport.rs +++ b/src/app/update/viewport.rs @@ -2690,6 +2690,19 @@ impl OpenCADStudio { }; let (vw, vh) = vp_size; + // An engaged grip owns the next left press (click-move-click placement + // or the release of a press-drag). Do not let the same press arm the + // normal box/lasso state or trigger another viewport control; the + // release path below will commit the grip. + if self.tabs[i].active_grip.is_some() { + self.tabs[i] + .scene + .selection + .borrow_mut() + .clear_left_selection_gesture(); + return Task::none(); + } + // Interactive navigation tools reuse the middle-button movement path, // so no selection/pick logic runs while the left button drives them. if self.tabs[i].orbit_mode @@ -2784,18 +2797,6 @@ impl OpenCADStudio { height: vh, }; - // An engaged grip owns the next left press (click-move-click placement - // or the release of a press-drag). Do not let the same press arm the - // normal box/lasso state; the release path below will commit the grip. - if self.tabs[i].active_grip.is_some() { - self.tabs[i] - .scene - .selection - .borrow_mut() - .clear_left_selection_gesture(); - return Task::none(); - } - if self.tabs[i].active_cmd.is_none() && self.tabs[i].active_grip.is_none() && !self.tabs[i].selected_grips.is_empty()