Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 70 additions & 8 deletions kitty/cocoa_window.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -135,6 +137,68 @@ + (GlobalMenuTarget *) shared_instance

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

Expand Down Expand Up @@ -213,14 +277,6 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
}
}

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;
Expand All @@ -244,6 +300,8 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
Py_RETURN_NONE;
}

#endif

@interface ServiceProvider : NSObject
@end

Expand Down Expand Up @@ -539,10 +597,14 @@ - (void)openFilesFromPasteboard:(NSPasteboard *)pasteboard type:(int)type {
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
}

Expand Down
9 changes: 7 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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')
Expand Down