From fbacdeca7b40fc580e946bd18120858dc3ef1113 Mon Sep 17 00:00:00 2001 From: Tommaso Bianchi Date: Sat, 22 Aug 2026 15:10:18 +0200 Subject: [PATCH] Port: only the visible canvas may consume the 3D-mouse queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Carries snaporca 9f0a6656bc. Mouse3DController::apply DRAINS the input queue and every BOUND canvas idles and calls it, but a hidden canvas's render() early-returns on _is_shown_on_screen() — so it swallows motion, applies it to the shared plater camera, and draws nothing. The next visible frame jumps by more than one state change. The plater keeps exactly one of its three views bound; the Design canvas binds once at construction and never unbinds, so two canvases drain the same queue. Guarded at the apply site so only the canvas actually on screen takes motion off the queue, whatever happens to be bound, and without touching the plater's view-switching state machine. Reported by exussum12 on PR #15238 as lag and jerkiness in the Design tab against "really smooth on the other tab"; he guessed the mechanism correctly. NOT verified with a device — there is no SpaceMouse here and the rig has no HID, so this is a mechanism traced in source and matched to a user's description, not a measurement. Co-Authored-By: Claude Opus 5 (1M context) --- src/slic3r/GUI/GLCanvas3D.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8532199cc1..5b19238729 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3228,7 +3228,21 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) // BBS //m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state(); - bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); + // ONLY THE CANVAS THE USER IS LOOKING AT MAY CONSUME THE 3D-MOUSE QUEUE. apply() DRAINS the + // queue, and every bound canvas idles — but a hidden canvas's render() early-returns on + // _is_shown_on_screen(), so the motion it swallowed is applied to the SHARED camera and never + // drawn. The next visible frame then jumps by more than one state change at once. + // + // The plater avoids this by binding exactly one of its three views at a time (Plater.cpp, + // around the current_panel switch). The Design tab's canvas binds once at construction and + // never unbinds, so from the moment it exists two canvases drain the same queue. Reported + // upstream as the SpaceMouse being "more severe lag, and jerkyness vs really smooth on the + // other tab ... its more than 1 state change" (OrcaSlicer PR #15238). + // + // Guarding here rather than at the bind sites fixes the whole class: whatever is bound, only + // the visible canvas takes motion off the queue. + bool mouse3d_controller_applied = _is_shown_on_screen() + && wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); m_dirty |= mouse3d_controller_applied; m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this); auto gizmo = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().get_current();