From 98a6149b4fe584cda9c2ba0736b513044a3e893e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 26 Oct 2019 12:27:01 +0200 Subject: [PATCH] LibGUI: Make GWindow drive relayout and do it recursively Instead of only doing a relayout in the widget you're invalidating, we now do a recursive top-down relayout so everything gets updated. This fixes invalid results after updating a preferred size in some situations with nested layouts. --- Libraries/LibGUI/GWidget.cpp | 19 ++++++------------- Libraries/LibGUI/GWidget.h | 3 ++- Libraries/LibGUI/GWindow.cpp | 13 +++++++++++++ Libraries/LibGUI/GWindow.h | 3 +++ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Libraries/LibGUI/GWidget.cpp b/Libraries/LibGUI/GWidget.cpp index 07b2fe98e02..a5004de332f 100644 --- a/Libraries/LibGUI/GWidget.cpp +++ b/Libraries/LibGUI/GWidget.cpp @@ -146,6 +146,10 @@ void GWidget::set_layout(OwnPtr&& layout) void GWidget::do_layout() { + for_each_child_widget([&](auto& child) { + child.do_layout(); + return IterationDecision::Continue; + }); custom_layout(); if (!m_layout) return; @@ -434,19 +438,8 @@ void GWidget::set_size_policy(SizePolicy horizontal_policy, SizePolicy vertical_ void GWidget::invalidate_layout() { - if (m_layout_dirty) - return; - m_layout_dirty = true; - deferred_invoke([this](auto&) { - m_layout_dirty = false; - auto* w = window(); - if (!w) - return; - if (!w->main_widget()) - return; - do_layout(); - w->main_widget()->do_layout(); - }); + if (window()) + window()->schedule_relayout(); } void GWidget::set_visible(bool visible) diff --git a/Libraries/LibGUI/GWidget.h b/Libraries/LibGUI/GWidget.h index c5f459e6901..b7acaa773b5 100644 --- a/Libraries/LibGUI/GWidget.h +++ b/Libraries/LibGUI/GWidget.h @@ -201,6 +201,8 @@ public: virtual void save_to(AK::JsonObject&) override; + void do_layout(); + protected: explicit GWidget(GWidget* parent = nullptr); @@ -234,7 +236,6 @@ private: void handle_mouseup_event(GMouseEvent&); void handle_enter_event(CEvent&); void handle_leave_event(CEvent&); - void do_layout(); void focus_previous_widget(); void focus_next_widget(); diff --git a/Libraries/LibGUI/GWindow.cpp b/Libraries/LibGUI/GWindow.cpp index 7620f30acc4..bd03ef61d34 100644 --- a/Libraries/LibGUI/GWindow.cpp +++ b/Libraries/LibGUI/GWindow.cpp @@ -736,3 +736,16 @@ void GWindow::set_fullscreen(bool fullscreen) request.value = fullscreen; GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetFullscreen); } + +void GWindow::schedule_relayout() +{ + if (m_layout_pending) + return; + m_layout_pending = true; + deferred_invoke([this](auto&) { + if (main_widget()) + main_widget()->do_layout(); + update(); + m_layout_pending = false; + }); +} diff --git a/Libraries/LibGUI/GWindow.h b/Libraries/LibGUI/GWindow.h index b33b62dfb1c..ff11e7e10a9 100644 --- a/Libraries/LibGUI/GWindow.h +++ b/Libraries/LibGUI/GWindow.h @@ -131,6 +131,8 @@ public: virtual void save_to(AK::JsonObject&) override; + void schedule_relayout(); + protected: GWindow(CObject* parent = nullptr); virtual void wm_event(GWMEvent&); @@ -175,4 +177,5 @@ private: String m_entered_keybind; int m_max_keybind_length { 0 }; HashMap> m_keyboard_activation_targets; + bool m_layout_pending { false }; };