Server增加获取消息发送者DISPLAY信息功能

This commit is contained in:
iaom 2023-02-13 17:10:55 +08:00
parent 423ab2f445
commit 39bd53a95a
11 changed files with 130 additions and 19 deletions

View File

@ -10,6 +10,7 @@
<method name="InvokedAction"> <method name="InvokedAction">
<arg name="id" type="u" direction="in"/> <arg name="id" type="u" direction="in"/>
<arg name="action_key" type="s" direction="in"/> <arg name="action_key" type="s" direction="in"/>
<arg name="action" type="s" direction="in"/>
<arg name="display" type="s" direction="in"/> <arg name="display" type="s" direction="in"/>
</method> </method>
</interface> </interface>

View File

@ -1,11 +1,22 @@
set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)
set(VERSION_MICRO 0)
set(UKUI_NOTIFICATION_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO})
find_package(KF5WindowSystem)
set(ukui-notification_LIB_SRCS set(ukui-notification_LIB_SRCS
notification-client.cpp notification-client.cpp
notification-client.h notification-client.h
popup-notification.h popup-notification.h
popup-notification.cpp popup-notification.cpp
ukui-notification_global.h ukui-notification_global.h
notification-client-private.h notification-client-private.h
) utils.h
utils.cpp)
set(HEADERS
notification-client.h
popup-notification.h
ukui-notification_global.h
utils.h)
if(COMMAND qt_add_dbus_interface) if(COMMAND qt_add_dbus_interface)
qt_add_dbus_interface(ukui-notification_LIB_SRCS ../dbus/org.freedesktop.Notifications.xml notifications_interface) qt_add_dbus_interface(ukui-notification_LIB_SRCS ../dbus/org.freedesktop.Notifications.xml notifications_interface)
qt_add_dbus_adaptor(ukui-notification_LIB_SRCS ../dbus/org.ukui.NotificationClient.xml notification-client-private.h UkuiNotification::NotificationClientPrivate) qt_add_dbus_adaptor(ukui-notification_LIB_SRCS ../dbus/org.ukui.NotificationClient.xml notification-client-private.h UkuiNotification::NotificationClientPrivate)
@ -19,6 +30,7 @@ target_link_libraries(ukui-notification
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Gui
KF5::WindowSystem
) )
target_compile_definitions(ukui-notification PRIVATE UKUINOTIFICATION_LIBRARY) target_compile_definitions(ukui-notification PRIVATE UKUINOTIFICATION_LIBRARY)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
@ -32,3 +44,10 @@ configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/ukui-notification.pc.in" "${CMAKE_CURRENT_SOURCE_DIR}/ukui-notification.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/ukui-notification.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/ukui-notification.pc.in"
INSTALL_DESTINATION ${PC_INSTALL_DIR}) INSTALL_DESTINATION ${PC_INSTALL_DIR})
set_target_properties(ukui-notification PROPERTIES
VERSION ${UKUI_NOTIFICATION_VERSION}
SOVERSION "1"
OUTPUT_NAME ukui-notification
)
install(TARGETS ukui-notification DESTINATION /usr/lib)
install(FILES ${HEADERS} DESTINATION /usr/include/ukui-notification)

View File

@ -28,11 +28,14 @@ public:
const QVariantMap &hints, const QVariantMap &hints,
int timeout); int timeout);
void closeNotification(uint id, NotificationClient::CloseReason reason); void closeNotification(uint id, NotificationClient::CloseReason reason);
void invokeAction(uint id, const QString &action_key, const QString &action, const QString &display);
private Q_SLOTS: private Q_SLOTS:
void notificationClosed(uint id, uint reason); void notificationClosed(uint id, uint reason);
void serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner); void serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner);
bool registerClient(); bool registerClient();
void unRegisterClient(); void unRegisterClient();
private: private:
OrgFreedesktopNotificationsInterface* m_notificationsInterface = nullptr; OrgFreedesktopNotificationsInterface* m_notificationsInterface = nullptr;
QDBusInterface *m_serverInterface = nullptr; QDBusInterface *m_serverInterface = nullptr;

View File

@ -31,7 +31,7 @@ bool NotificationClientPrivate::init()
qWarning() << "Failed to register NotificationClient DBus object!" << conn.lastError(); qWarning() << "Failed to register NotificationClient DBus object!" << conn.lastError();
return false; return false;
} }
QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"), auto *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"),
conn, conn,
QDBusServiceWatcher::WatchForOwnerChange, QDBusServiceWatcher::WatchForOwnerChange,
this); this);
@ -147,6 +147,20 @@ void NotificationClientPrivate::serviceChange(const QString &service, const QStr
} }
} }
void NotificationClientPrivate::invokeAction(uint id, const QString &action_key, const QString &action,
const QString &display)
{
if(!m_notificationsInterface) {
return;
}
QDBusMessage reply = m_notificationsInterface->callWithArgumentList(QDBus::NoBlock,
QStringLiteral("InvokedAction"),
{id, action_key, action, display});
if (reply.type() == QDBusMessage::ErrorMessage) {
qWarning() << "Failed to call InvokedAction!" << QDBusConnection::sessionBus().lastError();
}
}
NotificationClient::NotificationClient(QObject *parent) : QObject(parent), d(new NotificationClientPrivate(this)) NotificationClient::NotificationClient(QObject *parent) : QObject(parent), d(new NotificationClientPrivate(this))
{ {
qRegisterMetaType<PopupNotification>("PopupNotification"); qRegisterMetaType<PopupNotification>("PopupNotification");
@ -163,3 +177,8 @@ void NotificationClient::closeNotification(uint id, NotificationClient::CloseRea
{ {
d->closeNotification(id, reason); d->closeNotification(id, reason);
} }
void NotificationClient::invokeAction(uint id, const QString &action_key, const QString &action, const QString &display)
{
d->invokeAction(id, action_key, action, display);
}

View File

@ -31,6 +31,7 @@ public:
*/ */
bool registerClient(); bool registerClient();
void closeNotification(uint id, CloseReason reason); void closeNotification(uint id, CloseReason reason);
void invokeAction(uint id, const QString &action_key, const QString &action, const QString &display);
Q_SIGNALS: Q_SIGNALS:
void newNotification(const PopupNotification &notification); void newNotification(const PopupNotification &notification);
void notificationClosed(uint id, CloseReason closeReason); void notificationClosed(uint id, CloseReason closeReason);

View File

@ -0,0 +1,32 @@
//
// Created by zpf on 2023/2/13.
//
#include "utils.h"
#include <QFile>
#include <QByteArray>
#include <KWindowSystem>
using namespace UkuiNotification;
QString Utils::desktopEntryFromPid(uint pid)
{
return QString();
}
QString Utils::displayFromPid(uint pid)
{
QFile environFile(QStringLiteral("/proc/%1/environ").arg(QString::number(pid)));
if (environFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
const QByteArray DISPLAY = KWindowSystem::isPlatformWayland() ? QByteArrayLiteral("WAYLAND_DISPLAY") : QByteArrayLiteral("DISPLAY");
const auto lines = environFile.readAll().split('\0');
for (const QByteArray &line : lines) {
const int equalsIdx = line.indexOf('=');
if (equalsIdx <= 0) {
continue;
}
const QByteArray key = line.left(equalsIdx);
if (key == DISPLAY) {
const QByteArray value = line.mid(equalsIdx + 1);
return value;
}
}
}
return QString();
}

View File

@ -0,0 +1,14 @@
//
// Created by zpf on 2023/2/13.
//
#ifndef UKUI_NOTIFICATION_UTILS_H
#define UKUI_NOTIFICATION_UTILS_H
#include <QString>
namespace UkuiNotification {
namespace Utils {
QString desktopEntryFromPid(uint pid);
QString displayFromPid(uint pid);
}
}
#endif //UKUI_NOTIFICATION_UTILS_H

View File

@ -1,7 +1,8 @@
set (VERSION_MAJOR 1) set(VERSION_MAJOR 1)
set (VERSION_MINOR 0) set(VERSION_MINOR 0)
set (VERSION_MICRO 0) set(VERSION_MICRO 0)
set (NOTIFICATION_SERVER_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}) set(NOTIFICATION_SERVER_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO})
configure_file (notification-server-config.h.in notification-server-config.h @ONLY) configure_file (notification-server-config.h.in notification-server-config.h @ONLY)
set(3rdParties_DIR ../3rd-parties/qtsingleapplication/src/) set(3rdParties_DIR ../3rd-parties/qtsingleapplication/src/)
set(notificationServer_SRCS set(notificationServer_SRCS
@ -26,6 +27,7 @@ else()
qt5_add_dbus_adaptor(notificationServer_SRCS ../dbus/org.ukui.NotificationServer.xml server-private.h NotificationServer::ServerPrivate) qt5_add_dbus_adaptor(notificationServer_SRCS ../dbus/org.ukui.NotificationServer.xml server-private.h NotificationServer::ServerPrivate)
endif() endif()
add_executable(ukui-notification-server ${notificationServer_SRCS}) add_executable(ukui-notification-server ${notificationServer_SRCS})
include_directories(../libukui-notification)
target_include_directories(ukui-notification-server PUBLIC ${3rdParties_DIR}) target_include_directories(ukui-notification-server PUBLIC ${3rdParties_DIR})
target_link_libraries(ukui-notification-server target_link_libraries(ukui-notification-server
@ -33,6 +35,7 @@ target_link_libraries(ukui-notification-server
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Network
ukui-notification
) )
set(TS_FILES ukui-notification_zh_CN.ts) set(TS_FILES ukui-notification_zh_CN.ts)
if(COMMAND qt_create_translation) if(COMMAND qt_create_translation)
@ -40,3 +43,6 @@ if(COMMAND qt_create_translation)
else() else()
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR}/translations ${TS_FILES}) qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR}/translations ${TS_FILES})
endif() endif()
set(DBUS_SERVICE_FILE data/org.freedesktop.Notifications.service)
install(TARGETS ukui-notification-server DESTINATION /usr/bin)
install(FILES ${DBUS_SERVICE_FILE} DESTINATION /usr/share/dbus-1/services)

View File

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.freedesktop.Notification
Exec=/usr/bin/ukui-notification-server

View File

@ -51,7 +51,7 @@ public:
* @param reason * @param reason
*/ */
void CloseNotification(uint id, uint); void CloseNotification(uint id, uint);
void InvokedAction(uint id, const QString &action_key, const QString &display); void InvokedAction(uint id, const QString &action_key, const QString &action, const QString &display);
Q_SIGNALS: Q_SIGNALS:
void NotificationClosed(uint id, uint reason); void NotificationClosed(uint id, uint reason);
void ActionInvoked(uint id, const QString &actionKey); void ActionInvoked(uint id, const QString &actionKey);

View File

@ -8,6 +8,7 @@
#include "notificationsadaptor.h" #include "notificationsadaptor.h"
#include "notificationserveradaptor.h" #include "notificationserveradaptor.h"
#include "notification-server-config.h" #include "notification-server-config.h"
#include "utils.h"
using namespace NotificationServer; using namespace NotificationServer;
ServerPrivate::ServerPrivate(QObject *parent) : QObject(parent), m_notificationWatchers(new QDBusServiceWatcher(this)) ServerPrivate::ServerPrivate(QObject *parent) : QObject(parent), m_notificationWatchers(new QDBusServiceWatcher(this))
@ -35,7 +36,19 @@ uint ServerPrivate::Notify(const QString &app_name, uint replaces_id, const QStr
id = m_increasedNotificationId++; id = m_increasedNotificationId++;
} }
//TODO 在hint中增加DISPLAY信息,注意区分X和waylandDISPLAY信息决定了通知弹窗显示和action执行所在的DISPLAY uint pid = 0;
QDBusReply<uint> 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));
}
if(newHints.value(QStringLiteral("desktop-entry")).toString().isEmpty() && pid > 0) {
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;
for(const QString &service : m_notificationWatchers->watchedServices()) { for(const QString &service : m_notificationWatchers->watchedServices()) {
@ -43,7 +56,7 @@ uint ServerPrivate::Notify(const QString &app_name, uint replaces_id, const QStr
QStringLiteral("/NotificationClient"), QStringLiteral("/NotificationClient"),
QStringLiteral("org.ukui.NotificationClient"), QStringLiteral("org.ukui.NotificationClient"),
QStringLiteral("Notify")); QStringLiteral("Notify"));
msg.setArguments({app_name, id, app_icon, summary, body, actions, hints, timeout}); msg.setArguments({app_name, id, app_icon, summary, body, actions, newHints, timeout});
QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
} }
return id; return id;
@ -120,7 +133,7 @@ void ServerPrivate::CloseNotification(uint id, uint reason)
Q_EMIT NotificationClosed(id, reason); Q_EMIT NotificationClosed(id, reason);
} }
void ServerPrivate::InvokedAction(uint id, const QString &action_key, const QString &display) void ServerPrivate::InvokedAction(uint id, const QString &action_key, const QString &action, const QString &display)
{ {
//TODO: 异步执行action //TODO: 异步执行action
Q_EMIT ActionInvoked(id, action_key); Q_EMIT ActionInvoked(id, action_key);