windowplugin: Use standardized way to know whether a window is showing and maximized

This commit is contained in:
Devin Lin 2023-03-18 18:48:49 -07:00
parent 2653e2d816
commit da6e17f3f4
17 changed files with 127 additions and 156 deletions

View file

@ -80,7 +80,7 @@ Item {
target: MobileShellState.HomeScreenControls
function onOpenHomeScreen() {
if (!WindowPlugin.WindowUtil.allWindowsMinimized) {
if (WindowPlugin.WindowMaximizedTracker.showingWindow) {
itemContainer.zoomIn();
}

View file

@ -1,11 +1,12 @@
# SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
# 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

View file

@ -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
}
}
}

View file

@ -0,0 +1,11 @@
<!--
- Copyright 2023 Devin Lin <devin@kde.org>
- SPDX-License-Identifier: GPL-2.0-or-later
-->
<RCC>
<qresource prefix="/org/kde/plasma/private/mobileshell/windowplugin/">
<file>qml/WindowMaximizedTracker.qml</file>
</qresource>
</RCC>

View file

@ -7,6 +7,11 @@
#include <QQmlContext>
#include <QQuickItem>
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<WindowUtil>(uri, 1, 0, "WindowUtil", [](QQmlEngine *, QJSEngine *) -> QObject * {
return WindowUtil::instance();
});
qmlRegisterSingletonType(resolvePath("WindowMaximizedTracker.qml"), uri, 1, 0, "WindowMaximizedTracker");
}

View file

@ -7,6 +7,8 @@
#include "windowutil.h"
#include <KApplicationTrader>
#include <QGuiApplication>
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();
}

View file

@ -24,16 +24,12 @@
/**
* Utility class that provides useful functions related to windows and KWin+KWayland.
*
* TODO: Add per-screen support
*
* @author Devin Lin <devin@kde.org>
**/
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<QString, QList<KWayland::Client::PlasmaWindow *>> m_windows; // <storageId, window>

View file

@ -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"

View file

@ -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);
};

View file

@ -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();
}
}

View file

@ -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"

View file

@ -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);
};

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -74,7 +74,6 @@ MobileShell.NavigationPanel {
onTriggered: {
MobileShellState.HomeScreenControls.openHomeScreen();
WindowPlugin.WindowUtil.allWindowsMinimizedChanged();
}
}

View file

@ -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