diff --git a/2624.patch b/2624.patch new file mode 100644 index 0000000..2ed613b --- /dev/null +++ b/2624.patch @@ -0,0 +1,426 @@ +From 41f488a65ca67ee7e83a952c02af2fae60cc7583 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 14 Sep 2022 23:12:00 +0200 +Subject: [PATCH 1/3] tests/wayland-unit: Move out sync point wait helper + +Part-of: +--- + src/tests/meta-wayland-test-driver.c | 25 +++++++++++++++++++++++++ + src/tests/meta-wayland-test-driver.h | 3 +++ + src/tests/wayland-unit-tests.c | 20 +------------------- + 3 files changed, 29 insertions(+), 19 deletions(-) + +diff --git a/src/tests/meta-wayland-test-driver.c b/src/tests/meta-wayland-test-driver.c +index d418fa14f3..a9bb251234 100644 +--- a/src/tests/meta-wayland-test-driver.c ++++ b/src/tests/meta-wayland-test-driver.c +@@ -331,3 +331,28 @@ meta_wayland_test_driver_set_property (MetaWaylandTestDriver *test_driver, + g_strdup (name), + g_strdup (value)); + } ++ ++static void ++on_sync_point (MetaWaylandTestDriver *test_driver, ++ unsigned int sequence, ++ struct wl_resource *surface_resource, ++ struct wl_client *wl_client, ++ unsigned int *latest_sequence) ++{ ++ *latest_sequence = sequence; ++} ++ ++void ++meta_wayland_test_driver_wait_for_sync_point (MetaWaylandTestDriver *test_driver, ++ unsigned int sync_point) ++{ ++ gulong handler_id; ++ unsigned int latest_sequence = sync_point - 1; ++ ++ handler_id = g_signal_connect (test_driver, "sync-point", ++ G_CALLBACK (on_sync_point), ++ &latest_sequence); ++ while (latest_sequence != sync_point) ++ g_main_context_iteration (NULL, TRUE); ++ g_signal_handler_disconnect (test_driver, handler_id); ++} +diff --git a/src/tests/meta-wayland-test-driver.h b/src/tests/meta-wayland-test-driver.h +index b20af74496..dbd6ab82ba 100644 +--- a/src/tests/meta-wayland-test-driver.h ++++ b/src/tests/meta-wayland-test-driver.h +@@ -34,4 +34,7 @@ void meta_wayland_test_driver_set_property (MetaWaylandTestDriver *test_driver, + const char *name, + const char *value); + ++void meta_wayland_test_driver_wait_for_sync_point (MetaWaylandTestDriver *test_driver, ++ unsigned int sync_point); ++ + #endif /* META_WAYLAND_TEST_DRIVER_H */ +diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c +index 12dc6d8d36..2dc2f43815 100644 +--- a/src/tests/wayland-unit-tests.c ++++ b/src/tests/wayland-unit-tests.c +@@ -385,28 +385,10 @@ toplevel_activation (void) + meta_wayland_test_client_finish (data.wayland_test_client); + } + +-static void +-on_sync_point (MetaWaylandTestDriver *test_driver, +- unsigned int sequence, +- struct wl_resource *surface_resource, +- struct wl_client *wl_client, +- unsigned int *latest_sequence) +-{ +- *latest_sequence = sequence; +-} +- + static void + wait_for_sync_point (unsigned int sync_point) + { +- gulong handler_id; +- unsigned int latest_sequence = 0; +- +- handler_id = g_signal_connect (test_driver, "sync-point", +- G_CALLBACK (on_sync_point), +- &latest_sequence); +- while (latest_sequence != sync_point) +- g_main_context_iteration (NULL, TRUE); +- g_signal_handler_disconnect (test_driver, handler_id); ++ meta_wayland_test_driver_wait_for_sync_point (test_driver, sync_point); + } + + static gboolean +-- +GitLab + + +From 85ef0d1a46b9c8d179f33208b5396b6a1f4225c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 14 Sep 2022 23:12:52 +0200 +Subject: [PATCH 2/3] compositor-view/native: Check that the actor covers the + the view + +If we have a window that match the size (i.e. will pass the "fits +framebuffer" low level check), that doesn't mean it matches the +position. For example, if we have two monitors 2K monitors, with two 2K +sized windows, one on monitor A, and one on monitor both monitor A and +B, overlapping both, if the latter window is above the former, it'll end +up bing scanned out on both if it ends up fitting all the other +requirements. + +Fix this by checking that the paint box matches the stage view layout, +as that makes sure the actor we're painting isn't just partially on the +right view. + +Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2387 +Part-of: +--- + clutter/clutter/clutter-mutter.h | 5 +++++ + src/compositor/meta-compositor-view-native.c | 17 +++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h +index b383ff518c..04efa5d86d 100644 +--- a/clutter/clutter/clutter-mutter.h ++++ b/clutter/clutter/clutter-mutter.h +@@ -38,6 +38,11 @@ + #include "clutter-stage-view-private.h" + #include "clutter.h" + ++/* An epsilon larger than FLT_EPSILON that is useful when comparing coordinates ++ * while ignoring floating point precision loss that might happen during ++ * various matrix calculations. */ ++#define CLUTTER_COORDINATE_EPSILON (1.0 / 256.0) ++ + typedef struct _ClutterMainContext ClutterContext; + + typedef ClutterBackend * (* ClutterBackendConstructor) (gpointer user_data); +diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c +index 932d43a3b9..4c7e7f7a89 100644 +--- a/src/compositor/meta-compositor-view-native.c ++++ b/src/compositor/meta-compositor-view-native.c +@@ -83,6 +83,8 @@ find_scanout_candidate (MetaCompositorView *compositor_view, + CoglFramebuffer *framebuffer; + MetaWindowActor *window_actor; + MetaWindow *window; ++ MetaRectangle view_rect; ++ ClutterActorBox actor_box; + MetaSurfaceActor *surface_actor; + MetaSurfaceActorWayland *surface_actor_wayland; + MetaWaylandSurface *surface; +@@ -126,6 +128,21 @@ find_scanout_candidate (MetaCompositorView *compositor_view, + if (meta_surface_actor_is_obscured (surface_actor)) + return FALSE; + ++ if (!clutter_actor_get_paint_box (CLUTTER_ACTOR (surface_actor), ++ &actor_box)) ++ return FALSE; ++ ++ clutter_stage_view_get_layout (stage_view, &view_rect); ++ if (!G_APPROX_VALUE (actor_box.x1, view_rect.x, ++ CLUTTER_COORDINATE_EPSILON) || ++ !G_APPROX_VALUE (actor_box.y1, view_rect.y, ++ CLUTTER_COORDINATE_EPSILON) || ++ !G_APPROX_VALUE (actor_box.x2, view_rect.x + view_rect.width, ++ CLUTTER_COORDINATE_EPSILON) || ++ !G_APPROX_VALUE (actor_box.y2, view_rect.y + view_rect.height, ++ CLUTTER_COORDINATE_EPSILON)) ++ return FALSE; ++ + surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor); + surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland); + if (!surface) +-- +GitLab + + +From 6601c3b02ab9d3fddce71c26618138122bc3fe7e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 14 Sep 2022 23:18:37 +0200 +Subject: [PATCH 3/3] tests: Add partial-overlapping scanout test + +Make sure that if we wiggle a scan-out capable surface a bit, it won't +scan out if it's not exactly in the right position. Do this by first +making the window not fullscreen, then moving it back and forth, +verifying the correct scanout state for each presented frame. + +This test addition reproduces the issue described in +https://gitlab.gnome.org/GNOME/mutter/-/issues/2387. + +Part-of: +--- + src/tests/native-kms-render.c | 70 +++++++++++++++++-- + .../wayland-test-clients/dma-buf-scanout.c | 46 +++++++++++- + 2 files changed, 109 insertions(+), 7 deletions(-) + +diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c +index 278edf4bd2..6595eb5a29 100644 +--- a/src/tests/native-kms-render.c ++++ b/src/tests/native-kms-render.c +@@ -32,6 +32,7 @@ + #include "core/display-private.h" + #include "meta/meta-backend.h" + #include "meta-test/meta-context-test.h" ++#include "tests/meta-test-utils.h" + #include "tests/meta-wayland-test-driver.h" + #include "tests/meta-wayland-test-utils.h" + +@@ -44,6 +45,8 @@ typedef struct + int n_paints; + uint32_t fb_id; + } scanout; ++ ++ gboolean wait_for_scanout; + } KmsRenderingTest; + + static MetaContext *test_context; +@@ -139,7 +142,7 @@ on_scanout_presented (ClutterStage *stage, + if (test->scanout.n_paints > 0) + return; + +- if (test->scanout.fb_id == 0) ++ if (test->wait_for_scanout && test->scanout.fb_id == 0) + return; + + device_pool = meta_backend_native_get_device_pool (backend_native); +@@ -159,7 +162,10 @@ on_scanout_presented (ClutterStage *stage, + drm_crtc = drmModeGetCrtc (meta_device_file_get_fd (device_file), + meta_kms_crtc_get_id (kms_crtc)); + g_assert_nonnull (drm_crtc); +- g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id); ++ if (test->scanout.fb_id == 0) ++ g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id); ++ else ++ g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id); + drmModeFreeCrtc (drm_crtc); + + meta_device_file_release (device_file); +@@ -167,13 +173,19 @@ on_scanout_presented (ClutterStage *stage, + g_main_loop_quit (test->loop); + } + ++typedef enum ++{ ++ SCANOUT_WINDOW_STATE_NONE, ++ SCANOUT_WINDOW_STATE_FULLSCREEN, ++} ScanoutWindowState; ++ + static void + meta_test_kms_render_client_scanout (void) + { + MetaBackend *backend = meta_context_get_backend (test_context); + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (test_context); +- ClutterActor *stage = meta_backend_get_stage (backend); ++ ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); + MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); + MetaKmsDevice *kms_device = meta_kms_get_devices (kms)->data; + KmsRenderingTest test; +@@ -183,6 +195,9 @@ meta_test_kms_render_client_scanout (void) + gulong before_paint_handler_id; + gulong paint_view_handler_id; + gulong presented_handler_id; ++ MetaWindow *window; ++ MetaRectangle view_rect; ++ MetaRectangle buffer_rect; + + test_driver = meta_wayland_test_driver_new (wayland_compositor); + meta_wayland_test_driver_set_property (test_driver, +@@ -195,8 +210,15 @@ meta_test_kms_render_client_scanout (void) + + test = (KmsRenderingTest) { + .loop = g_main_loop_new (NULL, FALSE), ++ .wait_for_scanout = TRUE, + }; + ++ g_assert_cmpuint (g_list_length (clutter_stage_peek_stage_views (stage)), ++ ==, ++ 1); ++ clutter_stage_view_get_layout (clutter_stage_peek_stage_views (stage)->data, ++ &view_rect); ++ + paint_view_handler_id = + g_signal_connect (stage, "paint-view", + G_CALLBACK (on_scanout_paint_view), &test); +@@ -212,7 +234,46 @@ meta_test_kms_render_client_scanout (void) + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + g_main_loop_run (test.loop); +- g_main_loop_unref (test.loop); ++ ++ g_assert_cmpuint (test.scanout.fb_id, >, 0); ++ ++ g_debug ("Unmake fullscreen"); ++ window = meta_find_window_from_title (test_context, "dma-buf-scanout-test"); ++ g_assert_true (meta_window_is_fullscreen (window)); ++ meta_window_unmake_fullscreen (window); ++ ++ g_debug ("Wait for fullscreen"); ++ meta_wayland_test_driver_wait_for_sync_point (test_driver, ++ SCANOUT_WINDOW_STATE_NONE); ++ g_assert_false (meta_window_is_fullscreen (window)); ++ ++ g_debug ("Moving to 10, 10"); ++ meta_window_move_frame (window, TRUE, 10, 10); ++ ++ meta_window_get_buffer_rect (window, &buffer_rect); ++ g_assert_cmpint (buffer_rect.width, ==, view_rect.width); ++ g_assert_cmpint (buffer_rect.height, ==, view_rect.height); ++ g_assert_cmpint (buffer_rect.x, ==, 10); ++ g_assert_cmpint (buffer_rect.y, ==, 10); ++ ++ test.wait_for_scanout = FALSE; ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); ++ g_main_loop_run (test.loop); ++ ++ g_assert_cmpuint (test.scanout.fb_id, ==, 0); ++ ++ g_debug ("Moving back to 0, 0"); ++ meta_window_move_frame (window, TRUE, 0, 0); ++ ++ meta_window_get_buffer_rect (window, &buffer_rect); ++ g_assert_cmpint (buffer_rect.width, ==, view_rect.width); ++ g_assert_cmpint (buffer_rect.height, ==, view_rect.height); ++ g_assert_cmpint (buffer_rect.x, ==, 0); ++ g_assert_cmpint (buffer_rect.y, ==, 0); ++ ++ test.wait_for_scanout = TRUE; ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); ++ g_main_loop_run (test.loop); + + g_assert_cmpuint (test.scanout.fb_id, >, 0); + +@@ -223,6 +284,7 @@ meta_test_kms_render_client_scanout (void) + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); ++ g_main_loop_unref (test.loop); + } + + static void +diff --git a/src/tests/wayland-test-clients/dma-buf-scanout.c b/src/tests/wayland-test-clients/dma-buf-scanout.c +index 25b9066965..273413f43f 100644 +--- a/src/tests/wayland-test-clients/dma-buf-scanout.c ++++ b/src/tests/wayland-test-clients/dma-buf-scanout.c +@@ -53,6 +53,12 @@ + + #include "linux-dmabuf-unstable-v1-client-protocol.h" + ++typedef enum ++{ ++ WINDOW_STATE_NONE, ++ WINDOW_STATE_FULLSCREEN, ++} WindowState; ++ + typedef struct _Buffer + { + struct wl_buffer *buffer; +@@ -78,6 +84,10 @@ struct gbm_device *gbm_device; + + static GList *active_buffers; + ++static int prev_width; ++static int prev_height; ++static WindowState window_state; ++ + static struct + { + uint32_t format; +@@ -214,15 +224,44 @@ draw_main (int width, + wl_surface_attach (surface, buffer->buffer, 0, 0); + } + ++static WindowState ++parse_xdg_toplevel_state (struct wl_array *states) ++{ ++ uint32_t *state_ptr; ++ ++ wl_array_for_each (state_ptr, states) ++ { ++ uint32_t state = *state_ptr; ++ ++ if (state == XDG_TOPLEVEL_STATE_FULLSCREEN) ++ return WINDOW_STATE_FULLSCREEN; ++ } ++ ++ return WINDOW_STATE_NONE; ++} ++ + static void + handle_xdg_toplevel_configure (void *user_data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, +- struct wl_array *state) ++ struct wl_array *states) + { +- g_assert_cmpint (width, >, 0); +- g_assert_cmpint (height, >, 0); ++ g_assert (width > 0 || prev_width > 0); ++ g_assert (height > 0 || prev_width > 0); ++ ++ if (width > 0 && height > 0) ++ { ++ prev_width = width; ++ prev_height = height; ++ } ++ else ++ { ++ width = prev_width; ++ height = prev_height; ++ } ++ ++ window_state = parse_xdg_toplevel_state (states); + + draw_main (width, height); + } +@@ -270,6 +309,7 @@ handle_xdg_surface_configure (void *user_data, + frame_callback = wl_surface_frame (surface); + wl_callback_add_listener (frame_callback, &frame_listener, NULL); + wl_surface_commit (surface); ++ test_driver_sync_point (display->test_driver, window_state, NULL); + wl_display_flush (display->display); + } + +-- +GitLab + diff --git a/mutter.spec b/mutter.spec index 861dd53..e104659 100644 --- a/mutter.spec +++ b/mutter.spec @@ -32,6 +32,11 @@ Patch2: mutter-42.alpha-disable-tegra.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2623 Patch3: 2623.patch +# Backported from upstream +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2624 +# https://bugzilla.redhat.com/show_bug.cgi?id=2128660 +Patch4: 2624.patch + BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) BuildRequires: pkgconfig(libwacom) @@ -179,6 +184,8 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop %changelog * Thu Sep 22 2022 Kalev Lember - 43.0-2 - Backport upstream MR2623 to fix night light controls +- Backport upstream MR2624 to fix maximized windows appearing on all + screens (#2128660) * Sat Sep 17 2022 Florian Müllner - 43.0-1 - Update to 43.0