Centralize retained drag capture release

This commit is contained in:
2026-06-12 16:09:19 +02:00
parent 22748d9967
commit 9ac2c541dc
8 changed files with 31 additions and 16 deletions

View File

@@ -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 - 2026-06-12: DEBT-0063 was narrowed again. `NodePopupMenu` mouse-up release and
destroy now route through the retained popup close helper in destroy now route through the retained popup close helper in
`src/legacy_ui_overlay_services.*`. `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 - 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 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 2026 generator validation does not depend on an older `cmake` on PATH, and

View File

@@ -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 Floating-panel close and drag-outline cleanup now use the same retained close
helper while drag reparenting remains legacy-owned. helper while drag reparenting remains legacy-owned.
`NodePopupMenu` mouse-up close/release now uses the retained popup close helper. `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 Raw popup callback captures and full close/capture ownership remain part of
`DEBT-0063`. `DEBT-0063`.
`pano_cli inspect-image` exposes PNG IHDR metadata as JSON, `pano_cli inspect-image` exposes PNG IHDR metadata as JSON,

View File

@@ -20,6 +20,11 @@ void close_legacy_dialog_node(Node& node)
node.destroy(); node.destroy();
} }
void release_legacy_mouse_capture(Node& node) noexcept
{
node.mouse_release();
}
void configure_legacy_popup_overlay(Node& node) noexcept void configure_legacy_popup_overlay(Node& node) noexcept
{ {
node.m_mouse_ignore = false; 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 void close_legacy_popup_overlay(Node& node) noexcept
{ {
node.mouse_release(); release_legacy_mouse_capture(node);
node.destroy(); node.destroy();
} }
@@ -49,7 +54,7 @@ void close_legacy_popup_panel(
Node& node, Node& node,
const std::function<void(Node*)>& on_close) const std::function<void(Node*)>& on_close)
{ {
node.mouse_release(); release_legacy_mouse_capture(node);
if (node.m_parent) { if (node.m_parent) {
node.m_parent->remove_child(&node); node.m_parent->remove_child(&node);
} }

View File

@@ -14,6 +14,7 @@ namespace pp::panopainter {
void initialize_legacy_overlay_node(App& app, Node& node); void initialize_legacy_overlay_node(App& app, Node& node);
void close_legacy_dialog_node(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 configure_legacy_popup_overlay(Node& node) noexcept;
void activate_legacy_popup_overlay(Node& node) noexcept; void activate_legacy_popup_overlay(Node& node) noexcept;
void close_legacy_popup_overlay(Node& node) noexcept; void close_legacy_popup_overlay(Node& node) noexcept;

View File

@@ -3,6 +3,7 @@
#include "app_core/document_animation.h" #include "app_core/document_animation.h"
#include "legacy_document_animation_services.h" #include "legacy_document_animation_services.h"
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
#include "legacy_ui_overlay_services.h"
#include "node_button.h" #include "node_button.h"
#include "node_button_custom.h" #include "node_button_custom.h"
#include "canvas.h" #include "canvas.h"
@@ -412,12 +413,12 @@ kEventResult NodeAnimationTimeline::handle_event(Event* e)
break; break;
case kEventType::MouseUpL: case kEventType::MouseUpL:
m_dragging = false; m_dragging = false;
mouse_release(); pp::panopainter::release_legacy_mouse_capture(*this);
break; break;
case kEventType::MouseCancel: case kEventType::MouseCancel:
m_dragging = false; m_dragging = false;
m_frame = m_drag_start_frame; m_frame = m_drag_start_frame;
mouse_release(); pp::panopainter::release_legacy_mouse_capture(*this);
break; break;
default: default:
return kEventResult::Available; return kEventResult::Available;

View File

@@ -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); 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*) { mb->btn_ok->on_click = [this, mb](Node*) {
Asset::delete_file(App::I->data_path + "/settings/" + m_dir_name + ".bin"); 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->btn_cancel->on_click = [mb](Node*) {
mb->destroy(); pp::panopainter::close_legacy_dialog_node(*mb);
}; };
} }
@@ -615,7 +615,7 @@ void NodePanelBrushPreset::init()
if (plan) { if (plan) {
execute_preset_list_plan(plan.value()); execute_preset_list_plan(plan.value());
} }
mb->destroy(); pp::panopainter::close_legacy_dialog_node(*mb);
}; };
break; 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); 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*) { mb->btn_ok->on_click = [mb](Node*) {
Asset::delete_file(App::I->data_path + "/settings/presets.bin"); 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->btn_cancel->on_click = [mb](Node*) {
mb->destroy(); pp::panopainter::close_legacy_dialog_node(*mb);
}; };
} }
m_notification->SetVisibility(m_container->m_children.size() == 0); 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()); f.write((char*)sw.m_data.data(), sw.m_data.size());
pb->destroy(); pp::panopainter::close_legacy_dialog_node(*pb);
return true; return true;
} }
@@ -1047,7 +1047,7 @@ bool NodePanelBrushPreset::import_ppbr(const std::string& path)
save(); save();
App::I->stroke->m_brush_popup->reload(); App::I->stroke->m_brush_popup->reload();
pb->destroy(); pp::panopainter::close_legacy_dialog_node(*pb);
return true; return true;
} }
@@ -1143,7 +1143,7 @@ bool NodePanelBrushPreset::import_abr(const std::string& path)
save(); save();
App::I->stroke->m_brush_popup->reload(); App::I->stroke->m_brush_popup->reload();
pb->destroy(); pp::panopainter::close_legacy_dialog_node(*pb);
return true; return true;
} }

View File

@@ -497,7 +497,7 @@ void NodePanelGrid::bake_uvs()
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
worker.join(); 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); //stbi_write_jpg("bake-out.jpg", fb.getWidth(), fb.getHeight(), 4, data_out.get(), 75);
m_texture.update(data_out.get()); m_texture.update(data_out.get());
m_texture.create_mipmaps(); m_texture.create_mipmaps();
@@ -558,7 +558,7 @@ kEventResult NodeHeightmapOverlay::handle_event(Event* e)
} }
break; break;
case kEventType::MouseUpL: case kEventType::MouseUpL:
mouse_release(); pp::panopainter::release_legacy_mouse_capture(*this);
dragging = false; dragging = false;
break; break;
case kEventType::MouseMove: case kEventType::MouseMove:
@@ -573,7 +573,7 @@ kEventResult NodeHeightmapOverlay::handle_event(Event* e)
} }
break; break;
case kEventType::MouseCancel: case kEventType::MouseCancel:
mouse_release(); pp::panopainter::release_legacy_mouse_capture(*this);
dragging = false; dragging = false;
m_value = m_old_value; m_value = m_old_value;
set_value(m_value.x, m_value.y); set_value(m_value.x, m_value.y);

View File

@@ -81,7 +81,7 @@ kEventResult NodeLayer::handle_event(Event* e)
case kEventType::MouseUpL: case kEventType::MouseUpL:
if (on_highlight) if (on_highlight)
on_highlight(this, false); on_highlight(this, false);
mouse_release(); pp::panopainter::release_legacy_mouse_capture(*this);
break; break;
default: default:
return kEventResult::Available; return kEventResult::Available;