macOS: re-add deprecated notification API

The new User Notifications Framework is only available on macOS 10.14 and above, while the old NSUserNotification API is deprecated in macOS 11 (Big Sur) and will probably be removed in the future.
This commit compiles a simple test program to see if the Framework is available and then uses either the new or the old API.
This commit is contained in:
Luflosi 2020-09-28 01:33:40 +02:00
parent a5918b50f8
commit 0ae1f9906f
No known key found for this signature in database
GPG Key ID: 4E41E29EDCC345D0
2 changed files with 77 additions and 10 deletions

View File

@ -9,7 +9,9 @@
#include "state.h"
#include "monotonic.h"
#include <Cocoa/Cocoa.h>
#if !defined(KITTY_USE_DEPRECATED_MACOS_NOTIFICATION_API)
#include <UserNotifications/UserNotifications.h>
#endif
#include <AvailabilityMacros.h>
// Needed for _NSGetProgname
@ -135,6 +137,68 @@ get_dock_menu(id self UNUSED, SEL _cmd UNUSED, NSApplication *sender UNUSED) {
static PyObject *notification_activated_callback = NULL;
static PyObject*
set_notification_activated_callback(PyObject *self UNUSED, PyObject *callback) {
if (notification_activated_callback) Py_DECREF(notification_activated_callback);
notification_activated_callback = callback;
Py_INCREF(callback);
Py_RETURN_NONE;
}
#if defined(KITTY_USE_DEPRECATED_MACOS_NOTIFICATION_API)
@interface NotificationDelegate : NSObject <NSUserNotificationCenterDelegate>
@end
@implementation NotificationDelegate
- (void)userNotificationCenter:(NSUserNotificationCenter *)center
didDeliverNotification:(NSUserNotification *)notification {
(void)(center); (void)(notification);
}
- (BOOL) userNotificationCenter:(NSUserNotificationCenter *)center
shouldPresentNotification:(NSUserNotification *)notification {
(void)(center); (void)(notification);
return YES;
}
- (void) userNotificationCenter:(NSUserNotificationCenter *)center
didActivateNotification:(NSUserNotification *)notification {
(void)(center); (void)(notification);
if (notification_activated_callback) {
PyObject *ret = PyObject_CallFunction(notification_activated_callback, "z",
notification.userInfo[@"user_id"] ? [notification.userInfo[@"user_id"] UTF8String] : NULL);
if (ret == NULL) PyErr_Print();
else Py_DECREF(ret);
}
}
@end
static PyObject*
cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
char *identifier = NULL, *title = NULL, *informativeText = NULL, *subtitle = NULL;
if (!PyArg_ParseTuple(args, "zsz|z", &identifier, &title, &informativeText, &subtitle)) return NULL;
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
if (!center) {PyErr_SetString(PyExc_RuntimeError, "Failed to get the user notification center"); return NULL; }
if (!center.delegate) center.delegate = [[NotificationDelegate alloc] init];
NSUserNotification *n = [NSUserNotification new];
#define SET(x) { \
if (x) { \
NSString *t = @(x); \
n.x = t; \
[t release]; \
}}
SET(title); SET(subtitle); SET(informativeText);
#undef SET
if (identifier) {
n.userInfo = @{@"user_id": @(identifier)};
}
[center deliverNotification:n];
Py_RETURN_NONE;
}
#else
@interface NotificationDelegate : NSObject <UNUserNotificationCenterDelegate>
@end
@ -213,14 +277,6 @@ drain_pending_notifications(BOOL granted) {
}
}
PyObject*
set_notification_activated_callback(PyObject *self UNUSED, PyObject *callback) {
if (notification_activated_callback) Py_DECREF(notification_activated_callback);
notification_activated_callback = callback;
Py_INCREF(callback);
Py_RETURN_NONE;
}
static PyObject*
cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
char *identifier = NULL, *title = NULL, *body = NULL, *subtitle = NULL;
@ -244,6 +300,8 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
Py_RETURN_NONE;
}
#endif
@interface ServiceProvider : NSObject
@end
@ -539,10 +597,14 @@ cleanup() {
if (dockMenu) [dockMenu release];
dockMenu = nil;
Py_CLEAR(notification_activated_callback);
#if !defined(KITTY_USE_DEPRECATED_MACOS_NOTIFICATION_API)
drain_pending_notifications(NO);
free(notification_queue.notifications);
notification_queue.notifications = NULL;
notification_queue.capacity = 0;
#endif
} // autoreleasepool
}

View File

@ -213,7 +213,8 @@ def get_sanitize_args(cc: str, ccver: Tuple[int, int]) -> List[str]:
def test_compile(cc: str, *cflags: str, src: Optional[str] = None) -> bool:
src = src or 'int main(void) { return 0; }'
p = subprocess.Popen([cc] + list(cflags) + ['-x', 'c', '-o', os.devnull, '-'], stdin=subprocess.PIPE)
p = subprocess.Popen([cc] + list(cflags) + ['-x', 'c', '-o', os.devnull, '-'],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.PIPE)
stdin = p.stdin
assert stdin is not None
try:
@ -336,8 +337,12 @@ def kitty_env() -> Env:
if is_macos:
platform_libs = [
'-framework', 'CoreText', '-framework', 'CoreGraphics',
'-framework', 'UserNotifications'
]
user_notifications_framework = first_successful_compile(ans.cc, '-framework UserNotifications')
if user_notifications_framework != '':
platform_libs.extend(shlex.split(user_notifications_framework))
else:
cppflags.append('-DKITTY_USE_DEPRECATED_MACOS_NOTIFICATION_API')
# Apple deprecated OpenGL in Mojave (10.14) silence the endless
# warnings about it
cppflags.append('-DGL_SILENCE_DEPRECATION')