From 13b87c13c7de36e5258ff16500ae15a9a9041525 Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Sun, 16 Oct 2022 19:41:42 +0200 Subject: Fix set_as_toplevel event propagation to child In certain conditions events did not get propagated to Control childs of Node2D nodes when setting a parent of the Node2D to toplevel. This patch makes sure that such Control nodes become root control in the viewport. --- scene/gui/control.cpp | 6 ++++++ scene/gui/control.h | 3 +++ scene/main/canvas_item.cpp | 17 +++++++++++++++++ scene/main/canvas_item.h | 3 +++ 4 files changed, 29 insertions(+) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 565e450d60..0e4a6ab0e4 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -679,6 +679,12 @@ Transform2D Control::get_transform() const { return xform; } +void Control::_toplevel_changed_on_parent() { + // Update root control status. + _notification(NOTIFICATION_EXIT_CANVAS); + _notification(NOTIFICATION_ENTER_CANVAS); +} + /// Anchors and offsets. void Control::_set_anchor(Side p_side, real_t p_anchor) { diff --git a/scene/gui/control.h b/scene/gui/control.h index e526690cbe..97b5c54d18 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -288,6 +288,9 @@ private: void _update_minimum_size(); void _size_changed(); + void _toplevel_changed() override{}; // Controls don't need to do anything, only other CanvasItems. + void _toplevel_changed_on_parent() override; + void _clear_size_warning(); // Input events. diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 05d86f77f2..c4bf56c16f 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -401,11 +401,28 @@ void CanvasItem::set_as_top_level(bool p_top_level) { _exit_canvas(); top_level = p_top_level; + _toplevel_changed(); _enter_canvas(); _notify_transform(); } +void CanvasItem::_toplevel_changed() { + // Inform children that toplevel status has changed on a parent. + int childs = get_child_count(); + for (int i = 0; i < childs; i++) { + CanvasItem *child = Object::cast_to(get_child(i)); + if (child) { + child->_toplevel_changed_on_parent(); + } + } +} + +void CanvasItem::_toplevel_changed_on_parent() { + // Inform children that toplevel status has changed on a parent. + _toplevel_changed(); +} + bool CanvasItem::is_set_as_top_level() const { return top_level; } diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index b80289fdb4..e4470e0bd9 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -110,6 +110,9 @@ private: void _propagate_visibility_changed(bool p_parent_visible_in_tree); void _handle_visibility_change(bool p_visible); + virtual void _toplevel_changed(); + virtual void _toplevel_changed_on_parent(); + void _redraw_callback(); void _enter_canvas(); -- cgit v1.2.3