startupfeedback: Add support for multiple screens

Addresses https://invent.kde.org/plasma/plasma-mobile/-/issues/175
This commit is contained in:
Devin Lin 2024-03-09 22:50:55 -05:00
parent af58923a1e
commit e2e6590222
13 changed files with 125 additions and 56 deletions

View file

@ -64,12 +64,10 @@ MobileShell.BaseItem {
root.toggleFunction(); root.toggleFunction();
} else if (root.settingsCommand && !root.restrictedPermissions) { } else if (root.settingsCommand && !root.restrictedPermissions) {
closeRequested(); closeRequested();
MobileShellState.ShellDBusClient.openAppLaunchAnimation( MobileShellState.ShellDBusClient.openAppLaunchAnimation(
root.icon, __getCurrentScreenNumber(),
root.text, root.icon);
iconItem.Kirigami.ScenePosition.x + iconItem.width/2,
iconItem.Kirigami.ScenePosition.y + iconItem.height/2,
Math.min(iconItem.width, iconItem.height))
MobileShell.ShellUtil.executeCommand(root.settingsCommand); MobileShell.ShellUtil.executeCommand(root.settingsCommand);
} }
} }
@ -78,14 +76,22 @@ MobileShell.BaseItem {
if (root.settingsCommand && !root.restrictedPermissions) { if (root.settingsCommand && !root.restrictedPermissions) {
closeRequested(); closeRequested();
MobileShellState.ShellDBusClient.openAppLaunchAnimation( MobileShellState.ShellDBusClient.openAppLaunchAnimation(
root.icon, __getCurrentScreenNumber(),
root.text, root.icon);
iconItem.Kirigami.ScenePosition.x + iconItem.width/2,
iconItem.Kirigami.ScenePosition.y + iconItem.height/2,
Math.min(iconItem.width, iconItem.height))
MobileShell.ShellUtil.executeCommand(root.settingsCommand); MobileShell.ShellUtil.executeCommand(root.settingsCommand);
} else if (root.toggleFunction) { } else if (root.toggleFunction) {
root.toggleFunction(); root.toggleFunction();
} }
} }
function __getCurrentScreenNumber() {
const screens = Qt.application.screens;
for (let i = 0; i < screens.length; i++) {
if (screens[i].name === Screen.name) {
return i;
}
}
return 0;
}
} }

View file

@ -12,6 +12,7 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin
import org.kde.plasma.plasmoid
/** /**
* Component that animates an app opening from a location. * Component that animates an app opening from a location.
@ -25,8 +26,17 @@ MouseArea { // use mousearea to ensure clicks don't go behind
property alias icon: icon.source property alias icon: icon.source
property bool __openRequested: false property bool __openRequested: false
function open(splashIcon) {
iconParent.scale = 0.5;
background.scale = 0.5;
backgroundParent.x = 0;
backgroundParent.y = 0;
__openRequested = true;
updateIconSource(splashIcon);
}
function open(splashIcon, title, x, y, sourceIconSize) { function openWithPosition(splashIcon, x, y, sourceIconSize) {
iconParent.scale = sourceIconSize/iconParent.width; iconParent.scale = sourceIconSize/iconParent.width;
background.scale = 0; background.scale = 0;
backgroundParent.x = -root.width/2 + x backgroundParent.x = -root.width/2 + x
@ -61,19 +71,31 @@ MouseArea { // use mousearea to ensure clicks don't go behind
root.close(); root.close();
} }
} }
// open startupfeedback when notifier gives an app
Connections { Connections {
target: WindowPlugin.WindowUtil target: WindowPlugin.WindowUtil
function onAppActivationStarted(appId, iconName) { // Open StartupFeedback when the notifier gives an app (ex. from Milou search)
if (!openAnimComplex.running && !root.__openRequested) { // TODO: This is problematic with multiple screens, because we don't have any info given
iconParent.scale = 0.5; // on which screen the app is opening on. Thus StartupFeedback would just open on
background.scale = 0.5; // every single screen...
backgroundParent.x = 0 // -> We have it disabled for now until some solution is found. We manually open StartupFeedback
backgroundParent.y = 0 // from launches in the homescreen (call open()).
root.__openRequested = true; //
root.updateIconSource(iconName); // function onAppActivationStarted(appId, iconName) {
// if (!openAnimComplex.running && !root.__openRequested) {
// // TODO: this doesn't work because it gets triggered on screen 0 even if the app is opening on screen 1
// // HACK: We have no way of knowing which screen this app is going to open on
// // -> Assume the first screen for now
// if (Plasmoid.screen === 0) {
// root.open(iconName);
// }
// }
// }
function onAppActivationFinished(appId, iconName) {
if (iconName === root.icon.name) {
root.close();
} }
} }
} }

View file

@ -102,8 +102,20 @@ Item {
root.resetHomeScreenPosition(); root.resetHomeScreenPosition();
} }
function onOpenAppLaunchAnimationRequested(splashIcon, title, x, y, sourceIconSize) { function onOpenAppLaunchAnimationRequested(screen, splashIcon) {
startupFeedback.open(splashIcon, title, x, y, sourceIconSize); if (screen !== Plasmoid.screen) {
return;
}
startupFeedback.open(splashIcon);
}
function onOpenAppLaunchAnimationWithPositionRequested(screen, splashIcon, title, x, y, sourceIconSize) {
if (screen !== Plasmoid.screen) {
return;
}
startupFeedback.openWithPosition(splashIcon, x, y, sourceIconSize);
} }
function onCloseAppLaunchAnimationRequested() { function onCloseAppLaunchAnimationRequested() {

View file

@ -168,7 +168,6 @@ NanoShell.FullScreenOverlay {
onClicked: { onClicked: {
let coords = mapToItem(flickable, 0, 0); let coords = mapToItem(flickable, 0, 0);
MobileShellState.ShellDBusClient.openAppLaunchAnimation("audio-volume-high", i18n("Audio Settings"), coords.x, coords.y, Kirigami.Units.iconSizes.medium);
MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_pulseaudio"); MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_pulseaudio");
} }
} }

View file

@ -35,6 +35,10 @@ void ShellDBusClient::connectSignals()
connect(m_interface, &OrgKdePlasmashellInterface::openActionDrawerRequested, this, &ShellDBusClient::openActionDrawerRequested); connect(m_interface, &OrgKdePlasmashellInterface::openActionDrawerRequested, this, &ShellDBusClient::openActionDrawerRequested);
connect(m_interface, &OrgKdePlasmashellInterface::closeActionDrawerRequested, this, &ShellDBusClient::closeActionDrawerRequested); connect(m_interface, &OrgKdePlasmashellInterface::closeActionDrawerRequested, this, &ShellDBusClient::closeActionDrawerRequested);
connect(m_interface, &OrgKdePlasmashellInterface::openAppLaunchAnimationRequested, this, &ShellDBusClient::openAppLaunchAnimationRequested); connect(m_interface, &OrgKdePlasmashellInterface::openAppLaunchAnimationRequested, this, &ShellDBusClient::openAppLaunchAnimationRequested);
connect(m_interface,
&OrgKdePlasmashellInterface::openAppLaunchAnimationWithPositionRequested,
this,
&ShellDBusClient::openAppLaunchAnimationWithPositionRequested);
connect(m_interface, &OrgKdePlasmashellInterface::closeAppLaunchAnimationRequested, this, &ShellDBusClient::closeAppLaunchAnimationRequested); connect(m_interface, &OrgKdePlasmashellInterface::closeAppLaunchAnimationRequested, this, &ShellDBusClient::closeAppLaunchAnimationRequested);
connect(m_interface, &OrgKdePlasmashellInterface::openHomeScreenRequested, this, &ShellDBusClient::openHomeScreenRequested); connect(m_interface, &OrgKdePlasmashellInterface::openHomeScreenRequested, this, &ShellDBusClient::openHomeScreenRequested);
connect(m_interface, &OrgKdePlasmashellInterface::resetHomeScreenPositionRequested, this, &ShellDBusClient::resetHomeScreenPositionRequested); connect(m_interface, &OrgKdePlasmashellInterface::resetHomeScreenPositionRequested, this, &ShellDBusClient::resetHomeScreenPositionRequested);
@ -80,9 +84,14 @@ bool ShellDBusClient::isTaskSwitcherVisible() const
return m_isTaskSwitcherVisible; return m_isTaskSwitcherVisible;
} }
void ShellDBusClient::openAppLaunchAnimation(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize) void ShellDBusClient::openAppLaunchAnimation(int screen, QString splashIcon)
{ {
m_interface->openAppLaunchAnimation(splashIcon, title, x, y, sourceIconSize); m_interface->openAppLaunchAnimation(screen, splashIcon);
}
void ShellDBusClient::openAppLaunchAnimationWithPosition(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize)
{
m_interface->openAppLaunchAnimationWithPosition(screen, splashIcon, title, x, y, sourceIconSize);
} }
void ShellDBusClient::closeAppLaunchAnimation() void ShellDBusClient::closeAppLaunchAnimation()

View file

@ -34,7 +34,8 @@ public:
Q_INVOKABLE void openActionDrawer(); Q_INVOKABLE void openActionDrawer();
Q_INVOKABLE void closeActionDrawer(); Q_INVOKABLE void closeActionDrawer();
Q_INVOKABLE void openAppLaunchAnimation(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize); Q_INVOKABLE void openAppLaunchAnimation(int screen, QString splashIcon);
Q_INVOKABLE void openAppLaunchAnimationWithPosition(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize);
Q_INVOKABLE void closeAppLaunchAnimation(); Q_INVOKABLE void closeAppLaunchAnimation();
Q_INVOKABLE void openHomeScreen(); Q_INVOKABLE void openHomeScreen();
@ -47,7 +48,8 @@ Q_SIGNALS:
void isTaskSwitcherVisibleChanged(); void isTaskSwitcherVisibleChanged();
void openActionDrawerRequested(); void openActionDrawerRequested();
void closeActionDrawerRequested(); void closeActionDrawerRequested();
void openAppLaunchAnimationRequested(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize); void openAppLaunchAnimationRequested(int screen, QString splashIcon);
void openAppLaunchAnimationWithPositionRequested(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize);
void closeAppLaunchAnimationRequested(); void closeAppLaunchAnimationRequested();
void openHomeScreenRequested(); void openHomeScreenRequested();
void resetHomeScreenPositionRequested(); void resetHomeScreenPositionRequested();

View file

@ -69,9 +69,14 @@ void ShellDBusObject::closeActionDrawer()
Q_EMIT closeActionDrawerRequested(); Q_EMIT closeActionDrawerRequested();
} }
void ShellDBusObject::openAppLaunchAnimation(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize) void ShellDBusObject::openAppLaunchAnimation(int screen, QString splashIcon)
{ {
Q_EMIT openAppLaunchAnimationRequested(splashIcon, title, x, y, sourceIconSize); Q_EMIT openAppLaunchAnimationRequested(screen, splashIcon);
}
void ShellDBusObject::openAppLaunchAnimationWithPosition(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize)
{
Q_EMIT openAppLaunchAnimationWithPositionRequested(screen, splashIcon, title, x, y, sourceIconSize);
} }
void ShellDBusObject::closeAppLaunchAnimation() void ShellDBusObject::closeAppLaunchAnimation()

View file

@ -26,7 +26,8 @@ Q_SIGNALS:
Q_SCRIPTABLE void isTaskSwitcherVisibleChanged(); Q_SCRIPTABLE void isTaskSwitcherVisibleChanged();
Q_SCRIPTABLE void openActionDrawerRequested(); Q_SCRIPTABLE void openActionDrawerRequested();
Q_SCRIPTABLE void closeActionDrawerRequested(); Q_SCRIPTABLE void closeActionDrawerRequested();
Q_SCRIPTABLE void openAppLaunchAnimationRequested(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize); Q_SCRIPTABLE void openAppLaunchAnimationRequested(int screen, QString splashIcon);
Q_SCRIPTABLE void openAppLaunchAnimationWithPositionRequested(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize);
Q_SCRIPTABLE void closeAppLaunchAnimationRequested(); Q_SCRIPTABLE void closeAppLaunchAnimationRequested();
Q_SCRIPTABLE void openHomeScreenRequested(); Q_SCRIPTABLE void openHomeScreenRequested();
Q_SCRIPTABLE void resetHomeScreenPositionRequested(); Q_SCRIPTABLE void resetHomeScreenPositionRequested();
@ -46,7 +47,8 @@ public Q_SLOTS:
Q_SCRIPTABLE void openActionDrawer(); Q_SCRIPTABLE void openActionDrawer();
Q_SCRIPTABLE void closeActionDrawer(); Q_SCRIPTABLE void closeActionDrawer();
Q_SCRIPTABLE void openAppLaunchAnimation(QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize); Q_SCRIPTABLE void openAppLaunchAnimation(int screen, QString splashIcon);
Q_SCRIPTABLE void openAppLaunchAnimationWithPosition(int screen, QString splashIcon, QString title, qreal x, qreal y, qreal sourceIconSize);
Q_SCRIPTABLE void closeAppLaunchAnimation(); Q_SCRIPTABLE void closeAppLaunchAnimation();
Q_SCRIPTABLE void openHomeScreen(); Q_SCRIPTABLE void openHomeScreen();

View file

@ -73,7 +73,7 @@ void WindowUtil::initWayland()
auto iface = registry->createPlasmaActivationFeedback(name, version, this); auto iface = registry->createPlasmaActivationFeedback(name, version, this);
connect(iface, &PlasmaActivationFeedback::activation, this, [this](PlasmaActivation *activation) { connect(iface, &PlasmaActivationFeedback::activation, this, [this](PlasmaActivation *activation) {
connect(activation, &PlasmaActivation::applicationId, this, [this](const QString &appId) { connect(activation, &PlasmaActivation::applicationId, this, [this, activation](const QString &appId) {
// do not show activation screen for the plasmashell process // do not show activation screen for the plasmashell process
if (appId == "org.kde.plasmashell") { if (appId == "org.kde.plasmashell") {
return; return;
@ -98,13 +98,19 @@ void WindowUtil::initWayland()
}); });
if (!servicesFound.isEmpty()) { if (!servicesFound.isEmpty()) {
Q_EMIT appActivationStarted(appId, servicesFound.constFirst()->icon()); QString iconName = servicesFound.constFirst()->icon();
// Connect signal to when activation is complete to trigger event
connect(activation, &PlasmaActivation::finished, this, [this, appId, iconName]() {
Q_EMIT appActivationFinished(appId, iconName);
});
// Trigger app activation event
Q_EMIT appActivationStarted(appId, iconName);
} else { } else {
qDebug() << "WindowUtil: Could not find service" << appId; qDebug() << "WindowUtil: Could not find service" << appId;
} }
}); });
connect(activation, &PlasmaActivation::finished, this, &WindowUtil::appActivationFinished);
}); });
}); });

View file

@ -107,8 +107,8 @@ Q_SIGNALS:
// Emitted when an application is launched // Emitted when an application is launched
void appActivationStarted(const QString &appId, const QString &iconName); void appActivationStarted(const QString &appId, const QString &iconName);
// Emitted the application has finished launching // Emitted when an application has finished launching
void appActivationFinished(); void appActivationFinished(const QString &appId, const QString &iconName);
private Q_SLOTS: private Q_SLOTS:
void updateActiveWindowIsShell(); void updateActiveWindowIsShell();

View file

@ -11,6 +11,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.private.mobile.homescreen.folio 1.0 as Folio import org.kde.private.mobile.homescreen.folio 1.0 as Folio
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.plasmoid
AbstractDelegate { AbstractDelegate {
id: root id: root
@ -27,12 +28,13 @@ AbstractDelegate {
function launchApp() { function launchApp() {
if (application.icon !== "") { if (application.icon !== "") {
MobileShellState.ShellDBusClient.openAppLaunchAnimation( MobileShellState.ShellDBusClient.openAppLaunchAnimationWithPosition(
application.icon, Plasmoid.screen,
application.name, application.icon,
root.iconItem.Kirigami.ScenePosition.x + root.iconItem.width/2, application.name,
root.iconItem.Kirigami.ScenePosition.y + root.iconItem.height/2, root.iconItem.Kirigami.ScenePosition.x + root.iconItem.width/2,
Math.min(root.iconItem.width, root.iconItem.height)); root.iconItem.Kirigami.ScenePosition.y + root.iconItem.height/2,
Math.min(root.iconItem.width, root.iconItem.height));
} }
application.setMinimizedDelegate(root); application.setMinimizedDelegate(root);

View file

@ -14,6 +14,7 @@ import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutM
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.plasmoid
import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigami 2.19 as Kirigami
@ -77,12 +78,13 @@ Item {
function launchAppWithAnim(x: int, y: int, source, title: string, storageId: string) { function launchAppWithAnim(x: int, y: int, source, title: string, storageId: string) {
if (source !== "") { if (source !== "") {
MobileShellState.ShellDBusClient.openAppLaunchAnimation( MobileShellState.ShellDBusClient.openAppLaunchAnimationWithPosition(
source, Plasmoid.screen,
title, source,
iconLoader.Kirigami.ScenePosition.x + iconLoader.width/2, title,
iconLoader.Kirigami.ScenePosition.y + iconLoader.height/2, iconLoader.Kirigami.ScenePosition.x + iconLoader.width/2,
Math.min(iconLoader.width, iconLoader.height)); iconLoader.Kirigami.ScenePosition.y + iconLoader.height/2,
Math.min(iconLoader.width, iconLoader.height));
} }
application.setMinimizedDelegate(delegate); application.setMinimizedDelegate(delegate);

View file

@ -13,6 +13,7 @@ import org.kde.kirigami 2.10 as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.private.mobile.homescreen.halcyon 1.0 as Halcyon import org.kde.private.mobile.homescreen.halcyon 1.0 as Halcyon
import org.kde.plasma.plasmoid
MobileShell.GridView { MobileShell.GridView {
id: gridView id: gridView
@ -88,12 +89,13 @@ MobileShell.GridView {
onLaunch: (x, y, icon, title, storageId) => { onLaunch: (x, y, icon, title, storageId) => {
if (icon !== "") { if (icon !== "") {
MobileShellState.ShellDBusClient.openAppLaunchAnimation( MobileShellState.ShellDBusClient.openAppLaunchAnimationWithPosition(
icon, Plasmoid.screen,
title, icon,
delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, title,
delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2, delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2,
Math.min(delegate.iconItem.width, delegate.iconItem.height)); delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2,
Math.min(delegate.iconItem.width, delegate.iconItem.height));
} }
application.setMinimizedDelegate(delegate); application.setMinimizedDelegate(delegate);