Get closing of notifications working on macOS
This commit is contained in:
parent
3593e8d78d
commit
9024341b1f
5 changed files with 50 additions and 13 deletions
|
|
@ -376,7 +376,7 @@ def __init__(
|
|||
self.mouse_handler: Optional[Callable[[WindowSystemMouseEvent], None]] = None
|
||||
set_boss(self)
|
||||
self.mappings: Mappings = Mappings(global_shortcuts, self.refresh_active_tab_bar)
|
||||
self.notification_manager: NotificationManager = NotificationManager()
|
||||
self.notification_manager: NotificationManager = NotificationManager(debug=self.args.debug_keyboard or self.args.debug_rendering)
|
||||
|
||||
def startup_first_child(self, os_window_id: Optional[int], startup_sessions: Iterable[Session] = ()) -> None:
|
||||
si = startup_sessions or create_sessions(get_options(), self.args, default_session=get_options().startup_session)
|
||||
|
|
|
|||
|
|
@ -429,11 +429,15 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|||
withCompletionHandler:(void (^)(void))completionHandler {
|
||||
(void)(center);
|
||||
if (notification_activated_callback) {
|
||||
NSString *identifier = [[[response notification] request] identifier];
|
||||
PyObject *ret = PyObject_CallFunction(notification_activated_callback, "z",
|
||||
identifier ? [identifier UTF8String] : NULL);
|
||||
if (ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(ret);
|
||||
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
|
||||
NSString *identifier = [[[response notification] request] identifier];
|
||||
PyObject *ret = PyObject_CallFunction(notification_activated_callback, "z",
|
||||
identifier ? [identifier UTF8String] : NULL);
|
||||
if (ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(ret);
|
||||
} else if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
|
||||
NSLog(@"Notification was dismissed: %@", response.notification);
|
||||
}
|
||||
}
|
||||
completionHandler();
|
||||
}
|
||||
|
|
@ -455,6 +459,14 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|||
return center;
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_delivered_notification(const char *identifier) {
|
||||
UNUserNotificationCenter *center = get_notification_center_safely();
|
||||
if (!center) return false;
|
||||
[center removeDeliveredNotificationsWithIdentifiers:@[ @(identifier) ]];
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_notification(const char *identifier, const char *title, const char *body, const char *subtitle, int urgency) {
|
||||
UNUserNotificationCenter *center = get_notification_center_safely();
|
||||
|
|
@ -532,10 +544,17 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|||
}
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cocoa_remove_delivered_notification(PyObject *self UNUSED, PyObject *x) {
|
||||
if (!PyUnicode_Check(x)) { PyErr_SetString(PyExc_TypeError, "identifier must be a string"); return NULL; }
|
||||
if (remove_delivered_notification(PyUnicode_AsUTF8(x))) { Py_RETURN_TRUE; }
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
|
||||
char *identifier = NULL, *title = NULL, *body = NULL, *subtitle = NULL; int urgency = 1;
|
||||
if (!PyArg_ParseTuple(args, "zsz|zi", &identifier, &title, &body, &subtitle, &urgency)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "ssz|zi", &identifier, &title, &body, &subtitle, &urgency)) return NULL;
|
||||
|
||||
UNUserNotificationCenter *center = get_notification_center_safely();
|
||||
if (!center) Py_RETURN_NONE;
|
||||
|
|
@ -546,7 +565,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|||
// otherwise macOS refuses to show the preference checkbox for enable/disable notification sound.
|
||||
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
|
||||
completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
||||
if (error != nil) {
|
||||
if (!granted && error != nil) {
|
||||
log_error("Failed to request permission for showing notification: %s", [[error localizedDescription] UTF8String]);
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
|
@ -1048,6 +1067,7 @@ - (BOOL)openFileURLs:(NSPasteboard*)pasteboard
|
|||
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
|
||||
{"cocoa_set_global_shortcut", (PyCFunction)cocoa_set_global_shortcut, METH_VARARGS, ""},
|
||||
{"cocoa_send_notification", (PyCFunction)cocoa_send_notification, METH_VARARGS, ""},
|
||||
{"cocoa_remove_delivered_notification", (PyCFunction)cocoa_remove_delivered_notification, METH_O, ""},
|
||||
{"cocoa_set_notification_activated_callback", (PyCFunction)set_notification_activated_callback, METH_O, ""},
|
||||
{"cocoa_set_url_handler", (PyCFunction)cocoa_set_url_handler, METH_VARARGS, ""},
|
||||
{"cocoa_set_app_icon", (PyCFunction)cocoa_set_app_icon, METH_VARARGS, ""},
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ def os_window_has_background_image(os_window_id: int) -> bool:
|
|||
pass
|
||||
|
||||
|
||||
def dbus_set_notification_callback(c: Callable[[str, int, Union[str, int]], None]) -> None: ...
|
||||
def dbus_set_notification_callback(c: Optional[Callable[[str, int, Union[str, int]], None]]) -> None: ...
|
||||
|
||||
def dbus_send_notification(
|
||||
app_name: str,
|
||||
|
|
@ -561,7 +561,7 @@ def dbus_close_notification(dbus_notification_id: int) -> bool: ...
|
|||
|
||||
|
||||
def cocoa_send_notification(
|
||||
identifier: Optional[str],
|
||||
identifier: str,
|
||||
title: str,
|
||||
body: Optional[str],
|
||||
subtitle: Optional[str],
|
||||
|
|
@ -569,6 +569,7 @@ def cocoa_send_notification(
|
|||
) -> None:
|
||||
pass
|
||||
|
||||
def cocoa_remove_delivered_notification(identifier: str) -> bool: ...
|
||||
|
||||
def create_os_window(
|
||||
get_window_size: Callable[[int, int, int, int, float, float], Tuple[int,
|
||||
|
|
|
|||
|
|
@ -1423,7 +1423,8 @@ static PyObject *dbus_notification_callback = NULL;
|
|||
|
||||
static PyObject*
|
||||
dbus_set_notification_callback(PyObject *self UNUSED, PyObject *callback) {
|
||||
Py_CLEAR(dbus_notification_callback); dbus_notification_callback = callback; Py_INCREF(callback);
|
||||
Py_CLEAR(dbus_notification_callback);
|
||||
if (callback && callback != Py_None) { dbus_notification_callback = callback; Py_INCREF(callback); }
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -279,9 +279,16 @@ class MacOSIntegration(DesktopIntegration):
|
|||
|
||||
def initialize(self) -> None:
|
||||
from .fast_data_types import cocoa_set_notification_activated_callback
|
||||
self.id_counter = count()
|
||||
self.id_counter = count(start=1)
|
||||
cocoa_set_notification_activated_callback(self.notification_activated)
|
||||
|
||||
def close_notification(self, desktop_notification_id: int) -> bool:
|
||||
from .fast_data_types import cocoa_remove_delivered_notification
|
||||
close_succeeded = cocoa_remove_delivered_notification(str(desktop_notification_id))
|
||||
if debug_desktop_integration:
|
||||
log_error(f'Close request for {desktop_notification_id=} {"succeeded" if close_succeeded else "failed"}')
|
||||
return close_succeeded
|
||||
|
||||
def notify(self,
|
||||
title: str,
|
||||
body: str,
|
||||
|
|
@ -293,10 +300,15 @@ def notify(self,
|
|||
) -> int:
|
||||
desktop_notification_id = next(self.id_counter)
|
||||
from .fast_data_types import cocoa_send_notification
|
||||
cocoa_send_notification(str(desktop_notification_id), title, body, subtitle, urgency.value)
|
||||
# If the body is not set macos makes the title the body and uses
|
||||
# "kitty" as the title. So use a single space for the body in this
|
||||
# case.
|
||||
cocoa_send_notification(str(desktop_notification_id), title, body or ' ', subtitle, urgency.value)
|
||||
return desktop_notification_id
|
||||
|
||||
def notification_activated(self, ident: str) -> None:
|
||||
if debug_desktop_integration:
|
||||
log_error(f'Notification {ident} activated')
|
||||
try:
|
||||
desktop_notification_id = int(ident)
|
||||
except Exception:
|
||||
|
|
@ -434,7 +446,10 @@ def __init__(
|
|||
desktop_integration: Optional[DesktopIntegration] = None,
|
||||
channel: Channel = Channel(),
|
||||
log: Log = Log(),
|
||||
debug: bool = False,
|
||||
):
|
||||
global debug_desktop_integration
|
||||
debug_desktop_integration = debug
|
||||
if desktop_integration is None:
|
||||
self.desktop_integration = MacOSIntegration(self) if is_macos else FreeDesktopIntegration(self)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue