From 9e1f001ffe05f87f953f86bb6bcd777498f64193 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 10 Nov 2024 09:23:10 -0500 Subject: [PATCH] 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. --- CMakeLists.txt | 6 --- Libraries/LibWebView/CMakeLists.txt | 20 ++++++++++ .../EventLoop/EventLoopImplementationMacOS.h | 12 +++--- .../EventLoop/EventLoopImplementationMacOS.mm | 38 +++++++++---------- .../EventLoop}/EventLoopImplementationQt.cpp | 32 ++++++++++++---- .../EventLoop}/EventLoopImplementationQt.h | 27 +++---------- .../EventLoopImplementationQtEventTarget.cpp | 5 ++- .../EventLoopImplementationQtEventTarget.h | 5 +-- Meta/CMake/lagom_options.cmake | 6 +++ Services/WebContent/CMakeLists.txt | 7 +--- Services/WebContent/main.cpp | 4 +- Services/WebWorker/CMakeLists.txt | 8 +--- Services/WebWorker/main.cpp | 4 +- UI/AppKit/CMakeLists.txt | 1 - UI/AppKit/main.mm | 6 +-- UI/Qt/CMakeLists.txt | 2 - UI/Qt/main.cpp | 6 +-- 17 files changed, 98 insertions(+), 91 deletions(-) rename UI/AppKit/Application/EventLoopImplementation.h => Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.h (82%) rename UI/AppKit/Application/EventLoopImplementation.mm => Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm (90%) rename {UI/Qt => Libraries/LibWebView/EventLoop}/EventLoopImplementationQt.cpp (93%) rename {UI/Qt => Libraries/LibWebView/EventLoop}/EventLoopImplementationQt.h (82%) rename {UI/Qt => Libraries/LibWebView/EventLoop}/EventLoopImplementationQtEventTarget.cpp (63%) rename {UI/Qt => Libraries/LibWebView/EventLoop}/EventLoopImplementationQtEventTarget.h (81%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95fb560356..ecea1b9776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/Libraries/LibWebView/CMakeLists.txt b/Libraries/LibWebView/CMakeLists.txt index 9c68e48928..65bfe3414b 100644 --- a/Libraries/LibWebView/CMakeLists.txt +++ b/Libraries/LibWebView/CMakeLists.txt @@ -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=$ + * Copyright (c) 2023-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,9 +10,9 @@ #include #include -namespace Ladybird { +namespace WebView { -class CFEventLoopManager final : public Core::EventLoopManager { +class EventLoopManagerMacOS final : public Core::EventLoopManager { public: virtual NonnullOwnPtr 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 create(); + static NonnullOwnPtr 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 }; }; diff --git a/UI/AppKit/Application/EventLoopImplementation.mm b/Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm similarity index 90% rename from UI/AppKit/Application/EventLoopImplementation.mm rename to Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm index b6b0367730..4362367d27 100644 --- a/UI/AppKit/Application/EventLoopImplementation.mm +++ b/Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Tim Flynn + * Copyright (c) 2023-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,8 +11,8 @@ #include #include #include +#include -#import #import #import @@ -20,7 +20,7 @@ #include #include -namespace Ladybird { +namespace WebView { struct ThreadData { static ThreadData& the() @@ -201,12 +201,12 @@ static void post_application_event() [NSApp postEvent:event atStart:NO]; } -NonnullOwnPtr CFEventLoopManager::make_implementation() +NonnullOwnPtr 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(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(¬ifier, source); } -void CFEventLoopManager::unregister_notifier(Core::Notifier& notifier) +void EventLoopManagerMacOS::unregister_notifier(Core::Notifier& notifier) { if (auto source = ThreadData::the().notifiers.take(¬ifier); 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 handler) +int EventLoopManagerMacOS::register_signal(int signal_number, Function handler) { VERIFY(signal_number != 0); auto& info = *signals_info(); @@ -343,7 +343,7 @@ int CFEventLoopManager::register_signal(int signal_number, Function 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::create() +NonnullOwnPtr 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&& event) +void EventLoopImplementationMacOS::post_event(Core::EventReceiver& receiver, NonnullOwnPtr&& event) { m_thread_event_queue.post_event(receiver, move(event)); diff --git a/UI/Qt/EventLoopImplementationQt.cpp b/Libraries/LibWebView/EventLoop/EventLoopImplementationQt.cpp similarity index 93% rename from UI/Qt/EventLoopImplementationQt.cpp rename to Libraries/LibWebView/EventLoop/EventLoopImplementationQt.cpp index 0b3c767f84..15d64919c1 100644 --- a/UI/Qt/EventLoopImplementationQt.cpp +++ b/Libraries/LibWebView/EventLoop/EventLoopImplementationQt.cpp @@ -12,13 +12,16 @@ #include #include #include -#include -#include +#include +#include #include +#include +#include +#include #include -namespace Ladybird { +namespace WebView { struct ThreadData; static thread_local ThreadData* s_thread_data; @@ -36,6 +39,20 @@ struct ThreadData { HashMap> notifiers; }; +class QtEventLoopManagerEvent final : public QEvent { +public: + static QEvent::Type process_event_queue_event_type() + { + static auto const type = static_cast(QEvent::registerEventType()); + return type; + } + + QtEventLoopManagerEvent(QEvent::Type type) + : QEvent(type) + { + } +}; + class SignalHandlers : public RefCounted { 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()) { } @@ -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&& event) diff --git a/UI/Qt/EventLoopImplementationQt.h b/Libraries/LibWebView/EventLoop/EventLoopImplementationQt.h similarity index 82% rename from UI/Qt/EventLoopImplementationQt.h rename to Libraries/LibWebView/EventLoop/EventLoopImplementationQt.h index de9d0c0ace..05358cff1a 100644 --- a/UI/Qt/EventLoopImplementationQt.h +++ b/Libraries/LibWebView/EventLoop/EventLoopImplementationQt.h @@ -7,17 +7,14 @@ #pragma once #include -#include #include -#include #include -#include -#include -#include -#include +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::registerEventType()); - return type; - } - - QtEventLoopManagerEvent(QEvent::Type type) - : QEvent(type) - { - } -}; - class EventLoopImplementationQt final : public Core::EventLoopImplementation { public: static NonnullOwnPtr 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 m_event_loop; bool m_main_loop { false }; }; diff --git a/UI/Qt/EventLoopImplementationQtEventTarget.cpp b/Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.cpp similarity index 63% rename from UI/Qt/EventLoopImplementationQtEventTarget.cpp rename to Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.cpp index 258abc4a57..2bdca22f9b 100644 --- a/UI/Qt/EventLoopImplementationQtEventTarget.cpp +++ b/Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.cpp @@ -4,9 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include +#include -namespace Ladybird { +namespace WebView { bool EventLoopImplementationQtEventTarget::event(QEvent* event) { diff --git a/UI/Qt/EventLoopImplementationQtEventTarget.h b/Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.h similarity index 81% rename from UI/Qt/EventLoopImplementationQtEventTarget.h rename to Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.h index e9a723282a..4bc251e191 100644 --- a/UI/Qt/EventLoopImplementationQtEventTarget.h +++ b/Libraries/LibWebView/EventLoop/EventLoopImplementationQtEventTarget.h @@ -6,11 +6,10 @@ #pragma once -#include - #include +#include -namespace Ladybird { +namespace WebView { class EventLoopImplementationQtEventTarget final : public QObject { Q_OBJECT diff --git a/Meta/CMake/lagom_options.cmake b/Meta/CMake/lagom_options.cmake index be16e578cc..c7ad2d3033 100644 --- a/Meta/CMake/lagom_options.cmake +++ b/Meta/CMake/lagom_options.cmake @@ -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() diff --git a/Services/WebContent/CMakeLists.txt b/Services/WebContent/CMakeLists.txt index a4cd5bf056..03b9e1b336 100644 --- a/Services/WebContent/CMakeLists.txt +++ b/Services/WebContent/CMakeLists.txt @@ -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) diff --git a/Services/WebContent/main.cpp b/Services/WebContent/main.cpp index bc60b241c1..880966bfc5 100644 --- a/Services/WebContent/main.cpp +++ b/Services/WebContent/main.cpp @@ -34,8 +34,8 @@ #include #if defined(HAVE_QT) +# include # include -# include # if defined(HAVE_QT_MULTIMEDIA) # include @@ -71,7 +71,7 @@ ErrorOr 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; diff --git a/Services/WebWorker/CMakeLists.txt b/Services/WebWorker/CMakeLists.txt index a06e859e4c..8e413591d9 100644 --- a/Services/WebWorker/CMakeLists.txt +++ b/Services/WebWorker/CMakeLists.txt @@ -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() diff --git a/Services/WebWorker/main.cpp b/Services/WebWorker/main.cpp index 2433674dde..570c28c808 100644 --- a/Services/WebWorker/main.cpp +++ b/Services/WebWorker/main.cpp @@ -25,8 +25,8 @@ #include #if defined(HAVE_QT) +# include # include -# include #endif static ErrorOr initialize_resource_loader(JS::Heap&, int request_server_socket); @@ -52,7 +52,7 @@ ErrorOr 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; diff --git a/UI/AppKit/CMakeLists.txt b/UI/AppKit/CMakeLists.txt index e9e727f3b5..690c1a56fd 100644 --- a/UI/AppKit/CMakeLists.txt +++ b/UI/AppKit/CMakeLists.txt @@ -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 diff --git a/UI/AppKit/main.mm b/UI/AppKit/main.mm index 819cef6004..43767071d8 100644 --- a/UI/AppKit/main.mm +++ b/UI/AppKit/main.mm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, Tim Flynn + * Copyright (c) 2023-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #import #import -#import #import #import @@ -48,7 +48,7 @@ ErrorOr 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(); diff --git a/UI/Qt/CMakeLists.txt b/UI/Qt/CMakeLists.txt index ce3d78fa0e..ec171bee25 100644 --- a/UI/Qt/CMakeLists.txt +++ b/UI/Qt/CMakeLists.txt @@ -3,8 +3,6 @@ target_sources(ladybird PRIVATE Application.cpp AutoComplete.cpp BrowserWindow.cpp - EventLoopImplementationQt.cpp - EventLoopImplementationQtEventTarget.cpp FindInPageWidget.cpp Icon.cpp InspectorWidget.cpp diff --git a/UI/Qt/main.cpp b/UI/Qt/main.cpp index 1fc82956f6..f9204f7d6b 100644 --- a/UI/Qt/main.cpp +++ b/UI/Qt/main.cpp @@ -12,12 +12,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -64,11 +64,11 @@ ErrorOr 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(Core::EventLoop::current().impl()).set_main_loop(); + static_cast(Core::EventLoop::current().impl()).set_main_loop(); TRY(handle_attached_debugger()); platform_init();