mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-19 15:43:20 +00:00
LibWebView+UI: Generate action to enable/disable DevTools
This commit is contained in:
parent
6d30b0f4d4
commit
14d49d5a3a
Notes:
github-actions[bot]
2025-09-18 11:28:44 +00:00
Author: https://github.com/trflynn89
Commit: 14d49d5a3a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6221
Reviewed-by: https://github.com/AtkinsSJ
Reviewed-by: https://github.com/konradekk
13 changed files with 121 additions and 112 deletions
|
@ -453,6 +453,8 @@ ErrorOr<void> 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<ViewImplementation>, ViewImplementati
|
|||
view.debug_request("navigator-compatibility-mode"sv, m_navigator_compatibility_mode);
|
||||
}
|
||||
|
||||
ErrorOr<Application::DevtoolsState> Application::toggle_devtools_enabled()
|
||||
ErrorOr<void> 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()
|
||||
|
|
|
@ -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>, ViewImplementation&);
|
||||
|
||||
enum class DevtoolsState {
|
||||
Disabled,
|
||||
Enabled,
|
||||
};
|
||||
ErrorOr<DevtoolsState> toggle_devtools_enabled();
|
||||
ErrorOr<void> toggle_devtools_enabled();
|
||||
void refresh_tab_list();
|
||||
|
||||
protected:
|
||||
|
@ -115,6 +112,9 @@ protected:
|
|||
|
||||
virtual Optional<ByteString> 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<Action> m_open_about_page_action;
|
||||
RefPtr<Action> m_open_processes_page_action;
|
||||
RefPtr<Action> m_open_settings_page_action;
|
||||
RefPtr<Action> m_toggle_devtools_action;
|
||||
RefPtr<Action> m_view_source_action;
|
||||
|
||||
RefPtr<Menu> m_zoom_menu;
|
||||
|
|
|
@ -39,6 +39,7 @@ enum class ActionID {
|
|||
OpenAboutPage,
|
||||
OpenProcessesPage,
|
||||
OpenSettingsPage,
|
||||
ToggleDevTools,
|
||||
ViewSource,
|
||||
|
||||
OpenInNewTab,
|
||||
|
|
|
@ -26,6 +26,9 @@ private:
|
|||
virtual Optional<ByteString> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -37,4 +37,7 @@
|
|||
|
||||
- (void)removeTab:(nonnull TabController*)controller;
|
||||
|
||||
- (void)onDevtoolsEnabled;
|
||||
- (void)onDevtoolsDisabled;
|
||||
|
||||
@end
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<QApplication> m_application;
|
||||
BrowserWindow* m_active_window { nullptr };
|
||||
};
|
||||
|
|
|
@ -200,35 +200,10 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> 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<URL::URL> 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);
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue