diff --git a/containments/homescreen/CMakeLists.txt b/containments/homescreen/CMakeLists.txt index d1168dd0..c226e3c0 100644 --- a/containments/homescreen/CMakeLists.txt +++ b/containments/homescreen/CMakeLists.txt @@ -16,6 +16,7 @@ target_link_libraries(plasma_containment_phone_homescreen KF5::Service KF5::KIOGui KF5::Notifications + KF5::WaylandClient ) diff --git a/containments/homescreen/applicationlistmodel.cpp b/containments/homescreen/applicationlistmodel.cpp index ecb46acb..07c03d58 100644 --- a/containments/homescreen/applicationlistmodel.cpp +++ b/containments/homescreen/applicationlistmodel.cpp @@ -35,6 +35,10 @@ #include #include +#include +#include +#include + constexpr int MAX_FAVOURITES = 5; ApplicationListModel::ApplicationListModel(HomeScreen *parent) @@ -45,6 +49,7 @@ ApplicationListModel::ApplicationListModel(HomeScreen *parent) this, &ApplicationListModel::sycocaDbChanged); loadSettings(); + initWayland(); } ApplicationListModel::~ApplicationListModel() = default; @@ -79,7 +84,8 @@ QHash ApplicationListModel::roleNames() const {ApplicationEntryPathRole, QByteArrayLiteral("applicationEntryPath")}, {ApplicationOriginalRowRole, QByteArrayLiteral("applicationOriginalRow")}, {ApplicationStartupNotifyRole, QByteArrayLiteral("applicationStartupNotify")}, - {ApplicationLocationRole, QByteArrayLiteral("applicationLocation")} + {ApplicationLocationRole, QByteArrayLiteral("applicationLocation")}, + {ApplicationRunningRole, QByteArrayLiteral("applicationRunning")} }; } @@ -99,6 +105,57 @@ bool appNameLessThan(const ApplicationListModel::ApplicationData &a1, const Appl return a1.name.toLower() < a2.name.toLower(); } +void ApplicationListModel::initWayland() +{ + if (!QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { + return; + } + using namespace KWayland::Client; + ConnectionThread *connection = ConnectionThread::fromApplication(this); + + if (!connection) { + return; + } + auto *registry = new Registry(this); + registry->create(connection); + connect(registry, &Registry::plasmaWindowManagementAnnounced, this, + [this, registry] (quint32 name, quint32 version) { + m_windowManagement = registry->createPlasmaWindowManagement(name, version, this); + qRegisterMetaType >("QVector"); + + connect(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::windowCreated, + this, [this] (KWayland::Client::PlasmaWindow *window) { + if (window->appId() == QStringLiteral("org.kde.plasmashell")) { + return; + } + int idx = 0; + for (auto i = m_applicationList.begin(); i != m_applicationList.end(); i++) { + if ((*i).storageId == window->appId() + QStringLiteral(".desktop")) { + (*i).window = window; + emit dataChanged(index(idx, 0), index(idx, 0)); + connect(window, &KWayland::Client::PlasmaWindow::unmapped, this, [this, window] () { + int idx = 0; + for (auto i = m_applicationList.begin(); i != m_applicationList.end(); i++) { + if ((*i).storageId == window->appId() + QStringLiteral(".desktop")) { + (*i).window = nullptr; + emit dataChanged(index(idx, 0), index(idx, 0)); + break; + } + idx++; + } + }); + break; + } + idx++; + } + }); + } + ); + + registry->setup(); + connection->roundtrip(); +} + void ApplicationListModel::loadApplications() { auto cfg = KSharedConfig::openConfig(QStringLiteral("applications-blacklistrc")); @@ -224,6 +281,8 @@ QVariant ApplicationListModel::data(const QModelIndex &index, int role) const return m_applicationList.at(index.row()).startupNotify; case ApplicationLocationRole: return m_applicationList.at(index.row()).location; + case ApplicationRunningRole: + return m_applicationList.at(index.row()).window != nullptr; default: return QVariant(); @@ -339,6 +398,13 @@ void ApplicationListModel::runApplication(const QString &storageId) return; } + for (auto i = m_applicationList.begin(); i != m_applicationList.end(); i++) { + if ((*i).window && (*i).storageId == storageId) { + (*i).window->requestActivate(); + return; + } + } + KService::Ptr service = KService::serviceByStorageId(storageId); KIO::ApplicationLauncherJob *job = new KIO::ApplicationLauncherJob(service); job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled)); diff --git a/containments/homescreen/applicationlistmodel.h b/containments/homescreen/applicationlistmodel.h index c45220c1..adb0c846 100644 --- a/containments/homescreen/applicationlistmodel.h +++ b/containments/homescreen/applicationlistmodel.h @@ -30,6 +30,15 @@ class QString; +namespace KWayland +{ +namespace Client +{ +class PlasmaWindowManagement; +class PlasmaWindow; +} +} + class ApplicationListModel; class ApplicationListModel : public QAbstractListModel { @@ -54,6 +63,7 @@ public: QString entryPath; LauncherLocation location = LauncherLocation::Grid; bool startupNotify = true; + KWayland::Client::PlasmaWindow *window = nullptr; }; enum Roles { @@ -63,7 +73,8 @@ public: ApplicationEntryPathRole, ApplicationOriginalRowRole, ApplicationStartupNotifyRole, - ApplicationLocationRole + ApplicationLocationRole, + ApplicationRunningRole }; ApplicationListModel(HomeScreen *parent = nullptr); @@ -104,8 +115,11 @@ Q_SIGNALS: void maxFavoriteCountChanged(); private: + void initWayland(); + QList m_applicationList; + KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr; HomeScreen *m_homeScreen = nullptr; int m_maxFavoriteCount = 0; QStringList m_appOrder; diff --git a/containments/homescreen/package/contents/ui/launcher/Delegate.qml b/containments/homescreen/package/contents/ui/launcher/Delegate.qml index 85f39c12..a7aceb7b 100644 --- a/containments/homescreen/package/contents/ui/launcher/Delegate.qml +++ b/containments/homescreen/package/contents/ui/launcher/Delegate.qml @@ -93,7 +93,11 @@ ContainmentLayoutManager.ItemContainer { contentItem: MouseArea { onClicked: { - delegate.launch(delegate.x + (units.smallSpacing * 2), delegate.y + (units.smallSpacing * 2), icon.source, modelData.applicationName) + if (modelData.applicationRunning) { + delegate.launch(0, 0, "", modelData.applicationName); + } else { + delegate.launch(delegate.x + (units.smallSpacing * 2), delegate.y + (units.smallSpacing * 2), icon.source, modelData.applicationName); + } plasmoid.nativeInterface.applicationListModel.runApplication(modelData.applicationStorageId); } @@ -119,11 +123,17 @@ ContainmentLayoutManager.ItemContainer { usesPlasmaTheme: false source: modelData ? modelData.applicationIcon : "" - Behavior on scale { - NumberAnimation { - duration: units.longDuration - easing.type: Easing.InOutQuad + + Rectangle { + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom } + visible: model.applicationRunning + radius: width + width: units.smallSpacing + height: width + color: theme.highlightColor } } diff --git a/containments/homescreen/package/contents/ui/launcher/LauncherGrid.qml b/containments/homescreen/package/contents/ui/launcher/LauncherGrid.qml index 66583106..a92f42b9 100644 --- a/containments/homescreen/package/contents/ui/launcher/LauncherGrid.qml +++ b/containments/homescreen/package/contents/ui/launcher/LauncherGrid.qml @@ -68,14 +68,14 @@ LauncherContainer { } } onLaunch: (x, y, icon, title) => { - delegate.grabToImage((img) => { + if (icon !== "") { NanoShell.StartupFeedback.open( - icon, - title, - delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, - delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2, - Math.min(delegate.iconItem.width, delegate.iconItem.height) - )}); + icon, + title, + delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, + delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2, + Math.min(delegate.iconItem.width, delegate.iconItem.height)); + } root.launched(); } onParentFromLocationChanged: {