Browse Source

LibCore: Allow RPC clients to specify the currently inspected object

Add a SetInspectedObject call that tells us which Core::Object a remote
client is currently looking it. Objects get notified when they gain
their first inspector, and when they lose their last one.
Andreas Kling 5 năm trước cách đây
mục cha
commit
d16f8214d8
3 tập tin đã thay đổi với 43 bổ sung2 xóa
  1. 15 0
      Libraries/LibCore/EventLoop.cpp
  2. 17 2
      Libraries/LibCore/Object.cpp
  3. 11 0
      Libraries/LibCore/Object.h

+ 15 - 0
Libraries/LibCore/EventLoop.cpp

@@ -112,6 +112,8 @@ public:
     }
     virtual ~RPCClient() override
     {
+        if (m_inspected_object)
+            m_inspected_object->decrement_inspector_count({});
     }
 
     void send_response(const JsonObject& response)
@@ -161,6 +163,18 @@ public:
             return;
         }
 
+        if (type == "SetInspectedObject") {
+            auto address = request.get("address").to_number<uintptr_t>();
+            for (auto& object : Object::all_objects()) {
+                if ((uintptr_t)&object == address) {
+                    if (m_inspected_object)
+                        m_inspected_object->decrement_inspector_count({});
+                    m_inspected_object = object.make_weak_ptr();
+                    m_inspected_object->increment_inspector_count({});
+                }
+            }
+        }
+
         if (type == "Disconnect") {
             shutdown();
             return;
@@ -175,6 +189,7 @@ public:
 
 private:
     RefPtr<LocalSocket> m_socket;
+    WeakPtr<Object> m_inspected_object;
     int m_client_id { -1 };
 };
 

+ 17 - 2
Libraries/LibCore/Object.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Assertions.h>
+#include <AK/Badge.h>
 #include <AK/JsonObject.h>
 #include <LibCore/Event.h>
 #include <LibCore/EventLoop.h>
@@ -167,9 +168,9 @@ void Object::deferred_invoke(Function<void(Object&)> invokee)
 void Object::save_to(JsonObject& json)
 {
     json.set("class_name", class_name());
-    json.set("address", String::format("%p", this));
+    json.set("address", (uintptr_t)this);
     json.set("name", name());
-    json.set("parent", String::format("%p", parent()));
+    json.set("parent", (uintptr_t)parent());
 }
 
 bool Object::is_ancestor_of(const Object& other) const
@@ -205,6 +206,20 @@ bool Object::is_visible_for_timer_purposes() const
     return true;
 }
 
+void Object::increment_inspector_count(Badge<RPCClient>)
+{
+    ++m_inspector_count;
+    if (m_inspector_count == 1)
+        did_begin_inspection();
+}
+
+void Object::decrement_inspector_count(Badge<RPCClient>)
+{
+    --m_inspector_count;
+    if (!m_inspector_count)
+        did_end_inspection();
+}
+
 const LogStream& operator<<(const LogStream& stream, const Object& object)
 {
     return stream << object.class_name() << '{' << &object << '}';

+ 11 - 0
Libraries/LibCore/Object.h

@@ -36,6 +36,8 @@
 
 namespace Core {
 
+class RPCClient;
+
 enum class TimerShouldFireWhenNotVisible {
     No = 0,
     Yes
@@ -130,6 +132,11 @@ public:
 
     virtual bool is_visible_for_timer_purposes() const;
 
+    bool is_being_inspected() const { return m_inspector_count; }
+
+    void increment_inspector_count(Badge<RPCClient>);
+    void decrement_inspector_count(Badge<RPCClient>);
+
 protected:
     explicit Object(Object* parent = nullptr, bool is_widget = false);
 
@@ -139,10 +146,14 @@ protected:
     // NOTE: You may get child events for children that are not yet fully constructed!
     virtual void child_event(ChildEvent&);
 
+    virtual void did_begin_inspection() {}
+    virtual void did_end_inspection() {}
+
 private:
     Object* m_parent { nullptr };
     String m_name;
     int m_timer_id { 0 };
+    unsigned m_inspector_count { 0 };
     bool m_widget { false };
     NonnullRefPtrVector<Object> m_children;
 };