diff --git a/CMakeLists.txt b/CMakeLists.txt index 3540fb20..00490c47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,14 +81,6 @@ boption(SERVICE_UPOWER "UPower" ON) boption(SERVICE_NOTIFICATIONS "Notifications" ON) boption(BLUETOOTH "Bluetooth" ON) boption(NETWORK "Network" ON) -boption(WEBENGINE "WebEngine" ON) - -if (WEBENGINE_effective AND USE_JEMALLOC_effective) - message(FATAL_ERROR "WEBENGINE and USE_JEMALLOC are incompatible. " - "Chromium's PartitionAlloc conflicts with jemalloc. " - "Set -DUSE_JEMALLOC=OFF to use WebEngine.") -endif() - include(cmake/install-qml-module.cmake) include(cmake/util.cmake) @@ -144,10 +136,6 @@ if (DBUS) list(APPEND QT_FPDEPS DBus) endif() -if (WEBENGINE_effective) - list(APPEND QT_FPDEPS WebEngineQuick) -endif() - find_package(Qt6 REQUIRED COMPONENTS ${QT_FPDEPS}) # In Qt 6.10, private dependencies are required to be explicit, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b13d459..584bafe7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(ipc) add_subdirectory(window) add_subdirectory(io) add_subdirectory(widgets) +add_subdirectory(webengine) add_subdirectory(ui) if (CRASH_HANDLER) diff --git a/src/build/CMakeLists.txt b/src/build/CMakeLists.txt index 8128b92c..c1ffa597 100644 --- a/src/build/CMakeLists.txt +++ b/src/build/CMakeLists.txt @@ -15,12 +15,6 @@ else() set(CRASH_HANDLER_DEF 0) endif() -if (WEBENGINE) - set(WEBENGINE_DEF 1) -else() - set(WEBENGINE_DEF 0) -endif() - configure_file(build.hpp.in build.hpp @ONLY ESCAPE_QUOTES) target_include_directories(quickshell-build INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/build/build.hpp.in b/src/build/build.hpp.in index ea5269ba..acc3c58e 100644 --- a/src/build/build.hpp.in +++ b/src/build/build.hpp.in @@ -9,7 +9,6 @@ #define GIT_REVISION "@GIT_REVISION@" #define DISTRIBUTOR "@DISTRIBUTOR@" #define CRASH_HANDLER @CRASH_HANDLER_DEF@ -#define WEBENGINE @WEBENGINE_DEF@ #define BUILD_TYPE "@CMAKE_BUILD_TYPE@" #define COMPILER "@CMAKE_CXX_COMPILER_ID@ (@CMAKE_CXX_COMPILER_VERSION@)" #define COMPILE_FLAGS "@CMAKE_CXX_FLAGS@" diff --git a/src/launch/CMakeLists.txt b/src/launch/CMakeLists.txt index 86eec6ae..4db11bf0 100644 --- a/src/launch/CMakeLists.txt +++ b/src/launch/CMakeLists.txt @@ -20,8 +20,4 @@ qs_add_pchset(launch qs_pch(quickshell-launch SET launch) -if (WEBENGINE) - target_link_libraries(quickshell-launch PRIVATE Qt::WebEngineQuick) -endif() - target_link_libraries(quickshell PRIVATE quickshell-launch) diff --git a/src/launch/launch.cpp b/src/launch/launch.cpp index aa475bbc..a8e0c443 100644 --- a/src/launch/launch.cpp +++ b/src/launch/launch.cpp @@ -31,9 +31,7 @@ #include "../crash/handler.hpp" #endif -#if WEBENGINE -#include -#endif +#include "../webengine/webengine.hpp" namespace qs::launch { @@ -96,6 +94,7 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio else if (pragma == "NativeTextRendering") pragmas.nativeTextRendering = true; else if (pragma == "IgnoreSystemSettings") pragmas.desktopSettingsAware = false; else if (pragma == "RespectSystemStyle") pragmas.useSystemStyle = true; + else if (pragma == "UseWebEngine") pragmas.useWebEngine = true; else if (pragma.startsWith("IconTheme ")) pragmas.iconTheme = pragma.sliced(10); else if (pragma.startsWith("Env ")) { auto envPragma = pragma.sliced(4); @@ -117,8 +116,7 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio pragmas.stateDir = pragma.sliced(9).trimmed(); } else if (pragma.startsWith("CacheDir ")) { pragmas.cacheDir = pragma.sliced(9).trimmed(); - } else if (pragma == "UseWebEngine") pragmas.useWebEngine = true; - else { + } else { qCritical() << "Unrecognized pragma" << pragma; return -1; } @@ -231,11 +229,9 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio QGuiApplication* app = nullptr; auto qArgC = 1; // argv[0] must be valid; Chromium requires it, Qt won't consume it -#if WEBENGINE if (pragmas.useWebEngine) { - QtWebEngineQuick::initialize(); + qs::web_engine::init(); } -#endif if (pragmas.useQApplication) { app = new QApplication(qArgC, argv); diff --git a/src/webengine/CMakeLists.txt b/src/webengine/CMakeLists.txt new file mode 100644 index 00000000..954a467e --- /dev/null +++ b/src/webengine/CMakeLists.txt @@ -0,0 +1,3 @@ +if (BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/src/webengine/test/CMakeLists.txt b/src/webengine/test/CMakeLists.txt new file mode 100644 index 00000000..c52fbc55 --- /dev/null +++ b/src/webengine/test/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(webengine webengine.cpp) +target_link_libraries(webengine PRIVATE Qt::Core Qt::Test) +add_test(NAME webengine WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $) diff --git a/src/webengine/test/manual/webengine.qml b/src/webengine/test/manual/webengine.qml new file mode 100644 index 00000000..538ed950 --- /dev/null +++ b/src/webengine/test/manual/webengine.qml @@ -0,0 +1,14 @@ +//@ pragma UseWebEngine + +import Quickshell +import QtWebEngine + +FloatingWindow { + width: 800 + height: 600 + + WebEngineView { + anchors.fill: parent + url: "data:text/html,

