diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index 44351142e0..8cd6c6d82e 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/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(); - tab.m_dom_inspector_window->on_close = [&]() { - tab.m_page_view->document()->set_inspected_node(nullptr); - }; - } - auto* inspector_widget = static_cast(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); diff --git a/Userland/Applications/Browser/BrowserWindow.h b/Userland/Applications/Browser/BrowserWindow.h index c3b81d730d..79716b9143 100644 --- a/Userland/Applications/Browser/BrowserWindow.h +++ b/Userland/Applications/Browser/BrowserWindow.h @@ -7,6 +7,7 @@ #pragma once #include "BookmarksBarWidget.h" +#include "Tab.h" #include "WindowActions.h" #include #include @@ -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 m_select_all_action; RefPtr m_view_source_action; RefPtr m_inspect_dom_tree_action; + RefPtr m_inspect_dom_node_action; CookieJar& m_cookie_jar; WindowActions m_window_actions; diff --git a/Userland/Applications/Browser/InspectorWidget.cpp b/Userland/Applications/Browser/InspectorWidget.cpp index 9863c010f0..3d7ad71857 100644 --- a/Userland/Applications/Browser/InspectorWidget.cpp +++ b/Userland/Applications/Browser/InspectorWidget.cpp @@ -28,6 +28,8 @@ void InspectorWidget::set_inspected_node(GUI::ModelIndex const index) auto* node = static_cast(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(*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(m_dom_tree_view->model())->index_for_node(requested_node)); +} + InspectorWidget::InspectorWidget() { set_layout(); diff --git a/Userland/Applications/Browser/InspectorWidget.h b/Userland/Applications/Browser/InspectorWidget.h index afbd0e1eea..5d1274e3a2 100644 --- a/Userland/Applications/Browser/InspectorWidget.h +++ b/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(); diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index 5bd66626f4..53b4449014 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/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(*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(); + m_dom_inspector_window->on_close = [&]() { + m_page_view->document()->set_inspected_node(nullptr); + }; + } + auto* inspector_widget = static_cast(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(); + } +} + } diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h index 80052b168c..ff9a9c63a0 100644 --- a/Userland/Applications/Browser/Tab.h +++ b/Userland/Applications/Browser/Tab.h @@ -64,6 +64,12 @@ public: Function on_set_cookie; Function 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; }