mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-15 05:52:19 +00:00
Ladybird: Support multiple browser windows in Qt chrome
This also moves the ownership of the TaskManger to the Application.
This commit is contained in:
parent
2bb0f65309
commit
6b5deb2259
Notes:
sideshowbarker
2024-07-17 00:49:59 +09:00
Author: https://github.com/ADKaster
Commit: 6b5deb2259
Pull-request: https://github.com/SerenityOS/serenity/pull/24126
Reviewed-by: https://github.com/trflynn89 ✅
5 changed files with 93 additions and 42 deletions
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include "TaskManagerWindow.h"
|
||||||
#include <LibWebView/URL.h>
|
#include <LibWebView/URL.h>
|
||||||
#include <QFileOpenEvent>
|
#include <QFileOpenEvent>
|
||||||
|
|
||||||
|
@ -16,6 +17,11 @@ Application::Application(int& argc, char** argv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Application::~Application()
|
||||||
|
{
|
||||||
|
close_task_manager_window();
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::event(QEvent* event)
|
bool Application::event(QEvent* event)
|
||||||
{
|
{
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
|
@ -37,4 +43,33 @@ bool Application::event(QEvent* event)
|
||||||
return QApplication::event(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<URL::URL> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
|
#include <AK/HashTable.h>
|
||||||
|
#include <Ladybird/Qt/BrowserWindow.h>
|
||||||
#include <LibProtocol/RequestClient.h>
|
#include <LibProtocol/RequestClient.h>
|
||||||
#include <LibURL/URL.h>
|
#include <LibURL/URL.h>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
@ -18,11 +20,24 @@ class Application : public QApplication {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Application(int& argc, char** argv);
|
Application(int& argc, char** argv);
|
||||||
|
virtual ~Application() override;
|
||||||
|
|
||||||
virtual bool event(QEvent* event) override;
|
virtual bool event(QEvent* event) override;
|
||||||
|
|
||||||
Function<void(URL::URL)> on_open_file;
|
Function<void(URL::URL)> on_open_file;
|
||||||
RefPtr<Protocol::RequestClient> request_server_client;
|
RefPtr<Protocol::RequestClient> request_server_client;
|
||||||
|
|
||||||
|
BrowserWindow& new_window(Vector<URL::URL> 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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "BrowserWindow.h"
|
#include "BrowserWindow.h"
|
||||||
|
#include "Application.h"
|
||||||
#include "Icon.h"
|
#include "Icon.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SettingsDialog.h"
|
#include "SettingsDialog.h"
|
||||||
|
@ -82,6 +83,10 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
|
||||||
m_new_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::AddTab));
|
m_new_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::AddTab));
|
||||||
menu->addAction(m_new_tab_action);
|
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);
|
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->setIcon(load_icon_from_uri("resource://icons/16x16/close-tab.png"sv));
|
||||||
close_current_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Close));
|
close_current_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Close));
|
||||||
|
@ -213,8 +218,8 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
|
||||||
task_manager_action->setIcon(load_icon_from_uri("resource://icons/16x16/app-system-monitor.png"sv));
|
task_manager_action->setIcon(load_icon_from_uri("resource://icons/16x16/app-system-monitor.png"sv));
|
||||||
task_manager_action->setShortcuts({ QKeySequence("Ctrl+Shift+M") });
|
task_manager_action->setShortcuts({ QKeySequence("Ctrl+Shift+M") });
|
||||||
inspect_menu->addAction(task_manager_action);
|
inspect_menu->addAction(task_manager_action);
|
||||||
QObject::connect(task_manager_action, &QAction::triggered, this, [this] {
|
QObject::connect(task_manager_action, &QAction::triggered, this, [] {
|
||||||
show_task_manager_window();
|
static_cast<Ladybird::Application*>(QApplication::instance())->show_task_manager_window();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto* debug_menu = menuBar()->addMenu("&Debug");
|
auto* debug_menu = menuBar()->addMenu("&Debug");
|
||||||
|
@ -391,6 +396,10 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
|
||||||
QObject::connect(m_new_tab_action, &QAction::triggered, this, [this] {
|
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);
|
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<URL::URL> { ak_url_from_qstring(Settings::the()->new_tab_page()) };
|
||||||
|
(void)static_cast<Ladybird::Application*>(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(open_file_action, &QAction::triggered, this, &BrowserWindow::open_file);
|
||||||
QObject::connect(settings_action, &QAction::triggered, this, [this] {
|
QObject::connect(settings_action, &QAction::triggered, this, [this] {
|
||||||
if (!m_settings_dialog) {
|
if (!m_settings_dialog) {
|
||||||
|
@ -864,6 +873,9 @@ bool BrowserWindow::event(QEvent* event)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (event->type() == QEvent::WindowActivate)
|
||||||
|
static_cast<Ladybird::Application*>(QApplication::instance())->set_active_window(*this);
|
||||||
|
|
||||||
return QMainWindow::event(event);
|
return QMainWindow::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,23 +929,9 @@ void BrowserWindow::closeEvent(QCloseEvent* event)
|
||||||
Settings::the()->set_last_size(size());
|
Settings::the()->set_last_size(size());
|
||||||
Settings::the()->set_is_maximized(isMaximized());
|
Settings::the()->set_is_maximized(isMaximized());
|
||||||
|
|
||||||
|
QObject::deleteLater();
|
||||||
|
|
||||||
QMainWindow::closeEvent(event);
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,11 @@ public:
|
||||||
return *m_new_tab_action;
|
return *m_new_tab_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QAction& new_window_action()
|
||||||
|
{
|
||||||
|
return *m_new_window_action;
|
||||||
|
}
|
||||||
|
|
||||||
QAction& copy_selection_action()
|
QAction& copy_selection_action()
|
||||||
{
|
{
|
||||||
return *m_copy_selection_action;
|
return *m_copy_selection_action;
|
||||||
|
@ -141,9 +146,6 @@ private:
|
||||||
QString tool_tip_for_page_mute_state(Tab&) const;
|
QString tool_tip_for_page_mute_state(Tab&) const;
|
||||||
QTabBar::ButtonPosition audio_button_position_for_tab(int tab_index) 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;
|
QScreen* m_current_screen;
|
||||||
double m_device_pixel_ratio { 0 };
|
double m_device_pixel_ratio { 0 };
|
||||||
|
|
||||||
|
@ -155,6 +157,7 @@ private:
|
||||||
QAction* m_go_forward_action { nullptr };
|
QAction* m_go_forward_action { nullptr };
|
||||||
QAction* m_reload_action { nullptr };
|
QAction* m_reload_action { nullptr };
|
||||||
QAction* m_new_tab_action { nullptr };
|
QAction* m_new_tab_action { nullptr };
|
||||||
|
QAction* m_new_window_action { nullptr };
|
||||||
QAction* m_copy_selection_action { nullptr };
|
QAction* m_copy_selection_action { nullptr };
|
||||||
QAction* m_paste_action { nullptr };
|
QAction* m_paste_action { nullptr };
|
||||||
QAction* m_select_all_action { nullptr };
|
QAction* m_select_all_action { nullptr };
|
||||||
|
@ -163,9 +166,6 @@ private:
|
||||||
|
|
||||||
SettingsDialog* m_settings_dialog { nullptr };
|
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;
|
WebView::CookieJar& m_cookie_jar;
|
||||||
|
|
||||||
WebContentOptions m_web_content_options;
|
WebContentOptions m_web_content_options;
|
||||||
|
|
|
@ -103,6 +103,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
bool debug_web_content = false;
|
bool debug_web_content = false;
|
||||||
bool log_all_js_exceptions = false;
|
bool log_all_js_exceptions = false;
|
||||||
bool enable_idl_tracing = false;
|
bool enable_idl_tracing = false;
|
||||||
|
bool new_window = false;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help("The Ladybird web browser :^)");
|
args_parser.set_general_help("The Ladybird web browser :^)");
|
||||||
|
@ -117,17 +118,29 @@ ErrorOr<int> 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(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(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(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);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
WebView::ChromeProcess chrome_process;
|
WebView::ChromeProcess chrome_process;
|
||||||
auto new_window = false;
|
|
||||||
if (TRY(chrome_process.connect(raw_urls, new_window)) == WebView::ChromeProcess::ProcessDisposition::ExitProcess) {
|
if (TRY(chrome_process.connect(raw_urls, new_window)) == WebView::ChromeProcess::ProcessDisposition::ExitProcess) {
|
||||||
outln("Opening in existing process");
|
outln("Opening in existing process");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome_process.on_new_window = [](auto const& urls) {
|
chrome_process.on_new_tab = [&](auto const& raw_urls) {
|
||||||
dbgln("asked to open new window with urls: {}", 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();
|
WebView::ProcessManager::initialize();
|
||||||
|
@ -171,23 +184,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
.expose_internals_object = expose_internals_object ? Ladybird::ExposeInternalsObject::Yes : Ladybird::ExposeInternalsObject::No,
|
.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");
|
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()) {
|
if (Ladybird::Settings::the()->is_maximized()) {
|
||||||
window.showMaximized();
|
window.showMaximized();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue