diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index b51b545c637..0877bb1a794 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -453,6 +453,8 @@ ErrorOr Application::launch_devtools_server() m_browser_options.devtools_port = WebView::default_devtools_port; m_devtools = TRY(DevTools::DevToolsServer::create(*this, *m_browser_options.devtools_port)); + on_devtools_enabled(); + return {}; } @@ -683,6 +685,10 @@ void Application::initialize_actions() m_open_settings_page_action = Action::create("Settings"sv, ActionID::OpenSettingsPage, [this]() { open_url_in_new_tab(URL::about_settings(), Web::HTML::ActivateTab::Yes); }); + m_toggle_devtools_action = Action::create("Enable DevTools"sv, ActionID::ToggleDevTools, [this]() { + if (auto result = toggle_devtools_enabled(); result.is_error()) + display_error_dialog(MUST(String::formatted("Unable to start DevTools: {}", result.error()))); + }); m_view_source_action = Action::create("View Source"sv, ActionID::ViewSource, [this]() { if (auto view = active_web_view(); view.has_value()) view->get_source(); @@ -833,15 +839,26 @@ void Application::apply_view_options(Badge, ViewImplementati view.debug_request("navigator-compatibility-mode"sv, m_navigator_compatibility_mode); } -ErrorOr Application::toggle_devtools_enabled() +ErrorOr Application::toggle_devtools_enabled() { if (m_devtools) { m_devtools.clear(); - return DevtoolsState::Disabled; + on_devtools_disabled(); + } else { + TRY(launch_devtools_server()); } - TRY(launch_devtools_server()); - return DevtoolsState::Enabled; + return {}; +} + +void Application::on_devtools_enabled() const +{ + m_toggle_devtools_action->set_text("Disable DevTools"sv); +} + +void Application::on_devtools_disabled() const +{ + m_toggle_devtools_action->set_text("Enable DevTools"sv); } void Application::refresh_tab_list() diff --git a/Libraries/LibWebView/Application.h b/Libraries/LibWebView/Application.h index 37e7761860e..192a6f9fa6f 100644 --- a/Libraries/LibWebView/Application.h +++ b/Libraries/LibWebView/Application.h @@ -83,6 +83,7 @@ public: Action& open_about_page_action() { return *m_open_about_page_action; } Action& open_processes_page_action() { return *m_open_processes_page_action; } Action& open_settings_page_action() { return *m_open_settings_page_action; } + Action& toggle_devtools_action() { return *m_toggle_devtools_action; } Action& view_source_action() { return *m_view_source_action; } Menu& zoom_menu() { return *m_zoom_menu; } @@ -95,11 +96,7 @@ public: void apply_view_options(Badge, ViewImplementation&); - enum class DevtoolsState { - Disabled, - Enabled, - }; - ErrorOr toggle_devtools_enabled(); + ErrorOr toggle_devtools_enabled(); void refresh_tab_list(); protected: @@ -115,6 +112,9 @@ protected: virtual Optional ask_user_for_download_folder() const { return {}; } + virtual void on_devtools_enabled() const; + virtual void on_devtools_disabled() const; + Main::Arguments& arguments() { return m_arguments; } private: @@ -189,6 +189,7 @@ private: RefPtr m_open_about_page_action; RefPtr m_open_processes_page_action; RefPtr m_open_settings_page_action; + RefPtr m_toggle_devtools_action; RefPtr m_view_source_action; RefPtr m_zoom_menu; diff --git a/Libraries/LibWebView/Menu.h b/Libraries/LibWebView/Menu.h index 1ad34bd3b94..716443aaf53 100644 --- a/Libraries/LibWebView/Menu.h +++ b/Libraries/LibWebView/Menu.h @@ -39,6 +39,7 @@ enum class ActionID { OpenAboutPage, OpenProcessesPage, OpenSettingsPage, + ToggleDevTools, ViewSource, OpenInNewTab, diff --git a/UI/AppKit/Application/Application.h b/UI/AppKit/Application/Application.h index b1af6d96e80..c1c6240898d 100644 --- a/UI/AppKit/Application/Application.h +++ b/UI/AppKit/Application/Application.h @@ -26,6 +26,9 @@ private: virtual Optional ask_user_for_download_folder() const override; virtual void display_download_confirmation_dialog(StringView download_name, LexicalPath const& path) const override; virtual void display_error_dialog(StringView error_message) const override; + + virtual void on_devtools_enabled() const override; + virtual void on_devtools_disabled() const override; }; } diff --git a/UI/AppKit/Application/Application.mm b/UI/AppKit/Application/Application.mm index bccaf442a78..30fe6f6a31f 100644 --- a/UI/AppKit/Application/Application.mm +++ b/UI/AppKit/Application/Application.mm @@ -98,6 +98,22 @@ void Application::display_error_dialog(StringView error_message) const completionHandler:nil]; } +void Application::on_devtools_enabled() const +{ + WebView::Application::on_devtools_enabled(); + + ApplicationDelegate* delegate = [NSApp delegate]; + [delegate onDevtoolsEnabled]; +} + +void Application::on_devtools_disabled() const +{ + WebView::Application::on_devtools_disabled(); + + ApplicationDelegate* delegate = [NSApp delegate]; + [delegate onDevtoolsDisabled]; +} + } @interface Application () diff --git a/UI/AppKit/Application/ApplicationDelegate.h b/UI/AppKit/Application/ApplicationDelegate.h index 0c44a7572e7..5c0e001c4e5 100644 --- a/UI/AppKit/Application/ApplicationDelegate.h +++ b/UI/AppKit/Application/ApplicationDelegate.h @@ -37,4 +37,7 @@ - (void)removeTab:(nonnull TabController*)controller; +- (void)onDevtoolsEnabled; +- (void)onDevtoolsDisabled; + @end diff --git a/UI/AppKit/Application/ApplicationDelegate.mm b/UI/AppKit/Application/ApplicationDelegate.mm index d335034624f..1d0f93b3d19 100644 --- a/UI/AppKit/Application/ApplicationDelegate.mm +++ b/UI/AppKit/Application/ApplicationDelegate.mm @@ -25,8 +25,6 @@ @property (nonatomic, strong) InfoBar* info_bar; -@property (nonatomic, strong) NSMenuItem* toggle_devtools_menu_item; - - (NSMenuItem*)createApplicationMenu; - (NSMenuItem*)createFileMenu; - (NSMenuItem*)createEditMenu; @@ -124,6 +122,30 @@ [self.managed_tabs removeObject:controller]; } +- (void)onDevtoolsEnabled +{ + if (!self.info_bar) { + self.info_bar = [[InfoBar alloc] init]; + } + + auto message = MUST(String::formatted("DevTools is enabled on port {}", WebView::Application::browser_options().devtools_port)); + + [self.info_bar showWithMessage:Ladybird::string_to_ns_string(message) + dismissButtonTitle:@"Disable" + dismissButtonClicked:^{ + MUST(WebView::Application::the().toggle_devtools_enabled()); + } + activeTab:self.active_tab]; +} + +- (void)onDevtoolsDisabled +{ + if (self.info_bar) { + [self.info_bar hide]; + self.info_bar = nil; + } +} + #pragma mark - Private methods - (void)openLocation:(id)sender @@ -178,57 +200,6 @@ [current_window close]; } -- (void)toggleDevToolsEnabled:(id)sender -{ - if (auto result = WebView::Application::the().toggle_devtools_enabled(); result.is_error()) { - auto error_message = MUST(String::formatted("Unable to start DevTools: {}", result.error())); - - auto* dialog = [[NSAlert alloc] init]; - [dialog setMessageText:Ladybird::string_to_ns_string(error_message)]; - - [dialog beginSheetModalForWindow:self.active_tab - completionHandler:nil]; - } else { - switch (result.value()) { - case WebView::Application::DevtoolsState::Disabled: - [self devtoolsDisabled]; - break; - case WebView::Application::DevtoolsState::Enabled: - [self devtoolsEnabled]; - break; - } - } -} - -- (void)devtoolsDisabled -{ - [self.toggle_devtools_menu_item setTitle:@"Enable DevTools"]; - - if (self.info_bar) { - [self.info_bar hide]; - self.info_bar = nil; - } -} - -- (void)devtoolsEnabled -{ - [self.toggle_devtools_menu_item setTitle:@"Disable DevTools"]; - - if (!self.info_bar) { - self.info_bar = [[InfoBar alloc] init]; - } - - auto message = MUST(String::formatted("DevTools is enabled on port {}", WebView::Application::browser_options().devtools_port)); - - [self.info_bar showWithMessage:Ladybird::string_to_ns_string(message) - dismissButtonTitle:@"Disable" - dismissButtonClicked:^{ - MUST(WebView::Application::the().toggle_devtools_enabled()); - [self devtoolsDisabled]; - } - activeTab:self.active_tab]; -} - - (void)clearHistory:(id)sender { for (TabController* controller in self.managed_tabs) { @@ -388,12 +359,7 @@ auto* submenu = [[NSMenu alloc] initWithTitle:@"Inspect"]; [submenu addItem:Ladybird::create_application_menu_item(WebView::Application::the().view_source_action())]; - - self.toggle_devtools_menu_item = [[NSMenuItem alloc] initWithTitle:@"Enable DevTools" - action:@selector(toggleDevToolsEnabled:) - keyEquivalent:@"I"]; - [submenu addItem:self.toggle_devtools_menu_item]; - + [submenu addItem:Ladybird::create_application_menu_item(WebView::Application::the().toggle_devtools_action())]; [submenu addItem:Ladybird::create_application_menu_item(WebView::Application::the().open_processes_page_action())]; [menu setSubmenu:submenu]; @@ -439,7 +405,7 @@ auto const& browser_options = WebView::Application::browser_options(); if (browser_options.devtools_port.has_value()) - [self devtoolsEnabled]; + [self onDevtoolsEnabled]; Tab* tab = nil; diff --git a/UI/AppKit/Interface/Menu.mm b/UI/AppKit/Interface/Menu.mm index 0b6e726046f..4fabe122e29 100644 --- a/UI/AppKit/Interface/Menu.mm +++ b/UI/AppKit/Interface/Menu.mm @@ -155,6 +155,10 @@ static void initialize_native_control(WebView::Action& action, id control) set_control_image(control, @"gearshape"); [control setKeyEquivalent:@","]; break; + case WebView::ActionID::ToggleDevTools: + set_control_image(control, @"chevron.left.chevron.right"); + [control setKeyEquivalent:@"I"]; + break; case WebView::ActionID::ViewSource: set_control_image(control, @"text.document"); [control setKeyEquivalent:@"u"]; diff --git a/UI/Qt/Application.cpp b/UI/Qt/Application.cpp index adcdeb578d9..a2235302502 100644 --- a/UI/Qt/Application.cpp +++ b/UI/Qt/Application.cpp @@ -134,4 +134,20 @@ void Application::display_error_dialog(StringView error_message) const QMessageBox::warning(active_tab(), "Ladybird", qstring_from_ak_string(error_message)); } +void Application::on_devtools_enabled() const +{ + WebView::Application::on_devtools_enabled(); + + if (m_active_window) + m_active_window->on_devtools_enabled(); +} + +void Application::on_devtools_disabled() const +{ + WebView::Application::on_devtools_disabled(); + + if (m_active_window) + m_active_window->on_devtools_disabled(); +} + } diff --git a/UI/Qt/Application.h b/UI/Qt/Application.h index 083490ff8e0..5b84fd5112c 100644 --- a/UI/Qt/Application.h +++ b/UI/Qt/Application.h @@ -43,6 +43,9 @@ private: virtual void display_download_confirmation_dialog(StringView download_name, LexicalPath const& path) const override; virtual void display_error_dialog(StringView error_message) const override; + virtual void on_devtools_enabled() const override; + virtual void on_devtools_disabled() const override; + OwnPtr m_application; BrowserWindow* m_active_window { nullptr }; }; diff --git a/UI/Qt/BrowserWindow.cpp b/UI/Qt/BrowserWindow.cpp index f0e41aaf843..f155cf7a6fa 100644 --- a/UI/Qt/BrowserWindow.cpp +++ b/UI/Qt/BrowserWindow.cpp @@ -200,35 +200,10 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, IsPopupWindow }); auto* inspect_menu = m_hamburger_menu->addMenu("&Inspect"); - menuBar()->addMenu(inspect_menu); - - inspect_menu->addAction(create_application_action(*this, Application::the().view_source_action())); - - m_enable_devtools_action = new QAction("Enable &DevTools", this); - m_enable_devtools_action->setIcon(load_icon_from_uri("resource://icons/browser/dom-tree.png"sv)); - m_enable_devtools_action->setShortcuts({ - QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_I), - QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), - QKeySequence(Qt::Key_F12), - }); - inspect_menu->addAction(m_enable_devtools_action); - QObject::connect(m_enable_devtools_action, &QAction::triggered, this, [this] { - if (auto result = WebView::Application::the().toggle_devtools_enabled(); result.is_error()) { - auto error_message = MUST(String::formatted("Unable to start DevTools: {}", result.error())); - QMessageBox::warning(this, "Ladybird", qstring_from_ak_string(error_message)); - } else { - switch (result.value()) { - case WebView::Application::DevtoolsState::Disabled: - devtools_disabled(); - break; - case WebView::Application::DevtoolsState::Enabled: - devtools_enabled(); - break; - } - } - }); - + inspect_menu->addAction(create_application_action(*inspect_menu, Application::the().view_source_action())); + inspect_menu->addAction(create_application_action(*inspect_menu, Application::the().toggle_devtools_action())); inspect_menu->addAction(create_application_action(*inspect_menu, Application::the().open_processes_page_action())); + menuBar()->addMenu(inspect_menu); auto* debug_menu = create_application_menu(*m_hamburger_menu, Application::the().debug_menu()); m_hamburger_menu->addMenu(debug_menu); @@ -301,31 +276,28 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, IsPopupWindow setContextMenuPolicy(Qt::PreventContextMenu); if (browser_options.devtools_port.has_value()) - devtools_enabled(); + on_devtools_enabled(); } -void BrowserWindow::devtools_disabled() -{ - m_enable_devtools_action->setText("Enable &DevTools"); - setStatusBar(nullptr); -} - -void BrowserWindow::devtools_enabled() +void BrowserWindow::on_devtools_enabled() { auto* disable_button = new QPushButton("Disable", this); - connect(disable_button, &QPushButton::clicked, this, [this]() { + connect(disable_button, &QPushButton::clicked, this, []() { MUST(WebView::Application::the().toggle_devtools_enabled()); - devtools_disabled(); }); - m_enable_devtools_action->setText("Disable &DevTools"); statusBar()->addPermanentWidget(disable_button); auto message = MUST(String::formatted("DevTools is enabled on port {}", WebView::Application::browser_options().devtools_port)); statusBar()->showMessage(qstring_from_ak_string(message)); } +void BrowserWindow::on_devtools_disabled() +{ + setStatusBar(nullptr); +} + Tab& BrowserWindow::new_tab_from_url(URL::URL const& url, Web::HTML::ActivateTab activate_tab) { auto& tab = create_new_tab(activate_tab); diff --git a/UI/Qt/BrowserWindow.h b/UI/Qt/BrowserWindow.h index e29cd97f7a5..0d79953523e 100644 --- a/UI/Qt/BrowserWindow.h +++ b/UI/Qt/BrowserWindow.h @@ -51,6 +51,9 @@ public: double refresh_rate() const { return m_refresh_rate; } + void on_devtools_enabled(); + void on_devtools_disabled(); + public slots: void device_pixel_ratio_changed(qreal dpi); void refresh_rate_changed(qreal refresh_rate); @@ -104,9 +107,6 @@ private: double m_device_pixel_ratio { 0 }; double m_refresh_rate { 60.0 }; - void devtools_disabled(); - void devtools_enabled(); - QTabWidget* m_tabs_container { nullptr }; Tab* m_current_tab { nullptr }; @@ -117,7 +117,6 @@ private: QAction* m_new_tab_action { nullptr }; QAction* m_new_window_action { nullptr }; QAction* m_find_in_page_action { nullptr }; - QAction* m_enable_devtools_action { nullptr }; IsPopupWindow m_is_popup_window { IsPopupWindow::No }; }; diff --git a/UI/Qt/Menu.cpp b/UI/Qt/Menu.cpp index 9c8852bd072..6f00d132226 100644 --- a/UI/Qt/Menu.cpp +++ b/UI/Qt/Menu.cpp @@ -114,6 +114,14 @@ static void initialize_native_control(WebView::Action& action, QAction& qaction, qaction.setIcon(load_icon_from_uri("resource://icons/16x16/settings.png"sv)); qaction.setShortcut(QKeySequence::StandardKey::Preferences); break; + case WebView::ActionID::ToggleDevTools: + qaction.setIcon(load_icon_from_uri("resource://icons/browser/dom-tree.png"sv)); + qaction.setShortcuts({ + QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_I), + QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), + QKeySequence(Qt::Key_F12), + }); + break; case WebView::ActionID::ViewSource: qaction.setIcon(load_icon_from_uri("resource://icons/16x16/filetype-html.png"sv)); qaction.setShortcut(QKeySequence(Qt::CTRL | Qt::Key_U));