From a3e6182086f5deb7dcc7b269cbb9a308c81ce929 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Sat, 23 May 2026 15:33:23 +0200 Subject: [PATCH] Hide convergence chrome in Overview Track KWin Overview through the activeEffects DBus property and expose the state to Folio QML. Hide the workspace frame, dock overlay, and in-containment favourites scrim while Overview is active so the effect does not show Shift shell chrome in its desktop view. Set the state before invoking the Overview shortcut from Folio so the chrome is already gone when KWin starts composing the effect. The convergence dock invariant now guards both the hide rules and this ordering. --- containments/homescreens/folio/homescreen.cpp | 100 +++++++++++++++++- containments/homescreens/folio/homescreen.h | 10 +- .../homescreens/folio/qml/FolioHomeScreen.qml | 1 + containments/homescreens/folio/qml/main.qml | 8 +- tests/check-convergence-dock-invariant.sh | 27 +++++ 5 files changed, 142 insertions(+), 4 deletions(-) diff --git a/containments/homescreens/folio/homescreen.cpp b/containments/homescreens/folio/homescreen.cpp index 56b33360..3069c326 100644 --- a/containments/homescreens/folio/homescreen.cpp +++ b/containments/homescreens/folio/homescreen.cpp @@ -9,14 +9,48 @@ #include #include +#include #include +#include +#include #include #include #include #include +#include K_PLUGIN_CLASS_WITH_JSON(HomeScreen, "metadata.json") +namespace +{ + +const QString s_kwinService = QStringLiteral("org.kde.KWin"); +const QString s_kwinEffectsPath = QStringLiteral("/Effects"); +const QString s_kwinEffectsInterface = QStringLiteral("org.kde.kwin.Effects"); +const QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties"); + +QStringList effectListFromVariant(const QVariant &value) +{ + QVariant effectValue = value; + if (effectValue.canConvert()) { + effectValue = effectValue.value().variant(); + } + + if (effectValue.canConvert()) { + return effectValue.toStringList(); + } + + QStringList effects; + const QVariantList effectList = effectValue.toList(); + effects.reserve(effectList.size()); + for (const QVariant &effect : effectList) { + effects.append(effect.toString()); + } + return effects; +} + +} + HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args) : Plasma::Containment{parent, data, args} , m_folioSettings{new FolioSettings{this}} @@ -34,6 +68,20 @@ HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVari connect(KWindowSystem::self(), &KWindowSystem::showingDesktopChanged, this, &HomeScreen::showingDesktopChanged); + updateOverviewActive(); + QDBusConnection::sessionBus().connect(s_kwinService, + s_kwinEffectsPath, + s_dbusPropertiesInterface, + QStringLiteral("PropertiesChanged"), + this, + SLOT(onOverviewEffectsChanged(QString, QVariantMap, QStringList))); + + auto overviewRefreshTimer = new QTimer(this); + overviewRefreshTimer->setInterval(250); + overviewRefreshTimer->setTimerType(Qt::CoarseTimer); + connect(overviewRefreshTimer, &QTimer::timeout, this, &HomeScreen::updateOverviewActive); + overviewRefreshTimer->start(); + connect(this, &Plasma::Containment::appletAdded, this, &HomeScreen::onAppletAdded); connect(this, &Plasma::Containment::appletAboutToBeRemoved, this, &HomeScreen::onAppletAboutToBeRemoved); } @@ -91,8 +139,58 @@ PageListModel *HomeScreen::pageListModel() return m_pageListModel; } -void HomeScreen::triggerOverview() const +bool HomeScreen::overviewActive() const { + return m_overviewActive; +} + +void HomeScreen::setOverviewActive(bool overviewActive) +{ + if (m_overviewActive == overviewActive) { + return; + } + + m_overviewActive = overviewActive; + Q_EMIT overviewActiveChanged(); +} + +void HomeScreen::updateOverviewActive() +{ + QDBusInterface propIface(s_kwinService, s_kwinEffectsPath, s_dbusPropertiesInterface, QDBusConnection::sessionBus()); + if (!propIface.isValid()) { + setOverviewActive(false); + return; + } + + QDBusReply activeEffectsReply = propIface.call(QStringLiteral("Get"), s_kwinEffectsInterface, QStringLiteral("activeEffects")); + if (!activeEffectsReply.isValid()) { + setOverviewActive(false); + return; + } + + setOverviewActive(effectListFromVariant(activeEffectsReply.value().variant()).contains(QStringLiteral("overview"))); +} + +void HomeScreen::onOverviewEffectsChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) +{ + if (interface != s_kwinEffectsInterface) { + return; + } + + if (changed.contains(QStringLiteral("activeEffects"))) { + setOverviewActive(effectListFromVariant(changed.value(QStringLiteral("activeEffects"))).contains(QStringLiteral("overview"))); + return; + } + + if (invalidated.contains(QStringLiteral("activeEffects"))) { + updateOverviewActive(); + } +} + +void HomeScreen::triggerOverview() +{ + setOverviewActive(true); + QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kglobalaccel", "/component/kwin", "org.kde.kglobalaccel.Component", "invokeShortcut"); message.setArguments({QStringLiteral("Overview")}); QDBusConnection::sessionBus().send(message); diff --git a/containments/homescreens/folio/homescreen.h b/containments/homescreens/folio/homescreen.h index 0161b62e..f8d1acd9 100644 --- a/containments/homescreens/folio/homescreen.h +++ b/containments/homescreens/folio/homescreen.h @@ -43,6 +43,7 @@ class HomeScreen : public Plasma::Containment Q_PROPERTY(ApplicationListSearchModel *ApplicationListSearchModel READ applicationListSearchModel CONSTANT) Q_PROPERTY(FavouritesModel *FavouritesModel READ favouritesModel CONSTANT) Q_PROPERTY(PageListModel *PageListModel READ pageListModel CONSTANT) + Q_PROPERTY(bool overviewActive READ overviewActive NOTIFY overviewActiveChanged) public: HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args); @@ -50,7 +51,7 @@ public: void configChanged() override; - Q_INVOKABLE void triggerOverview() const; + Q_INVOKABLE void triggerOverview(); Q_INVOKABLE void triggerMinimizeAll() const; Q_INVOKABLE void activateVirtualDesktop(const QVariant &desktop) const; Q_INVOKABLE void createVirtualDesktop() const; @@ -64,15 +65,21 @@ public: ApplicationListSearchModel *applicationListSearchModel(); FavouritesModel *favouritesModel(); PageListModel *pageListModel(); + bool overviewActive() const; Q_SIGNALS: + void overviewActiveChanged(); void showingDesktopChanged(bool showingDesktop); private Q_SLOTS: + void onOverviewEffectsChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); void onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint); void onAppletAboutToBeRemoved(Plasma::Applet *applet); private: + void setOverviewActive(bool overviewActive); + void updateOverviewActive(); + FolioSettings *m_folioSettings{nullptr}; HomeScreenState *m_homeScreenState{nullptr}; WidgetsManager *m_widgetsManager{nullptr}; @@ -80,4 +87,5 @@ private: ApplicationListSearchModel *m_applicationListSearchModel{nullptr}; FavouritesModel *m_favouritesModel{nullptr}; PageListModel *m_pageListModel{nullptr}; + bool m_overviewActive{false}; }; diff --git a/containments/homescreens/folio/qml/FolioHomeScreen.qml b/containments/homescreens/folio/qml/FolioHomeScreen.qml index 299fa833..7fb662fd 100644 --- a/containments/homescreens/folio/qml/FolioHomeScreen.qml +++ b/containments/homescreens/folio/qml/FolioHomeScreen.qml @@ -358,6 +358,7 @@ Item { // don't show in settings mode opacity: 1 - folio.HomeScreenState.settingsOpenProgress visible: folio.FolioSettings.showFavouritesBarBackground + && !ShellSettings.Settings.convergenceModeEnabled anchors.top: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? favouritesBar.top : parent.top anchors.bottom: parent.bottom diff --git a/containments/homescreens/folio/qml/main.qml b/containments/homescreens/folio/qml/main.qml index a34ccc3b..5840497d 100644 --- a/containments/homescreens/folio/qml/main.qml +++ b/containments/homescreens/folio/qml/main.qml @@ -278,7 +278,9 @@ ContainmentItem { // task panel containment; this window only provides the visible dock. Window { id: dockOverlay - readonly property bool active: ShellSettings.Settings.convergenceModeEnabled && !ShellSettings.Settings.gamingModeEnabled + readonly property bool active: ShellSettings.Settings.convergenceModeEnabled + && !ShellSettings.Settings.gamingModeEnabled + && !folio.overviewActive visible: active opacity: active ? 1 : 0 @@ -882,7 +884,9 @@ ContainmentItem { Item { id: workspaceFrame anchors.fill: parent - visible: ShellSettings.Settings.convergenceModeEnabled && !ShellSettings.Settings.gamingModeEnabled + visible: ShellSettings.Settings.convergenceModeEnabled + && !ShellSettings.Settings.gamingModeEnabled + && !folio.overviewActive z: -1 readonly property real frameThickness: MobileShell.Constants.convergenceWorkspaceFrameThickness diff --git a/tests/check-convergence-dock-invariant.sh b/tests/check-convergence-dock-invariant.sh index be1dc876..94a5c653 100644 --- a/tests/check-convergence-dock-invariant.sh +++ b/tests/check-convergence-dock-invariant.sh @@ -11,6 +11,8 @@ panel="$repo_root/containments/panel/qml/main.qml" taskpanel="$repo_root/containments/taskpanel/qml/main.qml" folio_main="$repo_root/containments/homescreens/folio/qml/main.qml" folio_home="$repo_root/containments/homescreens/folio/qml/FolioHomeScreen.qml" +folio_backend="$repo_root/containments/homescreens/folio/homescreen.h" +folio_backend_cpp="$repo_root/containments/homescreens/folio/homescreen.cpp" action_content="$repo_root/components/mobileshell/qml/actiondrawer/private/ContentContainer.qml" action_landscape="$repo_root/components/mobileshell/qml/actiondrawer/private/LandscapeContentContainer.qml" quick_settings="$repo_root/components/mobileshell/qml/actiondrawer/private/QuickSettings.qml" @@ -64,6 +66,31 @@ require_line "$folio_main" "- MobileShell.Constants.convergenceWorkspaceFrameThi require_line "$folio_main" "readonly property real popupHeight: Math.max(0, popupBottomY - popupTopY)" require_line "$folio_main" "? popupTopY + animationY" require_line "$folio_home" "height: ShellSettings.Settings.convergenceModeEnabled ? MobileShell.Constants.convergenceDockHeight : Kirigami.Units.gridUnit * 6" +require_line "$folio_home" "&& !ShellSettings.Settings.convergenceModeEnabled" +require_line "$folio_backend" "Q_PROPERTY(bool overviewActive READ overviewActive NOTIFY overviewActiveChanged)" + +overview_hide_guards="$(grep -F "&& !folio.overviewActive" "$folio_main" | wc -l)" +if [[ "$overview_hide_guards" -ne 2 ]]; then + echo "Expected the Folio convergence workspace frame and dock overlay to hide during KWin Overview; found $overview_hide_guards overview guards" >&2 + exit 1 +fi + +if ! awk ' + /void HomeScreen::triggerOverview\(\)/ { in_trigger = 1; next } + in_trigger && /setOverviewActive\(true\);/ { saw_pre_hide = 1; next } + in_trigger && /createMethodCall/ { + if (saw_pre_hide) { + found = 1 + exit 0 + } + exit 1 + } + in_trigger && /^}/ { exit 1 } + END { if (!found) exit 1 } +' "$folio_backend_cpp"; then + echo "Expected Folio to hide convergence chrome before invoking KWin Overview" >&2 + exit 1 +fi require_line "$action_content" "readonly property real convergenceSurfaceTopInset: MobileShell.Constants.topPanelHeight" require_line "$action_content" "readonly property real convergenceSurfaceBottomInset: MobileShell.Constants.convergenceDockHeight + convergenceFrameThickness"