Forráskód Böngészése

Browser: Add "Inspect Element" to context menu :^)

This opens the DOM Inspector window, with the target element already
selected. (If the window is already open, it just selects the element.)

Note that this only applies to single-process mode for now. In OOP mode,
the "inspect element" action is disabled.
Sam Atkins 3 éve
szülő
commit
37f060b873

+ 8 - 19
Userland/Applications/Browser/BrowserWindow.cpp

@@ -212,29 +212,18 @@ void BrowserWindow::build_menus()
 
     m_inspect_dom_tree_action = GUI::Action::create(
         "Inspect &DOM Tree", { Mod_None, Key_F12 }, [this](auto&) {
-            auto& tab = active_tab();
-            if (tab.m_type == Tab::Type::InProcessWebView) {
-                if (!tab.m_dom_inspector_window) {
-                    tab.m_dom_inspector_window = GUI::Window::construct(this);
-                    tab.m_dom_inspector_window->resize(300, 500);
-                    tab.m_dom_inspector_window->set_title("DOM inspector");
-                    tab.m_dom_inspector_window->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/inspector-object.png"));
-                    tab.m_dom_inspector_window->set_main_widget<InspectorWidget>();
-                    tab.m_dom_inspector_window->on_close = [&]() {
-                        tab.m_page_view->document()->set_inspected_node(nullptr);
-                    };
-                }
-                auto* inspector_widget = static_cast<InspectorWidget*>(tab.m_dom_inspector_window->main_widget());
-                inspector_widget->set_document(tab.m_page_view->document());
-                tab.m_dom_inspector_window->show();
-                tab.m_dom_inspector_window->move_to_front();
-            } else {
-                tab.m_web_content_view->inspect_dom_tree();
-            }
+            active_tab().show_inspector_window(Tab::InspectorTarget::Document);
         },
         this);
     m_inspect_dom_tree_action->set_status_tip("Open DOM inspector window for this page");
 
+    m_inspect_dom_node_action = GUI::Action::create(
+        "&Inspect Element", [this](auto&) {
+            active_tab().show_inspector_window(Tab::InspectorTarget::HoveredElement);
+        },
+        this);
+    m_inspect_dom_node_action->set_status_tip("Open DOM inspector for this element");
+
     auto& inspect_menu = add_menu("&Inspect");
     inspect_menu.add_action(*m_view_source_action);
     inspect_menu.add_action(*m_inspect_dom_tree_action);

+ 3 - 0
Userland/Applications/Browser/BrowserWindow.h

@@ -7,6 +7,7 @@
 #pragma once
 
 #include "BookmarksBarWidget.h"
+#include "Tab.h"
 #include "WindowActions.h"
 #include <LibGUI/ActionGroup.h>
 #include <LibGUI/Window.h>
@@ -34,6 +35,7 @@ public:
     GUI::Action& select_all_action() { return *m_select_all_action; }
     GUI::Action& view_source_action() { return *m_view_source_action; }
     GUI::Action& inspect_dom_tree_action() { return *m_inspect_dom_tree_action; }
+    GUI::Action& inspect_dom_node_action() { return *m_inspect_dom_node_action; }
 
 private:
     explicit BrowserWindow(CookieJar&, URL);
@@ -49,6 +51,7 @@ private:
     RefPtr<GUI::Action> m_select_all_action;
     RefPtr<GUI::Action> m_view_source_action;
     RefPtr<GUI::Action> m_inspect_dom_tree_action;
+    RefPtr<GUI::Action> m_inspect_dom_node_action;
 
     CookieJar& m_cookie_jar;
     WindowActions m_window_actions;

+ 13 - 0
Userland/Applications/Browser/InspectorWidget.cpp

@@ -28,6 +28,8 @@ void InspectorWidget::set_inspected_node(GUI::ModelIndex const index)
     auto* node = static_cast<Web::DOM::Node*>(index.internal_data());
     m_inspected_node = node;
     m_document->set_inspected_node(node);
+    m_dom_tree_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set);
+    m_dom_tree_view->expand_all_parents_of(index);
     if (node && node->is_element()) {
         auto& element = verify_cast<Web::DOM::Element>(*node);
         if (element.specified_css_values()) {
@@ -40,6 +42,17 @@ void InspectorWidget::set_inspected_node(GUI::ModelIndex const index)
     }
 }
 
