diff --git a/Ladybird/BrowserWindow.cpp b/Ladybird/BrowserWindow.cpp index aabdc6cbff..1932ef623d 100644 --- a/Ladybird/BrowserWindow.cpp +++ b/Ladybird/BrowserWindow.cpp @@ -10,7 +10,6 @@ #include "Settings.h" #include "SettingsDialog.h" #include "WebView.h" -#include #include #include #include @@ -18,8 +17,7 @@ extern String s_serenity_resource_root; extern Browser::Settings* s_settings; -BrowserWindow::BrowserWindow(Core::EventLoop& event_loop) - : m_event_loop(event_loop) +BrowserWindow::BrowserWindow() { m_tabs_container = new QTabWidget; m_tabs_container->setElideMode(Qt::TextElideMode::ElideRight); @@ -257,13 +255,3 @@ void BrowserWindow::tab_favicon_changed(int index, QIcon icon) m_tabs_container->setTabIcon(index, icon); setWindowIcon(icon); } - -void BrowserWindow::closeEvent(QCloseEvent* event) -{ - QWidget::closeEvent(event); - - // FIXME: Ladybird only supports one window at the moment. When we support - // multiple windows, we'll only want to fire off the quit event when - // all of the browser windows have closed. - m_event_loop.quit(0); -} diff --git a/Ladybird/BrowserWindow.h b/Ladybird/BrowserWindow.h index b97a76f119..a184dd91c1 100644 --- a/Ladybird/BrowserWindow.h +++ b/Ladybird/BrowserWindow.h @@ -22,14 +22,12 @@ class WebView; class BrowserWindow : public QMainWindow { Q_OBJECT public: - explicit BrowserWindow(Core::EventLoop&); + explicit BrowserWindow(); WebView& view() const { return m_current_tab->view(); } int tab_index(Tab*); - virtual void closeEvent(QCloseEvent*) override; - public slots: void tab_title_changed(int index, QString const&); void tab_favicon_changed(int index, QIcon icon); @@ -44,6 +42,4 @@ private: QTabBar* m_tabs_bar { nullptr }; NonnullOwnPtrVector m_tabs; Tab* m_current_tab { nullptr }; - - Core::EventLoop& m_event_loop; }; diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index e907626c57..4af4585e26 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -49,6 +49,7 @@ set(SOURCES ConsoleClient.cpp ConsoleGlobalObject.cpp CookieJar.cpp + EventLoopPluginQt.cpp RequestManagerQt.cpp main.cpp WebView.cpp @@ -56,6 +57,7 @@ set(SOURCES Settings.cpp SettingsDialog.cpp Tab.cpp + TimerQt.cpp ) qt_add_executable(ladybird ${SOURCES} diff --git a/Ladybird/EventLoopPluginQt.cpp b/Ladybird/EventLoopPluginQt.cpp new file mode 100644 index 0000000000..266778430b --- /dev/null +++ b/Ladybird/EventLoopPluginQt.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#define AK_DONT_REPLACE_STD + +#include "EventLoopPluginQt.h" +#include "TimerQt.h" +#include +#include +#include +#include + +namespace Ladybird { + +EventLoopPluginQt::EventLoopPluginQt() = default; +EventLoopPluginQt::~EventLoopPluginQt() = default; + +void EventLoopPluginQt::spin_until(Function goal_condition) +{ + while (!goal_condition()) + QCoreApplication::processEvents(); +} + +void EventLoopPluginQt::deferred_invoke(Function function) +{ + VERIFY(function); + QTimer::singleShot(0, [function = move(function)] { + function(); + }); +} + +NonnullRefPtr EventLoopPluginQt::create_timer() +{ + return TimerQt::create(); +} + +} diff --git a/Ladybird/EventLoopPluginQt.h b/Ladybird/EventLoopPluginQt.h new file mode 100644 index 0000000000..f094ffcb6b --- /dev/null +++ b/Ladybird/EventLoopPluginQt.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Ladybird { + +class EventLoopPluginQt final : public Web::Platform::EventLoopPlugin { +public: + EventLoopPluginQt(); + virtual ~EventLoopPluginQt() override; + + virtual void spin_until(Function goal_condition) override; + virtual void deferred_invoke(Function) override; + virtual NonnullRefPtr create_timer() override; +}; + +} diff --git a/Ladybird/TimerQt.cpp b/Ladybird/TimerQt.cpp new file mode 100644 index 0000000000..3692a635e2 --- /dev/null +++ b/Ladybird/TimerQt.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#define AK_DONT_REPLACE_STD + +#include "TimerQt.h" +#include +#include + +namespace Ladybird { + +NonnullRefPtr TimerQt::create() +{ + return adopt_ref(*new TimerQt); +} + +TimerQt::TimerQt() +{ + m_timer = new QTimer; + QObject::connect(m_timer, &QTimer::timeout, [this] { + if (on_timeout) + on_timeout(); + }); +} + +TimerQt::~TimerQt() +{ + delete m_timer; +} + +void TimerQt::start() +{ + m_timer->start(); +} + +void TimerQt::start(int interval_ms) +{ + m_timer->start(interval_ms); +} + +void TimerQt::restart() +{ + restart(interval()); +} + +void TimerQt::restart(int interval_ms) +{ + if (is_active()) + stop(); + start(interval_ms); +} + +void TimerQt::stop() +{ + m_timer->stop(); +} + +void TimerQt::set_active(bool active) +{ + if (active) + m_timer->start(); + else + m_timer->stop(); +} + +bool TimerQt::is_active() const +{ + return m_timer->isActive(); +} + +int TimerQt::interval() const +{ + return m_timer->interval(); +} + +void TimerQt::set_interval(int interval_ms) +{ + m_timer->setInterval(interval_ms); +} + +bool TimerQt::is_single_shot() const +{ + return m_timer->isSingleShot(); +} + +void TimerQt::set_single_shot(bool single_shot) +{ + m_timer->setSingleShot(single_shot); +} + +} diff --git a/Ladybird/TimerQt.h b/Ladybird/TimerQt.h new file mode 100644 index 0000000000..2057cf38b4 --- /dev/null +++ b/Ladybird/TimerQt.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +class QTimer; + +namespace Ladybird { + +class TimerQt final : public Web::Platform::Timer { +public: + static NonnullRefPtr create(); + + virtual ~TimerQt(); + + virtual void start() override; + virtual void start(int interval_ms) override; + virtual void restart() override; + virtual void restart(int interval_ms) override; + virtual void stop() override; + + virtual void set_active(bool) override; + + virtual bool is_active() const override; + virtual int interval() const override; + virtual void set_interval(int interval_ms) override; + + virtual bool is_single_shot() const override; + virtual void set_single_shot(bool) override; + +private: + TimerQt(); + + QTimer* m_timer { nullptr }; +}; + +} diff --git a/Ladybird/WebView.cpp b/Ladybird/WebView.cpp index 61b1c90392..e304f2cd40 100644 --- a/Ladybird/WebView.cpp +++ b/Ladybird/WebView.cpp @@ -10,6 +10,7 @@ #include "WebView.h" #include "ConsoleClient.h" #include "CookieJar.h" +#include "EventLoopPluginQt.h" #include "RequestManagerQt.h" #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -819,6 +821,8 @@ static void platform_init() void initialize_web_engine() { + Web::Platform::EventLoopPlugin::install(*new Ladybird::EventLoopPluginQt); + Web::ImageDecoding::Decoder::initialize(HeadlessImageDecoderClient::create()); Web::ResourceLoader::initialize(RequestManagerQt::create()); Web::WebSockets::WebSocketClientManager::initialize(HeadlessWebSocketClientManager::create()); diff --git a/Ladybird/main.cpp b/Ladybird/main.cpp index 940f77fefe..c6af32fd3f 100644 --- a/Ladybird/main.cpp +++ b/Ladybird/main.cpp @@ -8,7 +8,6 @@ #include "Settings.h" #include "WebView.h" #include -#include #include #include #include @@ -29,22 +28,15 @@ ErrorOr serenity_main(Main::Arguments arguments) s_settings = new Browser::Settings(); - Core::EventLoop event_loop; - QApplication app(arguments.argc, arguments.argv); - BrowserWindow window(event_loop); + BrowserWindow window; window.setWindowTitle("Ladybird"); window.resize(800, 600); window.show(); - auto qt_event_loop_driver = Core::Timer::create_repeating(50, [&] { - app.processEvents(); - }); - qt_event_loop_driver->start(); - if (!url.is_empty()) { window.view().load(url); } - return event_loop.exec(); + return app.exec(); }