Framework for displaying simple OS notifications

This commit is contained in:
Kovid Goyal 2019-01-29 18:11:48 +05:30
parent c8dfe955d7
commit c2f6450af3
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 81 additions and 0 deletions

View File

@ -115,6 +115,58 @@ get_dock_menu(id self UNUSED, SEL _cmd UNUSED, NSApplication *sender UNUSED) {
return dockMenu;
}
@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);
}
@end
static PyObject*
cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
char *title = NULL, *subtitle = NULL, *message = NULL, *path_to_image = NULL;
if (!PyArg_ParseTuple(args, "ssz|z", &title, &message, &path_to_image, &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];
NSImage *img = nil;
if (path_to_image) {
NSString *p = [NSString stringWithUTF8String:path_to_image];
NSURL *url = [NSURL fileURLWithPath:p];
img = [[NSImage alloc] initWithContentsOfURL:url];
[url release]; [p release];
}
n.title = title ? [NSString stringWithUTF8String:title] : nil;
n.subtitle = subtitle ? [NSString stringWithUTF8String:subtitle] : nil;
n.informativeText = message ? [NSString stringWithUTF8String:message] : nil;
if (img) {
[n setValue:img forKey:@"_identityImage"];
[n setValue:@(false) forKey:@"_identityImageHasBorder"];
}
[center deliverNotification:n];
if (n.title) { [n.title release]; n.title = nil; }
if (n.subtitle) { [n.subtitle release]; n.subtitle = nil; }
if (n.informativeText) { [n.informativeText release]; n.informativeText = nil; }
if (img) [img release];
[n release];
Py_RETURN_NONE;
}
void
cocoa_create_global_menu(void) {
NSString* app_name = find_app_name();
@ -323,6 +375,7 @@ cleanup() {
static PyMethodDef module_methods[] = {
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
{"cocoa_set_new_window_trigger", (PyCFunction)cocoa_set_new_window_trigger, METH_VARARGS, ""},
{"cocoa_send_notification", (PyCFunction)cocoa_send_notification, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};

View File

@ -116,6 +116,7 @@ def wakeup():
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
terminfo_dir = os.path.join(base_dir, 'terminfo')
logo_data_file = os.path.join(base_dir, 'logo', 'kitty.rgba')
logo_png_file = os.path.join(base_dir, 'logo', 'kitty.png')
beam_cursor_data_file = os.path.join(base_dir, 'logo', 'beam-cursor.png')
try:
shell_path = pwd.getpwuid(os.geteuid()).pw_shell or '/bin/sh'

26
kitty/notify.py Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
import subprocess
from .constants import is_macos, logo_png_file
if is_macos:
from .fast_data_types import cocoa_send_notification
def notify(title, body, timeout=5000, application='kitty', icon=True):
if icon is True:
icon = None
cocoa_send_notification(title, body, icon)
else:
def notify(title, body, timeout=5000, application='kitty', icon=True):
cmd = ['notify-send', '-t', str(timeout), '-a', application]
if icon is True:
icon = logo_png_file
if icon:
cmd.extend(['-i', icon])
subprocess.Popen(
cmd + [title, body], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL)

View File

@ -636,6 +636,7 @@ def package(args, for_bundle=False, sh_launcher=False):
raise SystemExit('tic failed to output the compiled kitty terminfo file')
shutil.copy2('__main__.py', libdir)
shutil.copy2('logo/kitty.rgba', os.path.join(libdir, 'logo'))
shutil.copy2('logo/kitty.png', os.path.join(libdir, 'logo'))
shutil.copy2('logo/beam-cursor.png', os.path.join(libdir, 'logo'))
shutil.copy2('logo/beam-cursor@2x.png', os.path.join(libdir, 'logo'))