From c18098d872dda008569985bb755f9815a4823a5f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 26 Jul 2024 21:49:03 +0530 Subject: [PATCH] Cleanup DBUS send notification API --- glfw/glfw.py | 3 +-- glfw/glfw3.h | 5 +++++ glfw/linux_notify.c | 21 ++++++++++----------- glfw/linux_notify.h | 2 +- glfw/wl_window.c | 4 ++-- glfw/x11_window.c | 4 ++-- kitty/fast_data_types.pyi | 6 +++--- kitty/glfw-wrapper.h | 8 +++++++- kitty/glfw.c | 17 +++++++++++------ kitty/notifications.py | 2 +- 10 files changed, 43 insertions(+), 29 deletions(-) diff --git a/glfw/glfw.py b/glfw/glfw.py index d2d14661a..8a6cb877f 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -325,8 +325,7 @@ def generate_wrappers(glfw_header: str) -> None: void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c) pid_t glfwWaylandCompositorPID(void) - unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \ -const char *action_text, int32_t timeout, int urgency, GLFWDBusnotificationcreatedfun callback, void *data) + unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data) void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc) void glfwSetX11WindowAsDock(int32_t x11_window_id) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 1bba46b61..bea6f9095 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1315,6 +1315,11 @@ typedef struct GLFWLayerShellConfig { void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); } GLFWLayerShellConfig; +typedef struct GLFWDBUSNotificationData { + const char *app_name, *icon, *summary, *body, *action_name; + int32_t timeout; uint8_t urgency; +} GLFWDBUSNotificationData; + /*! @brief The function pointer type for error callbacks. * * This is the function pointer type for error callbacks. An error callback diff --git a/glfw/linux_notify.c b/glfw/linux_notify.c index 91f3849bd..1d6d258cb 100644 --- a/glfw/linux_notify.c +++ b/glfw/linux_notify.c @@ -93,10 +93,10 @@ cancel_user_notification(DBusConnection *session_bus, uint32_t *id) { } notification_id_type -glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, const char* action_name, int32_t timeout, int urgency, GLFWDBusnotificationcreatedfun callback, void *user_data) { +glfw_dbus_send_user_notification(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *user_data) { DBusConnection *session_bus = glfw_dbus_session_bus(); if (!session_bus) return 0; - if (timeout == -9999 && urgency == -9999) return cancel_user_notification(session_bus, user_data) ? 1 : 0; + if (n->timeout == -9999 && n->urgency == 255) return cancel_user_notification(session_bus, user_data) ? 1 : 0; static DBusConnection *added_signal_match = NULL; if (added_signal_match != session_bus) { dbus_bus_add_match(session_bus, "type='signal',interface='" NOTIFICATIONS_IFACE "',member='ActionInvoked'", NULL); @@ -119,16 +119,16 @@ glfw_dbus_send_user_notification(const char *app_name, const char* icon, const c dbus_message_iter_init_append(msg, &args); #define check_call(func, ...) if (!func(__VA_ARGS__)) { _glfwInputError(GLFW_PLATFORM_ERROR, "%s", "Out of memory allocating DBUS message for notification\n"); return 0; } #define APPEND(to, type, val) check_call(dbus_message_iter_append_basic, &to, type, &val); - APPEND(args, DBUS_TYPE_STRING, app_name) + APPEND(args, DBUS_TYPE_STRING, n->app_name) APPEND(args, DBUS_TYPE_UINT32, replaces_id) - APPEND(args, DBUS_TYPE_STRING, icon) - APPEND(args, DBUS_TYPE_STRING, summary) - APPEND(args, DBUS_TYPE_STRING, body) + APPEND(args, DBUS_TYPE_STRING, n->icon) + APPEND(args, DBUS_TYPE_STRING, n->summary) + APPEND(args, DBUS_TYPE_STRING, n->body) check_call(dbus_message_iter_open_container, &args, DBUS_TYPE_ARRAY, "s", &array); - if (action_name) { + if (n->action_name) { static const char* default_action = "default"; APPEND(array, DBUS_TYPE_STRING, default_action); - APPEND(array, DBUS_TYPE_STRING, action_name); + APPEND(array, DBUS_TYPE_STRING, n->action_name); } check_call(dbus_message_iter_close_container, &args, &array); check_call(dbus_message_iter_open_container, &args, DBUS_TYPE_ARRAY, "{sv}", &array); @@ -142,11 +142,10 @@ glfw_dbus_send_user_notification(const char *app_name, const char* icon, const c check_call(dbus_message_iter_close_container, &dict, &variant); \ check_call(dbus_message_iter_close_container, &array, &dict); \ } - uint8_t urgencyb = urgency & 3; - append_sv_dictionary_entry("urgency", DBUS_TYPE_BYTE, urgencyb); + append_sv_dictionary_entry("urgency", DBUS_TYPE_BYTE, n->urgency); check_call(dbus_message_iter_close_container, &args, &array); - APPEND(args, DBUS_TYPE_INT32, timeout) + APPEND(args, DBUS_TYPE_INT32, n->timeout) #undef check_call #undef APPEND if (!call_method_with_msg(session_bus, msg, 5000, notification_created, data)) return 0; diff --git a/glfw/linux_notify.h b/glfw/linux_notify.h index a60e7f9a1..6ca4e60a6 100644 --- a/glfw/linux_notify.h +++ b/glfw/linux_notify.h @@ -14,6 +14,6 @@ typedef unsigned long long notification_id_type; typedef void (*GLFWDBusnotificationcreatedfun)(notification_id_type, uint32_t, void*); typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, int, const char*); notification_id_type -glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, const char *action_name, int32_t timeout, int urgency, GLFWDBusnotificationcreatedfun, void*); +glfw_dbus_send_user_notification(const GLFWDBUSNotificationData *n, 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 8af8299ab..0b1566d0f 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -2720,8 +2720,8 @@ 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, const char *action_name, int32_t timeout, int urgency, GLFWDBusnotificationcreatedfun callback, void *data) { - return glfw_dbus_send_user_notification(app_name, icon, summary, body, action_name, timeout, urgency, callback, data); +GLFWAPI unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data) { + return glfw_dbus_send_user_notification(n, callback, data); } GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) { diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 2ac4f083b..ee11a4627 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -3253,8 +3253,8 @@ GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) { return glfw_xkb_keysym_from_name(keyName, caseSensitive); } -GLFWAPI unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, const char *action_name, int32_t timeout, int urgency,GLFWDBusnotificationcreatedfun callback, void *data) { - return glfw_dbus_send_user_notification(app_name, icon, summary, body, action_name, timeout, urgency, callback, data); +GLFWAPI unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data) { + return glfw_dbus_send_user_notification(n, callback, data); } GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) { diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 4b748ec8c..ad13b2976 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -550,10 +550,10 @@ def dbus_set_notification_callback(c: Optional[Callable[[str, int, Union[str, in def dbus_send_notification( app_name: str, - icon: str, - summary: str, + app_icon: str, + title: str, body: str, - action_name: str, + action_text: str = '', timeout: int = -1, urgency: int = 1, ) -> int: diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 9acc19242..4336f2c49 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1053,6 +1053,11 @@ typedef struct GLFWLayerShellConfig { void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); } GLFWLayerShellConfig; +typedef struct GLFWDBUSNotificationData { + const char *app_name, *icon, *summary, *body, *action_name; + int32_t timeout; uint8_t urgency; +} GLFWDBUSNotificationData; + /*! @brief The function pointer type for error callbacks. * * This is the function pointer type for error callbacks. An error callback @@ -1700,6 +1705,7 @@ typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*); typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, int, const char*); + typedef int (*glfwInit_func)(monotonic_t); GFW_EXTERN glfwInit_func glfwInit_impl; #define glfwInit glfwInit_impl @@ -2328,7 +2334,7 @@ typedef pid_t (*glfwWaylandCompositorPID_func)(void); GFW_EXTERN glfwWaylandCompositorPID_func glfwWaylandCompositorPID_impl; #define glfwWaylandCompositorPID glfwWaylandCompositorPID_impl -typedef unsigned long long (*glfwDBusUserNotify_func)(const char*, const char*, const char*, const char*, const char*, int32_t, int, GLFWDBusnotificationcreatedfun, void*); +typedef unsigned long long (*glfwDBusUserNotify_func)(const GLFWDBUSNotificationData*, GLFWDBusnotificationcreatedfun, void*); GFW_EXTERN glfwDBusUserNotify_func glfwDBusUserNotify_impl; #define glfwDBusUserNotify glfwDBusUserNotify_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index bcd4ce6fb..1c1f433e3 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -2092,15 +2092,19 @@ dbus_notification_created_callback(unsigned long long notification_id, uint32_t } static PyObject* -dbus_send_notification(PyObject *self UNUSED, PyObject *args) { - char *app_name, *icon, *summary, *body, *action_name; +dbus_send_notification(PyObject *self UNUSED, PyObject *args, PyObject *kw) { int timeout = -1, urgency = 1; - if (!PyArg_ParseTuple(args, "sssss|ii", &app_name, &icon, &summary, &body, &action_name, &timeout, &urgency)) return NULL; + GLFWDBUSNotificationData d = {.action_name=""}; + static const char* kwlist[] = {"app_name", "app_icon", "title", "body", "action_text", "timeout", "urgency", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kw, "ssss|sii", (char**)kwlist, + &d.app_name, &d.icon, &d.summary, &d.body, &d.action_name, &timeout, &urgency)) return NULL; if (!glfwDBusUserNotify) { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwDBusUserNotify, did you call glfw_init?"); return NULL; } - unsigned long long notification_id = glfwDBusUserNotify(app_name, icon, summary, body, action_name, timeout, urgency, dbus_notification_created_callback, NULL); + d.timeout = timeout; + d.urgency = urgency & 3; + unsigned long long notification_id = glfwDBusUserNotify(&d, dbus_notification_created_callback, NULL); return PyLong_FromUnsignedLongLong(notification_id); } @@ -2108,11 +2112,12 @@ static PyObject* dbus_close_notification(PyObject *self UNUSED, PyObject *args) { unsigned int id; if (!PyArg_ParseTuple(args, "I", &id)) return NULL; + GLFWDBUSNotificationData d = {.timeout=-9999, .urgency=255}; if (!glfwDBusUserNotify) { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwDBusUserNotify, did you call glfw_init?"); return NULL; } - if (glfwDBusUserNotify("", "", "", "", "", -9999, -9999, NULL, &id)) Py_RETURN_TRUE; + if (glfwDBusUserNotify(&d, NULL, &id)) Py_RETURN_TRUE; Py_RETURN_FALSE; } @@ -2280,9 +2285,9 @@ static PyMethodDef module_methods[] = { METHODB(make_x11_window_a_dock_window, METH_VARARGS), METHODB(strip_csi, METH_O), #ifndef __APPLE__ - METHODB(dbus_send_notification, METH_VARARGS), METHODB(dbus_close_notification, METH_VARARGS), METHODB(dbus_set_notification_callback, METH_O), + {"dbus_send_notification", (PyCFunction)(void (*) (void))(dbus_send_notification), METH_KEYWORDS | METH_VARARGS, NULL}, #else {"cocoa_recreate_global_menu", (PyCFunction)py_recreate_global_menu, METH_NOARGS, ""}, {"cocoa_clear_global_shortcuts", (PyCFunction)py_clear_global_shortcuts, METH_NOARGS, ""}, diff --git a/kitty/notifications.py b/kitty/notifications.py index 6ae209829..3fb0485e7 100644 --- a/kitty/notifications.py +++ b/kitty/notifications.py @@ -497,7 +497,7 @@ def notify(self, from .fast_data_types import dbus_send_notification app_icon = icon_name or icon_path or get_custom_window_icon()[1] or logo_png_file desktop_notification_id = dbus_send_notification( - application, app_icon, title, body, 'Click to see changes', timeout, urgency.value) + app_name=application, app_icon=app_icon, title=title, body=body, timeout=timeout, urgency=urgency.value) if debug_desktop_integration: log_error(f'Created notification with {desktop_notification_id=}') return desktop_notification_id