Use application name as thread identifier for cocoa notifications

This commit is contained in:
Kovid Goyal 2024-07-30 07:48:52 +05:30
parent 9b19f300fe
commit f998af56fc
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 15 additions and 11 deletions

View file

@ -453,13 +453,14 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
}
static void
schedule_notification(const char *identifier, const char *title, const char *body, int urgency) {
schedule_notification(const char *appname, const char *identifier, const char *title, const char *body, int urgency) {
UNUserNotificationCenter *center = get_notification_center_safely();
if (!center) return;
// Configure the notification's payload.
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
if (title) content.title = @(title);
if (body) content.body = @(body);
if (appname) content.threadIdentifier = @(appname);
content.sound = [UNNotificationSound defaultSound];
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
switch (urgency) {
@ -496,7 +497,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
typedef struct {
char *identifier, *title, *body;
char *identifier, *title, *body, *appname;
int urgency;
} QueuedNotification;
@ -507,9 +508,10 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
static NotificationQueue notification_queue = {0};
static void
queue_notification(const char *identifier, const char *title, const char* body, int urgency) {
queue_notification(const char *appname, const char *identifier, const char *title, const char* body, int urgency) {
ensure_space_for((&notification_queue), notifications, QueuedNotification, notification_queue.count + 16, capacity, 16, true);
QueuedNotification *n = notification_queue.notifications + notification_queue.count++;
n->appname = appname ? strdup(appname) : NULL;
n->identifier = identifier ? strdup(identifier) : NULL;
n->title = title ? strdup(title) : NULL;
n->body = body ? strdup(body) : NULL;
@ -521,13 +523,13 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
if (granted) {
for (size_t i = 0; i < notification_queue.count; i++) {
QueuedNotification *n = notification_queue.notifications + i;
schedule_notification(n->identifier, n->title, n->body, n->urgency);
schedule_notification(n->appname, n->identifier, n->title, n->body, n->urgency);
}
}
while(notification_queue.count) {
QueuedNotification *n = notification_queue.notifications + --notification_queue.count;
if (!granted) do_notification_callback(@(n->identifier), "creation_failed");
free(n->identifier); free(n->title); free(n->body);
free(n->identifier); free(n->title); free(n->body); free(n->appname);
memset(n, 0, sizeof(QueuedNotification));
}
}
@ -548,14 +550,15 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
static PyObject*
cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
char *identifier = NULL, *title = NULL, *body = NULL; int urgency = 1;
if (!PyArg_ParseTuple(args, "sss|i", &identifier, &title, &body, &urgency)) return NULL;
cocoa_send_notification(PyObject *self UNUSED, PyObject *args, PyObject *kw) {
const char *identifier = "", *title = "", *body = "", *appname = ""; int urgency = 1;
static const char* kwlist[] = {"appname", "identifier", "title", "body", "urgency", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "ssss|i", (char**)kwlist, &appname, &identifier, &title, &body, &urgency)) return NULL;
UNUserNotificationCenter *center = get_notification_center_safely();
if (!center) Py_RETURN_NONE;
if (!center.delegate) center.delegate = [[NotificationDelegate alloc] init];
queue_notification(identifier, title, body, urgency);
queue_notification(appname, identifier, title, body, urgency);
// The badge permission needs to be requested as well, even though it is not used,
// otherwise macOS refuses to show the preference checkbox for enable/disable notification sound.
@ -1058,7 +1061,7 @@ - (BOOL)openFileURLs:(NSPasteboard*)pasteboard
static PyMethodDef module_methods[] = {
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
{"cocoa_set_global_shortcut", (PyCFunction)cocoa_set_global_shortcut, METH_VARARGS, ""},
{"cocoa_send_notification", (PyCFunction)(void(*)(void))cocoa_send_notification, METH_VARARGS, ""},
{"cocoa_send_notification", (PyCFunction)(void(*)(void))cocoa_send_notification, METH_VARARGS | METH_KEYWORDS, ""},
{"cocoa_remove_delivered_notification", (PyCFunction)cocoa_remove_delivered_notification, METH_O, ""},
{"cocoa_live_delivered_notifications", (PyCFunction)cocoa_live_delivered_notifications, METH_NOARGS, ""},
{"cocoa_set_notification_activated_callback", (PyCFunction)set_notification_activated_callback, METH_O, ""},

View file

@ -562,6 +562,7 @@ def dbus_close_notification(dbus_notification_id: int) -> bool: ...
def cocoa_send_notification(
appname: str,
identifier: str,
title: str,
body: str,

View file

@ -487,7 +487,7 @@ def notify(self, nc: NotificationCommand, existing_desktop_notification_id: Opti
# for %% escaping.
body = (nc.body or ' ')
assert nc.urgency is not None
cocoa_send_notification(str(desktop_notification_id), nc.title, body, nc.urgency.value)
cocoa_send_notification(nc.application_name or 'kitty', str(desktop_notification_id), nc.title, body, nc.urgency.value)
return desktop_notification_id
def notification_activated(self, event: str, ident: str) -> None: