Skip to content

Commit ad02d3f

Browse files
committed
feat: add XdgActivation support for notifications
1. Implement ActivationToken signal in notification DBus adapters 2. Add XdgActivation token request for non-extended actions 3. Integrate activation token into dde-am execution for extended actions 4. Add isExtendedAction helper to check for deepin-specific actions Log: Notifications now properly set XDG_ACTIVATION_TOKEN when launching actions Influence: 1. Verify notification action buttons trigger ActivationToken signal 2. Test extended actions (x-deepin-action-*) set XDG_ACTIVATION_TOKEN in environment 3. Confirm non-extended actions emit ActivationToken before ActionInvoked 4. Check token is passed to dde-am process for app launching 5. Verify backward compatibility with existing notification flows 6. Test multiple rapid notifications to ensure proper token handling feat: 通知支持 XdgActivation 协议 1. 在通知DBus适配器中实现ActivationToken信号 2. 为非扩展操作添加XdgActivation令牌请求 3. 将激活令牌集成到扩展操作的dde-am执行中 4. 添加isExtendedAction辅助方法检查深度特定操作 Log: 通知现在在启动操作时正确设置 XDG_ACTIVATION_TOKEN Influence: 1. 验证通知操作按钮触发ActivationToken信号 2. 测试扩展操作(x-deepin-action-*)在环境中设置XDG_ACTIVATION_TOKEN 3. 确认非扩展操作在ActionInvoked之前发出ActivationToken 4. 检查令牌是否正确传递给dde-am进程用于应用启动 5. 验证与现有通知流程的向后兼容性 6. 测试多个快速通知以确保令牌处理正确
1 parent 889ea78 commit ad02d3f

5 files changed

Lines changed: 71 additions & 14 deletions

File tree

debian/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Depends:
8282
qml6-module-qtquick-layouts,
8383
qml6-module-qtquick-window,
8484
qt6-wayland (>= 6.8),
85-
dde-application-manager (>> 1.2.54),
85+
dde-application-manager (>> 1.2.55),
8686
${misc:Depends},
8787
${shlibs:Depends},
8888
Breaks:

frame/wayland/xdgactivation.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
#include "xdgactivation_p.h"
66

7-
#include <DSGApplication>
87
#include <DGuiApplicationHelper>
8+
#include <DSGApplication>
9+
#include <QCursor>
910
#include <QGuiApplication>
1011
#include <QLoggingCategory>
1112
#include <QMetaObject>
@@ -150,6 +151,11 @@ void XdgActivation::requestToken(QWindow *window, const QString &appId)
150151
qCWarning(dsXdgActivation) << "XDG activation request has empty app id";
151152

152153
auto effectiveWindow = window ? window : QGuiApplication::focusWindow();
154+
if (!effectiveWindow) {
155+
// fallback to top-level window at cursor position if the focused window is not a Wayland window
156+
qCDebug(dsXdgActivation) << "No focused window, falling back to top-level window at cursor position";
157+
effectiveWindow = QGuiApplication::topLevelAt(QCursor::pos());
158+
}
153159
if (!effectiveWindow) {
154160
qCWarning(dsXdgActivation) << "XDG activation request has no target window";
155161
Q_EMIT tokenReady({});

panels/notification/server/dbusadaptor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -32,7 +32,7 @@ public Q_SLOTS: // methods
3232
Q_SIGNALS:
3333
void ActionInvoked(uint id, const QString &actionKey);
3434
void NotificationClosed(uint id, uint reason);
35-
// todo void ActivationToken(uint id, const QString &activationToken)
35+
void ActivationToken(uint id, const QString &token);
3636
};
3737

3838
class DDENotificationDbusAdaptor : public QDBusAbstractAdaptor
@@ -54,7 +54,7 @@ public Q_SLOTS: // methods
5454
Q_SIGNALS:
5555
void ActionInvoked(uint id, const QString &actionKey);
5656
void NotificationClosed(uint id, uint reason);
57-
// todo void ActivationToken(uint id, const QString &activationToken)
57+
void ActivationToken(uint id, const QString &token);
5858

5959
public Q_SLOTS: // methods
6060
uint recordCount() const;

panels/notification/server/notificationmanager.cpp

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <appletbridge.h>
2828
#include <pluginloader.h>
29+
#include <wayland/xdgactivation.h>
2930

