| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-03-28 11:16:33 +02:00
										 |  |  |  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-02-26 09:09:45 -07:00
										 |  |  |  * Copyright (c) 2022, the SerenityOS developers. | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 11:53:16 +02:00
										 |  |  | #include <AK/Assertions.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-05 14:40:47 +01:00
										 |  |  | #include <AK/Badge.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-18 20:36:37 +02:00
										 |  |  | #include <AK/JsonObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 15:04:03 +01:00
										 |  |  | #include <LibCore/Event.h>
 | 
					
						
							|  |  |  | #include <LibCore/EventLoop.h>
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | #include <LibCore/EventReceiver.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-19 00:01:02 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | EventReceiver::EventReceiver(EventReceiver* parent) | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  |     : m_parent(parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  |     if (m_parent) | 
					
						
							| 
									
										
										
										
											2019-01-31 17:31:23 +01:00
										 |  |  |         m_parent->add_child(*this); | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | EventReceiver::~EventReceiver() | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |     // NOTE: We move our children out to a stack vector to prevent other
 | 
					
						
							|  |  |  |     //       code from trying to iterate over them.
 | 
					
						
							|  |  |  |     auto children = move(m_children); | 
					
						
							|  |  |  |     // NOTE: We also unparent the children, so that they won't try to unparent
 | 
					
						
							|  |  |  |     //       themselves in their own destructors.
 | 
					
						
							|  |  |  |     for (auto& child : children) | 
					
						
							| 
									
										
										
										
											2023-03-06 14:17:01 +01:00
										 |  |  |         child->m_parent = nullptr; | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 10:31:37 +01:00
										 |  |  |     stop_timer(); | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  |     if (m_parent) | 
					
						
							| 
									
										
										
										
											2019-01-31 17:31:23 +01:00
										 |  |  |         m_parent->remove_child(*this); | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::event(Core::Event& event) | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (event.type()) { | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     case Core::Event::Timer: | 
					
						
							|  |  |  |         return timer_event(static_cast<TimerEvent&>(event)); | 
					
						
							|  |  |  |     case Core::Event::ChildAdded: | 
					
						
							|  |  |  |     case Core::Event::ChildRemoved: | 
					
						
							|  |  |  |         return child_event(static_cast<ChildEvent&>(event)); | 
					
						
							|  |  |  |     case Core::Event::Invalid: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     case Core::Event::Custom: | 
					
						
							|  |  |  |         return custom_event(static_cast<CustomEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2018-10-10 15:12:38 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | ErrorOr<void> EventReceiver::try_add_child(EventReceiver& object) | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-05 01:09:49 +02:00
										 |  |  |     // FIXME: Should we support reparenting objects?
 | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!object.parent() || object.parent() == this); | 
					
						
							| 
									
										
										
										
											2021-11-24 13:09:51 +01:00
										 |  |  |     TRY(m_children.try_append(object)); | 
					
						
							| 
									
										
										
										
											2019-05-05 01:09:49 +02:00
										 |  |  |     object.m_parent = this; | 
					
						
							| 
									
										
										
										
											2020-07-16 20:44:21 +02:00
										 |  |  |     Core::ChildEvent child_event(Core::Event::ChildAdded, object); | 
					
						
							|  |  |  |     event(child_event); | 
					
						
							| 
									
										
										
										
											2021-11-24 13:09:51 +01:00
										 |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::add_child(EventReceiver& object) | 
					
						
							| 
									
										
										
										
											2021-11-24 13:09:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     MUST(try_add_child(object)); | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::insert_child_before(EventReceiver& new_child, EventReceiver& before_child) | 
					
						
							| 
									
										
										
										
											2019-11-05 20:41:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // FIXME: Should we support reparenting objects?
 | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!new_child.parent() || new_child.parent() == this); | 
					
						
							| 
									
										
										
										
											2019-11-05 20:41:27 +01:00
										 |  |  |     new_child.m_parent = this; | 
					
						
							|  |  |  |     m_children.insert_before_matching(new_child, [&](auto& existing_child) { return existing_child.ptr() == &before_child; }); | 
					
						
							| 
									
										
										
										
											2020-07-16 20:44:21 +02:00
										 |  |  |     Core::ChildEvent child_event(Core::Event::ChildAdded, new_child, &before_child); | 
					
						
							|  |  |  |     event(child_event); | 
					
						
							| 
									
										
										
										
											2019-11-05 20:41:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::remove_child(EventReceiver& object) | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |     for (size_t i = 0; i < m_children.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2023-03-06 14:17:01 +01:00
										 |  |  |         if (m_children[i] == &object) { | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |             // NOTE: We protect the child so it survives the handling of ChildRemoved.
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  |             NonnullRefPtr<EventReceiver> protector = object; | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |             object.m_parent = nullptr; | 
					
						
							| 
									
										
										
										
											2018-10-13 01:19:25 +02:00
										 |  |  |             m_children.remove(i); | 
					
						
							| 
									
										
										
										
											2020-07-16 20:44:21 +02:00
										 |  |  |             Core::ChildEvent child_event(Core::Event::ChildRemoved, object); | 
					
						
							|  |  |  |             event(child_event); | 
					
						
							| 
									
										
										
										
											2018-10-13 01:19:25 +02:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2018-10-10 16:49:36 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::remove_all_children() | 
					
						
							| 
									
										
										
										
											2020-12-27 17:14:44 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     while (!m_children.is_empty()) | 
					
						
							| 
									
										
										
										
											2023-03-06 14:17:01 +01:00
										 |  |  |         m_children.first()->remove_from_parent(); | 
					
						
							| 
									
										
										
										
											2020-12-27 17:14:44 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::timer_event(Core::TimerEvent&) | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::child_event(Core::ChildEvent&) | 
					
						
							| 
									
										
										
										
											2019-03-15 16:12:06 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::custom_event(CustomEvent&) | 
					
						
							| 
									
										
										
										
											2019-07-14 10:27:27 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::start_timer(int ms, TimerShouldFireWhenNotVisible fire_when_not_visible) | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-31 17:31:23 +01:00
										 |  |  |     if (m_timer_id) { | 
					
						
							| 
									
										
										
										
											2021-01-10 10:02:20 +01:00
										 |  |  |         dbgln("{} {:p} already has a timer!", class_name(), this); | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-01 03:50:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     m_timer_id = Core::EventLoop::register_timer(*this, ms, true, fire_when_not_visible); | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::stop_timer() | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-31 17:31:23 +01:00
										 |  |  |     if (!m_timer_id) | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     bool success = Core::EventLoop::unregister_timer(m_timer_id); | 
					
						
							| 
									
										
										
										
											2023-04-24 12:25:14 +02:00
										 |  |  |     if (!success) { | 
					
						
							| 
									
										
										
										
											2023-09-01 10:04:45 +02:00
										 |  |  |         dbgln("{:p} could not unregister timer {}", this, m_timer_id); | 
					
						
							| 
									
										
										
										
											2023-04-24 12:25:14 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-31 17:31:23 +01:00
										 |  |  |     m_timer_id = 0; | 
					
						
							| 
									
										
										
										
											2018-10-12 12:18:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::deferred_invoke(Function<void()> invokee) | 
					
						
							| 
									
										
										
										
											2021-08-30 10:43:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     Core::deferred_invoke([invokee = move(invokee), strong_this = NonnullRefPtr(*this)] { invokee(); }); | 
					
						
							| 
									
										
										
										
											2019-03-19 00:01:02 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-18 20:36:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | bool EventReceiver::is_ancestor_of(EventReceiver const& other) const | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (&other == this) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { | 
					
						
							|  |  |  |         if (ancestor == this) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::dispatch_event(Core::Event& e, EventReceiver* stay_within) | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!stay_within || stay_within == this || stay_within->is_ancestor_of(*this)); | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  |     auto* target = this; | 
					
						
							|  |  |  |     do { | 
					
						
							| 
									
										
										
										
											2021-03-28 11:16:33 +02:00
										 |  |  |         // If there's an event filter on this target, ask if it wants to swallow this event.
 | 
					
						
							|  |  |  |         if (target->m_event_filter && !target->m_event_filter(e)) | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  |         target->event(e); | 
					
						
							|  |  |  |         target = target->parent(); | 
					
						
							| 
									
										
										
										
											2020-01-21 21:37:49 +01:00
										 |  |  |         if (target == stay_within) { | 
					
						
							|  |  |  |             // Prevent the event from bubbling any further.
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:01:11 +01:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-01-21 21:37:49 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-23 18:08:18 +01:00
										 |  |  |     } while (target && !e.is_accepted()); | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-12-29 15:58:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | bool EventReceiver::is_visible_for_timer_purposes() const | 
					
						
							| 
									
										
										
										
											2019-12-29 15:58:07 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (parent()) | 
					
						
							|  |  |  |         return parent()->is_visible_for_timer_purposes(); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 18:09:39 +02:00
										 |  |  | void EventReceiver::set_event_filter(Function<bool(Core::Event&)> filter) | 
					
						
							| 
									
										
										
										
											2021-03-28 11:16:33 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     m_event_filter = move(filter); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | } |