From 7d96c20b2851c3ab29702acba1f2f0ee5d90c0fa Mon Sep 17 00:00:00 2001 From: Vasilito Date: Mon, 11 May 2026 10:09:58 +0100 Subject: [PATCH] feat: add KWin compositor integration with QML-free build Add P0-disable-qml-quick.patch for building KWin without QML/Quick dependencies. Update greeter scripts to prefer kwin_wayland. Enable kwin in redbear-full config. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- config/redbear-full.toml | 3 +- local/patches/kwin/P0-disable-qml-quick.patch | 764 ++++++++++++++++++ .../source/redbear-greeter-compositor | 31 +- .../source/redbear-kde-session | 18 +- 4 files changed, 804 insertions(+), 12 deletions(-) create mode 100644 local/patches/kwin/P0-disable-qml-quick.patch diff --git a/config/redbear-full.toml b/config/redbear-full.toml index 0cbf05b726..6856d65ba1 100644 --- a/config/redbear-full.toml +++ b/config/redbear-full.toml @@ -117,7 +117,8 @@ icu = {} konsole = {} kglobalacceld = {} -# kwin = {} # Blocked: Qt6 Wayland plugin import error (QML gate) +# kwin (real KWin compositor, QML-free build via KWIN_BUILD_QML_UI=OFF) +kwin = {} # Plasma + app packages — blocked on kirigami (QML gate) # plasma-framework = {} diff --git a/local/patches/kwin/P0-disable-qml-quick.patch b/local/patches/kwin/P0-disable-qml-quick.patch new file mode 100644 index 0000000000..27c93e36cf --- /dev/null +++ b/local/patches/kwin/P0-disable-qml-quick.patch @@ -0,0 +1,764 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -34,7 +34,9 @@ + include(KDEClangFormat) + include(KDEGitCommitHooks) + +-include(ECMFindQmlModule) ++if(KWIN_BUILD_QML_UI) ++ include(ECMFindQmlModule) ++endif() + include(ECMInstallIcons) + include(ECMOptionalAddSubdirectory) + include(ECMConfiguredInstall) +@@ -42,7 +44,9 @@ + include(ECMSetupQtPluginMacroNames) + include(ECMSetupVersion) + include(ECMQmlModule) +-include(ECMGenerateQmlTypes) ++if(KWIN_BUILD_QML_UI) ++ include(ECMGenerateQmlTypes) ++endif() + include(ECMDeprecationSettings) + + option(KWIN_BUILD_DECORATIONS "Enable building of KWin decorations." ON) +@@ -54,18 +58,25 @@ + option(KWIN_BUILD_X11_BACKEND "Enable building kwin_x11" ON) + option(KWIN_BUILD_GLOBALSHORTCUTS "Enable building of KWin with global shortcuts support" ON) + option(KWIN_BUILD_RUNNERS "Enable building of KWin with krunner support" ON) +- +-find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS ++option(KWIN_BUILD_QML_UI "Enable building of KWin QML UI components (OSD, outline, scripted effects). Requires Qt6::Quick." ON) ++ ++set(KWIN_QT6_REQUIRED_COMPONENTS + Concurrent + Core + Core5Compat + DBus + WaylandClient + Widgets + Sensors + Svg ++) ++if(KWIN_BUILD_QML_UI) ++ list(APPEND KWIN_QT6_REQUIRED_COMPONENTS Quick) ++endif() ++ ++find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS ++ ${KWIN_QT6_REQUIRED_COMPONENTS} + ) + + find_package(Qt6Test ${QT_MIN_VERSION} CONFIG QUIET) +@@ -144,18 +155,20 @@ + ) + add_feature_info("KF6DocTools" KF6DocTools_FOUND "Enable building documentation") + +-find_package(KF6Kirigami ${KF6_MIN_VERSION} CONFIG) +-set_package_properties(KF6Kirigami PROPERTIES +- DESCRIPTION "A QtQuick based components set" +- PURPOSE "Required at runtime for several QML effects" +- TYPE RUNTIME +-) +-find_package(Plasma ${PROJECT_DEP_VERSION} CONFIG) +-set_package_properties(Plasma PROPERTIES +- DESCRIPTION "A QtQuick based components set" +- PURPOSE "Required at runtime for several QML effects" +- TYPE RUNTIME +-) ++if(KWIN_BUILD_QML_UI) ++ find_package(KF6Kirigami ${KF6_MIN_VERSION} CONFIG) ++ set_package_properties(KF6Kirigami PROPERTIES ++ DESCRIPTION "A QtQuick based components set" ++ PURPOSE "Required at runtime for several QML effects" ++ TYPE RUNTIME ++ ) ++ find_package(Plasma ${PROJECT_DEP_VERSION} CONFIG) ++ set_package_properties(Plasma PROPERTIES ++ DESCRIPTION "A QtQuick based components set" ++ PURPOSE "Required at runtime for several QML effects" ++ TYPE RUNTIME ++ ) ++endif() + + find_package(KDecoration3 ${PROJECT_DEP_VERSION} CONFIG REQUIRED) + +@@ -415,14 +428,16 @@ + ) + endif() + +-ecm_find_qmlmodule(QtQuick 2.3) +-ecm_find_qmlmodule(QtQuick.Controls 2.15) +-ecm_find_qmlmodule(QtQuick.Layouts 1.3) +-ecm_find_qmlmodule(QtQuick.Window 2.1) +-ecm_find_qmlmodule(QtMultimedia 5.0) +-ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0) +-ecm_find_qmlmodule(org.kde.plasma.core 2.0) +-ecm_find_qmlmodule(org.kde.plasma.components 2.0) ++if(KWIN_BUILD_QML_UI) ++ ecm_find_qmlmodule(QtQuick 2.3) ++ ecm_find_qmlmodule(QtQuick.Controls 2.15) ++ ecm_find_qmlmodule(QtQuick.Layouts 1.3) ++ ecm_find_qmlmodule(QtQuick.Window 2.1) ++ ecm_find_qmlmodule(QtMultimedia 5.0) ++ ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0) ++ ecm_find_qmlmodule(org.kde.plasma.core 2.0) ++ ecm_find_qmlmodule(org.kde.plasma.components 2.0) ++endif() + + cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "PlasmaActivities_FOUND" OFF) + cmake_dependent_option(KWIN_BUILD_EIS "Enable building KWin with libeis support" ON "Libeis-1.0_FOUND" OFF) +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -16,7 +16,26 @@ + target_link_libraries(KWinEffectsInterface Qt::DBus) + + add_subdirectory(helpers) +-add_subdirectory(qml) ++if(KWIN_BUILD_QML_UI) ++ add_subdirectory(qml) ++endif() ++ ++set(kwin_qml_ui_effect_sources) ++set(kwin_qml_ui_scripting_sources) ++if(KWIN_BUILD_QML_UI) ++ list(APPEND kwin_qml_ui_effect_sources ++ effect/effectframe.cpp ++ effect/offscreenquickview.cpp ++ effect/quickeffect.cpp ++ ) ++ list(APPEND kwin_qml_ui_scripting_sources ++ scripting/desktopbackgrounditem.cpp ++ scripting/gesturehandler.cpp ++ scripting/scriptedquicksceneeffect.cpp ++ scripting/shortcuthandler.cpp ++ scripting/windowthumbnailitem.cpp ++ ) ++endif() + + if (KWIN_BUILD_KCMS) + add_subdirectory(kcms) +@@ -87,15 +106,13 @@ + effect/anidata.cpp + effect/animationeffect.cpp + effect/effect.cpp +- effect/effectframe.cpp + effect/effecthandler.cpp + effect/effectloader.cpp + effect/effecttogglablestate.cpp + effect/effectwindow.cpp + effect/logging.cpp + effect/offscreeneffect.cpp +- effect/offscreenquickview.cpp +- effect/quickeffect.cpp ++ ${kwin_qml_ui_effect_sources} + effect/timeline.cpp + focuschain.cpp + ftrace.cpp +@@ -183,19 +200,15 @@ + scene/workspacescene_qpainter.cpp + screenedge.cpp + scripting/dbuscall.cpp +- scripting/desktopbackgrounditem.cpp +- scripting/gesturehandler.cpp ++ ${kwin_qml_ui_scripting_sources} + scripting/screenedgehandler.cpp + scripting/scriptedeffect.cpp +- scripting/scriptedquicksceneeffect.cpp + scripting/scripting.cpp + scripting/scripting_logging.cpp + scripting/scriptingutils.cpp +- scripting/shortcuthandler.cpp + scripting/tilemodel.cpp + scripting/virtualdesktopmodel.cpp + scripting/windowmodel.cpp +- scripting/windowthumbnailitem.cpp + scripting/workspace_wrapper.cpp + shadow.cpp + sm.cpp +@@ -227,7 +240,6 @@ + target_link_libraries(kwin + PUBLIC + Qt::DBus +- Qt::Quick + Qt::Widgets + Wayland::Server + KF6::ConfigCore +@@ -243,11 +255,9 @@ + + KF6::ColorScheme + KF6::ConfigGui +- KF6::ConfigQml + KF6::Crash + KF6::GlobalAccel + KF6::I18n +- KF6::I18nQml + KF6::Package + KF6::Service + +@@ -263,6 +273,15 @@ + lcms2::lcms2 + PkgConfig::libdisplayinfo + ) ++ ++if(KWIN_BUILD_QML_UI) ++ target_link_libraries(kwin ++ PRIVATE ++ Qt::Quick ++ KF6::ConfigQml ++ KF6::I18nQml ++ ) ++endif() + + if (TARGET K::KGlobalAccelD) + target_link_libraries(kwin PRIVATE K::KGlobalAccelD) +@@ -617,11 +636,16 @@ + effect/effectwindow.h + effect/globals.h + effect/offscreeneffect.h +- effect/offscreenquickview.h +- effect/quickeffect.h + effect/timeline.h + effect/xcb.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/effect COMPONENT Devel) ++ ++if(KWIN_BUILD_QML_UI) ++ install(FILES ++ effect/offscreenquickview.h ++ effect/quickeffect.h ++ DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/effect COMPONENT Devel) ++endif() + + install(FILES + opengl/abstract_opengl_context_attribute_builder.h +--- a/src/config-kwin.h.cmake ++++ b/src/config-kwin.h.cmake +@@ -10,6 +10,7 @@ + #cmakedefine01 KWIN_BUILD_TABBOX + #cmakedefine01 KWIN_BUILD_ACTIVITIES + #cmakedefine01 KWIN_BUILD_GLOBALSHORTCUTS ++#cmakedefine01 KWIN_BUILD_QML_UI + #cmakedefine01 KWIN_BUILD_X11 + constexpr QLatin1String KWIN_CONFIG("kwinrc"); + constexpr QLatin1String KWIN_VERSION_STRING("${PROJECT_VERSION}"); +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -53,7 +53,9 @@ + #include + // Qt + #include ++#if KWIN_BUILD_QML_UI + #include ++#endif + #if KWIN_BUILD_X11 + #include + #endif +@@ -245,7 +247,9 @@ + void Application::createWorkspace() + { + // we want all QQuickWindows with an alpha buffer, do here as Workspace might create QQuickWindows ++#if KWIN_BUILD_QML_UI + QQuickWindow::setDefaultAlphaBuffer(true); ++#endif + + // This tries to detect compositing options and can use GLX. GLX problems + // (X errors) shouldn't cause kwin to abort, so this is out of the +@@ -357,9 +361,13 @@ + + std::unique_ptr Application::createOutline(Outline *outline) + { ++#if KWIN_BUILD_QML_UI + if (Compositor::compositing()) { + return std::make_unique(outline); + } ++#else ++ Q_UNUSED(outline) ++#endif + return nullptr; + } + +--- a/src/compositor_wayland.cpp ++++ b/src/compositor_wayland.cpp +@@ -35,7 +35,9 @@ + #include + #endif + #include ++#if KWIN_BUILD_QML_UI + #include ++#endif + + namespace KWin + { +@@ -207,6 +209,7 @@ + if (m_selectedCompositor == NoCompositing) { + m_selectedCompositor = m_backend->compositingType(); + ++#if KWIN_BUILD_QML_UI + switch (m_selectedCompositor) { + case NoCompositing: + break; +@@ -217,6 +220,7 @@ + QQuickWindow::setGraphicsApi(QSGRendererInterface::Software); + break; + } ++#endif + } + + createScene(); +--- a/src/onscreennotification.cpp ++++ b/src/onscreennotification.cpp +@@ -13,10 +13,12 @@ + #include "input_event_spy.h" + + #include ++#if KWIN_BUILD_QML_UI + #include + #include + #include + #include ++#endif + #include + #include + +@@ -67,10 +69,12 @@ + + OnScreenNotification::~OnScreenNotification() + { ++#if KWIN_BUILD_QML_UI + if (QQuickWindow *w = qobject_cast(m_mainItem.get())) { + w->hide(); + w->destroy(); + } ++#endif + } + + void OnScreenNotification::setConfig(KSharedConfigPtr config) +@@ -80,7 +84,11 @@ + + void OnScreenNotification::setEngine(QQmlEngine *engine) + { ++#if KWIN_BUILD_QML_UI + m_qmlEngine = engine; ++#else ++ Q_UNUSED(engine) ++#endif + } + + bool OnScreenNotification::isVisible() const +@@ -142,9 +150,11 @@ + void OnScreenNotification::show() + { + Q_ASSERT(m_visible); ++#if KWIN_BUILD_QML_UI + ensureQmlContext(); + ensureQmlComponent(); + createInputSpy(); ++#endif + if (m_timer->interval() != 0) { + m_timer->start(); + } +@@ -152,16 +162,19 @@ + + void OnScreenNotification::ensureQmlContext() + { ++#if KWIN_BUILD_QML_UI + Q_ASSERT(m_qmlEngine); + if (m_qmlContext) { + return; + } + m_qmlContext = std::make_unique(m_qmlEngine); + m_qmlContext->setContextProperty(QStringLiteral("osd"), this); ++#endif + } + + void OnScreenNotification::ensureQmlComponent() + { ++#if KWIN_BUILD_QML_UI + Q_ASSERT(m_config); + Q_ASSERT(m_qmlEngine); + if (m_qmlComponent) { +@@ -179,10 +192,12 @@ + } else { + m_qmlComponent.reset(); + } ++#endif + } + + void OnScreenNotification::createInputSpy() + { ++#if KWIN_BUILD_QML_UI + Q_ASSERT(!m_spy); + if (auto w = qobject_cast(m_mainItem.get())) { + m_spy = std::make_unique(this); +@@ -195,13 +210,16 @@ + m_animation->setEasingCurve(QEasingCurve::InOutCubic); + } + } ++#endif + } + + QRect OnScreenNotification::geometry() const + { ++#if KWIN_BUILD_QML_UI + if (QQuickWindow *w = qobject_cast(m_mainItem.get())) { + return w->geometry(); + } ++#endif + return QRect(); + } + +@@ -220,9 +238,13 @@ + + void OnScreenNotification::setSkipCloseAnimation(bool skip) + { ++#if KWIN_BUILD_QML_UI + if (QQuickWindow *w = qobject_cast(m_mainItem.get())) { + w->setProperty("KWIN_SKIP_CLOSE_ANIMATION", skip); + } ++#else ++ Q_UNUSED(skip) ++#endif + } + + } // namespace KWin +--- a/src/outline.cpp ++++ b/src/outline.cpp +@@ -18,10 +18,12 @@ + #include + // Qt + #include ++#if KWIN_BUILD_QML_UI + #include + #include + #include + #include ++#endif + #include + + namespace KWin +@@ -153,14 +155,17 @@ + + void CompositedOutlineVisual::hide() + { ++#if KWIN_BUILD_QML_UI + if (QQuickWindow *w = qobject_cast(m_mainItem.get())) { + w->hide(); + w->destroy(); + } ++#endif + } + + void CompositedOutlineVisual::show() + { ++#if KWIN_BUILD_QML_UI + if (!m_qmlContext) { + m_qmlContext = std::make_unique(Scripting::self()->qmlEngine()); + m_qmlContext->setContextProperty(QStringLiteral("outline"), m_outline); +@@ -183,6 +188,7 @@ + w->setProperty("__kwin_outline", true); + } + } ++#endif + } + + } // namespace +--- a/src/osd.cpp ++++ b/src/osd.cpp +@@ -10,7 +10,9 @@ + #include "scripting/scripting.h" + #include "workspace.h" + ++#if KWIN_BUILD_QML_UI + #include ++#endif + #include + + namespace KWin +@@ -22,7 +24,9 @@ + { + auto osd = new OnScreenNotification(workspace()); + osd->setConfig(kwinApp()->config()); ++#if KWIN_BUILD_QML_UI + osd->setEngine(Scripting::self()->qmlEngine()); ++#endif + return osd; + } + +--- a/src/effect/effectloader.cpp ++++ b/src/effect/effectloader.cpp +@@ -15,7 +15,9 @@ + #include "effect/effecthandler.h" + #include "plugin.h" + #include "scripting/scriptedeffect.h" ++#if KWIN_BUILD_QML_UI + #include "scripting/scriptedquicksceneeffect.h" ++#endif + #include "scripting/scripting.h" + #include "utils/common.h" + // KDE +@@ -26,8 +28,10 @@ + #include + #include + #include ++#if KWIN_BUILD_QML_UI + #include + #include ++#endif + #include + #include + #include +@@ -131,7 +135,12 @@ + if (api == QLatin1String("javascript")) { + return loadJavascriptEffect(effect); + } else if (api == QLatin1String("declarativescript")) { ++#if KWIN_BUILD_QML_UI + return loadDeclarativeEffect(effect); ++#else ++ qCDebug(KWIN_CORE) << "Skipping declarative effect because KWIN_BUILD_QML_UI is OFF:" << name; ++ return false; ++#endif + } else { + qCWarning(KWIN_CORE, "Failed to load %s effect: invalid X-Plasma-API field: %s. " + "Available options are javascript, and declarativescript", qPrintable(name), qPrintable(api)); +@@ -165,6 +174,10 @@ + + bool ScriptedEffectLoader::loadDeclarativeEffect(const KPluginMetaData &metadata) + { ++#if !KWIN_BUILD_QML_UI ++ Q_UNUSED(metadata) ++ return false; ++#else + const QString name = metadata.pluginId(); + const QString scriptFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, + QLatin1String("kwin/effects/") + name + QLatin1String("/contents/ui/main.qml")); +@@ -199,6 +212,7 @@ + Q_EMIT effectLoaded(effect, name); + m_loadedEffects << name; + return true; ++#endif + } + + void ScriptedEffectLoader::queryAndLoadAll() +--- a/src/effect/offscreenquickview.cpp ++++ b/src/effect/offscreenquickview.cpp +@@ -8,6 +8,9 @@ + */ + + #include "effect/offscreenquickview.h" ++#include "config-kwin.h" ++ ++#if KWIN_BUILD_QML_UI + #include "effect/effecthandler.h" + + #include "logging_p.h" +@@ -643,3 +646,4 @@ + } // namespace KWin + + #include "moc_offscreenquickview.cpp" ++#endif +--- a/src/effect/quickeffect.cpp ++++ b/src/effect/quickeffect.cpp +@@ -5,6 +5,9 @@ + */ + + #include "effect/quickeffect.h" ++#include "config-kwin.h" ++ ++#if KWIN_BUILD_QML_UI + #include "core/output.h" + #include "effect/effecthandler.h" + +@@ -629,3 +632,4 @@ + } // namespace KWin + + #include "moc_quickeffect.cpp" ++#endif +--- a/src/scripting/scriptedquicksceneeffect.cpp ++++ b/src/scripting/scriptedquicksceneeffect.cpp +@@ -5,6 +5,9 @@ + */ + + #include "scripting/scriptedquicksceneeffect.h" ++#include "config-kwin.h" ++ ++#if KWIN_BUILD_QML_UI + #include "main.h" + + #include +@@ -130,3 +133,4 @@ + } // namespace KWin + + #include "moc_scriptedquicksceneeffect.cpp" ++#endif +--- a/src/scripting/scripting.cpp ++++ b/src/scripting/scripting.cpp +@@ -12,17 +12,19 @@ + #include "scripting.h" + // own + #include "dbuscall.h" ++#if KWIN_BUILD_QML_UI + #include "desktopbackgrounditem.h" + #include "effect/quickeffect.h" + #include "gesturehandler.h" ++#include "scriptedquicksceneeffect.h" ++#include "shortcuthandler.h" ++#include "windowthumbnailitem.h" ++#endif + #include "screenedgehandler.h" +-#include "scriptedquicksceneeffect.h" + #include "scripting_logging.h" + #include "scriptingutils.h" +-#include "shortcuthandler.h" + #include "virtualdesktopmodel.h" + #include "windowmodel.h" +-#include "windowthumbnailitem.h" + #include "workspace_wrapper.h" + + #include "core/output.h" +@@ -35,10 +37,14 @@ + #include "workspace.h" + // KDE + #include ++#if KWIN_BUILD_QML_UI + #include ++#endif + #include + #include ++#if KWIN_BUILD_QML_UI + #include ++#endif + #include + // Qt + #include +@@ -46,10 +52,12 @@ + #include + #include + #include ++#if KWIN_BUILD_QML_UI + #include + #include + #include + #include ++#endif + #include + #include + #include +@@ -561,6 +569,7 @@ + return menu->menuAction(); + } + ++#if KWIN_BUILD_QML_UI + KWin::DeclarativeScript::DeclarativeScript(int id, QString scriptName, QString pluginName, QObject *parent) + : AbstractScript(id, scriptName, pluginName, parent) + , m_context(new QQmlContext(Scripting::self()->declarativeScriptSharedContext(), this)) +@@ -598,6 +607,7 @@ + } + setRunning(true); + } ++#endif + + KWin::JSEngineGlobalMethodsWrapper::JSEngineGlobalMethodsWrapper(KWin::DeclarativeScript *parent) + : QObject(parent) +@@ -626,12 +636,19 @@ + KWin::Scripting::Scripting(QObject *parent) + : QObject(parent) + , m_scriptsLock(new QRecursiveMutex) ++#if KWIN_BUILD_QML_UI + , m_qmlEngine(new QQmlEngine(this)) + , m_declarativeScriptSharedContext(new QQmlContext(m_qmlEngine, this)) ++#else ++ , m_qmlEngine(nullptr) ++ , m_declarativeScriptSharedContext(nullptr) ++#endif + , m_workspaceWrapper(new QtScriptWorkspaceWrapper(this)) + { ++#if KWIN_BUILD_QML_UI + m_qmlEngine->setProperty("_kirigamiTheme", QStringLiteral("KirigamiPlasmaStyle")); + m_qmlEngine->rootContext()->setContextObject(new KLocalizedQmlContext(m_qmlEngine)); ++#endif + init(); + QDBusConnection::sessionBus().registerObject(QStringLiteral("/Scripting"), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables); + connect(Workspace::self(), &Workspace::configChanged, this, &Scripting::start); +@@ -644,6 +661,7 @@ + qRegisterMetaType>(); + qRegisterMetaType>(); + ++#if KWIN_BUILD_QML_UI + qmlRegisterType("org.kde.kwin", 3, 0, "DesktopBackground"); + qmlRegisterType("org.kde.kwin", 3, 0, "WindowThumbnail"); + qmlRegisterType("org.kde.kwin", 3, 0, "DBusCall"); +@@ -671,6 +689,7 @@ + // TODO: call the qml types as the C++ types? + qmlRegisterUncreatableType("org.kde.kwin", 3, 0, "CustomTile", QStringLiteral("Cannot create objects of type Tile")); + qmlRegisterUncreatableType("org.kde.kwin", 3, 0, "Tile", QStringLiteral("Cannot create objects of type AbstractTile")); ++#endif + } + + void KWin::Scripting::start() +@@ -821,6 +840,7 @@ + + int KWin::Scripting::loadDeclarativeScript(const QString &filePath, const QString &pluginName) + { ++#if KWIN_BUILD_QML_UI + QMutexLocker locker(m_scriptsLock.get()); + if (isScriptLoaded(pluginName)) { + return -1; +@@ -830,6 +850,11 @@ + connect(script, &QObject::destroyed, this, &Scripting::scriptDestroyed); + scripts.append(script); + return id; ++#else ++ Q_UNUSED(filePath) ++ Q_UNUSED(pluginName) ++ return -1; ++#endif + } + + KWin::Scripting::~Scripting() +--- a/src/scripting/workspace_wrapper.h ++++ b/src/scripting/workspace_wrapper.h +@@ -10,9 +10,12 @@ + + #pragma once + ++#include "config-kwin.h" + #include "effect/globals.h" + #include ++#if KWIN_BUILD_QML_UI + #include ++#endif + #include + #include + #include +@@ -406,6 +409,7 @@ + explicit QtScriptWorkspaceWrapper(QObject *parent = nullptr); + }; + ++#if KWIN_BUILD_QML_UI + class DeclarativeScriptWorkspaceWrapper : public WorkspaceWrapper + { + Q_OBJECT +@@ -418,5 +422,6 @@ + + explicit DeclarativeScriptWorkspaceWrapper(QObject *parent = nullptr); + }; ++#endif + + } +--- a/src/scripting/workspace_wrapper.cpp ++++ b/src/scripting/workspace_wrapper.cpp +@@ -437,6 +437,7 @@ + return workspace()->windows(); + } + ++#if KWIN_BUILD_QML_UI + QQmlListProperty DeclarativeScriptWorkspaceWrapper::windows() + { + return QQmlListProperty(this, nullptr, &DeclarativeScriptWorkspaceWrapper::countWindowList, &DeclarativeScriptWorkspaceWrapper::atWindowList); +@@ -456,6 +457,7 @@ + : WorkspaceWrapper(parent) + { + } ++#endif + + } // KWin + diff --git a/local/recipes/system/redbear-greeter/source/redbear-greeter-compositor b/local/recipes/system/redbear-greeter/source/redbear-greeter-compositor index 8f54130668..2abd78e1d0 100755 --- a/local/recipes/system/redbear-greeter/source/redbear-greeter-compositor +++ b/local/recipes/system/redbear-greeter/source/redbear-greeter-compositor @@ -81,13 +81,18 @@ if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] && command -v dbus-launch >/dev/null 2 eval "$(dbus-launch --sh-syntax)" fi -if ! command -v redbear-compositor >/dev/null 2>&1; then - # Fall back to redbear-compositor (simpler Rust compositor) - if command -v /usr/bin/redbear-compositor >/dev/null 2>&1 || command -v redbear-compositor >/dev/null 2>&1; then - echo "redbear-greeter-compositor: redbear-compositor not found, using redbear-compositor" >&2 - exec /usr/bin/redbear-compositor - fi - echo "redbear-greeter-compositor: redbear-compositor not found, and redbear-compositor not found either" >&2 +# Prefer kwin_wayland (real KWin compositor). Fall back to redbear-compositor only if +# KWin is not installed (e.g. text-only target accidentally includes greeter). +COMPOSITOR="" +if command -v kwin_wayland >/dev/null 2>&1; then + COMPOSITOR="kwin_wayland" +elif command -v /usr/bin/kwin_wayland >/dev/null 2>&1; then + COMPOSITOR="/usr/bin/kwin_wayland" +elif command -v redbear-compositor >/dev/null 2>&1; then + COMPOSITOR="redbear-compositor" + echo "redbear-greeter-compositor: kwin_wayland not found, falling back to redbear-compositor" >&2 +else + echo "redbear-greeter-compositor: no compositor found (need kwin_wayland or redbear-compositor)" >&2 exit 1 fi @@ -102,9 +107,17 @@ fi if wait_for_drm_devices "$desired_drm_devices"; then export KWIN_DRM_DEVICES="${KWIN_DRM_DEVICES:-/scheme/drm/card0}" echo "redbear-greeter-compositor: using DRM compositor backend (KWIN_DRM_DEVICES=${KWIN_DRM_DEVICES})" >&2 - exec redbear-compositor --drm + if [ "$COMPOSITOR" = "kwin_wayland" ] || [ "$COMPOSITOR" = "/usr/bin/kwin_wayland" ]; then + exec "$COMPOSITOR" --drm + else + exec "$COMPOSITOR" --drm + fi else unset KWIN_DRM_DEVICES echo "redbear-greeter-compositor: DRM device not ready after wait, using virtual compositor backend" >&2 - exec redbear-compositor --virtual + if [ "$COMPOSITOR" = "kwin_wayland" ] || [ "$COMPOSITOR" = "/usr/bin/kwin_wayland" ]; then + exec "$COMPOSITOR" --virtual + else + exec "$COMPOSITOR" --virtual + fi fi diff --git a/local/recipes/system/redbear-greeter/source/redbear-kde-session b/local/recipes/system/redbear-greeter/source/redbear-kde-session index 1d995e332f..f9df81ea0d 100755 --- a/local/recipes/system/redbear-greeter/source/redbear-kde-session +++ b/local/recipes/system/redbear-greeter/source/redbear-kde-session @@ -231,6 +231,20 @@ launch_optional_component() { fi } +# Prefer kwin_wayland (real KWin compositor). Fall back to redbear-compositor. +COMPOSITOR="" +if command -v kwin_wayland >/dev/null 2>&1; then + COMPOSITOR="kwin_wayland" +elif command -v /usr/bin/kwin_wayland >/dev/null 2>&1; then + COMPOSITOR="/usr/bin/kwin_wayland" +elif command -v redbear-compositor >/dev/null 2>&1; then + COMPOSITOR="redbear-compositor" + echo "redbear-kde-session: kwin_wayland not found, falling back to redbear-compositor" >&2 +else + echo "redbear-kde-session: no compositor found (need kwin_wayland or redbear-compositor)" >&2 + exit 1 +fi + kwin_args=() if [ "$kwin_mode" = "drm" ]; then kwin_args+=(--drm) @@ -238,11 +252,11 @@ else kwin_args+=(--virtual) fi -redbear-compositor "${kwin_args[@]}" & +"$COMPOSITOR" "${kwin_args[@]}" & kwin_pid=$! if ! wait_for_wayland_socket; then - printf '%s\n' "redbear-kde-session: redbear-compositor failed to expose $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" >&2 + printf '%s\n' "redbear-kde-session: $COMPOSITOR failed to expose $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" >&2 exit 1 fi