summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-18 22:57:24 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-18 22:57:24 +0200
commit9e6b0ccc0e1d5f830b82ae719a689d0605e0f607 (patch)
tree2e829b65ee43485e5fdbb1e27c2b2c861bdf75d4
parent0e6b27362045c8f6511cec27c2e2108dd95c105a (diff)
downloadserenity-9e6b0ccc0e1d5f830b82ae719a689d0605e0f607.zip
LibCore+LibGUI: Make CObject child events synchronous.
...and then make GWidget layout invalidation lazy. This way we coalesce multiple invalidations into a single relayout and we don't have to worry about child widgets not being fully constructed.
-rw-r--r--LibCore/CObject.cpp7
-rw-r--r--LibCore/CObject.h5
-rw-r--r--LibGUI/GWidget.cpp22
-rw-r--r--LibGUI/GWidget.h1
4 files changed, 22 insertions, 13 deletions
diff --git a/LibCore/CObject.cpp b/LibCore/CObject.cpp
index 42b471eba0..e4f7392d87 100644
--- a/LibCore/CObject.cpp
+++ b/LibCore/CObject.cpp
@@ -4,8 +4,9 @@
#include <AK/Assertions.h>
#include <stdio.h>
-CObject::CObject(CObject* parent)
+CObject::CObject(CObject* parent, bool is_widget)
: m_parent(parent)
+ , m_widget(is_widget)
{
if (m_parent)
m_parent->add_child(*this);
@@ -43,7 +44,7 @@ void CObject::event(CEvent& event)
void CObject::add_child(CObject& object)
{
m_children.append(&object);
- CEventLoop::current().post_event(*this, make<CChildEvent>(CEvent::ChildAdded, object));
+ event(*make<CChildEvent>(CEvent::ChildAdded, object));
}
void CObject::remove_child(CObject& object)
@@ -51,7 +52,7 @@ void CObject::remove_child(CObject& object)
for (ssize_t i = 0; i < m_children.size(); ++i) {
if (m_children[i] == &object) {
m_children.remove(i);
- CEventLoop::current().post_event(*this, make<CChildEvent>(CEvent::ChildRemoved, object));
+ event(*make<CChildEvent>(CEvent::ChildRemoved, object));
return;
}
}
diff --git a/LibCore/CObject.h b/LibCore/CObject.h
index f8ae55a7b2..e0656b2019 100644
--- a/LibCore/CObject.h
+++ b/LibCore/CObject.h
@@ -10,7 +10,7 @@ class CTimerEvent;
class CObject : public Weakable<CObject> {
public:
- CObject(CObject* parent = nullptr);
+ CObject(CObject* parent = nullptr, bool is_widget = false);
virtual ~CObject();
virtual const char* class_name() const { return "CObject"; }
@@ -36,7 +36,7 @@ public:
void deferred_invoke(Function<void(CObject&)>);
- virtual bool is_widget() const { return false; }
+ bool is_widget() const { return m_widget; }
virtual bool is_window() const { return false; }
protected:
@@ -46,5 +46,6 @@ protected:
private:
CObject* m_parent { nullptr };
int m_timer_id { 0 };
+ bool m_widget { false };
Vector<CObject*> m_children;
};
diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp
index 59c0cb045a..139d3d8ea2 100644
--- a/LibGUI/GWidget.cpp
+++ b/LibGUI/GWidget.cpp
@@ -11,7 +11,7 @@
#include <unistd.h>
GWidget::GWidget(GWidget* parent)
- : CObject(parent)
+ : CObject(parent, true)
{
set_font(nullptr);
m_background_color = Color::LightGray;
@@ -143,7 +143,7 @@ void GWidget::do_layout()
void GWidget::notify_layout_changed(Badge<GLayout>)
{
- do_layout();
+ invalidate_layout();
}
void GWidget::handle_resize_event(GResizeEvent& event)
@@ -395,13 +395,19 @@ void GWidget::set_size_policy(SizePolicy horizontal_policy, SizePolicy vertical_
void GWidget::invalidate_layout()
{
- auto* w = window();
- if (!w)
+ if (m_layout_dirty)
return;
- if (!w->main_widget())
- return;
- do_layout();
- w->main_widget()->do_layout();
+ 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();
+ });
}
void GWidget::set_visible(bool visible)
diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h
index 1b53543cd5..6198365dfe 100644
--- a/LibGUI/GWidget.h
+++ b/LibGUI/GWidget.h
@@ -200,6 +200,7 @@ private:
bool m_visible { true };
bool m_greedy_for_hits { false };
bool m_enabled { true };
+ bool m_layout_dirty { false };
CElapsedTimer m_click_clock;
};