diff --git a/kitty/data-types.h b/kitty/data-types.h index d25dfbe5f..17965181c 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -386,7 +386,7 @@ void scroll_event(double, double, int, int); void on_key_input(GLFWkeyevent *ev); void request_window_attention(id_type, bool); #ifndef __APPLE__ -void play_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *role); +void play_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *role, const char *theme_name); #endif SPRITE_MAP_HANDLE alloc_sprite_map(unsigned int, unsigned int); SPRITE_MAP_HANDLE free_sprite_map(SPRITE_MAP_HANDLE); diff --git a/kitty/desktop.c b/kitty/desktop.c index 1e961378d..6ea89ab3b 100644 --- a/kitty/desktop.c +++ b/kitty/desktop.c @@ -148,7 +148,7 @@ load_libcanberra(void) { } typedef struct { - char *which_sound, *event_id, *media_role; + char *which_sound, *event_id, *media_role, *theme_name; bool is_path; } CanberraEvent; @@ -179,6 +179,7 @@ play_current_sound(void) { "event.description", e.event_id, "media.role", e.media_role, "canberra.cache-control", "permanent", + "canberra.xdg-theme.name", e.theme_name, NULL ); free_canberra_event_fields(&e); @@ -186,12 +187,13 @@ play_current_sound(void) { } static void -queue_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *media_role) { +queue_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *media_role, const char *theme_name) { pthread_mutex_lock(&canberra_lock); current_sound.which_sound = strdup(which_sound); current_sound.event_id = strdup(event_id); current_sound.media_role = strdup(media_role); current_sound.is_path = is_path; + current_sound.theme_name = strdup(theme_name); pthread_mutex_unlock(&canberra_lock); while (true) { ssize_t ret = write(canberra_pipe_w, "w", 1); @@ -222,7 +224,7 @@ canberra_play_loop(void *x UNUSED) { } void -play_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *media_role) { +play_canberra_sound(const char *which_sound, const char *event_id, bool is_path, const char *media_role, const char *theme_name) { load_libcanberra(); if (libcanberra_handle == NULL || canberra_ctx == NULL) return; int ret; @@ -235,15 +237,16 @@ play_canberra_sound(const char *which_sound, const char *event_id, bool is_path, fcntl(canberra_pipe_w, F_SETFL, flags | O_NONBLOCK); if ((ret = pthread_create(&canberra_thread, NULL, canberra_play_loop, NULL)) != 0) return; } - queue_canberra_sound(which_sound, event_id, is_path, media_role); + queue_canberra_sound(which_sound, event_id, is_path, media_role, theme_name); } static PyObject* play_desktop_sound(PyObject *self UNUSED, PyObject *args) { const char *which, *event_id = "test sound"; + const char *theme_name = "freedesktop"; int is_path = 0; - if (!PyArg_ParseTuple(args, "s|sp", &which, &event_id, &is_path)) return NULL; - play_canberra_sound(which, event_id, is_path, "event"); + if (!PyArg_ParseTuple(args, "s|sp", &which, &event_id, &is_path, &theme_name)) return NULL; + play_canberra_sound(which, event_id, is_path, "event", theme_name); Py_RETURN_NONE; } diff --git a/kitty/glfw.c b/kitty/glfw.c index 551fb95a3..3be19d0c8 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1387,8 +1387,8 @@ ring_audio_bell(void) { #ifdef __APPLE__ cocoa_system_beep(OPT(bell_path)); #else - if (OPT(bell_path)) play_canberra_sound(OPT(bell_path), "kitty bell", true, "event"); - else play_canberra_sound("bell", "kitty bell", false, "event"); + if (OPT(bell_path)) play_canberra_sound(OPT(bell_path), "kitty bell", true, "event", OPT(linux_bell_theme_name)); + else play_canberra_sound("bell", "kitty bell", false, "event", OPT(linux_bell_theme_name)); #endif } diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 6b0db14ab..fc91cc8dd 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -858,6 +858,12 @@ MP3 or WAV on macOS (NSSound) ''' ) +opt('linux_bell_theme_name', '__custom', + long_text='If audio bell is enabled on Linux, sets the XDG Sound Theme kitty will use to play the bell sound.' + ' Defaults to the custom theme name used by GNOME and Budgie, falling back to the default freedesktop theme if it does not exist.' + ' This option may be removed if Linux ever provides desktop-agnostic support for setting system sound themes.' + ) + egr() # }}} diff --git a/kitty/options/parse.py b/kitty/options/parse.py index 65e95aa39..71f7bf8a4 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1024,6 +1024,9 @@ class Parser: def kitty_mod(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['kitty_mod'] = to_modifiers(val) + def linux_bell_theme_name(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: + ans['linux_bell_theme_name'] = str(val) + def linux_display_server(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: val = val.lower() if val not in self.choices_for_linux_display_server: diff --git a/kitty/options/types.py b/kitty/options/types.py index 65c4c5286..958a2a345 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -376,6 +376,7 @@ option_names = ( # {{{ 'italic_font', 'kitten_alias', 'kitty_mod', + 'linux_bell_theme_name', 'linux_display_server', 'listen_on', 'macos_colorspace', @@ -534,6 +535,7 @@ class Options: input_delay: int = 3 italic_font: str = 'auto' kitty_mod: int = 5 + linux_bell_theme_name: str = '__custom' linux_display_server: choices_for_linux_display_server = 'auto' listen_on: str = 'none' macos_colorspace: choices_for_macos_colorspace = 'srgb' diff --git a/kitty/state.h b/kitty/state.h index dc693ca2d..875f29cd4 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -29,6 +29,7 @@ typedef struct { double wheel_scroll_multiplier, touch_scroll_multiplier; int wheel_scroll_min_lines; bool enable_audio_bell; + const char *linux_bell_theme_name; CursorShape cursor_shape; float cursor_beam_thickness; float cursor_underline_thickness;