Serenity Operating System
at master 294 lines 8.0 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, the SerenityOS developers. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/Assertions.h> 9#include <AK/Badge.h> 10#include <AK/JsonObject.h> 11#include <LibCore/Event.h> 12#include <LibCore/EventLoop.h> 13#include <LibCore/Object.h> 14#include <stdio.h> 15 16namespace Core { 17 18IntrusiveList<&Object::m_all_objects_list_node>& Object::all_objects() 19{ 20 static IntrusiveList<&Object::m_all_objects_list_node> objects; 21 return objects; 22} 23 24Object::Object(Object* parent) 25 : m_parent(parent) 26{ 27 all_objects().append(*this); 28 if (m_parent) 29 m_parent->add_child(*this); 30 31 REGISTER_READONLY_STRING_PROPERTY("class_name", class_name); 32 REGISTER_STRING_PROPERTY("name", name, set_name); 33 34 register_property( 35 "address", [this] { return FlatPtr(this); }, 36 [](auto&) { return false; }); 37 38 register_property( 39 "parent", [this] { return FlatPtr(this->parent()); }, 40 [](auto&) { return false; }); 41} 42 43Object::~Object() 44{ 45 // NOTE: We move our children out to a stack vector to prevent other 46 // code from trying to iterate over them. 47 auto children = move(m_children); 48 // NOTE: We also unparent the children, so that they won't try to unparent 49 // themselves in their own destructors. 50 for (auto& child : children) 51 child->m_parent = nullptr; 52 53 all_objects().remove(*this); 54 stop_timer(); 55 if (m_parent) 56 m_parent->remove_child(*this); 57} 58 59void Object::event(Core::Event& event) 60{ 61 switch (event.type()) { 62 case Core::Event::Timer: 63 return timer_event(static_cast<TimerEvent&>(event)); 64 case Core::Event::ChildAdded: 65 case Core::Event::ChildRemoved: 66 return child_event(static_cast<ChildEvent&>(event)); 67 case Core::Event::Invalid: 68 VERIFY_NOT_REACHED(); 69 break; 70 case Core::Event::Custom: 71 return custom_event(static_cast<CustomEvent&>(event)); 72 default: 73 break; 74 } 75} 76 77ErrorOr<void> Object::try_add_child(Object& object) 78{ 79 // FIXME: Should we support reparenting objects? 80 VERIFY(!object.parent() || object.parent() == this); 81 TRY(m_children.try_append(object)); 82 object.m_parent = this; 83 Core::ChildEvent child_event(Core::Event::ChildAdded, object); 84 event(child_event); 85 return {}; 86} 87 88void Object::add_child(Object& object) 89{ 90 MUST(try_add_child(object)); 91} 92 93void Object::insert_child_before(Object& new_child, Object& before_child) 94{ 95 // FIXME: Should we support reparenting objects? 96 VERIFY(!new_child.parent() || new_child.parent() == this); 97 new_child.m_parent = this; 98 m_children.insert_before_matching(new_child, [&](auto& existing_child) { return existing_child.ptr() == &before_child; }); 99 Core::ChildEvent child_event(Core::Event::ChildAdded, new_child, &before_child); 100 event(child_event); 101} 102 103void Object::remove_child(Object& object) 104{ 105 for (size_t i = 0; i < m_children.size(); ++i) { 106 if (m_children[i] == &object) { 107 // NOTE: We protect the child so it survives the handling of ChildRemoved. 108 NonnullRefPtr<Object> protector = object; 109 object.m_parent = nullptr; 110 m_children.remove(i); 111 Core::ChildEvent child_event(Core::Event::ChildRemoved, object); 112 event(child_event); 113 return; 114 } 115 } 116 VERIFY_NOT_REACHED(); 117} 118 119void Object::remove_all_children() 120{ 121 while (!m_children.is_empty()) 122 m_children.first()->remove_from_parent(); 123} 124 125void Object::timer_event(Core::TimerEvent&) 126{ 127} 128 129void Object::child_event(Core::ChildEvent&) 130{ 131} 132 133void Object::custom_event(CustomEvent&) 134{ 135} 136 137void Object::start_timer(int ms, TimerShouldFireWhenNotVisible fire_when_not_visible) 138{ 139 if (m_timer_id) { 140 dbgln("{} {:p} already has a timer!", class_name(), this); 141 VERIFY_NOT_REACHED(); 142 } 143 144 m_timer_id = Core::EventLoop::register_timer(*this, ms, true, fire_when_not_visible); 145} 146 147void Object::stop_timer() 148{ 149 if (!m_timer_id) 150 return; 151 bool success = Core::EventLoop::unregister_timer(m_timer_id); 152 VERIFY(success); 153 m_timer_id = 0; 154} 155 156void Object::dump_tree(int indent) 157{ 158 for (int i = 0; i < indent; ++i) { 159 out(" "); 160 } 161 out("{}{{{:p}}}", class_name(), this); 162 if (!name().is_null()) 163 out(" {}", name()); 164 outln(); 165 166 for_each_child([&](auto& child) { 167 child.dump_tree(indent + 2); 168 return IterationDecision::Continue; 169 }); 170} 171 172void Object::deferred_invoke(Function<void()> invokee) 173{ 174 Core::deferred_invoke([invokee = move(invokee), strong_this = NonnullRefPtr(*this)] { invokee(); }); 175} 176 177void Object::save_to(JsonObject& json) 178{ 179 for (auto& it : m_properties) { 180 auto& property = it.value; 181 json.set(property->name(), property->get()); 182 } 183} 184 185JsonValue Object::property(DeprecatedString const& name) const 186{ 187 auto it = m_properties.find(name); 188 if (it == m_properties.end()) 189 return JsonValue(); 190 return it->value->get(); 191} 192 193bool Object::set_property(DeprecatedString const& name, JsonValue const& value) 194{ 195 auto it = m_properties.find(name); 196 if (it == m_properties.end()) 197 return false; 198 return it->value->set(value); 199} 200 201bool Object::is_ancestor_of(Object const& other) const 202{ 203 if (&other == this) 204 return false; 205 for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { 206 if (ancestor == this) 207 return true; 208 } 209 return false; 210} 211 212void Object::dispatch_event(Core::Event& e, Object* stay_within) 213{ 214 VERIFY(!stay_within || stay_within == this || stay_within->is_ancestor_of(*this)); 215 auto* target = this; 216 do { 217 // If there's an event filter on this target, ask if it wants to swallow this event. 218 if (target->m_event_filter && !target->m_event_filter(e)) 219 return; 220 target->event(e); 221 target = target->parent(); 222 if (target == stay_within) { 223 // Prevent the event from bubbling any further. 224 return; 225 } 226 } while (target && !e.is_accepted()); 227} 228 229bool Object::is_visible_for_timer_purposes() const 230{ 231 if (parent()) 232 return parent()->is_visible_for_timer_purposes(); 233 return true; 234} 235 236void Object::increment_inspector_count(Badge<InspectorServerConnection>) 237{ 238 ++m_inspector_count; 239 if (m_inspector_count == 1) 240 did_begin_inspection(); 241} 242 243void Object::decrement_inspector_count(Badge<InspectorServerConnection>) 244{ 245 --m_inspector_count; 246 if (!m_inspector_count) 247 did_end_inspection(); 248} 249 250void Object::register_property(DeprecatedString const& name, Function<JsonValue()> getter, Function<bool(JsonValue const&)> setter) 251{ 252 m_properties.set(name, make<Property>(name, move(getter), move(setter))); 253} 254 255void Object::set_event_filter(Function<bool(Core::Event&)> filter) 256{ 257 m_event_filter = move(filter); 258} 259 260static HashMap<StringView, ObjectClassRegistration*>& object_classes() 261{ 262 static HashMap<StringView, ObjectClassRegistration*> s_map; 263 return s_map; 264} 265 266ObjectClassRegistration::ObjectClassRegistration(StringView class_name, Function<ErrorOr<NonnullRefPtr<Object>>()> factory, ObjectClassRegistration* parent_class) 267 : m_class_name(class_name) 268 , m_factory(move(factory)) 269 , m_parent_class(parent_class) 270{ 271 object_classes().set(class_name, this); 272} 273 274bool ObjectClassRegistration::is_derived_from(ObjectClassRegistration const& base_class) const 275{ 276 if (&base_class == this) 277 return true; 278 if (!m_parent_class) 279 return false; 280 return m_parent_class->is_derived_from(base_class); 281} 282 283void ObjectClassRegistration::for_each(Function<void(ObjectClassRegistration const&)> callback) 284{ 285 for (auto& it : object_classes()) { 286 callback(*it.value); 287 } 288} 289 290ObjectClassRegistration const* ObjectClassRegistration::find(StringView class_name) 291{ 292 return object_classes().get(class_name).value_or(nullptr); 293} 294}