diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 56b815a..a626cca 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -550,6 +550,11 @@ agent or engineer to remove them without reconstructing context from chat. - 2026-06-12: DEBT-0063 was narrowed again. `NodePopupMenu` mouse-up release and destroy now route through the retained popup close helper in `src/legacy_ui_overlay_services.*`. +- 2026-06-12: DEBT-0063 was narrowed again. Layer-row, animation-timeline, and + heightmap-overlay drag release paths now route mouse-capture release through + `src/legacy_ui_overlay_services.*`, and brush/grid progress or recovery + message dialogs now use the retained dialog close helper instead of direct + `destroy()` calls. Checked handles and scoped callback ownership remain open. - 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 3c8c088..0da031f 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -518,6 +518,9 @@ recording export progress cleanup also route through those helpers. Floating-panel close and drag-outline cleanup now use the same retained close helper while drag reparenting remains legacy-owned. `NodePopupMenu` mouse-up close/release now uses the retained popup close helper. +Layer-row, animation-timeline, and heightmap-overlay drag release paths now use +the same retained mouse-capture release helper, and brush/grid progress or +recovery message dialogs now route through the retained dialog close 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/legacy_ui_overlay_services.cpp b/src/legacy_ui_overlay_services.cpp index d034720..e4a7a71 100644 --- a/src/legacy_ui_overlay_services.cpp +++ b/src/legacy_ui_overlay_services.cpp @@ -20,6 +20,11 @@ void close_legacy_dialog_node(Node& node) node.destroy(); } +void release_legacy_mouse_capture(Node& node) noexcept +{ + node.mouse_release(); +} + void configure_legacy_popup_overlay(Node& node) noexcept { node.m_mouse_ignore = false; @@ -35,7 +40,7 @@ void activate_legacy_popup_overlay(Node& node) noexcept void close_legacy_popup_overlay(Node& node) noexcept { - node.mouse_release(); + release_legacy_mouse_capture(node); node.destroy(); } @@ -49,7 +54,7 @@ void close_legacy_popup_panel( Node& node, const std::function& on_close) { - node.mouse_release(); + release_legacy_mouse_capture(node); if (node.m_parent) { node.m_parent->remove_child(&node); } diff --git a/src/legacy_ui_overlay_services.h b/src/legacy_ui_overlay_services.h index 27db4d0..242ebc7 100644 --- a/src/legacy_ui_overlay_services.h +++ b/src/legacy_ui_overlay_services.h @@ -14,6 +14,7 @@ namespace pp::panopainter { void initialize_legacy_overlay_node(App& app, Node& node); void close_legacy_dialog_node(Node& node); +void release_legacy_mouse_capture(Node& node) noexcept; void configure_legacy_popup_overlay(Node& node) noexcept; void activate_legacy_popup_overlay(Node& node) noexcept; void close_legacy_popup_overlay(Node& node) noexcept; diff --git a/src/node_panel_animation.cpp b/src/node_panel_animation.cpp index bdd4695..b49a168 100644 --- a/src/node_panel_animation.cpp +++ b/src/node_panel_animation.cpp @@ -3,6 +3,7 @@ #include "app_core/document_animation.h" #include "legacy_document_animation_services.h" #include "legacy_ui_gl_dispatch.h" +#include "legacy_ui_overlay_services.h" #include "node_button.h" #include "node_button_custom.h" #include "canvas.h" @@ -412,12 +413,12 @@ kEventResult NodeAnimationTimeline::handle_event(Event* e) break; case kEventType::MouseUpL: m_dragging = false; - mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*this); break; case kEventType::MouseCancel: m_dragging = false; m_frame = m_drag_start_frame; - mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*this); break; default: return kEventResult::Available; diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index 7a1b666..93ae9d1 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -151,10 +151,10 @@ void NodePanelBrush::init() auto mb = App::I->message_box("Brushes", "Could not read brush textures file, it will be deleted.", true); mb->btn_ok->on_click = [this, mb](Node*) { Asset::delete_file(App::I->data_path + "/settings/" + m_dir_name + ".bin"); - mb->destroy(); + pp::panopainter::close_legacy_dialog_node(*mb); }; mb->btn_cancel->on_click = [mb](Node*) { - mb->destroy(); + pp::panopainter::close_legacy_dialog_node(*mb); }; } @@ -615,7 +615,7 @@ void NodePanelBrushPreset::init() if (plan) { execute_preset_list_plan(plan.value()); } - mb->destroy(); + pp::panopainter::close_legacy_dialog_node(*mb); }; break; } @@ -645,10 +645,10 @@ void NodePanelBrushPreset::init() auto mb = App::I->message_box("Presets", "Could not read brush presets file, it will be deleted.", true); mb->btn_ok->on_click = [mb](Node*) { Asset::delete_file(App::I->data_path + "/settings/presets.bin"); - mb->destroy(); + pp::panopainter::close_legacy_dialog_node(*mb); }; mb->btn_cancel->on_click = [mb](Node*) { - mb->destroy(); + pp::panopainter::close_legacy_dialog_node(*mb); }; } m_notification->SetVisibility(m_container->m_children.size() == 0); @@ -902,7 +902,7 @@ bool NodePanelBrushPreset::export_ppbr(const std::string& path_in, const PPBRInf } f.write((char*)sw.m_data.data(), sw.m_data.size()); - pb->destroy(); + pp::panopainter::close_legacy_dialog_node(*pb); return true; } @@ -1047,7 +1047,7 @@ bool NodePanelBrushPreset::import_ppbr(const std::string& path) save(); App::I->stroke->m_brush_popup->reload(); - pb->destroy(); + pp::panopainter::close_legacy_dialog_node(*pb); return true; } @@ -1143,7 +1143,7 @@ bool NodePanelBrushPreset::import_abr(const std::string& path) save(); App::I->stroke->m_brush_popup->reload(); - pb->destroy(); + pp::panopainter::close_legacy_dialog_node(*pb); return true; } diff --git a/src/node_panel_grid.cpp b/src/node_panel_grid.cpp index 32906ee..2a352f8 100644 --- a/src/node_panel_grid.cpp +++ b/src/node_panel_grid.cpp @@ -497,7 +497,7 @@ void NodePanelGrid::bake_uvs() std::this_thread::sleep_for(std::chrono::milliseconds(100)); } worker.join(); - pb->destroy(); + pp::panopainter::close_legacy_dialog_node(*pb); //stbi_write_jpg("bake-out.jpg", fb.getWidth(), fb.getHeight(), 4, data_out.get(), 75); m_texture.update(data_out.get()); m_texture.create_mipmaps(); @@ -558,7 +558,7 @@ kEventResult NodeHeightmapOverlay::handle_event(Event* e) } break; case kEventType::MouseUpL: - mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*this); dragging = false; break; case kEventType::MouseMove: @@ -573,7 +573,7 @@ kEventResult NodeHeightmapOverlay::handle_event(Event* e) } break; case kEventType::MouseCancel: - mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*this); dragging = false; m_value = m_old_value; set_value(m_value.x, m_value.y); diff --git a/src/node_panel_layer.cpp b/src/node_panel_layer.cpp index 91e8eb4..9be8965 100644 --- a/src/node_panel_layer.cpp +++ b/src/node_panel_layer.cpp @@ -81,7 +81,7 @@ kEventResult NodeLayer::handle_event(Event* e) case kEventType::MouseUpL: if (on_highlight) on_highlight(this, false); - mouse_release(); + pp::panopainter::release_legacy_mouse_capture(*this); break; default: return kEventResult::Available;