LibWebView+Services+UI: Move the EventLoop implementations to LibWebView

We currently compile the Qt event loop files multiple times, for every
target which wants to use them. This patch moves these to LibWebView as
a central location to avoid this.
This commit is contained in:
Timothy Flynn 2024-11-10 09:23:10 -05:00 committed by Tim Flynn
parent bd50a31be6
commit 9e1f001ffe
Notes: github-actions[bot] 2024-11-11 12:36:54 +00:00
17 changed files with 98 additions and 91 deletions

View file

@ -68,12 +68,6 @@ endif()
add_cxx_compile_options(-Wno-expansion-to-defined)
add_cxx_compile_options(-Wno-user-defined-literals)
if (ANDROID OR APPLE)
serenity_option(ENABLE_QT OFF CACHE BOOL "Build ladybird application using Qt GUI")
else()
serenity_option(ENABLE_QT ON CACHE BOOL "Build ladybird application using Qt GUI")
endif()
if (ANDROID AND ENABLE_QT)
message(STATUS "Disabling Qt for Android")
set(ENABLE_QT OFF CACHE BOOL "" FORCE)

View file

@ -19,6 +19,20 @@ set(SOURCES
${PUBLIC_SUFFIX_SOURCES}
)
if (ENABLE_QT)
list(APPEND SOURCES
EventLoop/EventLoopImplementationQt.cpp
EventLoop/EventLoopImplementationQtEventTarget.cpp
)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Core)
elseif (APPLE)
list(APPEND SOURCES
EventLoop/EventLoopImplementationMacOS.mm
)
endif()
set(GENERATED_SOURCES ${CURRENT_LIB_GENERATED})
embed_as_string(
@ -53,6 +67,12 @@ target_compile_definitions(LibWebView PRIVATE ENABLE_PUBLIC_SUFFIX=$<BOOL:${ENAB
find_package(SQLite3 REQUIRED)
target_link_libraries(LibWebView PRIVATE SQLite::SQLite3)
if (ENABLE_QT)
target_link_libraries(LibWebView PRIVATE Qt::Core)
elseif (APPLE)
target_link_libraries(LibWebView PRIVATE "-framework Cocoa")
endif()
if (ENABLE_INSTALL_HEADERS)
foreach(header ${GENERATED_SOURCES})
get_filename_component(extension ${header} EXT)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2023-2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -10,9 +10,9 @@
#include <AK/NonnullOwnPtr.h>
#include <LibCore/EventLoopImplementation.h>
namespace Ladybird {
namespace WebView {
class CFEventLoopManager final : public Core::EventLoopManager {
class EventLoopManagerMacOS final : public Core::EventLoopManager {
public:
virtual NonnullOwnPtr<Core::EventLoopImplementation> make_implementation() override;
@ -28,12 +28,12 @@ public:
virtual void unregister_signal(int) override;
};
class CFEventLoopImplementation final : public Core::EventLoopImplementation {
class EventLoopImplementationMacOS final : public Core::EventLoopImplementation {
public:
// FIXME: This currently only manages the main NSApp event loop, as that is all we currently
// interact with. When we need multiple event loops, or an event loop that isn't the
// NSApp loop, we will need to create our own CFRunLoop.
static NonnullOwnPtr<CFEventLoopImplementation> create();
static NonnullOwnPtr<EventLoopImplementationMacOS> create();
virtual int exec() override;
virtual size_t pump(PumpMode) override;
@ -47,7 +47,7 @@ public:
virtual void notify_forked_and_in_child() override { }
private:
CFEventLoopImplementation() = default;
EventLoopImplementationMacOS() = default;
int m_exit_code { 0 };
};

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2023-2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -11,8 +11,8 @@
#include <LibCore/Event.h>
#include <LibCore/Notifier.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibWebView/EventLoop/EventLoopImplementationMacOS.h>
#import <Application/EventLoopImplementation.h>
#import <Cocoa/Cocoa.h>
#import <CoreFoundation/CoreFoundation.h>
@ -20,7 +20,7 @@
#include <sys/time.h>
#include <sys/types.h>
namespace Ladybird {
namespace WebView {
struct ThreadData {
static ThreadData& the()
@ -201,12 +201,12 @@ static void post_application_event()
[NSApp postEvent:event atStart:NO];
}
NonnullOwnPtr<Core::EventLoopImplementation> CFEventLoopManager::make_implementation()
NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerMacOS::make_implementation()
{
return CFEventLoopImplementation::create();
return EventLoopImplementationMacOS::create();
}
intptr_t CFEventLoopManager::register_timer(Core::EventReceiver& receiver, int interval_milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible)
intptr_t EventLoopManagerMacOS::register_timer(Core::EventReceiver& receiver, int interval_milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible)
{
auto& thread_data = ThreadData::the();
@ -240,7 +240,7 @@ intptr_t CFEventLoopManager::register_timer(Core::EventReceiver& receiver, int i
return timer_id;
}
void CFEventLoopManager::unregister_timer(intptr_t timer_id)
void EventLoopManagerMacOS::unregister_timer(intptr_t timer_id)
{
auto& thread_data = ThreadData::the();
thread_data.timer_id_allocator.deallocate(static_cast<int>(timer_id));
@ -269,7 +269,7 @@ static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notificatio
post_application_event();
}
void CFEventLoopManager::register_notifier(Core::Notifier& notifier)
void EventLoopManagerMacOS::register_notifier(Core::Notifier& notifier)
{
auto notification_type = kCFSocketNoCallBack;
@ -301,7 +301,7 @@ void CFEventLoopManager::register_notifier(Core::Notifier& notifier)
ThreadData::the().notifiers.set(&notifier, source);
}
void CFEventLoopManager::unregister_notifier(Core::Notifier& notifier)
void EventLoopManagerMacOS::unregister_notifier(Core::Notifier& notifier)
{
if (auto source = ThreadData::the().notifiers.take(&notifier); source.has_value()) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), *source, kCFRunLoopCommonModes);
@ -309,7 +309,7 @@ void CFEventLoopManager::unregister_notifier(Core::Notifier& notifier)
}
}
void CFEventLoopManager::did_post_event()
void EventLoopManagerMacOS::did_post_event()
{
post_application_event();
}
@ -328,7 +328,7 @@ static void handle_signal(CFFileDescriptorRef f, CFOptionFlags callback_types, v
signal_handlers->dispatch();
}
int CFEventLoopManager::register_signal(int signal_number, Function<void(int)> handler)
int EventLoopManagerMacOS::register_signal(int signal_number, Function<void(int)> handler)
{
VERIFY(signal_number != 0);
auto& info = *signals_info();
@ -343,7 +343,7 @@ int CFEventLoopManager::register_signal(int signal_number, Function<void(int)> h
}
}
void CFEventLoopManager::unregister_signal(int handler_id)
void EventLoopManagerMacOS::unregister_signal(int handler_id)
{
VERIFY(handler_id != 0);
int remove_signal_number = 0;
@ -360,18 +360,18 @@ void CFEventLoopManager::unregister_signal(int handler_id)
info.signal_handlers.remove(remove_signal_number);
}
NonnullOwnPtr<CFEventLoopImplementation> CFEventLoopImplementation::create()
NonnullOwnPtr<EventLoopImplementationMacOS> EventLoopImplementationMacOS::create()
{
return adopt_own(*new CFEventLoopImplementation);
return adopt_own(*new EventLoopImplementationMacOS);
}
int CFEventLoopImplementation::exec()
int EventLoopImplementationMacOS::exec()
{
[NSApp run];
return m_exit_code;
}
size_t CFEventLoopImplementation::pump(PumpMode mode)
size_t EventLoopImplementationMacOS::pump(PumpMode mode)
{
auto* wait_until = mode == PumpMode::WaitForEvents ? [NSDate distantFuture] : [NSDate distantPast];
@ -392,18 +392,18 @@ size_t CFEventLoopImplementation::pump(PumpMode mode)
return 0;
}
void CFEventLoopImplementation::quit(int exit_code)
void EventLoopImplementationMacOS::quit(int exit_code)
{
m_exit_code = exit_code;
[NSApp stop:nil];
}
void CFEventLoopImplementation::wake()
void EventLoopImplementationMacOS::wake()
{
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
void CFEventLoopImplementation::post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&& event)
void EventLoopImplementationMacOS::post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&& event)
{
m_thread_event_queue.post_event(receiver, move(event));

View file

@ -12,13 +12,16 @@
#include <LibCore/Notifier.h>
#include <LibCore/System.h>
#include <LibCore/ThreadEventQueue.h>
#include <UI/Qt/EventLoopImplementationQt.h>
#include <UI/Qt/EventLoopImplementationQtEventTarget.h>
#include <LibWebView/EventLoop/EventLoopImplementationQt.h>
#include <LibWebView/EventLoop/EventLoopImplementationQtEventTarget.h>
#include <QCoreApplication>
#include <QEvent>
#include <QEventLoop>
#include <QSocketNotifier>
#include <QTimer>
namespace Ladybird {
namespace WebView {
struct ThreadData;
static thread_local ThreadData* s_thread_data;
@ -36,6 +39,20 @@ struct ThreadData {
HashMap<Core::Notifier*, NonnullOwnPtr<QSocketNotifier>> notifiers;
};
class QtEventLoopManagerEvent final : public QEvent {
public:
static QEvent::Type process_event_queue_event_type()
{
static auto const type = static_cast<QEvent::Type>(QEvent::registerEventType());
return type;
}
QtEventLoopManagerEvent(QEvent::Type type)
: QEvent(type)
{
}
};
class SignalHandlers : public RefCounted<SignalHandlers> {
AK_MAKE_NONCOPYABLE(SignalHandlers);
AK_MAKE_NONMOVABLE(SignalHandlers);
@ -165,6 +182,7 @@ static void dispatch_signal(int signal_number)
}
EventLoopImplementationQt::EventLoopImplementationQt()
: m_event_loop(make<QEventLoop>())
{
}
@ -174,7 +192,7 @@ int EventLoopImplementationQt::exec()
{
if (is_main_loop())
return QCoreApplication::exec();
return m_event_loop.exec();
return m_event_loop->exec();
}
size_t EventLoopImplementationQt::pump(PumpMode mode)
@ -184,7 +202,7 @@ size_t EventLoopImplementationQt::pump(PumpMode mode)
if (is_main_loop())
QCoreApplication::processEvents(qt_mode);
else
m_event_loop.processEvents(qt_mode);
m_event_loop->processEvents(qt_mode);
result += Core::ThreadEventQueue::current().process();
return result;
}
@ -194,13 +212,13 @@ void EventLoopImplementationQt::quit(int code)
if (is_main_loop())
QCoreApplication::exit(code);
else
m_event_loop.exit(code);
m_event_loop->exit(code);
}
void EventLoopImplementationQt::wake()
{
if (!is_main_loop())
m_event_loop.wakeUp();
m_event_loop->wakeUp();
}
void EventLoopImplementationQt::post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&& event)

View file

@ -7,17 +7,14 @@
#pragma once
#include <AK/Badge.h>
#include <AK/HashMap.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/OwnPtr.h>
#include <LibCore/EventLoopImplementation.h>
#include <QEvent>
#include <QEventLoop>
#include <QSocketNotifier>
#include <QTimer>
class QEvent;
class QEventLoop;
class QSocketNotifier;
namespace Ladybird {
namespace WebView {
class EventLoopImplementationQt;
class EventLoopImplementationQtEventTarget;
@ -50,20 +47,6 @@ private:
int m_signal_socket_fds[2] = { -1, -1 };
};
class QtEventLoopManagerEvent final : public QEvent {
public:
static QEvent::Type process_event_queue_event_type()
{
static auto const type = static_cast<QEvent::Type>(QEvent::registerEventType());
return type;
}
QtEventLoopManagerEvent(QEvent::Type type)
: QEvent(type)
{
}
};
class EventLoopImplementationQt final : public Core::EventLoopImplementation {
public:
static NonnullOwnPtr<EventLoopImplementationQt> create() { return adopt_own(*new EventLoopImplementationQt); }
@ -89,7 +72,7 @@ private:
EventLoopImplementationQt();
bool is_main_loop() const { return m_main_loop; }
QEventLoop m_event_loop;
NonnullOwnPtr<QEventLoop> m_event_loop;
bool m_main_loop { false };
};

View file

@ -4,9 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <UI/Qt/EventLoopImplementationQtEventTarget.h>
#include <LibWebView/EventLoop/EventLoopImplementationQt.h>
#include <LibWebView/EventLoop/EventLoopImplementationQtEventTarget.h>
namespace Ladybird {
namespace WebView {
bool EventLoopImplementationQtEventTarget::event(QEvent* event)
{

View file

@ -6,11 +6,10 @@
#pragma once
#include <UI/Qt/EventLoopImplementationQt.h>
#include <QEvent>
#include <QObject>
namespace Ladybird {
namespace WebView {
class EventLoopImplementationQtEventTarget final : public QObject {
Q_OBJECT

View file

@ -14,3 +14,9 @@ serenity_option(LAGOM_TOOLS_ONLY OFF CACHE BOOL "Don't build libraries, utilitie
serenity_option(ENABLE_LAGOM_CCACHE ON CACHE BOOL "Enable ccache for Lagom builds")
serenity_option(LAGOM_USE_LINKER "" CACHE STRING "The linker to use (e.g. lld, mold) instead of the system default")
serenity_option(ENABLE_LAGOM_COVERAGE_COLLECTION OFF CACHE STRING "Enable code coverage instrumentation for lagom binaries in clang")
if (ANDROID OR APPLE)
serenity_option(ENABLE_QT OFF CACHE BOOL "Build ladybird application using Qt GUI")
else()
serenity_option(ENABLE_QT ON CACHE BOOL "Build ladybird application using Qt GUI")
endif()

View file

@ -40,12 +40,7 @@ if (HAS_FONTCONFIG)
endif()
if (ENABLE_QT)
qt_add_executable(WebContent
${LADYBIRD_SOURCE_DIR}/UI/Qt/EventLoopImplementationQt.cpp
${LADYBIRD_SOURCE_DIR}/UI/Qt/EventLoopImplementationQtEventTarget.cpp
${LADYBIRD_SOURCE_DIR}/UI/Qt/StringUtils.cpp
main.cpp
)
qt_add_executable(WebContent main.cpp)
target_link_libraries(WebContent PRIVATE Qt::Core)
target_compile_definitions(WebContent PRIVATE HAVE_QT=1)

View file

@ -34,8 +34,8 @@
#include <WebContent/WebDriverConnection.h>
#if defined(HAVE_QT)
# include <LibWebView/EventLoop/EventLoopImplementationQt.h>
# include <QCoreApplication>
# include <UI/Qt/EventLoopImplementationQt.h>
# if defined(HAVE_QT_MULTIMEDIA)
# include <UI/Qt/AudioCodecPluginQt.h>
@ -71,7 +71,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
#if defined(HAVE_QT)
QCoreApplication app(arguments.argc, arguments.argv);
Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt);
Core::EventLoopManager::install(*new WebView::EventLoopManagerQt);
#endif
Core::EventLoop event_loop;

View file

@ -25,13 +25,7 @@ if (HAS_FONTCONFIG)
endif()
if (ENABLE_QT)
qt_add_executable(WebWorker
${LADYBIRD_SOURCE_DIR}/UI/Qt/EventLoopImplementationQt.cpp
${LADYBIRD_SOURCE_DIR}/UI/Qt/EventLoopImplementationQtEventTarget.cpp
${LADYBIRD_SOURCE_DIR}/UI/Qt/StringUtils.cpp
main.cpp
)
target_link_libraries(WebWorker PRIVATE Qt::Core)
qt_add_executable(WebWorker main.cpp)
target_link_libraries(WebWorker PRIVATE webworkerservice LibWebSocket)
target_compile_definitions(WebWorker PRIVATE HAVE_QT=1)
else()

View file

@ -25,8 +25,8 @@
#include <WebWorker/ConnectionFromClient.h>
#if defined(HAVE_QT)
# include <LibWebView/EventLoop/EventLoopImplementationQt.h>
# include <QCoreApplication>
# include <UI/Qt/EventLoopImplementationQt.h>
#endif
static ErrorOr<void> initialize_resource_loader(JS::Heap&, int request_server_socket);
@ -52,7 +52,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
#if defined(HAVE_QT)
QCoreApplication app(arguments.argc, arguments.argv);
Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt);
Core::EventLoopManager::install(*new WebView::EventLoopManagerQt);
#endif
Core::EventLoop event_loop;

View file

@ -2,7 +2,6 @@ add_library(ladybird_impl STATIC
${LADYBIRD_SOURCES}
Application/Application.mm
Application/ApplicationDelegate.mm
Application/EventLoopImplementation.mm
Interface/Event.mm
Interface/Inspector.mm
Interface/InspectorController.mm

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2023-2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -9,6 +9,7 @@
#include <LibMain/Main.h>
#include <LibWebView/Application.h>
#include <LibWebView/ChromeProcess.h>
#include <LibWebView/EventLoop/EventLoopImplementationMacOS.h>
#include <LibWebView/URL.h>
#include <LibWebView/ViewImplementation.h>
#include <LibWebView/WebContentClient.h>
@ -18,7 +19,6 @@
#import <Application/Application.h>
#import <Application/ApplicationDelegate.h>
#import <Application/EventLoopImplementation.h>
#import <Interface/Tab.h>
#import <Interface/TabController.h>
@ -48,7 +48,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
Application* application = [Application sharedApplication];
Core::EventLoopManager::install(*new Ladybird::CFEventLoopManager);
Core::EventLoopManager::install(*new WebView::EventLoopManagerMacOS);
[application setupWebViewApplication:arguments newTabPageURL:Browser::default_new_tab_url];
platform_init();

View file

@ -3,8 +3,6 @@ target_sources(ladybird PRIVATE
Application.cpp
AutoComplete.cpp
BrowserWindow.cpp
EventLoopImplementationQt.cpp
EventLoopImplementationQtEventTarget.cpp
FindInPageWidget.cpp
Icon.cpp
InspectorWidget.cpp

View file

@ -12,12 +12,12 @@
#include <LibMain/Main.h>
#include <LibWebView/Application.h>
#include <LibWebView/ChromeProcess.h>
#include <LibWebView/EventLoop/EventLoopImplementationQt.h>
#include <LibWebView/ProcessManager.h>
#include <LibWebView/URL.h>
#include <UI/HelperProcess.h>
#include <UI/Qt/Application.h>
#include <UI/Qt/BrowserWindow.h>
#include <UI/Qt/EventLoopImplementationQt.h>
#include <UI/Qt/Settings.h>
#include <UI/Qt/WebContentView.h>
#include <UI/Utilities.h>
@ -64,11 +64,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
{
AK::set_rich_debug_enabled(true);
Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt);
Core::EventLoopManager::install(*new WebView::EventLoopManagerQt);
auto app = Ladybird::Application::create(arguments, ak_url_from_qstring(Ladybird::Settings::the()->new_tab_page()));
static_cast<Ladybird::EventLoopImplementationQt&>(Core::EventLoop::current().impl()).set_main_loop();
static_cast<WebView::EventLoopImplementationQt&>(Core::EventLoop::current().impl()).set_main_loop();
TRY(handle_attached_debugger());
platform_init();