Serenity Operating System
at hosted 237 lines 6.9 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/Assertions.h> 28#include <AK/Badge.h> 29#include <AK/JsonObject.h> 30#include <LibCore/Event.h> 31#include <LibCore/EventLoop.h> 32#include <LibCore/Object.h> 33#include <stdio.h> 34 35namespace Core { 36 37IntrusiveList<Object, &Object::m_all_objects_list_node>& Object::all_objects() 38{ 39 static IntrusiveList<Object, &Object::m_all_objects_list_node> objects; 40 return objects; 41} 42 43Object::Object(Object* parent, bool is_widget) 44 : m_parent(parent) 45 , m_widget(is_widget) 46{ 47 all_objects().append(*this); 48 if (m_parent) 49 m_parent->add_child(*this); 50} 51 52Object::~Object() 53{ 54 // NOTE: We move our children out to a stack vector to prevent other 55 // code from trying to iterate over them. 56 auto children = move(m_children); 57 // NOTE: We also unparent the children, so that they won't try to unparent 58 // themselves in their own destructors. 59 for (auto& child : children) 60 child.m_parent = nullptr; 61 62 all_objects().remove(*this); 63 stop_timer(); 64 if (m_parent) 65 m_parent->remove_child(*this); 66} 67 68void Object::event(Core::Event& event) 69{ 70 switch (event.type()) { 71 case Core::Event::Timer: 72 return timer_event(static_cast<TimerEvent&>(event)); 73 case Core::Event::ChildAdded: 74 case Core::Event::ChildRemoved: 75 return child_event(static_cast<ChildEvent&>(event)); 76 case Core::Event::Invalid: 77 ASSERT_NOT_REACHED(); 78 break; 79 case Core::Event::Custom: 80 return custom_event(static_cast<CustomEvent&>(event)); 81 default: 82 break; 83 } 84} 85 86void Object::add_child(Object& object) 87{ 88 // FIXME: Should we support reparenting objects? 89 ASSERT(!object.parent() || object.parent() == this); 90 object.m_parent = this; 91 m_children.append(object); 92 event(*make<Core::ChildEvent>(Core::Event::ChildAdded, object)); 93} 94 95void Object::insert_child_before(Object& new_child, Object& before_child) 96{ 97 // FIXME: Should we support reparenting objects? 98 ASSERT(!new_child.parent() || new_child.parent() == this); 99 new_child.m_parent = this; 100 m_children.insert_before_matching(new_child, [&](auto& existing_child) { return existing_child.ptr() == &before_child; }); 101 event(*make<Core::ChildEvent>(Core::Event::ChildAdded, new_child, &before_child)); 102} 103 104void Object::remove_child(Object& object) 105{ 106 for (size_t i = 0; i < m_children.size(); ++i) { 107 if (m_children.ptr_at(i).ptr() == &object) { 108 // NOTE: We protect the child so it survives the handling of ChildRemoved. 109 NonnullRefPtr<Object> protector = object; 110 object.m_parent = nullptr; 111 m_children.remove(i); 112 event(*make<Core::ChildEvent>(Core::Event::ChildRemoved, object)); 113 return; 114 } 115 } 116 ASSERT_NOT_REACHED(); 117} 118 119void Object::timer_event(Core::TimerEvent&) 120{ 121} 122 123void Object::child_event(Core::ChildEvent&) 124{ 125} 126 127void Object::custom_event(CustomEvent&) 128{ 129} 130 131void Object::start_timer(int ms, TimerShouldFireWhenNotVisible fire_when_not_visible) 132{ 133 if (m_timer_id) { 134 dbgprintf("Object{%p} already has a timer!\n", this); 135 ASSERT_NOT_REACHED(); 136 } 137 138 m_timer_id = Core::EventLoop::register_timer(*this, ms, true, fire_when_not_visible); 139} 140 141void Object::stop_timer() 142{ 143 if (!m_timer_id) 144 return; 145 bool success = Core::EventLoop::unregister_timer(m_timer_id); 146 ASSERT(success); 147 m_timer_id = 0; 148} 149 150void Object::dump_tree(int indent) 151{ 152 for (int i = 0; i < indent; ++i) { 153 printf(" "); 154 } 155 printf("%s{%p}\n", class_name(), this); 156 157 for_each_child([&](auto& child) { 158 child.dump_tree(indent + 2); 159 return IterationDecision::Continue; 160 }); 161} 162 163void Object::deferred_invoke(Function<void(Object&)> invokee) 164{ 165 Core::EventLoop::current().post_event(*this, make<Core::DeferredInvocationEvent>(move(invokee))); 166} 167 168void Object::save_to(JsonObject& json) 169{ 170 json.set("class_name", class_name()); 171 json.set("address", (FlatPtr)this); 172 json.set("name", name()); 173 json.set("parent", (FlatPtr)parent()); 174} 175 176bool Object::set_property(const StringView& name, const JsonValue& value) 177{ 178 if (name == "name") { 179 set_name(value.to_string()); 180 return true; 181 } 182 return false; 183} 184 185bool Object::is_ancestor_of(const Object& other) const 186{ 187 if (&other == this) 188 return false; 189 for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { 190 if (ancestor == this) 191 return true; 192 } 193 return false; 194} 195 196void Object::dispatch_event(Core::Event& e, Object* stay_within) 197{ 198 ASSERT(!stay_within || stay_within == this || stay_within->is_ancestor_of(*this)); 199 auto* target = this; 200 do { 201 target->event(e); 202 target = target->parent(); 203 if (target == stay_within) { 204 // Prevent the event from bubbling any further. 205 e.accept(); 206 break; 207 } 208 } while (target && !e.is_accepted()); 209} 210 211bool Object::is_visible_for_timer_purposes() const 212{ 213 if (parent()) 214 return parent()->is_visible_for_timer_purposes(); 215 return true; 216} 217 218void Object::increment_inspector_count(Badge<RPCClient>) 219{ 220 ++m_inspector_count; 221 if (m_inspector_count == 1) 222 did_begin_inspection(); 223} 224 225void Object::decrement_inspector_count(Badge<RPCClient>) 226{ 227 --m_inspector_count; 228 if (!m_inspector_count) 229 did_end_inspection(); 230} 231 232const LogStream& operator<<(const LogStream& stream, const Object& object) 233{ 234 return stream << object.class_name() << '{' << &object << '}'; 235} 236 237}