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.
This commit is contained in:
Andreas Kling 2019-10-26 12:27:01 +02:00
parent d0799f3648
commit 98a6149b4f
Notes: sideshowbarker 2024-07-19 11:32:20 +09:00
4 changed files with 24 additions and 14 deletions

View file

@ -146,6 +146,10 @@ void GWidget::set_layout(OwnPtr<GLayout>&& 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)

View file

@ -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();

View file

@ -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;
});
}

View file

@ -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<String, WeakPtr<GWidget>> m_keyboard_activation_targets;
bool m_layout_pending { false };
};