From 1bf28646383718b460b8ad9b3df934e2a660b356 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 3 Feb 2019 13:20:07 +0530 Subject: [PATCH] API to handle DBus user notification activation --- glfw/glfw.py | 2 ++ glfw/linux_notify.c | 36 ++++++++++++++++++++++++++++++++++++ glfw/linux_notify.h | 4 ++++ glfw/wl_window.c | 4 ++++ glfw/x11_window.c | 4 ++++ kitty/glfw-wrapper.c | 2 ++ kitty/glfw-wrapper.h | 5 +++++ 7 files changed, 57 insertions(+) diff --git a/glfw/glfw.py b/glfw/glfw.py index 6193d0ec6..e240c51ad 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -180,6 +180,7 @@ def generate_wrappers(glfw_header): void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback) unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \ int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) + void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) '''.splitlines(): if line: functions.append(Function(line.strip(), check_fail=False)) @@ -200,6 +201,7 @@ typedef int (* GLFWapplicationshouldhandlereopenfun)(int); typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*); +typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*); {} const char* load_glfw(const char* path); diff --git a/glfw/linux_notify.c b/glfw/linux_notify.c index bd53e866a..ac43f1a34 100644 --- a/glfw/linux_notify.c +++ b/glfw/linux_notify.c @@ -21,6 +21,13 @@ typedef struct { void *data; } NotificationCreatedData; +static GLFWDBusnotificationactivatedfun activated_handler = NULL; + +void +glfw_dbus_set_user_notification_activated_handler(GLFWDBusnotificationactivatedfun handler) { + activated_handler = handler; +} + void notification_created(DBusMessage *msg, const char* errmsg, void *data) { if (errmsg) { @@ -33,10 +40,39 @@ notification_created(DBusMessage *msg, const char* errmsg, void *data) { if (ncd->callback) ncd->callback(ncd->next_id, notification_id, ncd->data); } +static DBusHandlerResult +message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { + (void)(user_data); + switch(glfw_dbus_match_signal(msg, NOTIFICATIONS_IFACE, "ActionInvoked", NULL)) { + case 0: + { + uint32_t notification_id; + const char *action; + if (glfw_dbus_get_args(msg, "Failed to get args from ActionInvoked notification signal", + DBUS_TYPE_UINT32, ¬ification_id, DBUS_TYPE_STRING, &action, DBUS_TYPE_INVALID)) { + if (activated_handler) { + activated_handler(notification_id, action); + } + } + + } + break; + default: + break; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + notification_id_type glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *user_data) { DBusConnection *session_bus = glfw_dbus_session_bus(); + static DBusConnection *added_signal_match = NULL; if (!session_bus) return 0; + if (added_signal_match != session_bus) { + dbus_bus_add_match(session_bus, "type='signal',interface='org.freedesktop.Notifications.ActionInvoked'", NULL); + static DBusObjectPathVTable vtable = {.message_function = message_handler}; + dbus_connection_try_register_object_path(session_bus, NOTIFICATIONS_PATH, &vtable, NULL, NULL); + } NotificationCreatedData *data = malloc(sizeof(NotificationCreatedData)); data->next_id = ++notification_id; data->callback = callback; data->data = user_data; diff --git a/glfw/linux_notify.h b/glfw/linux_notify.h index 808e7c903..03de5f94c 100644 --- a/glfw/linux_notify.h +++ b/glfw/linux_notify.h @@ -8,8 +8,12 @@ #include "dbus_glfw.h" +#include "internal.h" typedef unsigned long long notification_id_type; typedef void (*GLFWDBusnotificationcreatedfun)(notification_id_type, uint32_t, void*); +typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*); notification_id_type glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, int32_t timeout, GLFWDBusnotificationcreatedfun, void*); +void +glfw_dbus_set_user_notification_activated_handler(GLFWDBusnotificationactivatedfun handler); diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 23349a1c6..b38dc6cff 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -2135,3 +2135,7 @@ GLFWAPI void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long GLFWAPI unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) { return glfw_dbus_send_user_notification(app_name, icon, summary, body, timeout, callback, data); } + +GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) { + glfw_dbus_set_user_notification_activated_handler(handler); +} diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 8ce73899d..eac25c88b 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2898,3 +2898,7 @@ GLFWAPI int glfwGetXKBScancode(const char* keyName, GLFWbool caseSensitive) { GLFWAPI unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) { return glfw_dbus_send_user_notification(app_name, icon, summary, body, timeout, callback, data); } + +GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) { + glfw_dbus_set_user_notification_activated_handler(handler); +} diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index f2399489b..dbd2ca3a2 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -387,6 +387,8 @@ load_glfw(const char* path) { *(void **) (&glfwDBusUserNotify_impl) = dlsym(handle, "glfwDBusUserNotify"); + *(void **) (&glfwDBusSetUserNotificationHandler_impl) = dlsym(handle, "glfwDBusSetUserNotificationHandler"); + return NULL; } diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 148857be8..f25415018 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1396,6 +1396,7 @@ typedef int (* GLFWapplicationshouldhandlereopenfun)(int); typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*); +typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*); typedef int (*glfwInit_func)(); glfwInit_func glfwInit_impl; #define glfwInit glfwInit_impl @@ -1912,4 +1913,8 @@ typedef unsigned long long (*glfwDBusUserNotify_func)(const char*, const char*, glfwDBusUserNotify_func glfwDBusUserNotify_impl; #define glfwDBusUserNotify glfwDBusUserNotify_impl +typedef void (*glfwDBusSetUserNotificationHandler_func)(GLFWDBusnotificationactivatedfun); +glfwDBusSetUserNotificationHandler_func glfwDBusSetUserNotificationHandler_impl; +#define glfwDBusSetUserNotificationHandler glfwDBusSetUserNotificationHandler_impl + const char* load_glfw(const char* path);