瀏覽代碼

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.
Andreas Kling 5 年之前
父節點
當前提交
98a6149b4f
共有 4 個文件被更改,包括 24 次插入14 次删除
  1. 6 13
      Libraries/LibGUI/GWidget.cpp
  2. 2 1
      Libraries/LibGUI/GWidget.h
  3. 13 0
      Libraries/LibGUI/GWindow.cpp
  4. 3 0
      Libraries/LibGUI/GWindow.h

+ 6 - 13
Libraries/LibGUI/GWidget.cpp

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

+ 2 - 1
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();
 

+ 13 - 0
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;
+    });
+}

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