diff --git a/dbus/org.ukui.NotificationServer.xml b/dbus/org.ukui.NotificationServer.xml
index 9da7df5..af21fac 100644
--- a/dbus/org.ukui.NotificationServer.xml
+++ b/dbus/org.ukui.NotificationServer.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/libukui-notification/notification-client-private.h b/libukui-notification/notification-client-private.h
index 4f71a80..57ef56d 100644
--- a/libukui-notification/notification-client-private.h
+++ b/libukui-notification/notification-client-private.h
@@ -6,6 +6,7 @@
#define UKUI_NOTIFICATION_NOTIFICATION_CLIENT_PRIVATE_H
#include
#include
+#include
#include "notifications_interface.h"
#include "notification-client.h"
namespace UkuiNotification {
@@ -15,7 +16,15 @@ class NotificationClientPrivate : public QObject
public:
explicit NotificationClientPrivate(NotificationClient *q);
~NotificationClientPrivate() override;
+ /**
+ * 初始化客户端dbus服务并注册成为客户端
+ * @return
+ */
bool init();
+ /**
+ * 注销
+ */
+ void unregisterClient();
static QString clientServicePath();
static QString clientServiceInterface();
@@ -27,18 +36,23 @@ public:
const QStringList &actions,
const QVariantMap &hints,
int timeout);
- void closeNotification(uint id, NotificationClient::CloseReason reason);
- void invokeAction(uint id, const QString &action_key);
+ bool closeNotification(uint id, NotificationClient::CloseReason reason);
+ bool invokeAction(uint id, const QString &action_key);
private Q_SLOTS:
void notificationClosed(uint id, uint reason);
void serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner);
+ /**
+ * 用于注册客户端,或在服务发生变化(重启)后重新注册客户端
+ * @return true 成功 false 失败
+ */
bool registerClient();
- void unRegisterClient();
private:
OrgFreedesktopNotificationsInterface* m_notificationsInterface = nullptr;
QDBusInterface *m_serverInterface = nullptr;
+ QDBusServiceWatcher *m_watcher = nullptr;
+ bool m_registered = false;
NotificationClient *q;
};
}
diff --git a/libukui-notification/notification-client.cpp b/libukui-notification/notification-client.cpp
index 7a12157..48a4e8f 100644
--- a/libukui-notification/notification-client.cpp
+++ b/libukui-notification/notification-client.cpp
@@ -24,6 +24,10 @@ NotificationClientPrivate::~NotificationClientPrivate()
bool NotificationClientPrivate::init()
{
+ if(m_registered) {
+ return false;
+ }
+ m_registered = true;
new NotificationClientAdaptor(this);
QDBusConnection conn = QDBusConnection::sessionBus();
@@ -31,29 +35,26 @@ bool NotificationClientPrivate::init()
qWarning() << "Failed to register NotificationClient DBus object!" << conn.lastError();
return false;
}
- auto *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"),
+ m_watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"),
conn,
QDBusServiceWatcher::WatchForOwnerChange,
this);
- connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, [](const QString &service, const QString &oldOwner, const QString &newOwner){
- qDebug() << "serviceOwnerChanged" << service << oldOwner << newOwner;
- });
-
+ connect(m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &NotificationClientPrivate::serviceChange);
return registerClient();
}
bool NotificationClientPrivate::registerClient()
{
QDBusConnection conn = QDBusConnection::sessionBus();
- m_notificationsInterface = new OrgFreedesktopNotificationsInterface(QStringLiteral("org.freedesktop.Notifications"),
- QStringLiteral("/org/freedesktop/Notifications"),
- conn);
- if(!m_notificationsInterface->isValid()) {
- qWarning() << "Failed to creat dbus interface for notification server!" << conn.lastError();
- return false;
+ if(!m_notificationsInterface) {
+ m_notificationsInterface = new OrgFreedesktopNotificationsInterface(QStringLiteral("org.freedesktop.Notifications"),
+ QStringLiteral("/org/freedesktop/Notifications"),
+ conn);
+
+ connect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
+ this, &NotificationClientPrivate::notificationClosed);
}
- connect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
- this, &NotificationClientPrivate::notificationClosed);
+
if(!m_serverInterface) {
m_serverInterface = new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"),
QStringLiteral("/org/freedesktop/Notifications"),
@@ -65,7 +66,6 @@ bool NotificationClientPrivate::registerClient()
return false;
}
}
-
QDBusMessage reply = m_serverInterface->call(QStringLiteral("RegisterClient"));
if (reply.type() == QDBusMessage::ErrorMessage || reply.type() == QDBusMessage::InvalidMessage) {
qWarning() << "Failed to call RegisterClient!" << conn.lastError() << reply.type();
@@ -74,14 +74,25 @@ bool NotificationClientPrivate::registerClient()
return true;
}
-void NotificationClientPrivate::unRegisterClient()
+void NotificationClientPrivate::unregisterClient()
{
- disconnect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
- this, &NotificationClientPrivate::notificationClosed);
if(m_notificationsInterface) {
+ disconnect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
+ this, &NotificationClientPrivate::notificationClosed);
delete m_notificationsInterface;
m_notificationsInterface = nullptr;
}
+ QDBusConnection conn = QDBusConnection::sessionBus();
+ if(m_serverInterface) {
+ QDBusMessage reply = m_serverInterface->call(QStringLiteral("UnRegisterClient"));
+ if (reply.type() == QDBusMessage::ErrorMessage || reply.type() == QDBusMessage::InvalidMessage) {
+ qWarning() << "Failed to call UnRegisterClient!" << conn.lastError() << reply.type();
+ return;
+ }
+ }
+ conn.unregisterObject(clientServicePath(), QDBusConnection::UnregisterTree);
+
+ m_registered = false;
}
QString NotificationClientPrivate::clientServicePath()
@@ -126,38 +137,41 @@ void NotificationClientPrivate::notificationClosed(uint id, uint reason)
Q_EMIT q->notificationClosed(id, closeReason);
}
-void NotificationClientPrivate::closeNotification(uint id, NotificationClient::CloseReason reason)
+bool NotificationClientPrivate::closeNotification(uint id, NotificationClient::CloseReason reason)
{
- if(!m_notificationsInterface) {
- return;
+ if(!m_serverInterface) {
+ return false;
}
- QDBusMessage reply = m_notificationsInterface->callWithArgumentList(QDBus::NoBlock, QStringLiteral("CloseNotification"), {id, reason});
+ QDBusMessage reply = m_serverInterface->callWithArgumentList(QDBus::NoBlock, QStringLiteral("CloseNotification"), {id, reason});
if (reply.type() == QDBusMessage::ErrorMessage) {
qWarning() << "Failed to call CloseNotification!" << QDBusConnection::sessionBus().lastError();
+ return false;
}
+ return true;
}
void NotificationClientPrivate::serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner)
{
qDebug() << "Notification Service" << service << "status change, old owner:" << oldOwner << "new:" << newOwner;
- if(newOwner.isEmpty()) {
- unRegisterClient();
- } else if (oldOwner.isEmpty()) {
+ if(oldOwner.isEmpty() && m_registered) {
registerClient();
}
}
-void NotificationClientPrivate::invokeAction(uint id, const QString &action_key)
+bool NotificationClientPrivate::invokeAction(uint id, const QString &action_key)
{
- if(!m_notificationsInterface) {
- return;
+ if(!m_serverInterface) {
+ return false;
}
- QDBusMessage reply = m_notificationsInterface->callWithArgumentList(QDBus::NoBlock,
- QStringLiteral("InvokedAction"),
+ qDebug() << "invokeAction" << id << action_key;
+ QDBusMessage reply = m_serverInterface->callWithArgumentList(QDBus::NoBlock,
+ QStringLiteral("InvokeAction"),
{id, action_key});
if (reply.type() == QDBusMessage::ErrorMessage) {
qWarning() << "Failed to call InvokedAction!" << QDBusConnection::sessionBus().lastError();
+ return false;
}
+ return true;
}
NotificationClient::NotificationClient(QObject *parent) : QObject(parent), d(new NotificationClientPrivate(this))
@@ -172,12 +186,17 @@ bool NotificationClient::registerClient()
return d->init();
}
-void NotificationClient::closeNotification(uint id, NotificationClient::CloseReason reason)
+bool NotificationClient::closeNotification(uint id, NotificationClient::CloseReason reason)
{
- d->closeNotification(id, reason);
+ return d->closeNotification(id, reason);
}
-void NotificationClient::invokeAction(uint id, const QString &action_key)
+bool NotificationClient::invokeAction(uint id, const QString &action_key)
{
- d->invokeAction(id, action_key);
+ return d->invokeAction(id, action_key);
+}
+
+void NotificationClient::unregisterClient()
+{
+ d->unregisterClient();
}
diff --git a/libukui-notification/notification-client.h b/libukui-notification/notification-client.h
index 59783d0..11e0d88 100644
--- a/libukui-notification/notification-client.h
+++ b/libukui-notification/notification-client.h
@@ -30,8 +30,9 @@ public:
* @return ture-成功 false 失败
*/
bool registerClient();
- void closeNotification(uint id, CloseReason reason);
- void invokeAction(uint id, const QString &action_key);
+ void unregisterClient();
+ bool closeNotification(uint id, CloseReason reason);
+ bool invokeAction(uint id, const QString &action_key);
Q_SIGNALS:
void newNotification(const PopupNotification ¬ification);
void notificationClosed(uint id, CloseReason closeReason);
diff --git a/libukui-notification/popup-notification.cpp b/libukui-notification/popup-notification.cpp
index 4190575..634bf40 100644
--- a/libukui-notification/popup-notification.cpp
+++ b/libukui-notification/popup-notification.cpp
@@ -141,10 +141,9 @@ QSize PopupNotificationPrivate::maximumImageSize()
return QSize(256, 256);
}
-PopupNotification::PopupNotification(uint id, QObject *parent) : QObject(parent), d(new PopupNotificationPrivate())
+PopupNotification::PopupNotification(uint id) : d(new PopupNotificationPrivate())
{
d->m_id = id;
- d->m_createdTime = QDateTime::currentDateTimeUtc();
}
PopupNotification::PopupNotification(const PopupNotification &other) : d(new PopupNotificationPrivate(*other.d))
@@ -277,6 +276,7 @@ void PopupNotification::setHints(const QVariantMap &hints)
break;
}
}
+ d->m_createdTime = hints.value(QStringLiteral("x-ukui-createdTime")).toDateTime();
d->m_resident = hints.value(QStringLiteral("resident")).toBool();
d->m_resident = hints.value(QStringLiteral("transient")).toBool();
d->m_category = hints.value(QStringLiteral("category")).toString();
diff --git a/libukui-notification/popup-notification.h b/libukui-notification/popup-notification.h
index f75d4ef..1c5ecff 100644
--- a/libukui-notification/popup-notification.h
+++ b/libukui-notification/popup-notification.h
@@ -18,9 +18,9 @@ namespace UkuiNotification {
class PopupNotificationPrivate;
//TODO 可以增加通知基类,实现多种类型通知
typedef QList> ActionList;
-class UKUINOTIFICATION_EXPORT PopupNotification : public QObject
+class UKUINOTIFICATION_EXPORT PopupNotification
{
- Q_OBJECT
+ Q_GADGET
Q_PROPERTY(uint id READ id)
Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName)
Q_PROPERTY(QString applicationIconName READ applicationIconName WRITE setAplicationIconName)
@@ -52,7 +52,7 @@ public:
};
Q_ENUM(Urgency)
- explicit PopupNotification(uint id = 0, QObject *parent = nullptr);
+ explicit PopupNotification(uint id = 0);
PopupNotification(const PopupNotification &other);
PopupNotification &operator=(const PopupNotification &other);
PopupNotification &operator=(PopupNotification &&other) Q_DECL_NOEXCEPT;
diff --git a/notification-server/CMakeLists.txt b/notification-server/CMakeLists.txt
index 62e1f9b..4e22560 100644
--- a/notification-server/CMakeLists.txt
+++ b/notification-server/CMakeLists.txt
@@ -16,8 +16,6 @@ set(notificationServer_SRCS
${3rdParties_DIR}qtlocalpeer.cpp
notification-server-application.cpp
notification-server-application.h
- notification.cpp
- notification.h
)
if(COMMAND qt_add_dbus_adaptor)
qt_add_dbus_adaptor(notificationServer_SRCS ../dbus/org.freedesktop.Notifications.xml server-private.h NotificationServer::ServerPrivate)
diff --git a/notification-server/data/org.freedesktop.Notifications.service b/notification-server/data/org.freedesktop.Notifications.service
index 928c2ae..42ef202 100644
--- a/notification-server/data/org.freedesktop.Notifications.service
+++ b/notification-server/data/org.freedesktop.Notifications.service
@@ -1,3 +1,3 @@
[D-BUS Service]
-Name=org.freedesktop.Notification
+Name=org.freedesktop.Notifications
Exec=/usr/bin/ukui-notification-server
\ No newline at end of file
diff --git a/notification-server/notification.cpp b/notification-server/notification.cpp
deleted file mode 100644
index 9a1d502..0000000
--- a/notification-server/notification.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-//
-// Created by zpf on 23-2-1.
-//
-
-#include "notification.h"
-
-namespace NotificationServer {
-} // NotificationServer
\ No newline at end of file
diff --git a/notification-server/notification.h b/notification-server/notification.h
deleted file mode 100644
index 1dbf171..0000000
--- a/notification-server/notification.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Created by zpf on 23-2-1.
-//
-
-#ifndef UKUI_NOTIFICATION_NOTIFICATION_H
-#define UKUI_NOTIFICATION_NOTIFICATION_H
-
-namespace NotificationServer {
-
-class Notification
-{
-
-};
-
-} // NotificationServer
-
-#endif //UKUI_NOTIFICATION_NOTIFICATION_H
diff --git a/notification-server/server-private.h b/notification-server/server-private.h
index 4794119..d7558bf 100644
--- a/notification-server/server-private.h
+++ b/notification-server/server-private.h
@@ -6,9 +6,20 @@
#define UKUI_NOTIFICATION_SERVER_PRIVATE_H
#include
#include
+#include
class QDBusServiceWatcher;
namespace NotificationServer {
-
+class Notification {
+ friend class ServerPrivate;
+ QString m_appName;
+ uint m_id = 0;
+ QString m_appIcon;
+ QString m_summary;
+ QString m_body;
+ QStringList m_actions;
+ QVariantMap m_hints;
+ int m_timeout;
+};
class ServerPrivate : public QObject, protected QDBusContext
{
Q_OBJECT
@@ -51,7 +62,7 @@ public:
* @param reason 关闭原因
*/
void CloseNotification(uint id, uint);
- void InvokedAction(uint id, const QString &action_key);
+ void InvokeAction(uint id, const QString &action_key);
Q_SIGNALS:
void NotificationClosed(uint id, uint reason);
void ActionInvoked(uint id, const QString &actionKey);
@@ -65,8 +76,10 @@ public:
static QString notificationServicePath();
static QString notificationServiceInterface();
private:
+ void sendCache();
QDBusServiceWatcher *m_notificationWatchers = nullptr;
uint m_increasedNotificationId = 1;
+ QVector m_notificationsCache;
};
diff --git a/notification-server/server.cpp b/notification-server/server.cpp
index dc627fd..16bd398 100644
--- a/notification-server/server.cpp
+++ b/notification-server/server.cpp
@@ -11,6 +11,7 @@
#include "utils.h"
using namespace NotificationServer;
+
ServerPrivate::ServerPrivate(QObject *parent) : QObject(parent), m_notificationWatchers(new QDBusServiceWatcher(this))
{
m_notificationWatchers->setConnection(QDBusConnection::sessionBus());
@@ -36,13 +37,15 @@ uint ServerPrivate::Notify(const QString &app_name, uint replaces_id, const QStr
id = m_increasedNotificationId++;
}
+ QVariantMap newHints = hints;
+ newHints.insert(QStringLiteral("x-ukui-createdTime"), QDateTime::currentDateTimeUtc());
+
uint pid = 0;
QDBusReply pidReply = connection().interface()->servicePid(message().service());
if(pidReply.isValid()) {
pid = pidReply.value();
}
- QVariantMap newHints = hints;
if(newHints.value(QStringLiteral("x-ukui-display")).toString().isEmpty() && pid > 0) {
newHints.insert(QStringLiteral("x-ukui-display"), UkuiNotification::Utils::displayFromPid(pid));
}
@@ -50,7 +53,20 @@ uint ServerPrivate::Notify(const QString &app_name, uint replaces_id, const QStr
newHints.insert(QStringLiteral("desktop-entry"), UkuiNotification::Utils::desktopEntryFromPid(pid));
}
- qDebug() << "New message received:" << app_name << id << app_icon << summary << body << actions << hints << timeout;
+ qDebug() << "New message received:" << app_name << id << app_icon << summary << body
+ << actions << hints << timeout << "new hints" << newHints;
+ if(m_notificationWatchers->watchedServices().isEmpty()) {
+ Notification notification;
+ notification.m_appName = app_name;
+ notification.m_id = id;
+ notification.m_appIcon = app_icon;
+ notification.m_summary = summary;
+ notification.m_body = body;
+ notification.m_actions = actions;
+ notification.m_hints = newHints;
+ m_notificationsCache.append(notification);
+ return id;
+ }
for(const QString &service : m_notificationWatchers->watchedServices()) {
QDBusMessage msg = QDBusMessage::createMethodCall(service,
QStringLiteral("/NotificationClient"),
@@ -118,9 +134,9 @@ QString ServerPrivate::notificationServiceInterface()
void ServerPrivate::RegisterClient()
{
-// qDebug() << "Client Register:" << message().service();
m_notificationWatchers->addWatchedService(message().service());
qDebug() << "Watched services:" << m_notificationWatchers->watchedServices();
+ sendCache();
}
void ServerPrivate::UnRegisterClient()
@@ -133,11 +149,28 @@ void ServerPrivate::CloseNotification(uint id, uint reason)
Q_EMIT NotificationClosed(id, reason);
}
-void ServerPrivate::InvokedAction(uint id, const QString &action_key)
+void ServerPrivate::InvokeAction(uint id, const QString &action_key)
{
+ qDebug() << "InvokeAction" << id << action_key;
Q_EMIT ActionInvoked(id, action_key);
}
+void ServerPrivate::sendCache()
+{
+ while(!m_notificationsCache.isEmpty()) {
+ auto notification = m_notificationsCache.takeFirst();
+ for(const QString &service : m_notificationWatchers->watchedServices()) {
+ QDBusMessage msg = QDBusMessage::createMethodCall(service,
+ QStringLiteral("/NotificationClient"),
+ QStringLiteral("org.ukui.NotificationClient"),
+ QStringLiteral("Notify"));
+ msg.setArguments({notification.m_appName, notification.m_id, notification.m_appIcon, notification.m_summary,
+ notification.m_body, notification.m_actions, notification.m_hints, notification.m_timeout});
+ QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
+ }
+ }
+}
+
Server::Server(QObject *parent): QObject(parent), d(new ServerPrivate(this))
{
}