diff --git a/meson.build b/meson.build
index aebefe68f..a1cbc921d 100644
--- a/meson.build
+++ b/meson.build
@@ -38,7 +38,7 @@ gudev_req = '>= 232'
# wayland version requirements
wayland_server_req = '>= 1.20'
-wayland_protocols_req = '>= 1.36'
+wayland_protocols_req = '>= 1.38'
# native backend version requirements
libinput_req = '>= 1.19.0'
diff --git a/src/meson.build b/src/meson.build
index fa0e5c043..d0ff2bf75 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -559,6 +559,8 @@ if have_wayland
'wayland/meta-wayland-surface.c',
'wayland/meta-wayland-surface.h',
'wayland/meta-wayland-tablet.c',
+ 'wayland/meta-wayland-system-bell.c',
+ 'wayland/meta-wayland-system-bell.h',
'wayland/meta-wayland-tablet-cursor-surface.c',
'wayland/meta-wayland-tablet-cursor-surface.h',
'wayland/meta-wayland-tablet.h',
@@ -812,6 +814,7 @@ if have_wayland
['pointer-gestures', 'unstable', 'v1', ],
['primary-selection', 'unstable', 'v1', ],
['relative-pointer', 'unstable', 'v1', ],
+ ['xdg-system-bell', 'staging', 'v1', ],
['tablet', 'unstable', 'v2', ],
['text-input', 'unstable', 'v3', ],
['viewporter', 'stable', ],
diff --git a/src/wayland/meta-wayland-system-bell.c b/src/wayland/meta-wayland-system-bell.c
new file mode 100644
index 000000000..95ec7c219
--- /dev/null
+++ b/src/wayland/meta-wayland-system-bell.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ *
+ */
+
+#include "compositor/compositor-private.h"
+#include "config.h"
+
+#include "wayland/meta-wayland-system-bell.h"
+
+#include "core/bell.h"
+#include "wayland/meta-wayland-private.h"
+#include "wayland/meta-wayland-surface.h"
+#include "wayland/meta-wayland-versions.h"
+#include "wayland/meta-wayland.h"
+
+#include "xdg-system-bell-v1-server-protocol.h"
+
+static void
+system_bell_destroy (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy (resource);
+}
+
+static MetaWindow *
+find_window_from_resource (struct wl_resource *surface_resource)
+{
+ MetaWaylandSurface *surface;
+
+ surface = wl_resource_get_user_data (surface_resource);
+ if (!surface)
+ return NULL;
+
+ return meta_wayland_surface_get_window (surface);
+}
+
+static void
+system_bell_ring (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource)
+{
+ MetaDisplay *display = meta_get_display ();
+
+ if (surface_resource)
+ meta_bell_notify (display, find_window_from_resource (surface_resource));
+ else
+ meta_bell_notify (display, NULL);
+}
+
+static const struct xdg_system_bell_v1_interface system_bell_implementation =
+{
+ system_bell_destroy,
+ system_bell_ring,
+};
+
+static void
+system_bell_bind (struct wl_client *client,
+ void *user_data,
+ uint32_t version,
+ uint32_t id)
+{
+ MetaWaylandCompositor *compositor = user_data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create (client,
+ &xdg_system_bell_v1_interface,
+ version, id);
+ wl_resource_set_implementation (resource,
+ &system_bell_implementation,
+ compositor, NULL);
+}
+
+void
+meta_wayland_init_system_bell (MetaWaylandCompositor *compositor)
+{
+ if (wl_global_create (compositor->wayland_display,
+ &xdg_system_bell_v1_interface,
+ META_WP_SYSTEM_BELL_V1_VERSION,
+ compositor,
+ system_bell_bind) == NULL)
+ g_error ("Failed to create xdg_system_bell_v1 global");
+}
diff --git a/src/wayland/meta-wayland-system-bell.h b/src/wayland/meta-wayland-system-bell.h
new file mode 100644
index 000000000..5c2949a7c
--- /dev/null
+++ b/src/wayland/meta-wayland-system-bell.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ *
+ */
+
+#pragma once
+
+#include "wayland/meta-wayland-types.h"
+
+void meta_wayland_init_system_bell (MetaWaylandCompositor *compositor);
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 3673369a5..eae07de2d 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -59,5 +59,6 @@
#define META_XDG_DIALOG_VERSION 1
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
#define META_XDG_TOPLEVEL_TAG_V1_VERSION 1
+#define META_WP_SYSTEM_BELL_V1_VERSION 1
#endif
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index f2fc5959d..d1fa99641 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -45,6 +45,7 @@
#include "wayland/meta-wayland-region.h"
#include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-subsurface.h"
+#include "wayland/meta-wayland-system-bell.h"
#include "wayland/meta-wayland-tablet-manager.h"
#include "wayland/meta-wayland-xdg-dialog.h"
#include "wayland/meta-wayland-xdg-foreign.h"
@@ -447,6 +448,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_idle_inhibit_init (compositor);
meta_wayland_init_xdg_wm_dialog (compositor);
meta_wayland_xdg_toplevel_tag_init (compositor);
+ meta_wayland_init_system_bell (compositor);
/* Xwayland specific protocol, needs to be filtered out for all other clients */
if (meta_xwayland_grab_keyboard_init (compositor))