diff --git a/dbus/org.ukui.NotificationServer.xml b/dbus/org.ukui.NotificationServer.xml index 2a37cf7..d250743 100644 --- a/dbus/org.ukui.NotificationServer.xml +++ b/dbus/org.ukui.NotificationServer.xml @@ -10,6 +10,7 @@ + diff --git a/libukui-notification/CMakeLists.txt b/libukui-notification/CMakeLists.txt index 9912aa2..c4b68c5 100644 --- a/libukui-notification/CMakeLists.txt +++ b/libukui-notification/CMakeLists.txt @@ -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 - notification-client.cpp - notification-client.h - popup-notification.h - popup-notification.cpp - ukui-notification_global.h - notification-client-private.h - ) + notification-client.cpp + notification-client.h + popup-notification.h + popup-notification.cpp + ukui-notification_global.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) 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) @@ -19,6 +30,7 @@ target_link_libraries(ukui-notification Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Gui + KF5::WindowSystem ) target_compile_definitions(ukui-notification PRIVATE UKUINOTIFICATION_LIBRARY) include(CMakePackageConfigHelpers) @@ -31,4 +43,11 @@ set(PC_INSTALL_DIR "/usr/lib/pkgconfig") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/ukui-notification.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/ukui-notification.pc.in" - INSTALL_DESTINATION ${PC_INSTALL_DIR}) \ No newline at end of file + 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) \ No newline at end of file diff --git a/libukui-notification/notification-client-private.h b/libukui-notification/notification-client-private.h index 2d56092..b53f2f4 100644 --- a/libukui-notification/notification-client-private.h +++ b/libukui-notification/notification-client-private.h @@ -28,11 +28,14 @@ public: const QVariantMap &hints, int timeout); void closeNotification(uint id, NotificationClient::CloseReason reason); + void invokeAction(uint id, const QString &action_key, const QString &action, const QString &display); + private Q_SLOTS: void notificationClosed(uint id, uint reason); void serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner); bool registerClient(); void unRegisterClient(); + private: OrgFreedesktopNotificationsInterface* m_notificationsInterface = nullptr; QDBusInterface *m_serverInterface = nullptr; diff --git a/libukui-notification/notification-client.cpp b/libukui-notification/notification-client.cpp index 0fdbe97..483e629 100644 --- a/libukui-notification/notification-client.cpp +++ b/libukui-notification/notification-client.cpp @@ -31,7 +31,7 @@ bool NotificationClientPrivate::init() qWarning() << "Failed to register NotificationClient DBus object!" << conn.lastError(); return false; } - QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"), + auto *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"), conn, QDBusServiceWatcher::WatchForOwnerChange, 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)) { qRegisterMetaType("PopupNotification"); @@ -162,4 +176,9 @@ bool NotificationClient::registerClient() void NotificationClient::closeNotification(uint id, NotificationClient::CloseReason reason) { d->closeNotification(id, reason); -} \ No newline at end of file +} + +void NotificationClient::invokeAction(uint id, const QString &action_key, const QString &action, const QString &display) +{ + d->invokeAction(id, action_key, action, display); +} diff --git a/libukui-notification/notification-client.h b/libukui-notification/notification-client.h index 4bfab05..e6e8334 100644 --- a/libukui-notification/notification-client.h +++ b/libukui-notification/notification-client.h @@ -31,6 +31,7 @@ public: */ bool registerClient(); void closeNotification(uint id, CloseReason reason); + void invokeAction(uint id, const QString &action_key, const QString &action, const QString &display); Q_SIGNALS: void newNotification(const PopupNotification ¬ification); void notificationClosed(uint id, CloseReason closeReason); diff --git a/libukui-notification/utils.cpp b/libukui-notification/utils.cpp new file mode 100644 index 0000000..a9a426c --- /dev/null +++ b/libukui-notification/utils.cpp @@ -0,0 +1,32 @@ +// +// Created by zpf on 2023/2/13. +// +#include "utils.h" +#include +#include +#include +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(); +} \ No newline at end of file diff --git a/libukui-notification/utils.h b/libukui-notification/utils.h new file mode 100644 index 0000000..308f4db --- /dev/null +++ b/libukui-notification/utils.h @@ -0,0 +1,14 @@ +// +// Created by zpf on 2023/2/13. +// + +#ifndef UKUI_NOTIFICATION_UTILS_H +#define UKUI_NOTIFICATION_UTILS_H +#include +namespace UkuiNotification { +namespace Utils { + QString desktopEntryFromPid(uint pid); + QString displayFromPid(uint pid); +} +} +#endif //UKUI_NOTIFICATION_UTILS_H diff --git a/notification-server/CMakeLists.txt b/notification-server/CMakeLists.txt index 869b2bf..62e1f9b 100644 --- a/notification-server/CMakeLists.txt +++ b/notification-server/CMakeLists.txt @@ -1,7 +1,8 @@ -set (VERSION_MAJOR 1) -set (VERSION_MINOR 0) -set (VERSION_MICRO 0) -set (NOTIFICATION_SERVER_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}) +set(VERSION_MAJOR 1) +set(VERSION_MINOR 0) +set(VERSION_MICRO 0) +set(NOTIFICATION_SERVER_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}) + configure_file (notification-server-config.h.in notification-server-config.h @ONLY) set(3rdParties_DIR ../3rd-parties/qtsingleapplication/src/) set(notificationServer_SRCS @@ -26,6 +27,7 @@ else() qt5_add_dbus_adaptor(notificationServer_SRCS ../dbus/org.ukui.NotificationServer.xml server-private.h NotificationServer::ServerPrivate) endif() add_executable(ukui-notification-server ${notificationServer_SRCS}) +include_directories(../libukui-notification) target_include_directories(ukui-notification-server PUBLIC ${3rdParties_DIR}) target_link_libraries(ukui-notification-server @@ -33,10 +35,14 @@ target_link_libraries(ukui-notification-server Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Network + ukui-notification ) set(TS_FILES ukui-notification_zh_CN.ts) if(COMMAND qt_create_translation) qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR}/translations ${TS_FILES}) else() qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR}/translations ${TS_FILES}) -endif() \ No newline at end of file +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) \ No newline at end of file diff --git a/notification-server/data/org.freedesktop.Notifications.service b/notification-server/data/org.freedesktop.Notifications.service new file mode 100644 index 0000000..928c2ae --- /dev/null +++ b/notification-server/data/org.freedesktop.Notifications.service @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.freedesktop.Notification +Exec=/usr/bin/ukui-notification-server \ No newline at end of file diff --git a/notification-server/server-private.h b/notification-server/server-private.h index 8984d14..9c36ef0 100644 --- a/notification-server/server-private.h +++ b/notification-server/server-private.h @@ -51,7 +51,7 @@ public: * @param reason 关闭原因 */ 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: void NotificationClosed(uint id, uint reason); void ActionInvoked(uint id, const QString &actionKey); diff --git a/notification-server/server.cpp b/notification-server/server.cpp index 64806f9..e30f54b 100644 --- a/notification-server/server.cpp +++ b/notification-server/server.cpp @@ -8,6 +8,7 @@ #include "notificationsadaptor.h" #include "notificationserveradaptor.h" #include "notification-server-config.h" +#include "utils.h" using namespace NotificationServer; 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++; } - //TODO 在hint中增加DISPLAY信息,注意区分X和wayland,DISPLAY信息决定了通知弹窗显示和action执行所在的DISPLAY + 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)); + } + 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; 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("org.ukui.NotificationClient"), 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); } return id; @@ -120,7 +133,7 @@ void ServerPrivate::CloseNotification(uint id, uint 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 Q_EMIT ActionInvoked(id, action_key);