WebEngine works

If you see this, QtWebEngineQuick initialized correctly.

" + } +} diff --git a/src/webengine/test/webengine.cpp b/src/webengine/test/webengine.cpp new file mode 100644 index 00000000..97d0baae --- /dev/null +++ b/src/webengine/test/webengine.cpp @@ -0,0 +1,10 @@ +#include "webengine.hpp" + +#include +#include + +#include "../webengine.hpp" + +void WebEngineInitTest::init() { QVERIFY(qs::web_engine::init()); } + +QTEST_MAIN(WebEngineInitTest) diff --git a/src/webengine/test/webengine.hpp b/src/webengine/test/webengine.hpp new file mode 100644 index 00000000..0ae87ee8 --- /dev/null +++ b/src/webengine/test/webengine.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +class WebEngineInitTest: public QObject { + Q_OBJECT; + +private slots: + static void init(); +}; diff --git a/src/webengine/webengine.hpp b/src/webengine/webengine.hpp new file mode 100644 index 00000000..b03fa944 --- /dev/null +++ b/src/webengine/webengine.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +namespace qs::web_engine { + +inline bool init() { + using InitializeFunc = void (*)(); + + QLibrary lib("Qt6WebEngineQuick"); + if (!lib.load()) { + qWarning() << "Failed to load library:" << lib.errorString(); + qWarning() << "You might need to install the necessary package for Qt6WebEngineQuick."; + qWarning() << "QtWebEngineQuick is not loaded. Using the qml type WebEngineView from" + " QtWebEngine might lead to undefined behaviour!"; + return false; + } + + qDebug() << "Loaded library Qt6WebEngineQuick"; + + auto initialize = + reinterpret_cast(lib.resolve("_ZN16QtWebEngineQuick10initializeEv")); // NOLINT + if (!initialize) { + qWarning() << "Failed to resolve symbol 'void QtWebEngineQuick::initialize()' in lib" + " Qt6WebEngineQuick. This should not happen."; + qWarning() << "QtWebEngineQuick is not loaded. Using the qml type WebEngineView from" + " QtWebEngine might lead to undefined behaviour!"; + return false; + } + + qDebug() << "Found symbol QtWebEngineQuick::initialize(). Initializing WebEngine..."; + + initialize(); + + qWarning() << "WebEngine initialized. Note: WebEngine is incompatible with jemalloc." + " If quickshell crashes immediately, rebuild with -DUSE_JEMALLOC=OFF."; + + qDebug() << "Successfully initialized QtWebEngineQuick"; + return true; +} + +} // namespace qs::web_engine