mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
Ladybird: Use only the Qt event loop to speed everything up :^)
This patch removes the dual-event-loop setup, leaving only the Qt event loop. We teach LibWeb how to drive Qt by installing an EventLoopPlugin. This removes the 50ms latency on all UI interactions (and network requests, etc.)
This commit is contained in:
parent
dcab11f5e9
commit
37d844fd66
Notes:
sideshowbarker
2024-07-17 05:02:35 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/37d844fd66 Pull-request: https://github.com/SerenityOS/serenity/pull/16583 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/linusg
9 changed files with 209 additions and 28 deletions
|
@ -10,7 +10,6 @@
|
|||
#include "Settings.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include "WebView.h"
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <QAction>
|
||||
#include <QDialog>
|
||||
#include <QPlainTextEdit>
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<Tab> m_tabs;
|
||||
Tab* m_current_tab { nullptr };
|
||||
|
||||
Core::EventLoop& m_event_loop;
|
||||
};
|
||||
|
|
|
@ -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}
|
||||
|
|
40
Ladybird/EventLoopPluginQt.cpp
Normal file
40
Ladybird/EventLoopPluginQt.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#define AK_DONT_REPLACE_STD
|
||||
|
||||
#include "EventLoopPluginQt.h"
|
||||
#include "TimerQt.h"
|
||||
#include <AK/Function.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
EventLoopPluginQt::EventLoopPluginQt() = default;
|
||||
EventLoopPluginQt::~EventLoopPluginQt() = default;
|
||||
|
||||
void EventLoopPluginQt::spin_until(Function<bool()> goal_condition)
|
||||
{
|
||||
while (!goal_condition())
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void EventLoopPluginQt::deferred_invoke(Function<void()> function)
|
||||
{
|
||||
VERIFY(function);
|
||||
QTimer::singleShot(0, [function = move(function)] {
|
||||
function();
|
||||
});
|
||||
}
|
||||
|
||||
NonnullRefPtr<Web::Platform::Timer> EventLoopPluginQt::create_timer()
|
||||
{
|
||||
return TimerQt::create();
|
||||
}
|
||||
|
||||
}
|
23
Ladybird/EventLoopPluginQt.h
Normal file
23
Ladybird/EventLoopPluginQt.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class EventLoopPluginQt final : public Web::Platform::EventLoopPlugin {
|
||||
public:
|
||||
EventLoopPluginQt();
|
||||
virtual ~EventLoopPluginQt() override;
|
||||
|
||||
virtual void spin_until(Function<bool()> goal_condition) override;
|
||||
virtual void deferred_invoke(Function<void()>) override;
|
||||
virtual NonnullRefPtr<Web::Platform::Timer> create_timer() override;
|
||||
};
|
||||
|
||||
}
|
94
Ladybird/TimerQt.cpp
Normal file
94
Ladybird/TimerQt.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#define AK_DONT_REPLACE_STD
|
||||
|
||||
#include "TimerQt.h"
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
NonnullRefPtr<TimerQt> 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);
|
||||
}
|
||||
|
||||
}
|
42
Ladybird/TimerQt.h
Normal file
42
Ladybird/TimerQt.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Platform/Timer.h>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class TimerQt final : public Web::Platform::Timer {
|
||||
public:
|
||||
static NonnullRefPtr<TimerQt> 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 };
|
||||
};
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
#include "WebView.h"
|
||||
#include "ConsoleClient.h"
|
||||
#include "CookieJar.h"
|
||||
#include "EventLoopPluginQt.h"
|
||||
#include "RequestManagerQt.h"
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/ByteBuffer.h>
|
||||
|
@ -47,6 +48,7 @@
|
|||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Painting/StackingContext.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/WebSockets/WebSocket.h>
|
||||
#include <LibWebSocket/ConnectionInfo.h>
|
||||
#include <LibWebSocket/Message.h>
|
||||
|
@ -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());
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "Settings.h"
|
||||
#include "WebView.h"
|
||||
#include <LibCore/ArgsParser.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibMain/Main.h>
|
||||
#include <QApplication>
|
||||
|
@ -29,22 +28,15 @@ ErrorOr<int> 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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue