From da6e17f3f4c3fdf192125728ba6352e78882c2ca Mon Sep 17 00:00:00 2001 From: Devin Lin Date: Sat, 18 Mar 2023 18:48:49 -0700 Subject: [PATCH] windowplugin: Use standardized way to know whether a window is showing and maximized --- .../mobileshell/qml/homescreen/HomeScreen.qml | 2 +- components/windowplugin/CMakeLists.txt | 5 +- .../qml/WindowMaximizedTracker.qml | 39 ++++++++++ components/windowplugin/resources.qrc | 11 +++ components/windowplugin/windowplugin.cpp | 7 ++ components/windowplugin/windowutil.cpp | 77 ++++++++++--------- components/windowplugin/windowutil.h | 31 +++----- containments/homescreens/folio/homescreen.cpp | 10 --- containments/homescreens/folio/homescreen.h | 4 - .../folio/package/contents/ui/main.qml | 4 +- .../homescreens/halcyon/homescreen.cpp | 10 --- containments/homescreens/halcyon/homescreen.h | 4 - .../package/contents/ui/HomeScreen.qml | 6 +- .../halcyon/package/contents/ui/main.qml | 6 +- .../panel/package/contents/ui/main.qml | 34 +------- .../contents/ui/NavigationPanelComponent.qml | 1 - .../taskpanel/package/contents/ui/main.qml | 32 +------- 17 files changed, 127 insertions(+), 156 deletions(-) create mode 100644 components/windowplugin/qml/WindowMaximizedTracker.qml create mode 100644 components/windowplugin/resources.qrc diff --git a/components/mobileshell/qml/homescreen/HomeScreen.qml b/components/mobileshell/qml/homescreen/HomeScreen.qml index e134c50b..5f21ded8 100644 --- a/components/mobileshell/qml/homescreen/HomeScreen.qml +++ b/components/mobileshell/qml/homescreen/HomeScreen.qml @@ -80,7 +80,7 @@ Item { target: MobileShellState.HomeScreenControls function onOpenHomeScreen() { - if (!WindowPlugin.WindowUtil.allWindowsMinimized) { + if (WindowPlugin.WindowMaximizedTracker.showingWindow) { itemContainer.zoomIn(); } diff --git a/components/windowplugin/CMakeLists.txt b/components/windowplugin/CMakeLists.txt index 94926c0b..5d72ef57 100644 --- a/components/windowplugin/CMakeLists.txt +++ b/components/windowplugin/CMakeLists.txt @@ -1,11 +1,12 @@ # SPDX-FileCopyrightText: 2023 Devin Lin # SPDX-License-Identifier: GPL-2.0-or-later -add_library(windowplugin) -target_sources(windowplugin PRIVATE +set(windowplugin_SRCS windowplugin.cpp windowutil.cpp ) +qt_add_resources(RESOURCES resources.qrc) +add_library(windowplugin SHARED ${windowplugin_SRCS} ${RESOURCES}) target_link_libraries(windowplugin Qt::Qml diff --git a/components/windowplugin/qml/WindowMaximizedTracker.qml b/components/windowplugin/qml/WindowMaximizedTracker.qml new file mode 100644 index 00000000..72c39045 --- /dev/null +++ b/components/windowplugin/qml/WindowMaximizedTracker.qml @@ -0,0 +1,39 @@ +import QtQuick + +import org.kde.plasma.core as PlasmaCore +import org.kde.taskmanager as TaskManager + +pragma Singleton + +// Helper component that uses Plasma's tasks model to provide whether a maximized window is showing on the current screen. + +QtObject { + readonly property bool showingWindow: __internal.count > 0 + + property var __internal: PlasmaCore.SortFilterModel { + id: visibleMaximizedWindowsModel + filterRole: 'IsMinimized' + filterRegExp: 'false' + sourceModel: TaskManager.TasksModel { + id: tasksModel + filterByVirtualDesktop: true + filterByActivity: true + filterNotMaximized: true + filterByScreen: true + filterHidden: true + + virtualDesktop: virtualDesktopInfo.currentDesktop + activity: activityInfo.currentActivity + + groupMode: TaskManager.TasksModel.GroupDisabled + } + + property var vdi: TaskManager.VirtualDesktopInfo { + id: virtualDesktopInfo + } + + property var ai: TaskManager.ActivityInfo { + id: activityInfo + } + } +} diff --git a/components/windowplugin/resources.qrc b/components/windowplugin/resources.qrc new file mode 100644 index 00000000..374bd381 --- /dev/null +++ b/components/windowplugin/resources.qrc @@ -0,0 +1,11 @@ + + + + qml/WindowMaximizedTracker.qml + + + + diff --git a/components/windowplugin/windowplugin.cpp b/components/windowplugin/windowplugin.cpp index 950de2e3..1ff944b6 100644 --- a/components/windowplugin/windowplugin.cpp +++ b/components/windowplugin/windowplugin.cpp @@ -7,6 +7,11 @@ #include #include +QUrl resolvePath(std::string str) +{ + return QUrl("qrc:/org/kde/plasma/private/mobileshell/windowplugin/qml/" + QString::fromStdString(str)); +} + void WindowPlugin::registerTypes(const char *uri) { Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.plasma.private.mobileshell.windowplugin")); @@ -14,4 +19,6 @@ void WindowPlugin::registerTypes(const char *uri) qmlRegisterSingletonType(uri, 1, 0, "WindowUtil", [](QQmlEngine *, QJSEngine *) -> QObject * { return WindowUtil::instance(); }); + + qmlRegisterSingletonType(resolvePath("WindowMaximizedTracker.qml"), uri, 1, 0, "WindowMaximizedTracker"); } diff --git a/components/windowplugin/windowutil.cpp b/components/windowplugin/windowutil.cpp index a21c8fc4..252bf013 100644 --- a/components/windowplugin/windowutil.cpp +++ b/components/windowplugin/windowutil.cpp @@ -7,6 +7,8 @@ #include "windowutil.h" +#include + #include constexpr int ACTIVE_WINDOW_UPDATE_INVERVAL = 0; @@ -36,16 +38,6 @@ bool WindowUtil::isShowingDesktop() const return m_showingDesktop; } -bool WindowUtil::allWindowsMinimized() const -{ - return m_allWindowsMinimized; -} - -bool WindowUtil::allWindowsMinimizedExcludingShell() const -{ - return m_allWindowsMinimizedExcludingShell; -} - bool WindowUtil::activeWindowIsShell() const { return m_activeWindowIsShell; @@ -83,6 +75,40 @@ void WindowUtil::initWayland() m_activeWindowTimer->start(); }); + connect(registry, &Registry::plasmaActivationFeedbackAnnounced, this, [this, registry](quint32 name, quint32 version) { + auto iface = registry->createPlasmaActivationFeedback(name, version, this); + + connect(iface, &PlasmaActivationFeedback::activation, this, [this](PlasmaActivation *activation) { + connect(activation, &PlasmaActivation::applicationId, this, [this](const QString &appId) { + const auto servicesFound = KApplicationTrader::query([&appId](const KService::Ptr &service) { + if (service->exec().isEmpty()) + return false; + + if (service->desktopEntryName().compare(appId, Qt::CaseInsensitive) == 0) + return true; + + const auto idWithoutDesktop = QString(appId).remove(QStringLiteral(".desktop")); + if (service->desktopEntryName().compare(idWithoutDesktop, Qt::CaseInsensitive) == 0) + return true; + + const auto renamedFrom = service->property(QStringLiteral("X-Flatpak-RenamedFrom")).toStringList(); + if (renamedFrom.contains(appId, Qt::CaseInsensitive) || renamedFrom.contains(idWithoutDesktop, Qt::CaseInsensitive)) + return true; + + return false; + }); + + if (!servicesFound.isEmpty()) { + Q_EMIT appActivationStarted(appId, servicesFound.constFirst()->icon()); + } else { + qDebug() << "WindowUtil: Could not find service" << appId; + } + }); + + connect(activation, &PlasmaActivation::finished, this, &WindowUtil::appActivationFinished); + }); + }); + registry->setup(); connection->roundtrip(); } @@ -98,6 +124,7 @@ void WindowUtil::updateActiveWindow() disconnect(m_activeWindow.data(), &PlasmaWindow::closeableChanged, this, &WindowUtil::hasCloseableActiveWindowChanged); disconnect(m_activeWindow.data(), &PlasmaWindow::unmapped, this, &WindowUtil::forgetActiveWindow); } + m_activeWindow = m_windowManagement->activeWindow(); Q_EMIT activeWindowChanged(); @@ -106,29 +133,6 @@ void WindowUtil::updateActiveWindow() connect(m_activeWindow.data(), &PlasmaWindow::unmapped, this, &WindowUtil::forgetActiveWindow); } - // loop through windows - bool newAllMinimized = true; - bool newAllMinimizedExcludingShell = true; - for (auto *w : m_windowManagement->windows()) { - if (!w->isMinimized() && !w->skipTaskbar() && !w->isFullscreen()) { - newAllMinimized = false; - - if (w->appId() != QStringLiteral("org.kde.plasmashell")) { - newAllMinimizedExcludingShell = false; - } - } - } - - if (newAllMinimized != m_allWindowsMinimized) { - m_allWindowsMinimized = newAllMinimized; - Q_EMIT allWindowsMinimizedChanged(); - } - if (newAllMinimizedExcludingShell != m_allWindowsMinimizedExcludingShell) { - m_allWindowsMinimizedExcludingShell = newAllMinimizedExcludingShell; - Q_EMIT allWindowsMinimizedExcludingShellChanged(); - } - - // TODO: connect to closeableChanged, not needed right now as KWin doesn't provide this changeable Q_EMIT hasCloseableActiveWindowChanged(); } @@ -214,11 +218,12 @@ void WindowUtil::updateShowingDesktop(bool showing) void WindowUtil::updateActiveWindowIsShell() { - if (m_activeWindow) { - if (m_activeWindow->appId() == QStringLiteral("org.kde.plasmashell") && !m_activeWindowIsShell) { + auto activeWindow = m_windowManagement->activeWindow(); + if (activeWindow) { + if (activeWindow->appId() == QStringLiteral("org.kde.plasmashell") && !m_activeWindowIsShell) { m_activeWindowIsShell = true; Q_EMIT activeWindowIsShellChanged(); - } else if (m_activeWindow->appId() != QStringLiteral("org.kde.plasmashell") && m_activeWindowIsShell) { + } else if (activeWindow->appId() != QStringLiteral("org.kde.plasmashell") && m_activeWindowIsShell) { m_activeWindowIsShell = false; Q_EMIT activeWindowIsShellChanged(); } diff --git a/components/windowplugin/windowutil.h b/components/windowplugin/windowutil.h index ccb691d4..b6384421 100644 --- a/components/windowplugin/windowutil.h +++ b/components/windowplugin/windowutil.h @@ -24,16 +24,12 @@ /** * Utility class that provides useful functions related to windows and KWin+KWayland. * - * TODO: Add per-screen support - * * @author Devin Lin **/ class WindowUtil : public QObject { Q_OBJECT - Q_PROPERTY(bool showDesktop READ isShowingDesktop WRITE requestShowingDesktop NOTIFY showingDesktopChanged) - Q_PROPERTY(bool allWindowsMinimized READ allWindowsMinimized NOTIFY allWindowsMinimizedChanged) - Q_PROPERTY(bool allWindowsMinimizedExcludingShell READ allWindowsMinimizedExcludingShell NOTIFY allWindowsMinimizedExcludingShellChanged) + Q_PROPERTY(bool isShowingDesktop READ isShowingDesktop WRITE requestShowingDesktop NOTIFY showingDesktopChanged) Q_PROPERTY(bool hasCloseableActiveWindow READ hasCloseableActiveWindow NOTIFY hasCloseableActiveWindowChanged) Q_PROPERTY(bool activeWindowIsShell READ activeWindowIsShell NOTIFY activeWindowIsShellChanged) @@ -47,16 +43,6 @@ public: */ bool isShowingDesktop() const; - /** - * Whether all windows are minimized, including shell windows. - */ - bool allWindowsMinimized() const; - - /** - * Whether all windows are minimized, ignoring shell windows. - */ - bool allWindowsMinimizedExcludingShell() const; - /** * Whether the active window being shown is a shell window. */ @@ -105,14 +91,21 @@ public: Q_INVOKABLE void unsetAllMinimizedGeometries(QQuickItem *parent); Q_SIGNALS: + // Emitted when a window has been opened void windowCreated(KWayland::Client::PlasmaWindow *window); void showingDesktopChanged(bool showingDesktop); - void allWindowsMinimizedChanged(); - void allWindowsMinimizedExcludingShellChanged(); void hasCloseableActiveWindowChanged(); void activeWindowChanged(); void activeWindowIsShellChanged(); - void windowChanged(QString storageId); // emitted on window open or close + + // Emitted on window open or close + void windowChanged(QString storageId); + + // Emitted when an application is launched + void appActivationStarted(const QString &appId, const QString &iconName); + + // Emitted the application has finished launching + void appActivationFinished(); private Q_SLOTS: void updateActiveWindowIsShell(); @@ -129,8 +122,6 @@ private: QTimer *m_activeWindowTimer; bool m_showingDesktop = false; - bool m_allWindowsMinimized = true; - bool m_allWindowsMinimizedExcludingShell = true; bool m_activeWindowIsShell = false; QHash> m_windows; // diff --git a/containments/homescreens/folio/homescreen.cpp b/containments/homescreens/folio/homescreen.cpp index 16682495..0f65246d 100644 --- a/containments/homescreens/folio/homescreen.cpp +++ b/containments/homescreens/folio/homescreen.cpp @@ -24,16 +24,6 @@ void HomeScreen::configChanged() Plasma::Containment::configChanged(); } -bool HomeScreen::showingDesktop() const -{ - return KWindowSystem::showingDesktop(); -} - -void HomeScreen::setShowingDesktop(bool showingDesktop) -{ - KWindowSystem::setShowingDesktop(showingDesktop); -} - K_PLUGIN_CLASS_WITH_JSON(HomeScreen, "package/metadata.json") #include "homescreen.moc" diff --git a/containments/homescreens/folio/homescreen.h b/containments/homescreens/folio/homescreen.h index 87e96ab2..d20a387c 100644 --- a/containments/homescreens/folio/homescreen.h +++ b/containments/homescreens/folio/homescreen.h @@ -10,7 +10,6 @@ class HomeScreen : public Plasma::Containment { Q_OBJECT - Q_PROPERTY(bool showingDesktop READ showingDesktop WRITE setShowingDesktop NOTIFY showingDesktopChanged) public: HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args); @@ -18,9 +17,6 @@ public: void configChanged() override; - bool showingDesktop() const; - void setShowingDesktop(bool showingDesktop); - Q_SIGNALS: void showingDesktopChanged(bool showingDesktop); }; diff --git a/containments/homescreens/folio/package/contents/ui/main.qml b/containments/homescreens/folio/package/contents/ui/main.qml index cf3d8cdc..700f0e7a 100644 --- a/containments/homescreens/folio/package/contents/ui/main.qml +++ b/containments/homescreens/folio/package/contents/ui/main.qml @@ -44,7 +44,7 @@ MobileShell.HomeScreen { // - minimize windows (only if we are in an app) // - open app drawer // - close app drawer and, if necessary, restore windows - if (!plasmoid.nativeInterface.showingDesktop && !WindowPlugin.WindowUtil.allWindowsMinimized + if (!WindowPlugin.WindowUtil.isShowingDesktop && WindowPlugin.WindowMaximizedTracker.showingWindow || MobileShellState.Shell.actionDrawerVisible || searchWidget.isOpen ) { @@ -58,11 +58,9 @@ MobileShell.HomeScreen { searchWidget.close(); } - plasmoid.nativeInterface.showingDesktop = true; } else if (homescreen.homeScreenState.currentView === HomeScreenState.PageView) { homescreen.homeScreenState.openAppDrawer(); } else { - plasmoid.nativeInterface.showingDesktop = false; homescreen.homeScreenState.closeAppDrawer(); } } diff --git a/containments/homescreens/halcyon/homescreen.cpp b/containments/homescreens/halcyon/homescreen.cpp index 52947714..16f28134 100644 --- a/containments/homescreens/halcyon/homescreen.cpp +++ b/containments/homescreens/halcyon/homescreen.cpp @@ -18,16 +18,6 @@ HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVari HomeScreen::~HomeScreen() = default; -bool HomeScreen::showingDesktop() const -{ - return KWindowSystem::showingDesktop(); -} - -void HomeScreen::setShowingDesktop(bool showingDesktop) -{ - KWindowSystem::setShowingDesktop(showingDesktop); -} - K_PLUGIN_CLASS_WITH_JSON(HomeScreen, "package/metadata.json") #include "homescreen.moc" diff --git a/containments/homescreens/halcyon/homescreen.h b/containments/homescreens/halcyon/homescreen.h index 800d0c21..4e149e13 100644 --- a/containments/homescreens/halcyon/homescreen.h +++ b/containments/homescreens/halcyon/homescreen.h @@ -8,15 +8,11 @@ class HomeScreen : public Plasma::Containment { Q_OBJECT - Q_PROPERTY(bool showingDesktop READ showingDesktop WRITE setShowingDesktop NOTIFY showingDesktopChanged) public: HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args); ~HomeScreen() override; - bool showingDesktop() const; - void setShowingDesktop(bool showingDesktop); - Q_SIGNALS: void showingDesktopChanged(bool showingDesktop); }; diff --git a/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml b/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml index 1a682fa0..baf4d804 100644 --- a/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml +++ b/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml @@ -43,10 +43,10 @@ Item { } Connections { - target: WindowPlugin.WindowUtil + target: WindowPlugin.WindowMaximizedTracker - function onAllWindowsMinimizedChanged(){ - if (WindowPlugin.WindowUtil.allWindowsMinimized) { + function onShowingWindowChanged(){ + if (WindowPlugin.WindowMaximizedTracker.showingWindow) { swipeView.focusChild(); } } diff --git a/containments/homescreens/halcyon/package/contents/ui/main.qml b/containments/homescreens/halcyon/package/contents/ui/main.qml index 8b6ef4a4..5d7a591f 100644 --- a/containments/homescreens/halcyon/package/contents/ui/main.qml +++ b/containments/homescreens/halcyon/package/contents/ui/main.qml @@ -46,7 +46,7 @@ MobileShell.HomeScreen { // - minimize windows (only if we are in an app) // - open app drawer // - close app drawer and, if necessary, restore windows - if (!WindowPlugin.WindowUtil.showDesktop && !WindowPlugin.WindowUtil.allWindowsMinimized || search.isOpen) { + if (!WindowPlugin.WindowUtil.isShowingDesktop && WindowPlugin.WindowMaximizedTracker.showingWindow || search.isOpen) { // Always close action drawer if (MobileShellState.Shell.actionDrawerVisible) { MobileShellState.Shell.closeActionDrawer(); @@ -59,11 +59,11 @@ MobileShell.HomeScreen { homescreen.page = 0; - WindowPlugin.WindowUtil.showDesktop = true; + WindowPlugin.WindowUtil.isShowingDesktop = true; } else if (homescreen.page == 0) { homescreen.page = 1; } else { - WindowPlugin.WindowUtil.showDesktop = false; + WindowPlugin.WindowUtil.isShowingDesktop = false; homescreen.page = 0; } } diff --git a/containments/panel/package/contents/ui/main.qml b/containments/panel/package/contents/ui/main.qml index 463d38ec..d87a2e97 100644 --- a/containments/panel/package/contents/ui/main.qml +++ b/containments/panel/package/contents/ui/main.qml @@ -16,8 +16,9 @@ import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 3.0 as PlasmaComponents -import org.kde.plasma.private.mobileshell 1.0 as MobileShell -import org.kde.plasma.private.mobileshell.state 1.0 as MobileShellState +import org.kde.plasma.private.mobileshell as MobileShell +import org.kde.plasma.private.mobileshell.state as MobileShellState +import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin import org.kde.taskmanager 0.1 as TaskManager import org.kde.notificationmanager 1.0 as NotificationManager @@ -26,7 +27,7 @@ Item { id: root // only opaque if there are no maximized windows on this screen - readonly property bool showingApp: visibleMaximizedWindowsModel.count > 0 + readonly property bool showingApp: WindowPlugin.WindowMaximizedTracker.showingWindow readonly property color backgroundColor: topPanel.colorScopeColor Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground @@ -92,33 +93,6 @@ Item { MobileShellState.AudioProvider.bindShortcuts = true; } - TaskManager.VirtualDesktopInfo { - id: virtualDesktopInfo - } - - TaskManager.ActivityInfo { - id: activityInfo - } - - PlasmaCore.SortFilterModel { - id: visibleMaximizedWindowsModel - filterRole: 'IsMinimized' - filterRegExp: 'false' - sourceModel: TaskManager.TasksModel { - id: tasksModel - filterByVirtualDesktop: true - filterByActivity: true - filterNotMaximized: true - filterByScreen: true - filterHidden: true - - virtualDesktop: virtualDesktopInfo.currentDesktop - activity: activityInfo.currentActivity - - groupMode: TaskManager.TasksModel.GroupDisabled - } - } - // top panel component MobileShell.StatusBar { id: topPanel diff --git a/containments/taskpanel/package/contents/ui/NavigationPanelComponent.qml b/containments/taskpanel/package/contents/ui/NavigationPanelComponent.qml index 948f5446..ec0b8dd6 100644 --- a/containments/taskpanel/package/contents/ui/NavigationPanelComponent.qml +++ b/containments/taskpanel/package/contents/ui/NavigationPanelComponent.qml @@ -74,7 +74,6 @@ MobileShell.NavigationPanel { onTriggered: { MobileShellState.HomeScreenControls.openHomeScreen(); - WindowPlugin.WindowUtil.allWindowsMinimizedChanged(); } } diff --git a/containments/taskpanel/package/contents/ui/main.qml b/containments/taskpanel/package/contents/ui/main.qml index d8e861f6..8c4a1148 100644 --- a/containments/taskpanel/package/contents/ui/main.qml +++ b/containments/taskpanel/package/contents/ui/main.qml @@ -17,7 +17,8 @@ import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.private.nanoshell 2.0 as NanoShell import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings -import org.kde.plasma.private.mobileshell.state 1.0 as MobileShellState +import org.kde.plasma.private.mobileshell.state as MobileShellState +import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin PlasmaCore.ColorScope { id: root @@ -105,35 +106,8 @@ PlasmaCore.ColorScope { Component.onCompleted: setWindowProperties(); - TaskManager.VirtualDesktopInfo { - id: virtualDesktopInfo - } - - TaskManager.ActivityInfo { - id: activityInfo - } - - PlasmaCore.SortFilterModel { - id: visibleMaximizedWindowsModel - filterRole: 'IsMinimized' - filterRegExp: 'false' - sourceModel: TaskManager.TasksModel { - id: tasksModel - filterByVirtualDesktop: true - filterByActivity: true - filterNotMaximized: true - filterByScreen: true - filterHidden: true - - virtualDesktop: virtualDesktopInfo.currentDesktop - activity: activityInfo.currentActivity - - groupMode: TaskManager.TasksModel.GroupDisabled - } - } - // only opaque if there are no maximized windows on this screen - readonly property bool opaqueBar: visibleMaximizedWindowsModel.count > 0 + readonly property bool opaqueBar: WindowPlugin.WindowMaximizedTracker.showingWindow // contrasting colour colorGroup: opaqueBar ? PlasmaCore.Theme.NormalColorGroup : PlasmaCore.Theme.ComplementaryColorGroup