From 6b5deb22597f16a69dd01d61f7990e0c652a2474 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Fri, 26 Apr 2024 18:53:55 -0600 Subject: [PATCH] Ladybird: Support multiple browser windows in Qt chrome This also moves the ownership of the TaskManger to the Application. --- Ladybird/Qt/Application.cpp | 35 +++++++++++++++++++++++++++++++ Ladybird/Qt/Application.h | 15 ++++++++++++++ Ladybird/Qt/BrowserWindow.cpp | 34 ++++++++++++++---------------- Ladybird/Qt/BrowserWindow.h | 12 +++++------ Ladybird/Qt/main.cpp | 39 +++++++++++++++++++---------------- 5 files changed, 93 insertions(+), 42 deletions(-) diff --git a/Ladybird/Qt/Application.cpp b/Ladybird/Qt/Application.cpp index d305cfd03dd..73dc6e1726b 100644 --- a/Ladybird/Qt/Application.cpp +++ b/Ladybird/Qt/Application.cpp @@ -6,6 +6,7 @@ #include "Application.h" #include "StringUtils.h" +#include "TaskManagerWindow.h" #include #include @@ -16,6 +17,11 @@ Application::Application(int& argc, char** argv) { } +Application::~Application() +{ + close_task_manager_window(); +} + bool Application::event(QEvent* event) { switch (event->type()) { @@ -37,4 +43,33 @@ bool Application::event(QEvent* event) return QApplication::event(event); } +void Application::show_task_manager_window() +{ + if (!m_task_manager_window) { + m_task_manager_window = new TaskManagerWindow(nullptr); + } + m_task_manager_window->show(); + m_task_manager_window->activateWindow(); + m_task_manager_window->raise(); +} + +void Application::close_task_manager_window() +{ + if (m_task_manager_window) { + m_task_manager_window->close(); + delete m_task_manager_window; + m_task_manager_window = nullptr; + } +} + +BrowserWindow& Application::new_window(Vector const& initial_urls, WebView::CookieJar& cookie_jar, WebContentOptions const& web_content_options, StringView webdriver_content_ipc_path) +{ + auto* window = new BrowserWindow(initial_urls, cookie_jar, web_content_options, webdriver_content_ipc_path); + set_active_window(*window); + window->show(); + window->activateWindow(); + window->raise(); + return *window; +} + } diff --git a/Ladybird/Qt/Application.h b/Ladybird/Qt/Application.h index d0abd5dfae9..5a1a5d1b9e7 100644 --- a/Ladybird/Qt/Application.h +++ b/Ladybird/Qt/Application.h @@ -7,6 +7,8 @@ #pragma once #include +#include +#include #include #include #include @@ -18,11 +20,24 @@ class Application : public QApplication { public: Application(int& argc, char** argv); + virtual ~Application() override; virtual bool event(QEvent* event) override; Function on_open_file; RefPtr request_server_client; + + BrowserWindow& new_window(Vector const& initial_urls, WebView::CookieJar&, WebContentOptions const&, StringView webdriver_content_ipc_path); + + void show_task_manager_window(); + void close_task_manager_window(); + + BrowserWindow& active_window() { return *m_active_window; } + void set_active_window(BrowserWindow& w) { m_active_window = &w; } + +private: + TaskManagerWindow* m_task_manager_window { nullptr }; + BrowserWindow* m_active_window { nullptr }; }; } diff --git a/Ladybird/Qt/BrowserWindow.cpp b/Ladybird/Qt/BrowserWindow.cpp index afdba38901a..0206641bc50 100644 --- a/Ladybird/Qt/BrowserWindow.cpp +++ b/Ladybird/Qt/BrowserWindow.cpp @@ -8,6 +8,7 @@ */ #include "BrowserWindow.h" +#include "Application.h" #include "Icon.h" #include "Settings.h" #include "SettingsDialog.h" @@ -82,6 +83,10 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, WebView::Cook m_new_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::AddTab)); menu->addAction(m_new_tab_action); + m_new_window_action = new QAction("New &Window", this); + m_new_window_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::New)); + menu->addAction(m_new_window_action); + auto* close_current_tab_action = new QAction("&Close Current Tab", this); close_current_tab_action->setIcon(load_icon_from_uri("resource://icons/16x16/close-tab.png"sv)); close_current_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Close)); @@ -213,8 +218,8 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, WebView::Cook task_manager_action->setIcon(load_icon_from_uri("resource://icons/16x16/app-system-monitor.png"sv)); task_manager_action->setShortcuts({ QKeySequence("Ctrl+Shift+M") }); inspect_menu->addAction(task_manager_action); - QObject::connect(task_manager_action, &QAction::triggered, this, [this] { - show_task_manager_window(); + QObject::connect(task_manager_action, &QAction::triggered, this, [] { + static_cast(QApplication::instance())->show_task_manager_window(); }); auto* debug_menu = menuBar()->addMenu("&Debug"); @@ -391,6 +396,10 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, WebView::Cook QObject::connect(m_new_tab_action, &QAction::triggered, this, [this] { new_tab_from_url(ak_url_from_qstring(Settings::the()->new_tab_page()), Web::HTML::ActivateTab::Yes); }); + QObject::connect(m_new_window_action, &QAction::triggered, this, [this] { + auto initial_urls = Vector { ak_url_from_qstring(Settings::the()->new_tab_page()) }; + (void)static_cast(QApplication::instance())->new_window(initial_urls, m_cookie_jar, m_web_content_options, m_webdriver_content_ipc_path); + }); QObject::connect(open_file_action, &QAction::triggered, this, &BrowserWindow::open_file); QObject::connect(settings_action, &QAction::triggered, this, [this] { if (!m_settings_dialog) { @@ -864,6 +873,9 @@ bool BrowserWindow::event(QEvent* event) } #endif + if (event->type() == QEvent::WindowActivate) + static_cast(QApplication::instance())->set_active_window(*this); + return QMainWindow::event(event); } @@ -917,23 +929,9 @@ void BrowserWindow::closeEvent(QCloseEvent* event) Settings::the()->set_last_size(size()); Settings::the()->set_is_maximized(isMaximized()); + QObject::deleteLater(); + QMainWindow::closeEvent(event); } -void BrowserWindow::show_task_manager_window() -{ - if (!m_task_manager_window) { - m_task_manager_window = new TaskManagerWindow(this); - } - m_task_manager_window->show(); - m_task_manager_window->activateWindow(); - m_task_manager_window->raise(); -} - -void BrowserWindow::close_task_manager_window() -{ - if (m_task_manager_window) - m_task_manager_window->close(); -} - } diff --git a/Ladybird/Qt/BrowserWindow.h b/Ladybird/Qt/BrowserWindow.h index 71694f82539..22f7e9d8af6 100644 --- a/Ladybird/Qt/BrowserWindow.h +++ b/Ladybird/Qt/BrowserWindow.h @@ -57,6 +57,11 @@ public: return *m_new_tab_action; } + QAction& new_window_action() + { + return *m_new_window_action; + } + QAction& copy_selection_action() { return *m_copy_selection_action; @@ -141,9 +146,6 @@ private: QString tool_tip_for_page_mute_state(Tab&) const; QTabBar::ButtonPosition audio_button_position_for_tab(int tab_index) const; - void show_task_manager_window(); - void close_task_manager_window(); - QScreen* m_current_screen; double m_device_pixel_ratio { 0 }; @@ -155,6 +157,7 @@ private: QAction* m_go_forward_action { nullptr }; QAction* m_reload_action { nullptr }; QAction* m_new_tab_action { nullptr }; + QAction* m_new_window_action { nullptr }; QAction* m_copy_selection_action { nullptr }; QAction* m_paste_action { nullptr }; QAction* m_select_all_action { nullptr }; @@ -163,9 +166,6 @@ private: SettingsDialog* m_settings_dialog { nullptr }; - // FIXME: This should be owned at a higher level in case we have multiple browser windows - TaskManagerWindow* m_task_manager_window { nullptr }; - WebView::CookieJar& m_cookie_jar; WebContentOptions m_web_content_options; diff --git a/Ladybird/Qt/main.cpp b/Ladybird/Qt/main.cpp index e2d59ddbd89..cb26385baa7 100644 --- a/Ladybird/Qt/main.cpp +++ b/Ladybird/Qt/main.cpp @@ -103,6 +103,7 @@ ErrorOr serenity_main(Main::Arguments arguments) bool debug_web_content = false; bool log_all_js_exceptions = false; bool enable_idl_tracing = false; + bool new_window = false; Core::ArgsParser args_parser; args_parser.set_general_help("The Ladybird web browser :^)"); @@ -117,17 +118,29 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_option(log_all_js_exceptions, "Log all JavaScript exceptions", "log-all-js-exceptions"); args_parser.add_option(enable_idl_tracing, "Enable IDL tracing", "enable-idl-tracing"); args_parser.add_option(expose_internals_object, "Expose internals object", "expose-internals-object"); + args_parser.add_option(new_window, "Force opening in a new window", "new-window", 'n'); args_parser.parse(arguments); WebView::ChromeProcess chrome_process; - auto new_window = false; if (TRY(chrome_process.connect(raw_urls, new_window)) == WebView::ChromeProcess::ProcessDisposition::ExitProcess) { outln("Opening in existing process"); return 0; } - chrome_process.on_new_window = [](auto const& urls) { - dbgln("asked to open new window with urls: {}", urls); + chrome_process.on_new_tab = [&](auto const& raw_urls) { + auto& window = app.active_window(); + auto urls = sanitize_urls(raw_urls); + for (size_t i = 0; i < urls.size(); ++i) { + window.new_tab_from_url(urls[i], (i == 0) ? Web::HTML::ActivateTab::Yes : Web::HTML::ActivateTab::No); + } + window.show(); + window.activateWindow(); + window.raise(); + }; + + app.on_open_file = [&](auto file_url) { + auto& window = app.active_window(); + window.view().load(file_url); }; WebView::ProcessManager::initialize(); @@ -171,23 +184,13 @@ ErrorOr serenity_main(Main::Arguments arguments) .expose_internals_object = expose_internals_object ? Ladybird::ExposeInternalsObject::Yes : Ladybird::ExposeInternalsObject::No, }; - Ladybird::BrowserWindow window(sanitize_urls(raw_urls), cookie_jar, web_content_options, webdriver_content_ipc_path); + chrome_process.on_new_window = [&](auto const& urls) { + app.new_window(sanitize_urls(urls), cookie_jar, web_content_options, webdriver_content_ipc_path); + }; + + auto& window = app.new_window(sanitize_urls(raw_urls), cookie_jar, web_content_options, webdriver_content_ipc_path); window.setWindowTitle("Ladybird"); - chrome_process.on_new_tab = [&](auto const& raw_urls) { - auto urls = sanitize_urls(raw_urls); - for (size_t i = 0; i < urls.size(); ++i) { - window.new_tab_from_url(urls[i], (i == 0) ? Web::HTML::ActivateTab::Yes : Web::HTML::ActivateTab::No); - } - window.show(); - window.activateWindow(); - window.raise(); - }; - - app.on_open_file = [&](auto file_url) { - window.view().load(file_url); - }; - if (Ladybird::Settings::the()->is_maximized()) { window.showMaximized(); } else {