3031
DCORE_USE_NAMESPACE
3132
DS_USE_NAMESPACE
@@ -134,8 +135,30 @@ void NotificationManager::actionInvoked(qint64 id, uint bubbleId, const QString
134135
qInfo(notifyLog) << "Action invoked, bubbleId:" << bubbleId << ", id:" << id << ", actionKey" << actionKey;
135136
actionInvoked(id, actionKey);
136137

137-
Q_EMIT ActionInvoked(bubbleId, actionKey);
138-
Q_EMIT NotificationClosed(bubbleId, NotifyEntity::Closed);
138+
if (isExtendedAction(id, actionKey)) {
139+
// Extended action (x-deepin-action-*) handles token request internally in doActionInvoked,
140+
// so we skip the outer token request to avoid requesting twice.
141+
Q_EMIT ActionInvoked(bubbleId, actionKey);
142+
Q_EMIT NotificationClosed(bubbleId, NotifyEntity::Closed);
143+
} else {
144+
// For non-extended actions, emit ActivationToken first if available
145+
auto *activation = new DS_NAMESPACE::XdgActivation(this);
146+
connect(
147+
activation,
148+
&DS_NAMESPACE::XdgActivation::tokenReady,
149+
this,
150+
[this, bubbleId, actionKey, activation](const QString &token) {
151+
if (!token.isEmpty()) {
152+
Q_EMIT ActivationToken(bubbleId, token);
153+
qDebug(notifyLog) << "Emitted ActivationToken for non-extended action:" << token;
154+
}
155+
Q_EMIT ActionInvoked(bubbleId, actionKey);
156+
Q_EMIT NotificationClosed(bubbleId, NotifyEntity::Closed);
157+
activation->deleteLater();
158+
},
159+
Qt::SingleShotConnection);
160+
activation->requestToken();
161+
}
139162
}
140163

141164
void NotificationManager::notificationClosed(qint64 id, uint bubbleId, uint reason)
@@ -542,6 +565,16 @@ QString NotificationManager::appIdByAppName(const QString &appName) const
542565
return QString();
543566
}
544567

568+
bool NotificationManager::isExtendedAction(qint64 id, const QString &actionId) const
569+
{
570+
auto entity = m_persistence->fetchEntity(id);
571+
if (!entity.isValid()) {
572+
return false;
573+
}
574+
QMap<QString, QVariant> hints = entity.hints();
575+
return hints.contains("x-deepin-action-" + actionId);
576+
}
577+
545578
void NotificationManager::doActionInvoked(const NotifyEntity &entity, const QString &actionId)
546579
{
547580
qDebug(notifyLog) << "Invoke the notification:" << entity.id() << entity.appName() << actionId;
@@ -566,13 +599,27 @@ void NotificationManager::doActionInvoked(const NotifyEntity &entity, const QStr
566599
amArgs << "--" << args;
567600
}
568601

569-
QProcess pro;
570-
pro.setProgram("dde-am");
571-
pro.setArguments(amArgs);
572-
QProcessEnvironment proEnv = QProcessEnvironment::systemEnvironment();
573-
proEnv.remove("DSG_APP_ID");
574-
pro.setProcessEnvironment(proEnv);
575-
pro.startDetached();
602+
// Get activation token, then start process
603+
auto *activation = new DS_NAMESPACE::XdgActivation(this);
604+
auto amArgsCopy = amArgs;
605+
connect(activation, &DS_NAMESPACE::XdgActivation::tokenReady, this,
606+
[amArgsCopy, activation](const QString &token) {
607+
QProcess pro;
608+
pro.setProgram("dde-am");
609+
pro.setArguments(amArgsCopy);
610+
QProcessEnvironment proEnv = QProcessEnvironment::systemEnvironment();
611+
proEnv.remove("DSG_APP_ID");
612+
613+
if (!token.isEmpty()) {
614+
proEnv.insert("XDG_ACTIVATION_TOKEN", token);
615+
qDebug(notifyLog) << "Set XDG_ACTIVATION_TOKEN for extended action:" << token;
616+
}
617+
618+
pro.setProcessEnvironment(proEnv);
619+
pro.startDetached();
620+
activation->deleteLater();
621+
}, Qt::SingleShotConnection);
622+
activation->requestToken();
576623
}
577624
} else if (i.key() == "deepin-dde-shell-action-" + actionId) {
578625
const QString data(i.value().toString());

panels/notification/server/notificationmanager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class NotificationManager : public QObject, public QDBusContext
5050

5151
void NotificationStateChanged(qint64 id, int processedType);
5252

53+
// Activation token signal for Wayland
54+
void ActivationToken(uint id, const QString &token);
55+
5356
public Q_SLOTS:
5457
// Standard Notifications dbus implementation
5558
QStringList GetCapabilities();
@@ -78,6 +81,7 @@ public Q_SLOTS:
7881

7982
QString appIdByAppName(const QString &appName) const;
8083
void doActionInvoked(const NotifyEntity &entity, const QString &actionId);
84+
bool isExtendedAction(qint64 id, const QString &actionId) const;
8185
bool invokeShellAction(const QString &data);
8286
void initScreenLockedState();
8387

0 commit comments

Comments
 (0)