From bfaea5398e84cfd6ad0081d9dcd1f95a15a62a39 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 12 Jun 2026 16:29:11 +0200 Subject: [PATCH] Centralize canvas mode capture release --- docs/modernization/debt.md | 5 +++++ docs/modernization/roadmap.md | 2 ++ src/canvas_modes.cpp | 39 ++++++++++++++++++----------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index b091e91..20425b9 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -571,6 +571,11 @@ agent or engineer to remove them without reconstructing context from chat. title cleanup now use retained detach/close/destroy helpers in `src/legacy_ui_overlay_services.*`. Dock/drop child ownership and raw panel globals remain legacy-owned. +- 2026-06-12: DEBT-0063 was narrowed again. Retained canvas mode mouse-capture + release for camera, paint, line, grid, mask, and fill interactions now routes + through `src/legacy_ui_overlay_services.*` instead of direct `NodeCanvas` + release calls. Capture ownership is still raw until retained `Node` adopts + checked handles and scoped event/capture lifetime. - 2026-06-05: DEBT-0011 was narrowed. The Windows app package smoke target now passes the configure-time CMake executable into `package-smoke.ps1`, so VS 2026 generator validation does not depend on an older `cmake` on PATH, and diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 2c19e24..3984935 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -529,6 +529,8 @@ cleanup now route through those same retained close/destroy helpers. Toolbar popup restoration from docked floating stroke/layer/grid panels and restored floating color-panel title cleanup now use the retained detach/close/ destroy helpers. +Canvas mode mouse-capture release for camera, paint, line, grid, mask, and fill +interactions now routes through the retained capture-release helper. Raw popup callback captures and full close/capture ownership remain part of `DEBT-0063`. `pano_cli inspect-image` exposes PNG IHDR metadata as JSON, diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index b415661..abda1b6 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -8,6 +8,7 @@ #include "canvas.h" #include "shader.h" #include "node_canvas.h" +#include "legacy_ui_overlay_services.h" #include "legacy_ui_gl_dispatch.h" #include "app.h" #include "util.h" @@ -83,7 +84,7 @@ void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) if (m_draggingL) { m_draggingL = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); } break; case kEventType::MouseDownR: @@ -98,7 +99,7 @@ void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; case kEventType::MouseUpR: m_draggingR = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); break; case kEventType::MouseMove: if (m_draggingR) @@ -131,7 +132,7 @@ void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; case kEventType::MouseCancel: m_draggingR = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); break; default: break; @@ -207,7 +208,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) case kEventType::MouseUpL: if (m_dragging && !m_picking) { - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); App::I->render_task_async([] { Canvas::I->stroke_end(); @@ -215,7 +216,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) } if (m_dragging && m_picking) { - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); glm::vec4 pix = Canvas::I->pick_get(loc); Canvas::I->m_current_brush->m_tip_color = pix; App::I->brush_update(true, false); @@ -239,7 +240,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) case kEventType::MouseUpR: if (m_dragging && m_resizing) { - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; m_resizing = false; } @@ -275,7 +276,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) Canvas::I->stroke_cancel(); }); m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); } if (m_picking) m_picking = false; @@ -377,7 +378,7 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_drag_pos = loc; break; case kEventType::MouseUpL: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); if (m_dragging) { App::I->render_task_async([=] @@ -396,7 +397,7 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_cur_pos = loc; break; case kEventType::MouseCancel: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; break; default: @@ -487,7 +488,7 @@ void CanvasModeCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; case kEventType::MouseUpL: m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); Canvas::I->m_cam_pos = { 0, 0, 0 }; break; case kEventType::MouseMove: @@ -496,7 +497,7 @@ void CanvasModeCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; case kEventType::MouseCancel: m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); break; default: break; @@ -552,7 +553,7 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; } case kEventType::MouseUpL: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; ActionManager::add(m_action.release()); //commit(); @@ -574,7 +575,7 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc) if (m_dragging && m_selected_index == m_lines.size() - 1) m_lines.pop_back(); m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); break; default: break; @@ -728,7 +729,7 @@ void CanvasModeMaskFree::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; } case kEventType::MouseUpL: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; if (m_points2d.size() > 3) { @@ -802,7 +803,7 @@ void CanvasModeMaskFree::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_shape.update_vertices(m_points.data(), (int)m_points.size()); } m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); if (m_points.size() < 4) { m_points.clear(); @@ -933,7 +934,7 @@ void CanvasModeMaskLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; } case kEventType::MouseUpL: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; if (m_points.size() > 1) { @@ -961,7 +962,7 @@ void CanvasModeMaskLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_shape.update_vertices(m_points.data(), (int)m_points.size()); } m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); if (m_points.size() < 4) { m_points.clear(); @@ -1058,7 +1059,7 @@ void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; } case kEventType::MouseUpL: - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; break; case kEventType::MouseMove: @@ -1083,7 +1084,7 @@ void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_shape.update_vertices(m_points.data(), (int)m_points.size()); } m_dragging = false; - node->mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*node); if (m_points.size() < 4) { m_points.clear();