Update sound support in desktop notifications spec

Add a short list of standard sound names.
This commit is contained in:
Kovid Goyal
2024-08-04 20:19:39 +05:30
parent 40d1781404
commit 2c743dcdb2
7 changed files with 53 additions and 18 deletions

View File

@@ -13,6 +13,7 @@
#include <Carbon/Carbon.h>
#include <Cocoa/Cocoa.h>
#include <UserNotifications/UserNotifications.h>
#import <AudioToolbox/AudioServices.h>
#include <AvailabilityMacros.h>
// Needed for _NSGetProgname
@@ -1185,7 +1186,15 @@ bundle_image_as_png(PyObject *self UNUSED, PyObject *args, PyObject *kw) {@autor
return convert_image_to_png(icon, image_size, output_path);
}}
static PyObject*
play_system_sound_by_id_async(PyObject *self UNUSED, PyObject *which) {
if (!PyLong_Check(which)) { PyErr_SetString(PyExc_TypeError, "system sound id must be an integer"); return NULL; }
AudioServicesPlaySystemSound(PyLong_AsUnsignedLong(which));
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{"cocoa_play_system_sound_by_id_async", play_system_sound_by_id_async, METH_O, ""},
{"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 | METH_KEYWORDS, ""},

View File

@@ -204,6 +204,16 @@ standard_icon_names = {
'text-editor': ('utilities-text-editor', '📄'),
}
# See https://github.com/TUNER88/iOSSystemSoundsLibrary for Apple's system
# sound ids not all of which are available on macOS.
standard_sound_names = {
'error': ('dialog-error', 1),
'info': ('dialog-information', 2),
'warning': ('dialog-warning', 3),
'warn': ('dialog-warning', 3),
'question': ('dialog-question', 4),
}
def glfw_path(module: str) -> str:
prefix = 'kitty.' if getattr(sys, 'frozen', False) else ''

View File

@@ -1702,6 +1702,7 @@ def timed_debug_print(x: str) -> None: ...
def opengl_version_string() -> str: ...
def systemd_move_pid_into_new_scope(pid: int, scope_name: str, description: str) -> str: ...
def play_desktop_sound_async(name: str, event_id: str = 'test sound', is_path: bool = False, theme_name: str = '') -> str: ...
def cocoa_play_system_sound_by_id_async(sound_id: int) -> None: ...
class MousePosition(TypedDict):
cell_x: int

View File

@@ -12,7 +12,7 @@ from itertools import count
from typing import Any, Callable, NamedTuple, Optional, Set, Union
from weakref import ReferenceType, ref
from .constants import cache_dir, config_dir, is_macos, logo_png_file, standard_icon_names
from .constants import cache_dir, config_dir, is_macos, logo_png_file, standard_icon_names, standard_sound_names
from .fast_data_types import ESC_OSC, StreamingBase64Decoder, add_timer, base64_decode, current_focused_os_window_id, get_boss, get_options
from .types import run_once
from .typing import WindowType
@@ -486,7 +486,7 @@ class DesktopIntegration:
i = f'i={identifier or "0"}:'
p = ','.join(x.value for x in PayloadType if x.value and self.payload_type_supported(x))
c = ':c=1' if self.supports_close_events else ''
s = 'silent' + (f',{self.supports_sound_names}' if self.supports_sound_names else '')
s = 'system,silent,' + ','.join(sorted(standard_sound_names))
return f'99;{i}p=?;a={actions}:o={when}:u={urgency}:p={p}{c}:w=1:s={s}'
@@ -596,7 +596,7 @@ class MacOSIntegration(DesktopIntegration):
cocoa_send_notification(
nc.application_name or 'kitty', str(desktop_notification_id), nc.title, body,
category=category, categories=categories, image_path=image_path, urgency=nc.urgency.value,
muted=nc.sound_name == 'silent',
muted=nc.sound_name == 'silent' or nc.sound_name in standard_sound_names,
)
return desktop_notification_id
@@ -616,9 +616,12 @@ class MacOSIntegration(DesktopIntegration):
log_error(f'Got unexpected notification activated event with id: {ident!r} from cocoa')
return
if event == 'created':
self.notification_manager.notification_created(desktop_notification_id)
n = self.notification_manager.notification_created(desktop_notification_id)
from .fast_data_types import cocoa_live_delivered_notifications
cocoa_live_delivered_notifications() # so that we purge dead notifications
if n and n.sound_name in standard_sound_names:
from .fast_data_types import cocoa_play_system_sound_by_id_async
cocoa_play_system_sound_by_id_async(standard_sound_names[n.sound_name][1])
elif event == 'activated':
self.notification_manager.notification_activated(desktop_notification_id, 0)
elif event == 'creation_failed':
@@ -690,8 +693,9 @@ class FreeDesktopIntegration(DesktopIntegration):
# supports named sounds or not so we play the named sound
# ourselves and tell the server to mute any sound it might play.
if n.sound_name not in ('system', 'silent'):
sn = standard_sound_names[n.sound_name][0] if n.sound_name in standard_sound_names else n.sound_name
from .fast_data_types import play_desktop_sound_async
play_desktop_sound_async(n.sound_name, event_id='desktop notification')
play_desktop_sound_async(sn, event_id='desktop notification')
def dispatch_event_from_desktop(self, event_type: str, dbus_notification_id: int, extra: Union[int, str]) -> None:
if event_type == 'capabilities':