mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
components/mobileshell: Add mechanism to keep track of and stop launched apps
This commit is contained in:
parent
c2b9a06e61
commit
7385ca9dca
9 changed files with 138 additions and 17 deletions
|
|
@ -22,10 +22,6 @@ MouseArea { // use mousearea to ensure clicks don't go behind
|
|||
visible: false
|
||||
|
||||
property alias backgroundColor: background.color
|
||||
Kirigami.ImageColors {
|
||||
id: colorGenerator
|
||||
source: icon.source
|
||||
}
|
||||
|
||||
function open(splashIcon, title, x, y, sourceIconSize, color) {
|
||||
iconParent.scale = sourceIconSize/iconParent.width;
|
||||
|
|
@ -83,6 +79,11 @@ MouseArea { // use mousearea to ensure clicks don't go behind
|
|||
background.state = "closed";
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.ImageColors {
|
||||
id: colorGenerator
|
||||
source: icon.source
|
||||
}
|
||||
|
||||
Item {
|
||||
id: backgroundParent
|
||||
|
|
|
|||
|
|
@ -243,5 +243,12 @@ Item {
|
|||
id: startupFeedback
|
||||
z: 999999
|
||||
anchors.fill: parent
|
||||
|
||||
// if the startup feedback closes, clear the shell's stored launching app
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
MobileShell.ShellUtil.clearLaunchingApp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ PlasmaComponents.Label {
|
|||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
MobileShell.ShellUtil.launchApp("org.kde.kclock");
|
||||
MobileShell.ShellUtil.launchApp("org.kde.kclock.desktop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import QtQuick.Controls 2.15 as Controls
|
|||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
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.extras 2.0 as PlasmaExtras
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
*/
|
||||
|
||||
#include "shellutil.h"
|
||||
#include "windowutil.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KFileUtils>
|
||||
#include <KIO/ApplicationLauncherJob>
|
||||
#include <KLocalizedString>
|
||||
#include <KNotification>
|
||||
#include <KNotificationJobUiDelegate>
|
||||
|
||||
#include <QDBusPendingReply>
|
||||
#include <QDateTime>
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
|
||||
ShellUtil::ShellUtil(QObject *parent)
|
||||
: QObject{parent}
|
||||
, m_launchingApp{nullptr}
|
||||
{
|
||||
m_localeConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::SimpleConfig);
|
||||
m_localeConfigWatcher = KConfigWatcher::create(m_localeConfig);
|
||||
|
|
@ -77,13 +79,54 @@ bool ShellUtil::isSystem24HourFormat()
|
|||
return timeFormat == QStringLiteral(FORMAT24H);
|
||||
}
|
||||
|
||||
void ShellUtil::launchApp(const QString &app)
|
||||
void ShellUtil::launchApp(const QString &storageId)
|
||||
{
|
||||
const KService::Ptr appService = KService::serviceByDesktopName(app);
|
||||
if (!appService) {
|
||||
qWarning() << "Could not find" << app;
|
||||
// try to activate a running window first
|
||||
auto windows = WindowUtil::instance()->windowsFromStorageId(storageId);
|
||||
|
||||
if (!windows.empty()) {
|
||||
windows[0]->requestActivate();
|
||||
return;
|
||||
}
|
||||
auto job = new KIO::ApplicationLauncherJob(appService, this);
|
||||
|
||||
// now try launching the window
|
||||
KService::Ptr service = KService::serviceByStorageId(storageId);
|
||||
if (!service) {
|
||||
qWarning() << "Could not find" << storageId;
|
||||
return;
|
||||
}
|
||||
|
||||
auto job = new KIO::ApplicationLauncherJob(service, this);
|
||||
job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled));
|
||||
job->start();
|
||||
|
||||
setLaunchingApp(job);
|
||||
}
|
||||
|
||||
bool ShellUtil::isLaunchingApp()
|
||||
{
|
||||
return m_launchingApp != nullptr;
|
||||
}
|
||||
|
||||
void ShellUtil::setLaunchingApp(KIO::ApplicationLauncherJob *launcherJob)
|
||||
{
|
||||
m_launchingApp = launcherJob;
|
||||
connect(launcherJob, &KIO::ApplicationLauncherJob::result, this, [this](auto *job) {
|
||||
m_launchingAppPids = m_launchingApp->pids();
|
||||
});
|
||||
Q_EMIT isLaunchingAppChanged();
|
||||
}
|
||||
|
||||
void ShellUtil::cancelLaunchingApp()
|
||||
{
|
||||
for (auto pid : m_launchingAppPids) {
|
||||
QProcess::execute("kill", {QString::number(pid)});
|
||||
}
|
||||
clearLaunchingApp();
|
||||
}
|
||||
|
||||
void ShellUtil::clearLaunchingApp()
|
||||
{
|
||||
m_launchingApp = nullptr;
|
||||
Q_EMIT isLaunchingAppChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <QQuickItem>
|
||||
|
||||
#include <KConfigWatcher>
|
||||
#include <KIO/ApplicationLauncherJob>
|
||||
#include <KSharedConfig>
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +23,7 @@ class ShellUtil : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isSystem24HourFormat READ isSystem24HourFormat NOTIFY isSystem24HourFormatChanged)
|
||||
Q_PROPERTY(bool launchingApp READ isLaunchingApp NOTIFY isLaunchingAppChanged)
|
||||
Q_PROPERTY(bool isLaunchingApp READ isLaunchingApp NOTIFY isLaunchingAppChanged)
|
||||
|
||||
public:
|
||||
ShellUtil(QObject *parent = nullptr);
|
||||
|
|
@ -52,21 +53,44 @@ public:
|
|||
Q_INVOKABLE void executeCommand(const QString &command);
|
||||
|
||||
/**
|
||||
* Launch an application by name.
|
||||
* Launch an application by name. Sets the internal "launched app" state.
|
||||
*
|
||||
* @param app The name of the application to launch.
|
||||
* @param storageId The storage id of the application to launch.
|
||||
*/
|
||||
Q_INVOKABLE void launchApp(const QString &app);
|
||||
Q_INVOKABLE void launchApp(const QString &storageId);
|
||||
|
||||
/**
|
||||
* Whether the system is using 24 hour format.
|
||||
*/
|
||||
Q_INVOKABLE bool isSystem24HourFormat();
|
||||
|
||||
/**
|
||||
* Whether an application is being launched.
|
||||
*/
|
||||
Q_INVOKABLE bool isLaunchingApp();
|
||||
|
||||
/**
|
||||
* Cancels an application launch by running `kill pid` for every associated pid of the launching app.
|
||||
*/
|
||||
Q_INVOKABLE void cancelLaunchingApp();
|
||||
|
||||
/**
|
||||
* Clears the currently stored launching app.
|
||||
*
|
||||
* This should be called if the application window finally shows.
|
||||
*/
|
||||
Q_INVOKABLE void clearLaunchingApp();
|
||||
|
||||
Q_SIGNALS:
|
||||
void isSystem24HourFormatChanged();
|
||||
void isLaunchingAppChanged();
|
||||
|
||||
private:
|
||||
void setLaunchingApp(KIO::ApplicationLauncherJob *launcherJob);
|
||||
|
||||
KConfigWatcher::Ptr m_localeConfigWatcher;
|
||||
KSharedConfig::Ptr m_localeConfig;
|
||||
|
||||
KIO::ApplicationLauncherJob *m_launchingApp;
|
||||
QVector<qint64> m_launchingAppPids;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ void WindowUtil::initWayland()
|
|||
connect(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::windowCreated, this, [this](KWayland::Client::PlasmaWindow *window) {
|
||||
Q_EMIT windowCreated(window);
|
||||
});
|
||||
connect(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::windowCreated, this, &WindowUtil::windowCreatedSlot);
|
||||
|
||||
connect(m_windowManagement, &PlasmaWindowManagement::showingDesktopChanged, this, &WindowUtil::updateShowingDesktop);
|
||||
connect(m_windowManagement, &PlasmaWindowManagement::activeWindowChanged, m_activeWindowTimer, qOverload<>(&QTimer::start));
|
||||
|
|
@ -222,3 +223,34 @@ void WindowUtil::forgetActiveWindow()
|
|||
m_activeWindow.clear();
|
||||
Q_EMIT hasCloseableActiveWindowChanged();
|
||||
}
|
||||
|
||||
QList<KWayland::Client::PlasmaWindow *> WindowUtil::windowsFromStorageId(const QString &storageId) const
|
||||
{
|
||||
if (!m_windows.contains(storageId)) {
|
||||
return {};
|
||||
}
|
||||
return m_windows[storageId];
|
||||
}
|
||||
|
||||
void WindowUtil::windowCreatedSlot(KWayland::Client::PlasmaWindow *window)
|
||||
{
|
||||
QString storageId = window->appId() + QStringLiteral(".desktop");
|
||||
|
||||
// ignore empty windows
|
||||
if (storageId == ".desktop" || storageId == "org.kde.plasmashell.desktop") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_windows.contains(storageId)) {
|
||||
m_windows[storageId] = {};
|
||||
}
|
||||
m_windows[storageId].push_back(window);
|
||||
|
||||
// listen for window close
|
||||
connect(window, &KWayland::Client::PlasmaWindow::unmapped, this, [this, storageId]() {
|
||||
m_windows.remove(storageId);
|
||||
Q_EMIT windowChanged(storageId);
|
||||
});
|
||||
|
||||
Q_EMIT windowChanged(storageId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ public:
|
|||
*/
|
||||
bool hasCloseableActiveWindow() const;
|
||||
|
||||
/**
|
||||
* Get the list of windows associated to a storage id.
|
||||
*/
|
||||
QList<KWayland::Client::PlasmaWindow *> windowsFromStorageId(const QString &storageId) const;
|
||||
|
||||
/**
|
||||
* Close the current active window.
|
||||
*/
|
||||
|
|
@ -99,11 +104,13 @@ Q_SIGNALS:
|
|||
void hasCloseableActiveWindowChanged();
|
||||
void activeWindowChanged();
|
||||
void activeWindowIsShellChanged();
|
||||
void windowChanged(QString storageId); // emitted on window open or close
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateActiveWindowIsShell();
|
||||
void forgetActiveWindow();
|
||||
void updateShowingDesktop(bool showing);
|
||||
void windowCreatedSlot(KWayland::Client::PlasmaWindow *window);
|
||||
|
||||
private:
|
||||
void initWayland();
|
||||
|
|
@ -117,4 +124,6 @@ private:
|
|||
bool m_allWindowsMinimized = true;
|
||||
bool m_allWindowsMinimizedExcludingShell = true;
|
||||
bool m_activeWindowIsShell = false;
|
||||
|
||||
QHash<QString, QList<KWayland::Client::PlasmaWindow *>> m_windows; // <storageId, window>
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ MobileShell.NavigationPanel {
|
|||
rightAction: MobileShell.NavigationPanelAction {
|
||||
id: closeAppAction
|
||||
|
||||
enabled: Keyboards.KWinVirtualKeyboard.visible || root.taskSwitcher.visible || MobileShell.WindowUtil.hasCloseableActiveWindow
|
||||
enabled: Keyboards.KWinVirtualKeyboard.visible || root.taskSwitcher.visible || MobileShell.WindowUtil.hasCloseableActiveWindow || MobileShell.ShellUtil.isLaunchingApp
|
||||
iconSource: Keyboards.KWinVirtualKeyboard.visible ? "go-down-symbolic" : "mobile-close-app"
|
||||
// mobile-close-app (from plasma-frameworks) seems to have less margins than icons from breeze-icons
|
||||
iconSizeFactor: Keyboards.KWinVirtualKeyboard.visible ? 1 : 0.75
|
||||
|
|
@ -101,6 +101,12 @@ MobileShell.NavigationPanel {
|
|||
if (root.taskSwitcher.tasksModel.activeTask !== 0) {
|
||||
root.taskSwitcher.tasksModel.requestClose(root.taskSwitcher.tasksModel.activeTask);
|
||||
}
|
||||
MobileShell.HomeScreenControls.closeAppLaunchAnimation();
|
||||
} else if (MobileShell.ShellUtil.isLaunchingApp) {
|
||||
|
||||
// cancel the launching of the app
|
||||
MobileShell.HomeScreenControls.closeAppLaunchAnimation();
|
||||
MobileShell.ShellUtil.cancelLaunchingApp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue