1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:37:46 +00:00

LibCore+LibGUI+WindowServer: Make events bubble up through ancestors

With this patch, CEvents no longer stop at the target object, but will
bubble up the ancestor chain as long as CEvent::is_accepted() is false.

To the set accepted flag, call CEvent::accept().
To clear the accepted flag, call CEvent::ignore().

Events start out in the accepted state, so if you want them to bubble
up, you have to call ignore() on them.

Using this mechanism, we now ignore non-tabbing keydown events in
GWidget, causing them to bubble up through the widget's ancestors. :^)
This commit is contained in:
Andreas Kling 2019-09-20 20:37:31 +02:00
parent 74c4e62659
commit fcc3745b02
9 changed files with 54 additions and 17 deletions

View file

@ -31,8 +31,13 @@ public:
unsigned type() const { return m_type; }
bool is_accepted() const { return m_accepted; }
void accept() { m_accepted = true; }
void ignore() { m_accepted = false; }
private:
unsigned m_type { Type::Invalid };
bool m_accepted { true };
};
class CDeferredInvocationEvent : public CEvent {

View file

@ -245,7 +245,7 @@ void CEventLoop::pump(WaitMode mode)
#endif
static_cast<CDeferredInvocationEvent&>(event).m_invokee(*receiver);
} else {
receiver->event(event);
receiver->dispatch_event(event);
}
if (m_exit_requested) {

View file

@ -134,3 +134,24 @@ void CObject::save_to(JsonObject& json)
json.set("name", name());
json.set("parent", String::format("%p", parent()));
}
bool CObject::is_ancestor_of(const CObject& other) const
{
if (&other == this)
return false;
for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) {
if (ancestor == this)
return true;
}
return false;
}
void CObject::dispatch_event(CEvent& e, CObject* stay_within)
{
ASSERT(!stay_within || stay_within == this || stay_within->is_ancestor_of(*this));
auto* target = this;
do {
target->event(e);
target = target->parent();
} while (target && target != stay_within && !e.is_accepted());
}

View file

@ -48,6 +48,8 @@ public:
template<typename T, typename Callback>
void for_each_child_of_type(Callback callback);
bool is_ancestor_of(const CObject&) const;
CObject* parent() { return m_parent; }
const CObject* parent() const { return m_parent; }
@ -71,6 +73,8 @@ public:
static IntrusiveList<CObject, &CObject::m_all_objects_list_node>& all_objects();
void dispatch_event(CEvent&, CObject* stay_within = nullptr);
protected:
explicit CObject(CObject* parent = nullptr, bool is_widget = false);