mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 16:37:27 +00:00
Wayland: When the compositor supports the xdg-system-bell protocol use it to play the default bell sound
This commit is contained in:
parent
4f6d97c143
commit
5d2e258c35
13 changed files with 48 additions and 13 deletions
|
|
@ -103,6 +103,10 @@ Detailed list of changes
|
|||
|
||||
- Fix a regression that caused automatic color themes to not be re-applied after config file reload (:iss:`8530`)
|
||||
|
||||
- Wayland: When the compositor supports the `xdg-system-bell
|
||||
<https://wayland.app/protocols/xdg-system-bell-v1>`__ protocol use it to play
|
||||
the default bell sound
|
||||
|
||||
0.41.1 [2025-04-03]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -324,6 +324,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
||||
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
|
||||
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
|
||||
bool glfwWaylandBeep(GLFWwindow *handle)
|
||||
void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c)
|
||||
pid_t glfwWaylandCompositorPID(void)
|
||||
unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@
|
|||
"staging/single-pixel-buffer/single-pixel-buffer-v1.xml",
|
||||
"unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
"staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml",
|
||||
"staging/xdg-system-bell/xdg-system-bell-v1.xml",
|
||||
|
||||
"kwin-blur-v1.xml",
|
||||
"wlr-layer-shell-unstable-v1.xml"
|
||||
|
|
|
|||
7
glfw/wl_init.c
vendored
7
glfw/wl_init.c
vendored
|
|
@ -603,6 +603,9 @@ static void registryHandleGlobal(void* data UNUSED,
|
|||
else if (is(xdg_toplevel_icon_manager_v1)) {
|
||||
_glfw.wl.xdg_toplevel_icon_manager_v1 = wl_registry_bind(registry, name, &xdg_toplevel_icon_manager_v1_interface, 1);
|
||||
}
|
||||
else if (is(xdg_system_bell_v1)) {
|
||||
_glfw.wl.xdg_system_bell_v1 = wl_registry_bind(registry, name, &xdg_system_bell_v1_interface, 1);
|
||||
}
|
||||
#undef is
|
||||
}
|
||||
|
||||
|
|
@ -712,7 +715,7 @@ get_compositor_missing_capabilities(void) {
|
|||
C(blur, org_kde_kwin_blur_manager); C(server_side_decorations, decorationManager);
|
||||
C(cursor_shape, wp_cursor_shape_manager_v1); C(layer_shell, zwlr_layer_shell_v1);
|
||||
C(single_pixel_buffer, wp_single_pixel_buffer_manager_v1); C(preferred_scale, has_preferred_buffer_scale);
|
||||
C(idle_inhibit, idle_inhibit_manager); C(icon, xdg_toplevel_icon_manager_v1);
|
||||
C(idle_inhibit, idle_inhibit_manager); C(icon, xdg_toplevel_icon_manager_v1); C(bell, xdg_system_bell_v1);
|
||||
if (_glfw.wl.xdg_wm_base_version < 6) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-state-suspended");
|
||||
if (_glfw.wl.xdg_wm_base_version < 5) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-capabilities");
|
||||
#undef C
|
||||
|
|
@ -889,6 +892,8 @@ void _glfwPlatformTerminate(void)
|
|||
xdg_activation_v1_destroy(_glfw.wl.xdg_activation_v1);
|
||||
if (_glfw.wl.xdg_toplevel_icon_manager_v1)
|
||||
xdg_toplevel_icon_manager_v1_destroy(_glfw.wl.xdg_toplevel_icon_manager_v1);
|
||||
if (_glfw.wl.xdg_system_bell_v1)
|
||||
xdg_system_bell_v1_destroy(_glfw.wl.xdg_system_bell_v1);
|
||||
if (_glfw.wl.wp_single_pixel_buffer_manager_v1)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(_glfw.wl.wp_single_pixel_buffer_manager_v1);
|
||||
if (_glfw.wl.wp_cursor_shape_manager_v1)
|
||||
|
|
|
|||
2
glfw/wl_platform.h
vendored
2
glfw/wl_platform.h
vendored
|
|
@ -67,6 +67,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||
#include "wayland-single-pixel-buffer-v1-client-protocol.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-xdg-toplevel-icon-v1-client-protocol.h"
|
||||
#include "wayland-xdg-system-bell-v1-client-protocol.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
|
|
@ -338,6 +339,7 @@ typedef struct _GLFWlibraryWayland
|
|||
struct zwp_primary_selection_source_v1* dataSourceForPrimarySelection;
|
||||
struct xdg_activation_v1* xdg_activation_v1;
|
||||
struct xdg_toplevel_icon_manager_v1* xdg_toplevel_icon_manager_v1;
|
||||
struct xdg_system_bell_v1* xdg_system_bell_v1;
|
||||
struct wp_cursor_shape_manager_v1* wp_cursor_shape_manager_v1;
|
||||
struct wp_cursor_shape_device_v1* wp_cursor_shape_device_v1;
|
||||
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1;
|
||||
|
|
|
|||
8
glfw/wl_window.c
vendored
8
glfw/wl_window.c
vendored
|
|
@ -2835,3 +2835,11 @@ _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) {
|
|||
window = window->next;
|
||||
}
|
||||
}
|
||||
|
||||
GLFWAPI bool glfwWaylandBeep(GLFWwindow *handle) {
|
||||
if (!_glfw.wl.xdg_system_bell_v1) return false;
|
||||
_GLFWwindow *window = (_GLFWwindow*)handle;
|
||||
xdg_system_bell_v1_ring(_glfw.wl.xdg_system_bell_v1, window ? window->wl.surface : NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1501,7 +1501,7 @@ class Boss:
|
|||
else:
|
||||
self.visual_window_select_action_trigger(self.current_visual_select.window_ids[0] if self.current_visual_select.window_ids else 0)
|
||||
if get_options().enable_audio_bell:
|
||||
ring_bell()
|
||||
ring_bell(tab.os_window_id)
|
||||
|
||||
def visual_window_select_action_trigger(self, window_id: int = 0) -> None:
|
||||
if self.current_visual_select:
|
||||
|
|
@ -1545,7 +1545,7 @@ class Boss:
|
|||
if len(selectable_windows) < 2:
|
||||
self.visual_window_select_action_trigger(selectable_windows[0][0] if selectable_windows else 0)
|
||||
if get_options().enable_audio_bell:
|
||||
ring_bell()
|
||||
ring_bell(tab.os_window_id)
|
||||
return None
|
||||
cvs = self.current_visual_select
|
||||
|
||||
|
|
|
|||
|
|
@ -1012,7 +1012,7 @@ def set_active_window(os_window_id: int, tab_id: int, window_id: int) -> None:
|
|||
pass
|
||||
|
||||
|
||||
def ring_bell() -> None:
|
||||
def ring_bell(os_window_id: int = 0) -> None:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
|||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
|
|
@ -488,6 +488,9 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwWaylandIsWindowFullyCreated_impl) = dlsym(handle, "glfwWaylandIsWindowFullyCreated");
|
||||
if (glfwWaylandIsWindowFullyCreated_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandBeep_impl) = dlsym(handle, "glfwWaylandBeep");
|
||||
if (glfwWaylandBeep_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandSetupLayerShellForNextWindow_impl) = dlsym(handle, "glfwWaylandSetupLayerShellForNextWindow");
|
||||
if (glfwWaylandSetupLayerShellForNextWindow_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
|
|
|||
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
|
|
@ -2344,6 +2344,10 @@ typedef bool (*glfwWaylandIsWindowFullyCreated_func)(GLFWwindow*);
|
|||
GFW_EXTERN glfwWaylandIsWindowFullyCreated_func glfwWaylandIsWindowFullyCreated_impl;
|
||||
#define glfwWaylandIsWindowFullyCreated glfwWaylandIsWindowFullyCreated_impl
|
||||
|
||||
typedef bool (*glfwWaylandBeep_func)(GLFWwindow*);
|
||||
GFW_EXTERN glfwWaylandBeep_func glfwWaylandBeep_impl;
|
||||
#define glfwWaylandBeep glfwWaylandBeep_impl
|
||||
|
||||
typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(const GLFWLayerShellConfig*);
|
||||
GFW_EXTERN glfwWaylandSetupLayerShellForNextWindow_func glfwWaylandSetupLayerShellForNextWindow_impl;
|
||||
#define glfwWaylandSetupLayerShellForNextWindow glfwWaylandSetupLayerShellForNextWindow_impl
|
||||
|
|
|
|||
18
kitty/glfw.c
18
kitty/glfw.c
|
|
@ -1814,7 +1814,7 @@ cocoa_hide_other_apps(PYNOARG) {
|
|||
}
|
||||
|
||||
static void
|
||||
ring_audio_bell(void) {
|
||||
ring_audio_bell(OSWindow *w) {
|
||||
static monotonic_t last_bell_at = -1;
|
||||
monotonic_t now = monotonic();
|
||||
if (last_bell_at >= 0 && now - last_bell_at <= ms_to_monotonic_t(100ll)) return;
|
||||
|
|
@ -1823,13 +1823,19 @@ ring_audio_bell(void) {
|
|||
cocoa_system_beep(OPT(bell_path));
|
||||
#else
|
||||
if (OPT(bell_path)) play_canberra_sound(OPT(bell_path), "kitty bell", true, "event", OPT(bell_theme));
|
||||
else play_canberra_sound("bell", "kitty bell", false, "event", OPT(bell_theme));
|
||||
else {
|
||||
if (!global_state.is_wayland || !glfwWaylandBeep(w ? w->handle : NULL)) play_canberra_sound(
|
||||
"bell", "kitty bell", false, "event", OPT(bell_theme));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
ring_bell(PYNOARG) {
|
||||
ring_audio_bell();
|
||||
ring_bell(PyObject *self UNUSED, PyObject *args) {
|
||||
unsigned long long os_window_id = 0;
|
||||
if (!PyArg_ParseTuple(args, "|K", &os_window_id)) return NULL;
|
||||
OSWindow *w = os_window_for_id(os_window_id);
|
||||
ring_audio_bell(w);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1918,7 +1924,7 @@ void
|
|||
request_window_attention(id_type kitty_window_id, bool audio_bell) {
|
||||
OSWindow *w = os_window_for_kitty_window(kitty_window_id);
|
||||
if (w) {
|
||||
if (audio_bell) ring_audio_bell();
|
||||
if (audio_bell) ring_audio_bell(w);
|
||||
if (OPT(window_alert_on_bell)) glfwRequestWindowAttention(w->handle);
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
|
@ -2408,7 +2414,7 @@ static PyMethodDef module_methods[] = {
|
|||
METHODB(get_clipboard_mime, METH_VARARGS),
|
||||
METHODB(toggle_secure_input, METH_NOARGS),
|
||||
METHODB(get_content_scale_for_window, METH_NOARGS),
|
||||
METHODB(ring_bell, METH_NOARGS),
|
||||
METHODB(ring_bell, METH_VARARGS),
|
||||
METHODB(toggle_fullscreen, METH_VARARGS),
|
||||
METHODB(toggle_maximized, METH_VARARGS),
|
||||
METHODB(change_os_window_state, METH_VARARGS),
|
||||
|
|
|
|||
|
|
@ -1039,7 +1039,8 @@ MP3 or WAV on macOS (NSSound).
|
|||
opt('linux_bell_theme', '__custom', ctype='!bell_theme',
|
||||
long_text='''
|
||||
The XDG Sound Theme kitty will use to play the bell sound.
|
||||
Defaults to the custom theme name specified in the
|
||||
On Wayland, when the compositor supports it, it is asked to play the system default
|
||||
bell sound. Otherwise, defaults to the custom theme name specified in the
|
||||
:link:`XDG Sound theme specification <https://specifications.freedesktop.org/sound-theme-spec/latest/sound_lookup.html>,
|
||||
falling back to the default freedesktop theme if it does not exist.
|
||||
To change your sound theme desktop wide, create :file:`~/.local/share/sounds/__custom/index.theme` with the contents:
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ class Tab: # {{{
|
|||
if w is not None and self.resize_window_by(
|
||||
w.id, increment, is_horizontal) is not None:
|
||||
if get_options().enable_audio_bell:
|
||||
ring_bell()
|
||||
ring_bell(self.os_window_id)
|
||||
|
||||
@ac('win', 'Reset window sizes undoing any dynamic resizing of windows')
|
||||
def reset_window_sizes(self) -> None:
|
||||
|
|
@ -463,7 +463,7 @@ class Tab: # {{{
|
|||
ret = self.current_layout.layout_action(action_name, args, self.windows)
|
||||
if ret is None:
|
||||
if get_options().enable_audio_bell:
|
||||
ring_bell()
|
||||
ring_bell(self.os_window_id)
|
||||
return
|
||||
self.relayout()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue