On Mon, 14 Jul 2025 at 14:16:57 +0100, Simon McVittie wrote:
[x] attach debdiff against the package in testing
Now really attached. smcv
diffstat for mutter-48.3.1 mutter-48.4 NEWS | 18 ++++++++ cogl/cogl/cogl-pipeline.c | 7 ++- debian/changelog | 62 ++++++++++++++++++++++++++++ debian/control | 2 debian/gbp.conf | 4 - debian/watch | 2 doc/reference/clutter/clutter.toml.in | 4 - doc/reference/cogl/cogl.toml.in | 4 - doc/reference/meta/meta.toml.in | 4 - doc/reference/mtk/mtk.toml.in | 4 - doc/website/index.html | 1 meson.build | 2 src/backends/native/meta-gpu-kms.c | 2 src/backends/native/meta-kms-impl-device.c | 10 ++++ src/backends/native/meta-kms.c | 2 src/backends/native/meta-onscreen-native.c | 2 src/backends/native/meta-output-kms.c | 11 ++++ src/backends/native/meta-output-kms.h | 2 src/backends/native/meta-seat-impl.c | 4 - src/compositor/compositor-private.h | 6 +- src/compositor/compositor.c | 10 ++-- src/core/bell.c | 64 ++++++++++++++++++++++++----- src/core/display-private.h | 7 +-- src/core/meta-context-main.c | 2 src/core/window.c | 7 +++ src/tests/test-runner.c | 2 src/wayland/meta-wayland-data-device.c | 59 ++++---------------------- src/wayland/meta-wayland-data-source.c | 59 ++++++++++++++++++++++++++ src/wayland/meta-wayland-data-source.h | 3 + src/wayland/meta-wayland-seat.c | 4 - src/x11/meta-x11-display.c | 8 +++ 31 files changed, 286 insertions(+), 92 deletions(-) diff -Nru mutter-48.3.1/cogl/cogl/cogl-pipeline.c mutter-48.4/cogl/cogl/cogl-pipeline.c --- mutter-48.3.1/cogl/cogl/cogl-pipeline.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/cogl/cogl/cogl-pipeline.c 2025-06-29 11:00:20.000000000 +0100 @@ -121,11 +121,14 @@ { for (CoglPipeline *child = pipeline->first_child; - child != NULL; - child = child->next_sibling) + child != NULL;) { + CoglPipeline *next = child->next_sibling; + if (!callback (child, user_data)) break; + + child = next; } } diff -Nru mutter-48.3.1/debian/changelog mutter-48.4/debian/changelog --- mutter-48.3.1/debian/changelog 2025-06-14 10:07:10.000000000 +0100 +++ mutter-48.4/debian/changelog 2025-07-13 12:27:01.000000000 +0100 @@ -1,3 +1,65 @@ +mutter (48.4-2) unstable; urgency=medium + + * Team upload + * d/gbp.conf, d/control: Switch packaging branch for trixie + * Expand previous changelog entry to document all upstream changes + * Upload to unstable + + -- Simon McVittie <s...@debian.org> Sun, 13 Jul 2025 12:27:01 +0100 + +mutter (48.4-1) experimental; urgency=medium + + [ Jeremy Bícha ] + * New upstream bugfix release + - Unlink outputs from unused connectors in update_outputs, avoiding a + use-after-free when a monitor is disconnected + (mutter!4474 upstream) + - Fix a crash caused by a use-after-free when clearing many + accumulated notifications + (mutter#3970 upstream, LP: #2102063) + - Fix a non-reproducible crash caused by a use-after-free when dragging + an epiphany-browser tab to create a new window + (mutter#4157 upstream) + - Fix the logic for when to disable the --no-x11 option + (mutter!4485 upstream, not relevant to how we configure it in Debian) + - Rate-limit visual alerts to 2 per second, to comply with the European + Accessibility Act and avoid potentially triggering photosensitive + seizures + (mutter!4487 upstream) + - Fix a rare crash with a NULL pointer dereference + (mutter#4147 upstream, LP: #2100243) + - Avoid reopening an inactive Nvidia GPU when not needed + (mutter#3550 upstream) + - Fix a NULL dereference in the tests + (mutter!4495 upstream) + - Fix stacking order for windows that get activated before mapped + (mutter!4462 upstream) + - Fix incorrect cursor over Xwayland clients + (mutter#4033 upstream, LP: #2111502) + - Improve Wayland spec compliance by sending Wayland seat name before + its capabilities + (mutter#4119 upstream) + - Improve X11 compatibility (especially in Wine) by moving the X11 focus + to a shared dummy window when the Wayland focus is really on any + non-X11 window + (mutter!4447 upstream) + - Wait longer for hotplugged monitors to detect their input sources, + improving compatibility with e.g. MSI PRO MP275Q + (mutter!4442 upstream) + - Make sure the cursor is updated after modesetting, even if there is no + application window to redraw + (mutter!4452 upstream) + - Fix high resolution scroll events getting converted to discrete events + that intermittently switch direction + (mutter#4128 upstream) + - Documentation updates + + [ Simon McVittie ] + * d/gbp.conf: Use upstream/48.x branch for trixie + * d/watch: Only watch for 48.x releases + + -- Jeremy Bícha <jbi...@ubuntu.com> Thu, 03 Jul 2025 08:48:17 -0400 + mutter (48.3.1-2) unstable; urgency=medium * Team upload diff -Nru mutter-48.3.1/debian/control mutter-48.4/debian/control --- mutter-48.3.1/debian/control 2025-06-14 10:07:10.000000000 +0100 +++ mutter-48.4/debian/control 2025-07-13 12:27:01.000000000 +0100 @@ -102,7 +102,7 @@ Rules-Requires-Root: no Standards-Version: 4.7.0 Homepage: https://mutter.gnome.org/ -Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git +Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b debian/trixie Vcs-Browser: https://salsa.debian.org/gnome-team/mutter Package: mutter diff -Nru mutter-48.3.1/debian/gbp.conf mutter-48.4/debian/gbp.conf --- mutter-48.3.1/debian/gbp.conf 2025-06-14 10:07:10.000000000 +0100 +++ mutter-48.4/debian/gbp.conf 2025-07-13 12:27:01.000000000 +0100 @@ -1,7 +1,7 @@ [DEFAULT] pristine-tar = True -debian-branch = debian/latest -upstream-branch = upstream/latest +debian-branch = debian/trixie +upstream-branch = upstream/48.x [buildpackage] sign-tags = True diff -Nru mutter-48.3.1/debian/watch mutter-48.4/debian/watch --- mutter-48.3.1/debian/watch 2025-06-14 10:07:10.000000000 +0100 +++ mutter-48.4/debian/watch 2025-07-13 12:27:01.000000000 +0100 @@ -1,4 +1,4 @@ version=4 opts="searchmode=plain, uversionmangle=s/\.(alpha|beta|rc)/~$1/, downloadurlmangle=s|cache.json||" \ https://download.gnome.org/sources/@PACKAGE@/cache.json \ - [\d.]+/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ + 48/@PACKAGE@-([\d.]+)@ARCHIVE_EXT@ diff -Nru mutter-48.3.1/doc/reference/clutter/clutter.toml.in mutter-48.4/doc/reference/clutter/clutter.toml.in --- mutter-48.3.1/doc/reference/clutter/clutter.toml.in 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/doc/reference/clutter/clutter.toml.in 2025-06-29 11:00:20.000000000 +0100 @@ -2,8 +2,8 @@ version = "@version@" browse_url = "https://gitlab.gnome.org/GNOME/mutter/" repository_url = "https://gitlab.gnome.org/GNOME/mutter.git" -website_url = "https://blogs.gnome.org/shell-dev/" -docs_url = "https://mutter.gnome.org/" +website_url = "https://mutter.gnome.org" +docs_url = "https://mutter.gnome.org/clutter" logo_url = "logo.svg" authors = "Mutter Development Team" license = "GPL-2.0-or-later" diff -Nru mutter-48.3.1/doc/reference/cogl/cogl.toml.in mutter-48.4/doc/reference/cogl/cogl.toml.in --- mutter-48.3.1/doc/reference/cogl/cogl.toml.in 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/doc/reference/cogl/cogl.toml.in 2025-06-29 11:00:20.000000000 +0100 @@ -2,8 +2,8 @@ version = "@version@" browse_url = "https://gitlab.gnome.org/GNOME/mutter/" repository_url = "https://gitlab.gnome.org/GNOME/mutter.git" -website_url = "https://blogs.gnome.org/shell-dev/" -docs_url = "https://mutter.gnome.org/" +website_url = "https://mutter.gnome.org" +docs_url = "https://mutter.gnome.org/cogl" logo_url = "logo.svg" authors = "Mutter Development Team" license = "GPL-2.0-or-later" diff -Nru mutter-48.3.1/doc/reference/meta/meta.toml.in mutter-48.4/doc/reference/meta/meta.toml.in --- mutter-48.3.1/doc/reference/meta/meta.toml.in 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/doc/reference/meta/meta.toml.in 2025-06-29 11:00:20.000000000 +0100 @@ -2,8 +2,8 @@ version = "@version@" browse_url = "https://gitlab.gnome.org/GNOME/mutter/" repository_url = "https://gitlab.gnome.org/GNOME/mutter.git" -website_url = "https://blogs.gnome.org/shell-dev/" -docs_url = "https://mutter.gnome.org/" +website_url = "https://mutter.gnome.org" +docs_url = "https://mutter.gnome.org/meta" logo_url = "logo.svg" authors = "Mutter Development Team" license = "GPL-2.0-or-later" diff -Nru mutter-48.3.1/doc/reference/mtk/mtk.toml.in mutter-48.4/doc/reference/mtk/mtk.toml.in --- mutter-48.3.1/doc/reference/mtk/mtk.toml.in 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/doc/reference/mtk/mtk.toml.in 2025-06-29 11:00:20.000000000 +0100 @@ -2,8 +2,8 @@ version = "@version@" browse_url = "https://gitlab.gnome.org/GNOME/mutter/" repository_url = "https://gitlab.gnome.org/GNOME/mutter.git" -website_url = "https://blogs.gnome.org/shell-dev/" -docs_url = "https://mutter.gnome.org/" +website_url = "https://mutter.gnome.org" +docs_url = "https://mutter.gnome.org/mtk" logo_url = "logo.svg" authors = "Mutter Development Team" license = "GPL-2.0-or-later" diff -Nru mutter-48.3.1/doc/website/index.html mutter-48.4/doc/website/index.html --- mutter-48.3.1/doc/website/index.html 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/doc/website/index.html 2025-06-29 11:00:20.000000000 +0100 @@ -126,6 +126,7 @@ <li><a href="https://gitlab.gnome.org/GNOME/mutter/-/jobs/artifacts/main/file/coveragereport/index.html?job=coverage">Code Coverage Report</a></li> + <li><a href="https://blogs.gnome.org/shell-dev/">Development blog</a></li> </ul> </div> diff -Nru mutter-48.3.1/meson.build mutter-48.4/meson.build --- mutter-48.3.1/meson.build 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/meson.build 2025-06-29 11:00:20.000000000 +0100 @@ -1,5 +1,5 @@ project('mutter', 'c', - version: '48.3.1', + version: '48.4', meson_version: '>= 1.3.0', license: 'GPL-2.0-or-later', ) diff -Nru mutter-48.3.1/NEWS mutter-48.4/NEWS --- mutter-48.3.1/NEWS 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/NEWS 2025-06-29 11:00:20.000000000 +0100 @@ -1,3 +1,21 @@ +48.4 +==== +* Unlink outputs from unused connectors in update_outputs [Michel; !4474] +* Add speed limit to Visual alerts [Sergio; !4487] +* Fix behavior of windows that get activated before mapped [Alessandro; !4462] +* Fix incorrect cursor over Xwayland clients [Carlos; !4433] +* Fix hi-res scroll events getting converted to flip-flopping discrete events + [Peter; !4459] +* Fixed crash [Daniel; !4303] +* Misc. bug fixes and cleanups [Alessandro, Jonas, Jordan, Alessandro, Corentin, + Daniel, Lukáš, Rémi, Michel; !4481, !4482, !4485, !4492, !4496, !4495, !4444, + !4447, !4442, !4452] + +Contributors: + Alessandro Astone, Rémi Bernon, Sergio Costas Rodriguez, Michel Dänzer, + Carlos Garnacho, Peter Hutterer, Corentin Noël, Jordan Petridis, + Lukáš Tyrychtr, Daniel van Vugt, Jonas Ådahl + 48.3.1 ====== * Fix Xwayland windows becoming unresponsive to events [Jonas; !4475] diff -Nru mutter-48.3.1/src/backends/native/meta-gpu-kms.c mutter-48.4/src/backends/native/meta-gpu-kms.c --- mutter-48.3.1/src/backends/native/meta-gpu-kms.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-gpu-kms.c 2025-06-29 11:00:20.000000000 +0100 @@ -351,6 +351,8 @@ MetaOutput *old_output; GError *error = NULL; + meta_unlink_kms_connector (kms_connector); + if (!meta_kms_connector_get_current_state (kms_connector)) continue; diff -Nru mutter-48.3.1/src/backends/native/meta-kms.c mutter-48.4/src/backends/native/meta-kms.c --- mutter-48.3.1/src/backends/native/meta-kms.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-kms.c 2025-06-29 11:00:20.000000000 +0100 @@ -373,7 +373,7 @@ } ensure_hotplug_timeout_source (kms); - g_source_set_ready_time (kms->hotplug_timeout, now + 2 * G_USEC_PER_SEC); + g_source_set_ready_time (kms->hotplug_timeout, now + 3 * G_USEC_PER_SEC); g_hash_table_insert (kms->hotplug_events, g_steal_pointer (&hotplug_event), NULL); diff -Nru mutter-48.3.1/src/backends/native/meta-kms-impl-device.c mutter-48.4/src/backends/native/meta-kms-impl-device.c --- mutter-48.3.1/src/backends/native/meta-kms-impl-device.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-kms-impl-device.c 2025-06-29 11:00:20.000000000 +0100 @@ -1131,11 +1131,13 @@ drmModeRes *drm_resources; MetaKmsResourceChanges changes; GList *l; + gboolean had_fd_open; meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); meta_topic (META_DEBUG_KMS, "Updating device state for %s", priv->path); + had_fd_open = !!priv->device_file; if (!ensure_device_file (impl_device, &error)) { g_warning ("Failed to reopen '%s': %s", priv->path, error->message); @@ -1172,6 +1174,9 @@ drmModeFreeResources (drm_resources); + if (changes == META_KMS_RESOURCE_CHANGE_NONE && !had_fd_open) + clear_latched_fd_hold (impl_device); + return changes; err: @@ -1781,11 +1786,14 @@ crtc_frame = get_crtc_frame (impl_device, latch_crtc); if (!crtc_frame) { + const MetaKmsCrtcState *crtc_state = + meta_kms_crtc_get_current_state (latch_crtc); + crtc_frame = g_new0 (CrtcFrame, 1); crtc_frame->impl_device = impl_device; crtc_frame->crtc = latch_crtc; crtc_frame->deadline.timer_fd = -1; - crtc_frame->await_flush = TRUE; + crtc_frame->await_flush = !crtc_state->is_active; g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame); } diff -Nru mutter-48.3.1/src/backends/native/meta-onscreen-native.c mutter-48.4/src/backends/native/meta-onscreen-native.c --- mutter-48.3.1/src/backends/native/meta-onscreen-native.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-onscreen-native.c 2025-06-29 11:00:20.000000000 +0100 @@ -1833,7 +1833,7 @@ g_warning ("Direct scanout page flip failed: %s", error->message); cogl_scanout_notify_failed (scanout, onscreen); - if (onscreen_native->next_frame == NULL) + if (onscreen_native->next_frame == NULL && view != NULL) { clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); diff -Nru mutter-48.3.1/src/backends/native/meta-output-kms.c mutter-48.4/src/backends/native/meta-output-kms.c --- mutter-48.3.1/src/backends/native/meta-output-kms.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-output-kms.c 2025-06-29 11:00:20.000000000 +0100 @@ -99,6 +99,17 @@ kms_connector_output_kms_quark); } +void +meta_unlink_kms_connector (MetaKmsConnector *connector) +{ + if (!kms_connector_output_kms_quark) + return; + + g_object_set_qdata (G_OBJECT (connector), + kms_connector_output_kms_quark, + NULL); +} + static GBytes * meta_output_kms_read_edid (MetaOutputNative *output_native) { diff -Nru mutter-48.3.1/src/backends/native/meta-output-kms.h mutter-48.4/src/backends/native/meta-output-kms.h --- mutter-48.3.1/src/backends/native/meta-output-kms.h 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-output-kms.h 2025-06-29 11:00:20.000000000 +0100 @@ -41,6 +41,8 @@ MetaOutputKms * meta_output_kms_from_kms_connector (MetaKmsConnector *connector); +void meta_unlink_kms_connector (MetaKmsConnector *connector); + MetaOutputKms * meta_output_kms_new (MetaGpuKms *gpu_kms, MetaKmsConnector *kms_connector, MetaOutput *old_output, diff -Nru mutter-48.3.1/src/backends/native/meta-seat-impl.c mutter-48.4/src/backends/native/meta-seat-impl.c --- mutter-48.3.1/src/backends/native/meta-seat-impl.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/backends/native/meta-seat-impl.c 2025-06-29 11:00:20.000000000 +0100 @@ -1218,7 +1218,7 @@ evdev_device->value120.acc_dx += (int32_t) dx_value120; evdev_device->value120.acc_dy += (int32_t) dy_value120; - if (abs (evdev_device->value120.acc_dx) >= 60) + if (dx_value120 != 0 && abs (evdev_device->value120.acc_dx) >= 60) { low_res_value = (evdev_device->value120.acc_dx / 120); if (low_res_value == 0) @@ -1230,7 +1230,7 @@ evdev_device->value120.acc_dx -= (low_res_value * 120); } - if (abs (evdev_device->value120.acc_dy) >= 60) + if (dy_value120 != 0 && abs (evdev_device->value120.acc_dy) >= 60) { low_res_value = (evdev_device->value120.acc_dy / 120); if (low_res_value == 0) diff -Nru mutter-48.3.1/src/compositor/compositor.c mutter-48.4/src/compositor/compositor.c --- mutter-48.3.1/src/compositor/compositor.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/compositor/compositor.c 2025-06-29 11:00:20.000000000 +0100 @@ -1282,7 +1282,8 @@ void meta_compositor_flash_display (MetaCompositor *compositor, - MetaDisplay *display) + MetaDisplay *display, + int n_flashes) { MetaBackend *backend; ClutterActor *stage; @@ -1308,7 +1309,7 @@ transition = clutter_actor_get_transition (flash, "opacity"); clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), n_flashes); g_signal_connect (transition, "stopped", G_CALLBACK (flash_out_completed), flash); @@ -1327,7 +1328,8 @@ void meta_compositor_flash_window (MetaCompositor *compositor, - MetaWindow *window) + MetaWindow *window, + int n_flashes) { ClutterActor *window_actor = CLUTTER_ACTOR (meta_window_actor_from_window (window)); @@ -1356,7 +1358,7 @@ if (transition) { clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), n_flashes); g_signal_connect (transition, "stopped", G_CALLBACK (window_flash_out_completed), flash); diff -Nru mutter-48.3.1/src/compositor/compositor-private.h mutter-48.4/src/compositor/compositor-private.h --- mutter-48.3.1/src/compositor/compositor-private.h 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/compositor/compositor-private.h 2025-06-29 11:00:20.000000000 +0100 @@ -52,7 +52,8 @@ int64_t monotonic_time_us); void meta_compositor_flash_window (MetaCompositor *compositor, - MetaWindow *window); + MetaWindow *window, + int n_flashes); MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *compositor, MetaWindow *window); @@ -141,7 +142,8 @@ GList *stack); void meta_compositor_flash_display (MetaCompositor *compositor, - MetaDisplay *display); + MetaDisplay *display, + int n_flashes); void meta_compositor_show_tile_preview (MetaCompositor *compositor, MetaWindow *window, diff -Nru mutter-48.3.1/src/core/bell.c mutter-48.4/src/core/bell.c --- mutter-48.3.1/src/core/bell.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/core/bell.c 2025-06-29 11:00:20.000000000 +0100 @@ -54,6 +54,11 @@ #include "core/util-private.h" #include "core/window-private.h" #include "meta/compositor.h" +#include "mtk/mtk.h" + +/* Time limits to prevent Photosensitive Seizures */ +#define MIN_TIME_BETWEEN_VISUAL_ALERTS_MS 500 +#define MIN_TIME_BETWEEN_DOUBLE_VISUAL_ALERT_MS 3000 G_DEFINE_TYPE (MetaBell, meta_bell, G_TYPE_OBJECT) @@ -120,7 +125,7 @@ /** * bell_flash_fullscreen: * @display: The display the event came in on - * @xkb_ev: The bell event + * @n_flashes: The number of times to flash the screen * * Flashes one screen, or all screens, in response to a bell event. * If the event is on a particular window, flash the screen that @@ -129,15 +134,17 @@ * If the configure script found we had no XKB, this does not exist. */ static void -bell_flash_fullscreen (MetaDisplay *display) +bell_flash_fullscreen (MetaDisplay *display, + int n_flashes) { - meta_compositor_flash_display (display->compositor, display); + meta_compositor_flash_display (display->compositor, display, n_flashes); } static void -bell_flash_window (MetaWindow *window) +bell_flash_window (MetaWindow *window, + int n_flashes) { - meta_compositor_flash_window (window->display->compositor, window); + meta_compositor_flash_window (window->display->compositor, window, n_flashes); } /** @@ -150,12 +157,13 @@ */ static void bell_flash_frame (MetaDisplay *display, - MetaWindow *window) + MetaWindow *window, + int n_flashes) { if (window) - bell_flash_window (window); + bell_flash_window (window, n_flashes); else - bell_flash_fullscreen (display); + bell_flash_fullscreen (display, n_flashes); } /** @@ -170,13 +178,49 @@ bell_visual_notify (MetaDisplay *display, MetaWindow *window) { + /* + * The European Accessibility Act (EAA), in the Annex I, Section I, 2.J, + * specifies that products "shall avoid triggering photosensitive seizures". + * + * According to the Web Content Accessibility Guidelines (WCAG), any + * element that flashes in the screen must have a maximum period of + * 3Hz to avoid the risk of Photosensitivity Seizures. + * + * If several alarm bells are sent fast enough, the Visual alerts could + * flash the screen or the window at speeds about 8-9Hz (tested with a + * simple BASH script), which is greater than the currently accepted + * limit of 3Hz. + * + * To avoid this, a timeout is added to ensure that no visual alerts are + * sent with less than 500ms of difference, to set a maximum flash speed + * of 2Hz. + * + * A property in display is used to keep the last time a visual alert has been + * sent because not only a "single flash zone" can trigger a seizure, but also + * slower patterns combined. So a global timeout for all the desktop is the + * safest approach. + */ + int64_t now_us; + int64_t time_difference_ms; + int n_flashes; + + now_us = g_get_monotonic_time (); + time_difference_ms = us2ms (now_us - display->last_visual_bell_time_us); + + if (time_difference_ms < MIN_TIME_BETWEEN_VISUAL_ALERTS_MS) + return; + + display->last_visual_bell_time_us = now_us; + + n_flashes = (time_difference_ms < MIN_TIME_BETWEEN_DOUBLE_VISUAL_ALERT_MS) ? 1 : 2; + switch (meta_prefs_get_visual_bell_type ()) { case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH: - bell_flash_fullscreen (display); + bell_flash_fullscreen (display, n_flashes); break; case G_DESKTOP_VISUAL_BELL_FRAME_FLASH: - bell_flash_frame (display, window); + bell_flash_frame (display, window, n_flashes); break; } } diff -Nru mutter-48.3.1/src/core/display-private.h mutter-48.4/src/core/display-private.h --- mutter-48.3.1/src/core/display-private.h 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/core/display-private.h 2025-06-29 11:00:20.000000000 +0100 @@ -120,11 +120,11 @@ GSList *pending_pings; /* Pending focus change */ - guint focus_timeout_id; + guint focus_timeout_id; /* Pending autoraise */ - guint autoraise_timeout_id; - MetaWindow* autoraise_window; + guint autoraise_timeout_id; + MetaWindow *autoraise_window; MetaKeyBindingManager key_binding_manager; @@ -157,6 +157,7 @@ guint check_fullscreen_later; MetaBell *bell; + int64_t last_visual_bell_time_us; MetaWorkspaceManager *workspace_manager; MetaSoundPlayer *sound_player; diff -Nru mutter-48.3.1/src/core/meta-context-main.c mutter-48.4/src/core/meta-context-main.c --- mutter-48.3.1/src/core/meta-context-main.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/core/meta-context-main.c 2025-06-29 11:00:20.000000000 +0100 @@ -666,6 +666,8 @@ N_("Run as a nested compositor"), NULL }, +#endif +#ifdef HAVE_XWAYLAND { "no-x11", 0, 0, G_OPTION_ARG_NONE, &context_main->options.no_x11, diff -Nru mutter-48.3.1/src/core/window.c mutter-48.4/src/core/window.c --- mutter-48.3.1/src/core/window.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/core/window.c 2025-06-29 11:00:20.000000000 +0100 @@ -5181,6 +5181,13 @@ g_return_if_fail (!window->override_redirect); + /* Flush pending visible state now. + * It is important that this runs before meta_stack_raise() because + * showing a window may overwrite its stacking order based on the + * stacking rules for newly shown windows. + */ + meta_window_flush_calc_showing (window); + ancestor = meta_window_find_root_ancestor (window); meta_topic (META_DEBUG_WINDOW_OPS, diff -Nru mutter-48.3.1/src/tests/test-runner.c mutter-48.4/src/tests/test-runner.c --- mutter-48.3.1/src/tests/test-runner.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/tests/test-runner.c 2025-06-29 11:00:20.000000000 +0100 @@ -296,7 +296,7 @@ if ((filter & STACK_FILTER_SHOWING) && window && window->hidden) continue; - if (workspace && !meta_window_located_on_workspace (window, workspace)) + if (window && workspace && !meta_window_located_on_workspace (window, workspace)) continue; if (window != NULL && window->title) diff -Nru mutter-48.3.1/src/wayland/meta-wayland-data-device.c mutter-48.4/src/wayland/meta-wayland-data-device.c --- mutter-48.3.1/src/wayland/meta-wayland-data-device.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/wayland/meta-wayland-data-device.c 2025-06-29 11:00:20.000000000 +0100 @@ -26,8 +26,6 @@ #include "wayland/meta-wayland-data-device.h" -#include <gio/gunixoutputstream.h> -#include <glib-unix.h> #include <glib.h> #include <stdio.h> #include <stdlib.h> @@ -235,6 +233,12 @@ g_autoptr (MetaCursorSprite) cursor_sprite = NULL; MetaCursorRenderer *cursor_renderer; +#ifdef HAVE_X11_CLIENT + /* X11 DnD lets the drag source client drive pointer cursor updates */ + if (META_IS_WAYLAND_DATA_SOURCE_XWAYLAND (drag_grab->drag_data_source)) + return; +#endif + cursor_sprite = META_CURSOR_SPRITE (meta_cursor_sprite_xcursor_new (cursor, cursor_tracker)); cursor_renderer = @@ -276,10 +280,7 @@ on_data_source_action_changed (MetaWaylandDataSource *source, MetaWaylandDragGrab *drag_grab) { -#ifdef HAVE_X11_CLIENT - if (!META_IS_WAYLAND_DATA_SOURCE_XWAYLAND (source)) -#endif - meta_wayland_drag_grab_update_cursor (drag_grab); + meta_wayland_drag_grab_update_cursor (drag_grab); } static void @@ -453,6 +454,8 @@ MetaDisplay *display = display_from_data_device (data_device); MetaCompositor *compositor = meta_display_get_compositor (display); + meta_wayland_drag_grab_set_cursor (drag_grab, META_CURSOR_DEFAULT); + meta_wayland_drag_grab_set_source (drag_grab, NULL); meta_wayland_drag_grab_set_focus (drag_grab, NULL); @@ -485,55 +488,11 @@ drag_grab->handler = NULL; } - meta_wayland_drag_grab_set_cursor (drag_grab, META_CURSOR_DEFAULT); meta_dnd_wayland_handle_end_modal (compositor); g_free (drag_grab); } -static gboolean -on_fake_read_hup (GIOChannel *channel, - GIOCondition condition, - gpointer data) -{ - MetaWaylandDataSource *source = data; - - meta_wayland_data_source_notify_finish (source); - g_io_channel_shutdown (channel, FALSE, NULL); - g_io_channel_unref (channel); - - return G_SOURCE_REMOVE; -} - -static void -meta_wayland_data_source_fake_read (MetaWaylandDataSource *source, - const gchar *mimetype) -{ - GIOChannel *channel; - int p[2]; - - if (!g_unix_open_pipe (p, FD_CLOEXEC, NULL)) - { - meta_wayland_data_source_notify_finish (source); - return; - } - - if (!g_unix_set_fd_nonblocking (p[0], TRUE, NULL) || - !g_unix_set_fd_nonblocking (p[1], TRUE, NULL)) - { - meta_wayland_data_source_notify_finish (source); - close (p[0]); - close (p[1]); - return; - } - - meta_wayland_data_source_send (source, mimetype, p[1]); - close (p[1]); - channel = g_io_channel_unix_new (p[0]); - g_io_channel_set_close_on_unref (channel, TRUE); - g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source); -} - static MetaWaylandSurface * drag_grab_get_focus_surface (MetaWaylandEventHandler *handler, ClutterInputDevice *device, diff -Nru mutter-48.3.1/src/wayland/meta-wayland-data-source.c mutter-48.4/src/wayland/meta-wayland-data-source.c --- mutter-48.3.1/src/wayland/meta-wayland-data-source.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/wayland/meta-wayland-data-source.c 2025-06-29 11:00:20.000000000 +0100 @@ -23,6 +23,8 @@ #include "config.h" +#include <gio/gunixoutputstream.h> +#include <glib-unix.h> #include <unistd.h> #include "wayland/meta-wayland-data-source.h" @@ -46,6 +48,10 @@ enum wl_data_device_manager_dnd_action current_dnd_action; MetaWaylandSeat *seat; MetaWaylandToplevelDrag *toplevel_drag; + + GIOChannel *fake_read_channel; + guint fake_read_watch_id; + guint actions_set : 1; guint in_ask : 1; guint drop_performed : 1; @@ -160,6 +166,9 @@ meta_wayland_data_source_get_instance_private (source); char **pos; + g_clear_handle_id (&priv->fake_read_watch_id, g_source_remove); + g_clear_pointer (&priv->fake_read_channel, g_io_channel_unref); + wl_array_for_each (pos, &priv->mime_types) g_free (*pos); wl_array_release (&priv->mime_types); @@ -582,6 +591,56 @@ META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source); } +static gboolean +on_fake_read_hup (GIOChannel *channel, + GIOCondition condition, + gpointer user_data) +{ + MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (user_data); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->fake_read_watch_id = 0; + meta_wayland_data_source_notify_finish (source); + g_io_channel_shutdown (channel, FALSE, NULL); + g_clear_pointer (&priv->fake_read_channel, g_io_channel_unref); + + return G_SOURCE_REMOVE; +} + +void +meta_wayland_data_source_fake_read (MetaWaylandDataSource *source, + const char *mimetype) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + GIOChannel *channel; + int p[2]; + + if (!g_unix_open_pipe (p, FD_CLOEXEC, NULL)) + { + meta_wayland_data_source_notify_finish (source); + return; + } + + if (!g_unix_set_fd_nonblocking (p[0], TRUE, NULL) || + !g_unix_set_fd_nonblocking (p[1], TRUE, NULL)) + { + meta_wayland_data_source_notify_finish (source); + close (p[0]); + close (p[1]); + return; + } + + meta_wayland_data_source_send (source, mimetype, p[1]); + close (p[1]); + channel = g_io_channel_unix_new (p[0]); + g_io_channel_set_close_on_unref (channel, TRUE); + priv->fake_read_channel = channel; + priv->fake_read_watch_id = + g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source); +} + gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, const char *mime_type) diff -Nru mutter-48.3.1/src/wayland/meta-wayland-data-source.h mutter-48.4/src/wayland/meta-wayland-data-source.h --- mutter-48.3.1/src/wayland/meta-wayland-data-source.h 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/wayland/meta-wayland-data-source.h 2025-06-29 11:00:20.000000000 +0100 @@ -111,6 +111,9 @@ void meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source); void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source); +void meta_wayland_data_source_fake_read (MetaWaylandDataSource *source, + const char *mimetype); + void meta_wayland_data_source_set_toplevel_drag (MetaWaylandDataSource *source, MetaWaylandToplevelDrag *toplevel_drag); diff -Nru mutter-48.3.1/src/wayland/meta-wayland-seat.c mutter-48.4/src/wayland/meta-wayland-seat.c --- mutter-48.3.1/src/wayland/meta-wayland-seat.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/wayland/meta-wayland-seat.c 2025-06-29 11:00:20.000000000 +0100 @@ -98,10 +98,10 @@ wl_resource_set_implementation (resource, &seat_interface, seat, unbind_resource); wl_list_insert (&seat->base_resource_list, wl_resource_get_link (resource)); - wl_seat_send_capabilities (resource, seat->capabilities); - if (version >= WL_SEAT_NAME_SINCE_VERSION) wl_seat_send_name (resource, "seat0"); + + wl_seat_send_capabilities (resource, seat->capabilities); } static uint32_t diff -Nru mutter-48.3.1/src/x11/meta-x11-display.c mutter-48.4/src/x11/meta-x11-display.c --- mutter-48.3.1/src/x11/meta-x11-display.c 2025-06-02 23:01:18.000000000 +0100 +++ mutter-48.4/src/x11/meta-x11-display.c 2025-06-29 11:00:20.000000000 +0100 @@ -2261,6 +2261,14 @@ if (focus_window) data[0] = meta_window_x11_get_xwindow (focus_window); +#ifdef HAVE_XWAYLAND + else if (x11_display->focus_xwindow && meta_is_wayland_compositor ()) + /* On Wayland, when a Wayland window is focused, indicate that an + * actual window is focused rather than None, as None is otherwise + * also used during transient focus changes. + */ + data[0] = x11_display->no_focus_window; +#endif else data[0] = None;