+void InspectorWidget::set_inspected_node(Web::DOM::Node* requested_node)
+{
+    dbgln("Inspected node: {:p}", requested_node);
+    if (requested_node == nullptr) {
+        set_inspected_node(GUI::ModelIndex {});
+        return;
+    }
+
+    set_inspected_node(static_cast<Web::DOMTreeModel*>(m_dom_tree_view->model())->index_for_node(requested_node));
+}
+
 InspectorWidget::InspectorWidget()
 {
     set_layout<GUI::VerticalBoxLayout>();

+ 1 - 0
Userland/Applications/Browser/InspectorWidget.h

@@ -18,6 +18,7 @@ public:
 
     void set_document(Web::DOM::Document*);
     void set_dom_json(String);
+    void set_inspected_node(Web::DOM::Node*);
 
 private:
     InspectorWidget();

+ 38 - 0
Userland/Applications/Browser/Tab.cpp

@@ -220,6 +220,8 @@ Tab::Tab(BrowserWindow& window, Type type)
     m_link_context_menu->add_action(GUI::Action::create("&Download", [this](auto&) {
         start_download(m_link_context_menu_url);
     }));
+    m_link_context_menu->add_separator();
+    m_link_context_menu->add_action(window.inspect_dom_node_action());
 
     hooks().on_link_context_menu_request = [this](auto& url, auto& screen_position) {
         m_link_context_menu_url = url;
@@ -245,6 +247,8 @@ Tab::Tab(BrowserWindow& window, Type type)
     m_image_context_menu->add_action(GUI::Action::create("&Download", [this](auto&) {
         start_download(m_image_context_menu_url);
     }));
+    m_image_context_menu->add_separator();
+    m_image_context_menu->add_action(window.inspect_dom_node_action());
 
     hooks().on_image_context_menu_request = [this](auto& image_url, auto& screen_position, const Gfx::ShareableBitmap& shareable_bitmap) {
         m_image_context_menu_url = image_url;
@@ -354,9 +358,13 @@ Tab::Tab(BrowserWindow& window, Type type)
     m_page_context_menu->add_separator();
     m_page_context_menu->add_action(window.view_source_action());
     m_page_context_menu->add_action(window.inspect_dom_tree_action());
+    m_page_context_menu->add_action(window.inspect_dom_node_action());
     hooks().on_context_menu_request = [&](auto& screen_position) {
         m_page_context_menu->popup(screen_position);
     };
+
+    // FIXME: This is temporary, until the OOPWV properly supports the DOM Inspector
+    window.inspect_dom_node_action().set_enabled(type == Type::InProcessWebView);
 }
 
 Tab::~Tab()
@@ -504,4 +512,34 @@ BrowserWindow& Tab::window()
     return static_cast<BrowserWindow&>(*Widget::window());
 }
 
+void Tab::show_inspector_window(Browser::Tab::InspectorTarget target)
+{
+    if (m_type == Tab::Type::InProcessWebView) {
+        if (!m_dom_inspector_window) {
+            m_dom_inspector_window = GUI::Window::construct(this);
+            m_dom_inspector_window->resize(300, 500);
+            m_dom_inspector_window->set_title("DOM inspector");
+            m_dom_inspector_window->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/inspector-object.png"));
+            m_dom_inspector_window->set_main_widget<InspectorWidget>();
+            m_dom_inspector_window->on_close = [&]() {
+                m_page_view->document()->set_inspected_node(nullptr);
+            };
+        }
+        auto* inspector_widget = static_cast<InspectorWidget*>(m_dom_inspector_window->main_widget());
+        inspector_widget->set_document(m_page_view->document());
+        switch (target) {
+        case InspectorTarget::Document:
+            inspector_widget->set_inspected_node(nullptr);
+            break;
+        case InspectorTarget::HoveredElement:
+            inspector_widget->set_inspected_node(m_page_view->document()->hovered_node());
+            break;
+        }
+        m_dom_inspector_window->show();
+        m_dom_inspector_window->move_to_front();
+    } else {
+        m_web_content_view->inspect_dom_tree();
+    }
+}
+
 }

+ 6 - 0
Userland/Applications/Browser/Tab.h

@@ -64,6 +64,12 @@ public:
     Function<void(const URL&, const Web::Cookie::ParsedCookie& cookie, Web::Cookie::Source source)> on_set_cookie;
     Function<void()> on_dump_cookies;
 
+    enum class InspectorTarget {
+        Document,
+        HoveredElement
+    };
+    void show_inspector_window(InspectorTarget);
+
     const String& title() const { return m_title; }
     const Gfx::Bitmap* icon() const { return m_icon; }