From 266ab57361dfbb2425509c9693b0ec098ab1748b Mon Sep 17 00:00:00 2001 From: m2 <69128853+m2Giles@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:59:22 -0400 Subject: [PATCH 01/41] chore: update dependency for devpod. (#21) --- staging/devpod/devpod.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/devpod/devpod.spec b/staging/devpod/devpod.spec index 06f8585..3a86177 100644 --- a/staging/devpod/devpod.spec +++ b/staging/devpod/devpod.spec @@ -24,7 +24,7 @@ Requires: libbsd Requires: libdeflate Requires: libgcc Requires: libwmf -Requires: openssl1.1 +Requires: openssl Requires: pango Requires: webkit2gtk4.1 From fe079bb863b5d29cf86cc72a0ae717e755b11d6d Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 08:22:17 -0700 Subject: [PATCH 02/41] feat: Add Mutter with Xwayland fractional scaling --- ...nput-region-from-frame-window-for-de.patch | 115 + staging/mutter/0001-modified-3329.patch | 145 ++ ...-center-initial-setup-fedora-welcome.patch | 28 + ...tor-Special-case-shaped-Java-windows.patch | 70 + staging/mutter/3567.patch | 2090 +++++++++++++++++ .../mutter-42.alpha-disable-tegra.patch | 25 + staging/mutter/mutter.spec | 218 ++ 7 files changed, 2691 insertions(+) create mode 100644 staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch create mode 100644 staging/mutter/0001-modified-3329.patch create mode 100644 staging/mutter/0001-place-Always-center-initial-setup-fedora-welcome.patch create mode 100644 staging/mutter/0001-window-actor-Special-case-shaped-Java-windows.patch create mode 100644 staging/mutter/3567.patch create mode 100644 staging/mutter/mutter-42.alpha-disable-tegra.patch create mode 100644 staging/mutter/mutter.spec diff --git a/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch b/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch new file mode 100644 index 0000000..c2baf41 --- /dev/null +++ b/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch @@ -0,0 +1,115 @@ +From 1d5c47f8970c2027de5f6fa49b84de73d55b419b Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Thu, 5 Oct 2023 13:09:46 -0700 +Subject: [PATCH] Revert "x11: Use input region from frame window for decorated + windows" + +This reverts commit d991961ae2a5c8cf2e58ff1072239f4902b0f767. It +seems to cause the broken mouse interaction bug reported in +https://bugzilla.redhat.com/show_bug.cgi?id=2239128 . + +Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 +--- + src/core/frame.c | 7 ------- + src/x11/window-x11.c | 29 ++++++++++------------------- + 2 files changed, 10 insertions(+), 26 deletions(-) + +diff --git a/src/core/frame.c b/src/core/frame.c +index 145f0b7bd7..1c90ce4231 100644 +--- a/src/core/frame.c ++++ b/src/core/frame.c +@@ -35,7 +35,6 @@ + #include "x11/window-props.h" + + #include +-#include + + #define EVENT_MASK (SubstructureRedirectMask | \ + StructureNotifyMask | SubstructureNotifyMask | \ +@@ -109,9 +108,6 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, + XChangeWindowAttributes (x11_display->xdisplay, + frame->xwindow, CWEventMask, &attrs); + +- if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) +- XShapeSelectInput (x11_display->xdisplay, frame->xwindow, ShapeNotifyMask); +- + meta_x11_display_register_x_window (x11_display, &frame->xwindow, window); + + if (window->mapped) +@@ -220,9 +216,6 @@ meta_window_destroy_frame (MetaWindow *window) + window->reparents_pending += 1; + } + +- if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) +- XShapeSelectInput (x11_display->xdisplay, frame->xwindow, NoEventMask); +- + XDeleteProperty (x11_display->xdisplay, + meta_window_x11_get_xwindow (window), + x11_display->atom__MUTTER_NEEDS_FRAME); +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index 745c45db18..8edff883c9 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -2082,10 +2082,6 @@ meta_window_x11_constructed (GObject *object) + priv->keys_grabbed = FALSE; + priv->grab_on_frame = FALSE; + +- g_signal_connect (window, "notify::decorated", +- G_CALLBACK (meta_window_x11_update_input_region), +- window); +- + G_OBJECT_CLASS (meta_window_x11_parent_class)->constructed (object); + } + +@@ -2400,21 +2396,16 @@ meta_window_x11_update_input_region (MetaWindow *window) + g_autoptr (MtkRegion) region = NULL; + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); +- Window xwindow; + ++ /* Decorated windows don't have an input region, because ++ we don't shape the frame to match the client windows ++ (so the events are blocked by the frame anyway) ++ */ + if (window->decorated) + { +- if (!window->frame) +- { +- if (priv->input_region) +- meta_window_set_input_region (window, NULL); +- return; +- } +- xwindow = window->frame->xwindow; +- } +- else +- { +- xwindow = priv->xwindow; ++ if (priv->input_region) ++ meta_window_set_input_region (window, NULL); ++ return; + } + + if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) +@@ -2426,7 +2417,7 @@ meta_window_x11_update_input_region (MetaWindow *window) + + mtk_x11_error_trap_push (x11_display->xdisplay); + rects = XShapeGetRectangles (x11_display->xdisplay, +- xwindow, ++ priv->xwindow, + ShapeInput, + &n_rects, + &ordering); +@@ -2480,8 +2471,8 @@ meta_window_x11_update_input_region (MetaWindow *window) + + client_area.x = 0; + client_area.y = 0; +- client_area.width = window->buffer_rect.width; +- client_area.height = window->buffer_rect.height; ++ client_area.width = priv->client_rect.width; ++ client_area.height = priv->client_rect.height; + + /* The shape we get back from the client may have coordinates + * outside of the frame. The X SHAPE Extension requires that +-- +2.43.2 + diff --git a/staging/mutter/0001-modified-3329.patch b/staging/mutter/0001-modified-3329.patch new file mode 100644 index 0000000..54f0ed4 --- /dev/null +++ b/staging/mutter/0001-modified-3329.patch @@ -0,0 +1,145 @@ +From e20ebeefa42997fe65008b11ef771c71b697273c Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Fri, 20 Oct 2023 22:12:23 -0700 +Subject: [PATCH] modified 3329 + +Signed-off-by: Adam Williamson +--- + src/compositor/meta-compositor-x11.c | 2 ++ + src/core/display.c | 34 ---------------------------- + src/tests/x11-test.sh | 3 +++ + src/x11/meta-x11-display.c | 30 +++++++++++++++++++++++- + 4 files changed, 34 insertions(+), 35 deletions(-) + +diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c +index 1ad3327dd..ce7bc1945 100644 +--- a/src/compositor/meta-compositor-x11.c ++++ b/src/compositor/meta-compositor-x11.c +@@ -188,6 +188,8 @@ meta_compositor_x11_manage (MetaCompositor *compositor, + + compositor_x11->have_x11_sync_object = meta_sync_ring_init (xdisplay); + ++ meta_x11_display_redirect_windows (x11_display, display); ++ + return TRUE; + } + +diff --git a/src/core/display.c b/src/core/display.c +index 0a191c0fb..b16e50e21 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -930,9 +930,6 @@ meta_display_new (MetaContext *context, + MetaDisplay *display; + MetaDisplayPrivate *priv; + guint32 timestamp; +-#ifdef HAVE_X11_CLIENT +- Window old_active_xwindow = None; +-#endif + MetaMonitorManager *monitor_manager; + MetaSettings *settings; + MetaInputCapture *input_capture; +@@ -1048,14 +1045,6 @@ meta_display_new (MetaContext *context, + display->last_focus_time = timestamp; + display->last_user_time = timestamp; + +-#ifdef HAVE_X11 +- if (!meta_is_wayland_compositor ()) +- meta_prop_get_window (display->x11_display, +- display->x11_display->xroot, +- display->x11_display->atom__NET_ACTIVE_WINDOW, +- &old_active_xwindow); +-#endif +- + if (!meta_compositor_manage (display->compositor, error)) + { + g_object_unref (display); +@@ -1076,30 +1065,7 @@ meta_display_new (MetaContext *context, + g_signal_connect (display->gesture_tracker, "state-changed", + G_CALLBACK (gesture_tracker_state_changed), display); + +- /* We know that if mutter is running as a Wayland compositor, +- * we start out with no windows. +- */ +-#ifdef HAVE_X11_CLIENT +- if (!meta_is_wayland_compositor ()) +- meta_display_manage_all_xwindows (display); +- +- if (old_active_xwindow != None) +- { +- MetaWindow *old_active_window; +- old_active_window = meta_x11_display_lookup_x_window (display->x11_display, +- old_active_xwindow); +- if (old_active_window) +- meta_window_focus (old_active_window, timestamp); +- else +- meta_display_unset_input_focus (display, timestamp); +- } +- else +- { +- meta_display_unset_input_focus (display, timestamp); +- } +-#else + meta_display_unset_input_focus (display, timestamp); +-#endif + + g_signal_connect (stage, "notify::is-grabbed", + G_CALLBACK (on_is_grabbed_changed), display); +diff --git a/src/tests/x11-test.sh b/src/tests/x11-test.sh +index 59e460fc3..d95b2460f 100755 +--- a/src/tests/x11-test.sh ++++ b/src/tests/x11-test.sh +@@ -34,6 +34,9 @@ echo \# Launched with pid $MUTTER2_PID + MUTTER2_PID=$! + wait $MUTTER1_PID + ++echo \# Waiting for the second mutter to finish loading ++gdbus wait --session org.gnome.Mutter.IdleMonitor ++ + sleep 2 + + echo \# Terminating clients > /dev/stderr +diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c +index 4e98203dd..4ca620410 100644 +--- a/src/x11/meta-x11-display.c ++++ b/src/x11/meta-x11-display.c +@@ -300,8 +300,36 @@ static void + on_x11_display_opened (MetaX11Display *x11_display, + MetaDisplay *display) + { ++ Window old_active_xwindow = None; ++ ++ if (!meta_is_wayland_compositor ()) ++ { ++ meta_prop_get_window (display->x11_display, ++ display->x11_display->xroot, ++ display->x11_display->atom__NET_ACTIVE_WINDOW, ++ &old_active_xwindow); ++ } ++ ++ if (meta_is_wayland_compositor ()) ++ meta_x11_display_redirect_windows (x11_display, display); ++ ++ + meta_display_manage_all_xwindows (display); +- meta_x11_display_redirect_windows (x11_display, display); ++ ++ if (old_active_xwindow != None) ++ { ++ MetaWindow *old_active_window; ++ ++ old_active_window = meta_x11_display_lookup_x_window (x11_display, ++ old_active_xwindow); ++ if (old_active_window) ++ { ++ uint32_t timestamp; ++ ++ timestamp = display->x11_display->timestamp; ++ meta_window_focus (old_active_window, timestamp); ++ } ++ } + } + + static void +-- +2.41.0 + diff --git a/staging/mutter/0001-place-Always-center-initial-setup-fedora-welcome.patch b/staging/mutter/0001-place-Always-center-initial-setup-fedora-welcome.patch new file mode 100644 index 0000000..078b791 --- /dev/null +++ b/staging/mutter/0001-place-Always-center-initial-setup-fedora-welcome.patch @@ -0,0 +1,28 @@ +From 692546a9701a7b363e6190af441a95385c244907 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 2 Dec 2022 22:49:41 +0100 +Subject: [PATCH] place: Always center initial-setup/fedora-welcome + +--- + src/core/place.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/core/place.c b/src/core/place.c +index f9877dfc7..a69a3ebd1 100644 +--- a/src/core/place.c ++++ b/src/core/place.c +@@ -321,6 +321,11 @@ window_place_centered (MetaWindow *window) + + type = window->type; + ++ if (g_strcmp0 (meta_window_get_wm_class (window), "org.gnome.InitialSetup") == 0 || ++ g_strcmp0 (meta_window_get_wm_class (window), "org.fedoraproject.welcome-screen") == 0 || ++ g_strcmp0 (meta_window_get_wm_class (window), "fedora-welcome") == 0) ++ return TRUE; ++ + return (type == META_WINDOW_DIALOG || + type == META_WINDOW_MODAL_DIALOG || + type == META_WINDOW_SPLASHSCREEN || +-- +2.39.2 + diff --git a/staging/mutter/0001-window-actor-Special-case-shaped-Java-windows.patch b/staging/mutter/0001-window-actor-Special-case-shaped-Java-windows.patch new file mode 100644 index 0000000..51f9ecf --- /dev/null +++ b/staging/mutter/0001-window-actor-Special-case-shaped-Java-windows.patch @@ -0,0 +1,70 @@ +From b3b5aa01c63aee1df079e0394b0e6372df1838d0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 12 May 2017 13:40:31 +0200 +Subject: [PATCH] window-actor: Special-case shaped Java windows + +OpenJDK wrongly assumes that shaping a window implies no shadows. +They got lucky until commit b975676c changed the fallback case, +but now their compliance tests are broken. Make them happy again +by special-casing shaped Java windows. +--- + src/compositor/meta-window-actor-x11.c | 8 ++++++++ + src/x11/window-x11-private.h | 2 ++ + src/x11/window-x11.c | 9 +++++++++ + 3 files changed, 19 insertions(+) + +diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c +index 19827af331..7d5e46ac75 100644 +--- a/src/compositor/meta-window-actor-x11.c ++++ b/src/compositor/meta-window-actor-x11.c +@@ -424,6 +424,14 @@ has_shadow (MetaWindowActorX11 *actor_x11) + */ + if (window->has_custom_frame_extents) + return FALSE; ++ ++ /* ++ * OpenJDK wrongly assumes that shaping a window implies no compositor ++ * shadows; make its compliance tests happy to give it what it wants ... ++ */ ++ if (g_strcmp0 (window->res_name, "sun-awt-X11-XWindowPeer") == 0 && ++ meta_window_x11_is_shaped (window)) ++ return FALSE; + + /* + * Generate shadows for all other windows. +diff --git a/src/x11/window-x11-private.h b/src/x11/window-x11-private.h +index c947744ee5..cb862f0d72 100644 +--- a/src/x11/window-x11-private.h ++++ b/src/x11/window-x11-private.h +@@ -125,6 +125,8 @@ gboolean meta_window_x11_has_pointer (MetaWindow *window); + gboolean meta_window_x11_same_application (MetaWindow *window, + MetaWindow *other_window); + ++gboolean meta_window_x11_is_shaped (MetaWindow *window); ++ + void meta_window_x11_shutdown_group (MetaWindow *window); + + META_EXPORT +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index 745c45db18..83cdd2e420 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -2585,6 +2585,15 @@ meta_window_x11_update_shape_region (MetaWindow *window) + meta_window_set_shape_region (window, region); + } + ++gboolean ++meta_window_x11_is_shaped (MetaWindow *window) ++{ ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); ++ MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); ++ ++ return priv->shape_region != NULL; ++} ++ + /* Generally meta_window_x11_same_application() is a better idea + * of "sameness", since it handles the case where multiple apps + * want to look like the same app or the same app wants to look +-- +2.43.2 + diff --git a/staging/mutter/3567.patch b/staging/mutter/3567.patch new file mode 100644 index 0000000..ebfe6d4 --- /dev/null +++ b/staging/mutter/3567.patch @@ -0,0 +1,2090 @@ +From d577df46a223fc821595b113bd89cfeb19a29014 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:41:20 +0100 +Subject: [PATCH 1/4] x11-display: Expose UI scaling factor via D-Bus + +This replaces the `legacy-ui-scaling-factor` entry in +`org.gnome.Mutter.DisplayConfig`, with the motivation being to no longer +expose X11 specific state via the monitor configuration API. +--- + .../org.gnome.Mutter.DisplayConfig.xml | 4 -- + data/dbus-interfaces/org.gnome.Mutter.X11.xml | 8 +++ + src/backends/meta-monitor-manager.c | 7 -- + src/meson.build | 5 ++ + src/x11/meta-x11-display.c | 64 ++++++++++++++++++- + 5 files changed, 76 insertions(+), 12 deletions(-) + create mode 100644 data/dbus-interfaces/org.gnome.Mutter.X11.xml + +diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +index af78ec0517d..7f1957529f0 100644 +--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml ++++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +@@ -420,10 +420,6 @@ + always use the same scale. Absence of + this means logical monitor scales can + differ. +- * "legacy-ui-scaling-factor" (i): The legacy scaling factor traditionally +- used to scale X11 clients (commonly +- communicated via the +- Gdk/WindowScalingFactor XSetting entry). + --> + + +diff --git a/data/dbus-interfaces/org.gnome.Mutter.X11.xml b/data/dbus-interfaces/org.gnome.Mutter.X11.xml +new file mode 100644 +index 00000000000..3d3c8a42f87 +--- /dev/null ++++ b/data/dbus-interfaces/org.gnome.Mutter.X11.xml +@@ -0,0 +1,8 @@ ++ ++ ++ ++ ++ ++ +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 24995edb6fc..94512cef3e5 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -2048,14 +2048,12 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, + GDBusMethodInvocation *invocation, + MetaMonitorManager *manager) + { +- MetaSettings *settings = meta_backend_get_settings (manager->backend); + GVariantBuilder monitors_builder; + GVariantBuilder logical_monitors_builder; + GVariantBuilder properties_builder; + GList *l; + int i; + MetaMonitorManagerCapability capabilities; +- int ui_scaling_factor; + int max_screen_width, max_screen_height; + + g_variant_builder_init (&monitors_builder, +@@ -2244,11 +2242,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, + g_variant_new_boolean (TRUE)); + } + +- ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); +- g_variant_builder_add (&properties_builder, "{sv}", +- "legacy-ui-scaling-factor", +- g_variant_new_int32 (ui_scaling_factor)); +- + if (meta_monitor_manager_get_max_screen_size (manager, + &max_screen_width, + &max_screen_height)) +diff --git a/src/meson.build b/src/meson.build +index 47ee8f570eb..f6079fd8a85 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -943,6 +943,11 @@ dbus_interfaces = [ + 'interface': 'org.gnome.Mutter.DebugControl.xml', + 'prefix': 'org.gnome.Mutter', + }, ++ { ++ 'name': 'meta-dbus-x11', ++ 'interface': 'org.gnome.Mutter.X11.xml', ++ 'prefix': 'org.gnome.Mutter', ++ }, + ] + + if have_profiler +diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c +index 3c3a65061bb..fa2a33f6eca 100644 +--- a/src/x11/meta-x11-display.c ++++ b/src/x11/meta-x11-display.c +@@ -70,7 +70,7 @@ + #include "wayland/meta-xwayland-private.h" + #endif + +-G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++#include "meta-dbus-x11.h" + + static GQuark quark_x11_display_logical_monitor_data = 0; + +@@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData + int xinerama_index; + } MetaX11DisplayLogicalMonitorData; + ++typedef struct _MetaX11DisplayPrivate ++{ ++ MetaDBusX11 *dbus_api; ++ guint dbus_name_id; ++} MetaX11DisplayPrivate; ++ ++G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++ + static char *get_screen_name (Display *xdisplay, + int number); + +@@ -151,13 +159,46 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) + g_free (filter); + } + ++static void ++on_bus_acquired (GDBusConnection *connection, ++ const char *name, ++ gpointer user_data) ++{ ++ MetaX11Display *x11_display = user_data; ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ ++ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), ++ connection, ++ "/org/gnome/Mutter/X11", ++ NULL); ++} ++ ++static void ++update_ui_scaling_factor (MetaX11Display *x11_display) ++{ ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ MetaBackend *backend = backend_from_x11_display (x11_display); ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ int ui_scaling_factor; ++ ++ ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); ++ meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); ++} ++ + static void + meta_x11_display_dispose (GObject *object) + { + MetaX11Display *x11_display = META_X11_DISPLAY (object); ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); + + x11_display->closing = TRUE; + ++ g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); ++ g_clear_object (&priv->dbus_api); ++ + g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); + + g_clear_list (&x11_display->event_funcs, +@@ -1196,6 +1237,23 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) + on_frames_client_died, x11_display); + } + ++static void ++initialize_dbus_interface (MetaX11Display *x11_display) ++{ ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ ++ priv->dbus_api = meta_dbus_x11_skeleton_new (); ++ priv->dbus_name_id = ++ g_bus_own_name (G_BUS_TYPE_SESSION, ++ "org.gnome.Mutter.X11", ++ G_BUS_NAME_OWNER_FLAGS_NONE, ++ on_bus_acquired, ++ NULL, NULL, ++ x11_display, NULL); ++ update_ui_scaling_factor (x11_display); ++} ++ + /** + * meta_x11_display_new: + * +@@ -1290,6 +1348,8 @@ meta_x11_display_new (MetaDisplay *display, + x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); + x11_display->display = display; + ++ initialize_dbus_interface (x11_display); ++ + /* here we use XDisplayName which is what the user + * probably put in, vs. DisplayString(display) which is + * canonicalized by XOpenDisplay() +@@ -1947,6 +2007,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, + } + + x11_display->has_xinerama_indices = FALSE; ++ ++ update_ui_scaling_factor (x11_display); + } + + static Bool +-- +GitLab + + +From 9a329a024bc2f9de3415fdc7a4ba9d8152b27e5c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Tue, 20 Feb 2024 23:51:48 +0100 +Subject: [PATCH 2/4] Add an experimental feature for letting Xwayland clients + scale natively + +With the next commits we'll introduce a new mode for scaling of Xwayland apps, +we'll want to put this mode behind an experimental setting though, so add +that setting. +--- + data/org.gnome.mutter.gschema.xml.in | 8 ++++++++ + src/backends/meta-settings-private.h | 1 + + src/backends/meta-settings.c | 2 ++ + 3 files changed, 11 insertions(+) + +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index fa8cf95dd87..cb60308b6e2 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -4,6 +4,7 @@ + + + ++ + + + + + +diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h +index ca14ce67cb4..90e6998187e 100644 +--- a/src/backends/meta-settings-private.h ++++ b/src/backends/meta-settings-private.h +@@ -31,6 +31,7 @@ typedef enum _MetaExperimentalFeature + META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0), + META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1), + META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND = (1 << 2), ++ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING = (1 << 3), + } MetaExperimentalFeature; + + typedef enum _MetaXwaylandExtension +diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c +index 486ac5abb7f..1042c845b9c 100644 +--- a/src/backends/meta-settings.c ++++ b/src/backends/meta-settings.c +@@ -294,6 +294,8 @@ experimental_features_handler (GVariant *features_variant, + feature = META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS; + else if (g_str_equal (feature_str, "autoclose-xwayland")) + feature = META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND; ++ else if (g_str_equal (feature_str, "xwayland-native-scaling")) ++ feature = META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING; + + if (feature) + g_message ("Enabling experimental feature '%s'", feature_str); +-- +GitLab + + +From 2c3832f66550d62fd733686d7b956c3f9b8a12b1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:42:46 +0100 +Subject: [PATCH 3/4] context: Put Wayland compositor getter in the context + header + +--- + src/meta/meta-context.h | 5 +++++ + src/meta/meta-wayland-compositor.h | 3 --- + src/meta/types.h | 4 ++++ + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h +index ef36bd2c303..2adb9b07e0f 100644 +--- a/src/meta/meta-context.h ++++ b/src/meta/meta-context.h +@@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, + META_EXPORT + gboolean meta_context_restore_rlimit_nofile (MetaContext *context, + GError **error); ++ ++#ifdef HAVE_WAYLAND ++META_EXPORT ++MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); ++#endif +diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h +index 7f4a507057c..3df92fda57d 100644 +--- a/src/meta/meta-wayland-compositor.h ++++ b/src/meta/meta-wayland-compositor.h +@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, + META, WAYLAND_COMPOSITOR, + GObject) + +-META_EXPORT +-MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); +- + META_EXPORT + struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); + +diff --git a/src/meta/types.h b/src/meta/types.h +index cbe2a9a3d7f..8fba4a839ef 100644 +--- a/src/meta/types.h ++++ b/src/meta/types.h +@@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; + + typedef struct _MetaWorkspaceManager MetaWorkspaceManager; + typedef struct _MetaSelection MetaSelection; ++ ++#ifdef HAVE_WAYLAND ++typedef struct _MetaWaylandCompositor MetaWaylandCompositor; ++#endif +-- +GitLab + + +From 24f445e20f7da35df4e53cef13578b91dd372c6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:52:44 +0100 +Subject: [PATCH 4/4] Add experimental mode to use native scaling of Xwayland + clients + +Allow scale-aware Xwayland clients to scale by an integer scale +themselves, instead of letting them render them at 1x scale and then +scaling up the texture, making it look blurry. + +When monitor framebuffers are scaled, this special cases Xwayland and +sends output regions in a way that Xwayland think everything is N times +as large as the logical region, where N is the ceil of the max monitor +scale. + +This is done by introducing a "stage" vs "protocol" coordinate space for +X11, where the "protocol" coordinate space is "stage" multiplied by a +scaling factor. + +We're guarding this behind a new experimental feature +"xwayland-native-scaling", which can only come into effect when enabled +together with "scale-monitor-framebuffer". +--- + src/backends/meta-monitor-manager-private.h | 2 + + src/backends/meta-monitor-manager.c | 6 + + src/compositor/meta-window-actor-x11.c | 22 +- + src/core/frame.c | 106 +++++-- + src/wayland/meta-wayland-cursor-surface.c | 52 ++-- + src/wayland/meta-wayland-outputs.c | 46 ++- + src/wayland/meta-wayland-pointer.c | 14 + + src/wayland/meta-wayland-private.h | 2 + + src/wayland/meta-wayland-surface.c | 30 +- + src/wayland/meta-window-xwayland.c | 71 ++++- + src/wayland/meta-xwayland-private.h | 1 + + src/wayland/meta-xwayland-surface.c | 10 +- + src/wayland/meta-xwayland.c | 56 ++++ + src/wayland/meta-xwayland.h | 2 + + src/x11/meta-x11-display.c | 200 +++++++++++-- + src/x11/window-props.c | 104 ++++++- + src/x11/window-x11.c | 305 ++++++++++++++++---- + src/x11/window-x11.h | 38 +++ + 18 files changed, 898 insertions(+), 169 deletions(-) + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index 0760a341a86..6ed3fc2c3f5 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * + MetaMonitorsConfig *config, + MetaMonitorsConfigMethod method, + GError **error); ++ ++MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 94512cef3e5..c8e42a87539 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -4099,3 +4099,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) + + return priv->virtual_monitors; + } ++ ++MetaLogicalMonitorLayoutMode ++meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) ++{ ++ return manager->layout_mode; ++} +diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c +index 19827af331c..7df10e6c151 100644 +--- a/src/compositor/meta-window-actor-x11.c ++++ b/src/compositor/meta-window-actor-x11.c +@@ -688,11 +688,23 @@ meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, + + surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); + if (surface) +- meta_surface_actor_process_damage (surface, +- event->area.x, +- event->area.y, +- event->area.width, +- event->area.height); ++ { ++ MetaWindow *window = ++ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); ++ MtkRectangle damage; ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->area.x, event->area.y, ++ event->area.width, event->area.height, ++ &damage.x, &damage.y, ++ &damage.width, &damage.height); ++ meta_surface_actor_process_damage (surface, ++ damage.x, ++ damage.y, ++ damage.width, ++ damage.height); ++ } + + meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); + } +diff --git a/src/core/frame.c b/src/core/frame.c +index 914b144b89d..592d2df8982 100644 +--- a/src/core/frame.c ++++ b/src/core/frame.c +@@ -33,6 +33,7 @@ + #include "x11/meta-x11-display-private.h" + #include "x11/window-x11.h" + #include "x11/window-props.h" ++#include "x11/window-x11.h" + + #include + #include +@@ -66,6 +67,7 @@ meta_window_set_frame_xwindow (MetaWindow *window, + XSetWindowAttributes attrs; + gulong create_serial = 0; + MetaFrame *frame; ++ int child_x, child_y; + + if (window->frame) + return; +@@ -127,11 +129,19 @@ meta_window_set_frame_xwindow (MetaWindow *window, + meta_stack_tracker_record_remove (window->display->stack_tracker, + meta_window_x11_get_xwindow (window), + XNextRequest (x11_display->xdisplay)); ++ meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), ++ frame->child_x, ++ frame->child_y, ++ 0, 0, ++ &child_x, ++ &child_y, ++ NULL, NULL); ++ + XReparentWindow (x11_display->xdisplay, + meta_window_x11_get_xwindow (window), + frame->xwindow, +- frame->child_x, +- frame->child_y); ++ child_x, ++ child_y); + window->reparents_pending += 1; + /* FIXME handle this error */ + mtk_x11_error_trap_pop (x11_display->xdisplay); +@@ -201,6 +211,8 @@ meta_window_destroy_frame (MetaWindow *window) + + if (!x11_display->closing) + { ++ int child_x, child_y; ++ + if (!window->unmanaging) + { + meta_stack_tracker_record_add (window->display->stack_tracker, +@@ -208,6 +220,14 @@ meta_window_destroy_frame (MetaWindow *window) + XNextRequest (x11_display->xdisplay)); + } + ++ meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), ++ window->frame->rect.x + borders.invisible.left, ++ window->frame->rect.y + borders.invisible.top, ++ 0, 0, ++ &child_x, ++ &child_y, ++ NULL, NULL); ++ + XReparentWindow (x11_display->xdisplay, + meta_window_x11_get_xwindow (window), + x11_display->xroot, +@@ -215,8 +235,7 @@ meta_window_destroy_frame (MetaWindow *window) + * coordinates here means we'll need to ensure a configure + * notify event is sent; see bug 399552. + */ +- window->frame->rect.x + borders.invisible.left, +- window->frame->rect.y + borders.invisible.top); ++ child_x, child_y); + window->reparents_pending += 1; + } + +@@ -270,6 +289,7 @@ meta_frame_query_borders (MetaFrame *frame, + MetaFrameBorders *borders) + { + MetaWindow *window = frame->window; ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaX11Display *x11_display = window->display->x11_display; + int format, res; + Atom type; +@@ -295,12 +315,22 @@ meta_frame_query_borders (MetaFrame *frame, + + if (res == Success && nitems == 4) + { +- borders->invisible = (MetaFrameBorder) { +- ((long *) data)[0], +- ((long *) data)[1], +- ((long *) data)[2], +- ((long *) data)[3], +- }; ++ int left, right, top, bottom; ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ ((long *) data)[0], ++ ((long *) data)[1], ++ ((long *) data)[2], ++ ((long *) data)[3], ++ &left, ++ &right, ++ &top, ++ &bottom); ++ ++ borders->invisible.left = left; ++ borders->invisible.right = right; ++ borders->invisible.top = top; ++ borders->invisible.bottom = bottom; + } + + g_clear_pointer (&data, XFree); +@@ -321,12 +351,21 @@ meta_frame_query_borders (MetaFrame *frame, + + if (res == Success && nitems == 4) + { +- borders->visible = (MetaFrameBorder) { +- ((long *) data)[0], +- ((long *) data)[1], +- ((long *) data)[2], +- ((long *) data)[3], +- }; ++ int left, right, top, bottom; ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ ((long *) data)[0], ++ ((long *) data)[1], ++ ((long *) data)[2], ++ ((long *) data)[3], ++ &left, ++ &right, ++ &top, ++ &bottom); ++ borders->visible.left = left; ++ borders->visible.right = right; ++ borders->visible.top = top; ++ borders->visible.bottom = bottom; + } + + g_clear_pointer (&data, XFree); +@@ -370,7 +409,9 @@ meta_frame_sync_to_window (MetaFrame *frame, + gboolean need_resize) + { + MetaWindow *window = frame->window; ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaX11Display *x11_display = window->display->x11_display; ++ MtkRectangle rect; + + meta_topic (META_DEBUG_GEOMETRY, + "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", +@@ -381,12 +422,22 @@ meta_frame_sync_to_window (MetaFrame *frame, + + mtk_x11_error_trap_push (x11_display->xdisplay); + ++ meta_window_x11_stage_to_protocol (window_x11, ++ frame->rect.x, ++ frame->rect.y, ++ frame->rect.width, ++ frame->rect.height, ++ &rect.x, ++ &rect.y, ++ &rect.width, ++ &rect.height); ++ + XMoveResizeWindow (x11_display->xdisplay, + frame->xwindow, +- frame->rect.x, +- frame->rect.y, +- frame->rect.width, +- frame->rect.height); ++ rect.x, ++ rect.y, ++ rect.width, ++ rect.height); + + mtk_x11_error_trap_pop (x11_display->xdisplay); + +@@ -423,6 +474,7 @@ static void + send_configure_notify (MetaFrame *frame) + { + MetaX11Display *x11_display = frame->window->display->x11_display; ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (frame->window); + XEvent event = { 0 }; + + /* We never get told by the frames client, just reassert the +@@ -432,10 +484,16 @@ send_configure_notify (MetaFrame *frame) + event.xconfigure.display = x11_display->xdisplay; + event.xconfigure.event = frame->xwindow; + event.xconfigure.window = frame->xwindow; +- event.xconfigure.x = frame->rect.x; +- event.xconfigure.y = frame->rect.y; +- event.xconfigure.width = frame->rect.width; +- event.xconfigure.height = frame->rect.height; ++ ++ meta_window_x11_stage_to_protocol (window_x11, ++ frame->rect.x, ++ frame->rect.y, ++ frame->rect.width, ++ frame->rect.height, ++ &event.xconfigure.x, ++ &event.xconfigure.y, ++ &event.xconfigure.width, ++ &event.xconfigure.height); + event.xconfigure.border_width = 0; + event.xconfigure.above = None; + event.xconfigure.override_redirect = False; +diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c +index 87a8895c886..5a16ce7d879 100644 +--- a/src/wayland/meta-wayland-cursor-surface.c ++++ b/src/wayland/meta-wayland-cursor-surface.c +@@ -92,37 +92,29 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, + { + MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface); + MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role); +- +- if (!meta_wayland_surface_is_xwayland (surface)) ++ MetaContext *context = ++ meta_wayland_compositor_get_context (surface->compositor); ++ MetaBackend *backend = meta_context_get_backend (context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ MetaLogicalMonitor *logical_monitor; ++ ++ logical_monitor = ++ meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); ++ if (logical_monitor) + { +- MetaWaylandSurfaceRole *surface_role = +- META_WAYLAND_SURFACE_ROLE (cursor_surface); +- MetaWaylandSurface *surface = +- meta_wayland_surface_role_get_surface (surface_role); +- MetaContext *context = +- meta_wayland_compositor_get_context (surface->compositor); +- MetaBackend *backend = meta_context_get_backend (context); +- MetaMonitorManager *monitor_manager = +- meta_backend_get_monitor_manager (backend); +- MetaLogicalMonitor *logical_monitor; +- +- logical_monitor = +- meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); +- if (logical_monitor) +- { +- int surface_scale = surface->applied_state.scale; +- float texture_scale; +- +- if (meta_backend_is_stage_views_scaled (backend)) +- texture_scale = 1.0 / surface_scale; +- else +- texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / +- surface_scale); +- +- meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); +- meta_cursor_sprite_set_texture_transform (cursor_sprite, +- surface->buffer_transform); +- } ++ int surface_scale = surface->applied_state.scale; ++ float texture_scale; ++ ++ if (meta_backend_is_stage_views_scaled (backend)) ++ texture_scale = 1.0 / surface_scale; ++ else ++ texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / ++ surface_scale); ++ ++ meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); ++ meta_cursor_sprite_set_texture_transform (cursor_sprite, ++ surface->buffer_transform); + } + + meta_wayland_surface_update_outputs (surface); +diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c +index f7a56f2f274..23398eb45b6 100644 +--- a/src/wayland/meta-wayland-outputs.c ++++ b/src/wayland/meta-wayland-outputs.c +@@ -31,6 +31,10 @@ + #include "backends/meta-monitor-manager-private.h" + #include "wayland/meta-wayland-private.h" + ++#ifdef HAVE_XWAYLAND ++#include "wayland/meta-xwayland.h" ++#endif ++ + #include "xdg-output-unstable-v1-server-protocol.h" + + /* Wayland protocol headers list new additions, not deprecations */ +@@ -50,6 +54,8 @@ struct _MetaWaylandOutput + { + GObject parent; + ++ MetaWaylandCompositor *compositor; ++ + struct wl_global *global; + uint32_t mode_flags; + float refresh_rate; +@@ -427,6 +433,7 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor, + MetaWaylandOutput *wayland_output; + + wayland_output = g_object_new (META_TYPE_WAYLAND_OUTPUT, NULL); ++ wayland_output->compositor = compositor; + wayland_output->global = wl_global_create (compositor->wayland_display, + &wl_output_interface, + META_WL_OUTPUT_VERSION, +@@ -601,6 +608,19 @@ static const struct zxdg_output_v1_interface + meta_xdg_output_destroy, + }; + ++static gboolean ++is_xwayland_resource (MetaWaylandOutput *wayland_output, ++ struct wl_resource *resource) ++{ ++#ifdef HAVE_XWAYLAND ++ MetaXWaylandManager *manager = &wayland_output->compositor->xwayland_manager; ++ ++ return resource && wl_resource_get_client (resource) == manager->client; ++#else ++ return FALSE; ++#endif ++} ++ + static void + send_xdg_output_events (struct wl_resource *resource, + MetaWaylandOutput *wayland_output, +@@ -615,8 +635,28 @@ send_xdg_output_events (struct wl_resource *resource, + logical_monitor = meta_monitor_get_logical_monitor (monitor); + layout = meta_logical_monitor_get_layout (logical_monitor); + +- zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); +- zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++ if (is_xwayland_resource (wayland_output, resource)) ++ { ++#ifdef HAVE_XWAYLAND ++ MetaXWaylandManager *xwayland_manager = ++ &wayland_output->compositor->xwayland_manager; ++ int xwayland_scale; ++ ++ xwayland_scale = meta_xwayland_get_effective_scale (xwayland_manager); ++ layout.x *= xwayland_scale; ++ layout.y *= xwayland_scale; ++ layout.width *= xwayland_scale; ++ layout.height *= xwayland_scale; ++ ++ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); ++ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++#endif ++ } ++ else ++ { ++ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); ++ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++ } + + version = wl_resource_get_version (resource); + +@@ -736,7 +776,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + +- g_signal_connect (monitor_manager, "monitors-changed-internal", ++ g_signal_connect (monitor_manager, "monitors-changed", + G_CALLBACK (on_monitors_changed), compositor); + + compositor->outputs = +diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c +index 98534953930..7ceb6a3daa8 100644 +--- a/src/wayland/meta-wayland-pointer.c ++++ b/src/wayland/meta-wayland-pointer.c +@@ -1190,6 +1190,20 @@ pointer_set_cursor (struct wl_client *client, + cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); + meta_wayland_cursor_surface_set_renderer (cursor_surface, + cursor_renderer); ++ ++#ifdef HAVE_XWAYLAND ++ if (meta_wayland_surface_is_xwayland (surface)) ++ { ++ MetaXWaylandManager *xwayland_manager = ++ &surface->compositor->xwayland_manager; ++ int scale; ++ ++ scale = meta_xwayland_get_effective_scale (xwayland_manager); ++ hot_x = round (hot_x / (double) scale); ++ hot_y = round (hot_y / (double) scale); ++ } ++#endif ++ + meta_wayland_cursor_surface_set_hotspot (cursor_surface, + hot_x, hot_y); + +diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h +index e8d442c0398..834753ffdd3 100644 +--- a/src/wayland/meta-wayland-private.h ++++ b/src/wayland/meta-wayland-private.h +@@ -77,6 +77,8 @@ struct _MetaXWaylandManager + int rr_error_base; + + gboolean should_enable_ei_portal; ++ ++ double highest_monitor_scale; + }; + + struct _MetaWaylandCompositor +diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c +index 3761c7b725d..0c06020bb8b 100644 +--- a/src/wayland/meta-wayland-surface.c ++++ b/src/wayland/meta-wayland-surface.c +@@ -773,8 +773,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, + state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL)); + } + +- if (state->scale > 0) +- surface->applied_state.scale = state->scale; ++ if (meta_wayland_surface_is_xwayland (surface)) ++ { ++#ifdef HAVE_XWAYLAND ++ MetaXWaylandManager *xwayland_manager = ++ &surface->compositor->xwayland_manager; ++ ++ surface->applied_state.scale = meta_xwayland_get_effective_scale (xwayland_manager); ++#endif ++ } ++ else if (state->scale > 0) ++ { ++ surface->applied_state.scale = state->scale; ++ } + + if (state->has_new_buffer_transform) + surface->buffer_transform = state->buffer_transform; +@@ -962,8 +973,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) + MetaMultiTexture *committed_texture = surface->committed_state.texture; + int committed_scale = surface->committed_state.scale; + +- if ((meta_multi_texture_get_width (committed_texture) % committed_scale != 0) || +- (meta_multi_texture_get_height (committed_texture) % committed_scale != 0)) ++ if (((meta_multi_texture_get_width (committed_texture) % committed_scale != 0) || ++ (meta_multi_texture_get_height (committed_texture) % committed_scale != 0)) && ++ !meta_wayland_surface_is_xwayland (surface)) + { + if (!surface->role || !META_IS_WAYLAND_CURSOR_SURFACE (surface->role)) + { +@@ -1497,6 +1509,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) + g_hash_table_foreach (surface->compositor->outputs, + update_surface_output_state, + surface); ++ ++ if (meta_wayland_surface_is_xwayland (surface)) ++ { ++#ifdef HAVE_XWAYLAND ++ MetaXWaylandManager *xwayland_manager = ++ &surface->compositor->xwayland_manager; ++ ++ surface->applied_state.scale = meta_xwayland_get_effective_scale (xwayland_manager); ++#endif ++ } + } + + void +diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c +index 1299a351ca7..5fb00696267 100644 +--- a/src/wayland/meta-window-xwayland.c ++++ b/src/wayland/meta-window-xwayland.c +@@ -27,8 +27,9 @@ + #include "x11/window-x11-private.h" + #include "x11/xprops.h" + #include "wayland/meta-window-xwayland.h" +-#include "wayland/meta-wayland.h" ++#include "wayland/meta-wayland-private.h" + #include "wayland/meta-wayland-surface-private.h" ++#include "wayland/meta-xwayland.h" + + enum + { +@@ -315,6 +316,72 @@ meta_window_xwayland_process_property_notify (MetaWindow *window, + meta_window_queue (window, META_QUEUE_MOVE_RESIZE); + } + ++static void ++meta_window_xwayland_stage_to_protocol (MetaWindowX11 *window_x11, ++ int stage_x, ++ int stage_y, ++ int stage_width, ++ int stage_height, ++ int *protocol_x, ++ int *protocol_y, ++ int *protocol_width, ++ int *protocol_height) ++{ ++ MetaDisplay *display = meta_window_get_display (META_WINDOW (window_x11)); ++ MetaContext *context = meta_display_get_context (display); ++ MetaWaylandCompositor *wayland_compositor = ++ meta_context_get_wayland_compositor (context); ++ MetaXWaylandManager *xwayland_manager = &wayland_compositor->xwayland_manager; ++ int scale; ++ ++ scale = meta_xwayland_get_effective_scale (xwayland_manager); ++ if (protocol_x) ++ *protocol_x = stage_x * scale; ++ if (protocol_y) ++ *protocol_y = stage_y * scale; ++ if (protocol_width) ++ *protocol_width = stage_width * scale; ++ if (protocol_height) ++ *protocol_height = stage_height * scale; ++} ++ ++static void ++meta_window_xwayland_protocol_to_stage (MetaWindowX11 *window_x11, ++ int protocol_x, ++ int protocol_y, ++ int protocol_width, ++ int protocol_height, ++ int *stage_x, ++ int *stage_y, ++ int *stage_width, ++ int *stage_height) ++{ ++ MetaDisplay *display = meta_window_get_display (META_WINDOW (window_x11)); ++ MetaContext *context = meta_display_get_context (display); ++ MetaWaylandCompositor *wayland_compositor = ++ meta_context_get_wayland_compositor (context); ++ MetaXWaylandManager *xwayland_manager = &wayland_compositor->xwayland_manager; ++ MtkRectangle rect; ++ int scale; ++ ++ rect.x = protocol_x; ++ rect.y = protocol_y; ++ rect.width = protocol_width; ++ rect.height = protocol_height; ++ ++ scale = meta_xwayland_get_effective_scale (xwayland_manager); ++ mtk_rectangle_scale_double (&rect, 1.0 / scale, MTK_ROUNDING_STRATEGY_GROW, &rect); ++ ++ if (stage_x) ++ *stage_x = rect.x; ++ if (stage_y) ++ *stage_y = rect.y; ++ if (stage_width) ++ *stage_width = rect.width; ++ if (stage_height) ++ *stage_height = rect.height; ++} ++ + static void + meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) + { +@@ -331,6 +398,8 @@ meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) + window_x11_class->thaw_commits = meta_window_xwayland_thaw_commits; + window_x11_class->always_update_shape = meta_window_xwayland_always_update_shape; + window_x11_class->process_property_notify = meta_window_xwayland_process_property_notify; ++ window_x11_class->stage_to_protocol = meta_window_xwayland_stage_to_protocol; ++ window_x11_class->protocol_to_stage = meta_window_xwayland_protocol_to_stage; + + gobject_class->get_property = meta_window_xwayland_get_property; + gobject_class->set_property = meta_window_xwayland_set_property; +diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h +index 7a9cb73fdf9..9e06f03155f 100644 +--- a/src/wayland/meta-xwayland-private.h ++++ b/src/wayland/meta-xwayland-private.h +@@ -20,6 +20,7 @@ + #include + + #include "wayland/meta-wayland-private.h" ++#include "wayland/meta-xwayland.h" + + gboolean + meta_xwayland_init (MetaXWaylandManager *manager, +diff --git a/src/wayland/meta-xwayland-surface.c b/src/wayland/meta-xwayland-surface.c +index 8fa1c72a969..c6daf9b2670 100644 +--- a/src/wayland/meta-xwayland-surface.c ++++ b/src/wayland/meta-xwayland-surface.c +@@ -163,13 +163,19 @@ meta_xwayland_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_ + float *out_sy) + { + MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role); ++ MetaWaylandSurface *surface = ++ meta_wayland_surface_role_get_surface (surface_role); ++ MetaWaylandCompositor *compositor = ++ meta_wayland_surface_get_compositor (surface); + MtkRectangle window_rect = { 0 }; ++ int xwayland_scale; + + if (xwayland_surface->window) + meta_window_get_buffer_rect (xwayland_surface->window, &window_rect); + +- *out_sx = abs_x - window_rect.x; +- *out_sy = abs_y - window_rect.y; ++ xwayland_scale = meta_xwayland_get_effective_scale (&compositor->xwayland_manager); ++ *out_sx = (abs_x - window_rect.x) * xwayland_scale; ++ *out_sy = (abs_y - window_rect.y) * xwayland_scale; + } + + static MetaWaylandSurface * +diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c +index ea9c27d74a0..828e6f64efe 100644 +--- a/src/wayland/meta-xwayland.c ++++ b/src/wayland/meta-xwayland.c +@@ -1051,6 +1051,29 @@ meta_xwayland_shutdown (MetaWaylandCompositor *compositor) + } + } + ++static void ++update_highest_monitor_scale (MetaXWaylandManager *manager) ++{ ++ MetaWaylandCompositor *compositor = manager->compositor; ++ MetaContext *context = meta_wayland_compositor_get_context (compositor); ++ MetaBackend *backend = meta_context_get_backend (context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ GList *logical_monitors; ++ GList *l; ++ double scale = 1.0; ++ ++ logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager); ++ for (l = logical_monitors; l; l = l->next) ++ { ++ MetaLogicalMonitor *logical_monitor = l->data; ++ ++ scale = MAX (scale, meta_logical_monitor_get_scale (logical_monitor)); ++ } ++ ++ manager->highest_monitor_scale = scale; ++} ++ + gboolean + meta_xwayland_init (MetaXWaylandManager *manager, + MetaWaylandCompositor *compositor, +@@ -1058,6 +1081,9 @@ meta_xwayland_init (MetaXWaylandManager *manager, + GError **error) + { + MetaContext *context = compositor->context; ++ MetaBackend *backend = meta_context_get_backend (context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); + MetaX11DisplayPolicy policy; + int display = 0; + +@@ -1121,6 +1147,10 @@ meta_xwayland_init (MetaXWaylandManager *manager, + /* Xwayland specific protocol, needs to be filtered out for all other clients */ + meta_xwayland_grab_keyboard_init (compositor); + ++ g_signal_connect_swapped (monitor_manager, "monitors-changed-internal", ++ G_CALLBACK (update_highest_monitor_scale), manager); ++ update_highest_monitor_scale (manager); ++ + return TRUE; + } + +@@ -1312,3 +1342,29 @@ meta_xwayland_set_should_enable_ei_portal (MetaXWaylandManager *manager, + { + manager->should_enable_ei_portal = should_enable_ei_portal; + } ++ ++int ++meta_xwayland_get_effective_scale (MetaXWaylandManager *manager) ++{ ++ MetaWaylandCompositor *compositor = manager->compositor; ++ MetaContext *context = meta_wayland_compositor_get_context (compositor); ++ MetaBackend *backend = meta_context_get_backend (context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ ++ switch (meta_monitor_manager_get_layout_mode (monitor_manager)) ++ { ++ case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: ++ break; ++ ++ case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: ++ if (meta_settings_is_experimental_feature_enabled (settings, ++ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING) && ++ meta_settings_is_experimental_feature_enabled (settings, ++ META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) ++ return ceil (manager->highest_monitor_scale); ++ } ++ ++ return 1; ++} +diff --git a/src/wayland/meta-xwayland.h b/src/wayland/meta-xwayland.h +index daf9d1abb03..ae7a06977e4 100644 +--- a/src/wayland/meta-xwayland.h ++++ b/src/wayland/meta-xwayland.h +@@ -48,3 +48,5 @@ META_EXPORT_TEST + gboolean meta_xwayland_signal (MetaXWaylandManager *manager, + int signum, + GError **error); ++ ++int meta_xwayland_get_effective_scale (MetaXWaylandManager *manager); +diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c +index fa2a33f6eca..84e639c1b01 100644 +--- a/src/x11/meta-x11-display.c ++++ b/src/x11/meta-x11-display.c +@@ -130,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) + return meta_context_get_backend (context); + } + ++static void ++stage_to_protocol (MetaX11Display *x11_display, ++ int stage_x, ++ int stage_y, ++ int *protocol_x, ++ int *protocol_y) ++{ ++ MetaDisplay *display = meta_x11_display_get_display (x11_display); ++ MetaContext *context = meta_display_get_context (display); ++ int scale = 1; ++ ++ switch (meta_context_get_compositor_type (context)) ++ { ++ case META_COMPOSITOR_TYPE_WAYLAND: ++ { ++#ifdef HAVE_XWAYLAND ++ MetaWaylandCompositor *wayland_compositor = ++ meta_context_get_wayland_compositor (context); ++ MetaXWaylandManager *xwayland_manager = ++ &wayland_compositor->xwayland_manager; ++ ++ scale = meta_xwayland_get_effective_scale (xwayland_manager); ++#endif ++ break; ++ } ++ ++ case META_COMPOSITOR_TYPE_X11: ++ break; ++ } ++ ++ if (protocol_x) ++ *protocol_x = stage_x * scale; ++ if (protocol_y) ++ *protocol_y = stage_y * scale; ++} ++ + static void + meta_x11_display_unmanage_windows (MetaX11Display *x11_display) + { +@@ -180,10 +216,32 @@ update_ui_scaling_factor (MetaX11Display *x11_display) + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); + MetaBackend *backend = backend_from_x11_display (x11_display); +- MetaSettings *settings = meta_backend_get_settings (backend); +- int ui_scaling_factor; ++ MetaContext *context = meta_backend_get_context (backend); ++ int ui_scaling_factor = 1; ++ ++ switch (meta_context_get_compositor_type (context)) ++ { ++ case META_COMPOSITOR_TYPE_WAYLAND: ++ { ++#ifdef HAVE_XWAYLAND ++ MetaWaylandCompositor *wayland_compositor = ++ meta_context_get_wayland_compositor (context); ++ MetaXWaylandManager *xwayland_manager = ++ &wayland_compositor->xwayland_manager; ++ ++ ui_scaling_factor = meta_xwayland_get_effective_scale (xwayland_manager); ++#endif ++ break; ++ } ++ case META_COMPOSITOR_TYPE_X11: ++ { ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ ++ ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); ++ break; ++ } ++ } + +- ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); + meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); + } + +@@ -613,6 +671,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) + return; + + meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); ++ stage_to_protocol (x11_display, ++ monitor_width, monitor_height, ++ &monitor_width, &monitor_height); + + data[0] = monitor_width; + data[1] = monitor_height; +@@ -1022,14 +1083,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, + + for (l = logical_monitors; l; l = l->next) + { +- MtkRectangle area; +- +- meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, &area); +- +- tmp[0] = area.x; +- tmp[1] = area.y; +- tmp[2] = area.width; +- tmp[3] = area.height; ++ MtkRectangle stage_area; ++ MtkRectangle protocol_area; ++ ++ meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, ++ &stage_area); ++ ++ stage_to_protocol (x11_display, ++ stage_area.x, stage_area.y, ++ &protocol_area.x, &protocol_area.y); ++ stage_to_protocol (x11_display, ++ stage_area.width, stage_area.height, ++ &protocol_area.width, &protocol_area.height); ++ tmp[0] = protocol_area.x; ++ tmp[1] = protocol_area.y; ++ tmp[2] = protocol_area.width; ++ tmp[3] = protocol_area.height; + + tmp += 4; + } +@@ -1058,7 +1127,6 @@ set_work_area_hint (MetaDisplay *display, + int num_workspaces; + GList *l; + unsigned long *data, *tmp; +- MtkRectangle area; + + num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); + data = g_new (unsigned long, num_workspaces * 4); +@@ -1067,14 +1135,22 @@ set_work_area_hint (MetaDisplay *display, + for (l = workspace_manager->workspaces; l; l = l->next) + { + MetaWorkspace *workspace = l->data; ++ MtkRectangle stage_area; ++ MtkRectangle protocol_area; + +- meta_workspace_get_work_area_all_monitors (workspace, &area); ++ meta_workspace_get_work_area_all_monitors (workspace, &stage_area); + set_workspace_work_area_hint (workspace, x11_display); + +- tmp[0] = area.x; +- tmp[1] = area.y; +- tmp[2] = area.width; +- tmp[3] = area.height; ++ stage_to_protocol (x11_display, ++ stage_area.x, stage_area.y, ++ &protocol_area.x, &protocol_area.y); ++ stage_to_protocol (x11_display, ++ stage_area.width, stage_area.height, ++ &protocol_area.width, &protocol_area.height); ++ tmp[0] = protocol_area.x; ++ tmp[1] = protocol_area.y; ++ tmp[2] = protocol_area.width; ++ tmp[3] = protocol_area.height; + + tmp += 4; + } +@@ -1254,6 +1330,41 @@ initialize_dbus_interface (MetaX11Display *x11_display) + update_ui_scaling_factor (x11_display); + } + ++static void ++experimental_features_changed (MetaSettings *settings, ++ MetaExperimentalFeature old_experimental_features, ++ MetaX11Display *x11_display) ++{ ++ gboolean was_xwayland_native_scaling; ++ gboolean was_stage_views_scaled; ++ gboolean is_xwayland_native_scaling; ++ gboolean is_stage_views_scaled; ++ ++ was_xwayland_native_scaling = ++ !!(old_experimental_features & ++ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING); ++ was_stage_views_scaled = ++ !!(old_experimental_features & ++ META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); ++ ++ is_xwayland_native_scaling = ++ meta_settings_is_experimental_feature_enabled ( ++ settings, ++ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING); ++ is_stage_views_scaled = ++ meta_settings_is_experimental_feature_enabled ( ++ settings, ++ META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); ++ ++ if (is_xwayland_native_scaling != was_xwayland_native_scaling || ++ is_stage_views_scaled != was_stage_views_scaled) ++ { ++ update_ui_scaling_factor (x11_display); ++ set_desktop_geometry_hint (x11_display); ++ set_work_area_hint (x11_display->display, x11_display); ++ } ++} ++ + /** + * meta_x11_display_new: + * +@@ -1272,6 +1383,7 @@ meta_x11_display_new (MetaDisplay *display, + MetaBackend *backend = meta_context_get_backend (context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); ++ MetaSettings *settings = meta_backend_get_settings (backend); + g_autoptr (MetaX11Display) x11_display = NULL; + Display *xdisplay; + Screen *xscreen; +@@ -1442,7 +1554,7 @@ meta_x11_display_new (MetaDisplay *display, + "monitors-changed-internal", + G_CALLBACK (on_monitors_changed_internal), + x11_display, +- 0); ++ G_CONNECT_AFTER); + + init_leader_window (x11_display, ×tamp); + x11_display->timestamp = timestamp; +@@ -1535,6 +1647,11 @@ meta_x11_display_new (MetaDisplay *display, + + meta_prefs_add_listener (prefs_changed_callback, x11_display); + ++ g_signal_connect_object (settings, ++ "experimental-features-changed", ++ G_CALLBACK (experimental_features_changed), ++ x11_display, 0); ++ + set_work_area_hint (display, x11_display); + + g_signal_connect_object (display, "workareas-changed", +@@ -1744,16 +1861,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) + } + + static void +-set_cursor_theme (Display *xdisplay, +- MetaBackend *backend) ++set_cursor_theme (Display *xdisplay, ++ const char *theme, ++ int size) + { +- MetaSettings *settings = meta_backend_get_settings (backend); +- int scale; +- +- scale = meta_settings_get_ui_scaling_factor (settings); +- XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ()); +- XcursorSetDefaultSize (xdisplay, +- meta_prefs_get_cursor_size () * scale); ++ XcursorSetTheme (xdisplay, theme); ++ XcursorSetDefaultSize (xdisplay, size); + } + + static void +@@ -1805,8 +1918,37 @@ static void + update_cursor_theme (MetaX11Display *x11_display) + { + MetaBackend *backend = backend_from_x11_display (x11_display); ++ MetaContext *context = meta_backend_get_context (backend); ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ int scale = 1; ++ int size; ++ const char *theme; ++ ++ switch (meta_context_get_compositor_type (context)) ++ { ++ case META_COMPOSITOR_TYPE_WAYLAND: ++ { ++#ifdef HAVE_XWAYLAND ++ MetaWaylandCompositor *wayland_compositor = ++ meta_context_get_wayland_compositor (context); ++ MetaXWaylandManager *xwayland_manager = ++ &wayland_compositor->xwayland_manager; ++ ++ scale = meta_xwayland_get_effective_scale (xwayland_manager); ++#endif ++ break; ++ } ++ ++ case META_COMPOSITOR_TYPE_X11: ++ scale = meta_settings_get_ui_scaling_factor (settings); ++ break; ++ } ++ ++ size = meta_prefs_get_cursor_size () * scale; ++ ++ theme = meta_prefs_get_cursor_theme (); + +- set_cursor_theme (x11_display->xdisplay, backend); ++ set_cursor_theme (x11_display->xdisplay, theme, size); + schedule_reload_x11_cursor (x11_display); + + if (META_IS_BACKEND_X11 (backend)) +@@ -1814,7 +1956,7 @@ update_cursor_theme (MetaX11Display *x11_display) + MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); + Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); + +- set_cursor_theme (xdisplay, backend); ++ set_cursor_theme (xdisplay, theme, size); + meta_backend_x11_reload_cursor (backend_x11); + } + } +diff --git a/src/x11/window-props.c b/src/x11/window-props.c +index 73f80395b0c..2c67e91f486 100644 +--- a/src/x11/window-props.c ++++ b/src/x11/window-props.c +@@ -305,10 +305,15 @@ reload_icon_geometry (MetaWindow *window, + { + MtkRectangle geometry; + +- geometry.x = (int)value->v.cardinal_list.cardinals[0]; +- geometry.y = (int)value->v.cardinal_list.cardinals[1]; +- geometry.width = (int)value->v.cardinal_list.cardinals[2]; +- geometry.height = (int)value->v.cardinal_list.cardinals[3]; ++ meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), ++ value->v.cardinal_list.cardinals[0], ++ value->v.cardinal_list.cardinals[1], ++ value->v.cardinal_list.cardinals[2], ++ value->v.cardinal_list.cardinals[3], ++ &geometry.x, ++ &geometry.y, ++ &geometry.width, ++ &geometry.height); + + meta_window_set_icon_geometry (window, &geometry); + } +@@ -370,11 +375,24 @@ reload_gtk_frame_extents (MetaWindow *window, + } + else + { ++ int left, right, top, bottom; + MetaFrameBorder extents; +- extents.left = (int)value->v.cardinal_list.cardinals[0]; +- extents.right = (int)value->v.cardinal_list.cardinals[1]; +- extents.top = (int)value->v.cardinal_list.cardinals[2]; +- extents.bottom = (int)value->v.cardinal_list.cardinals[3]; ++ ++ meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), ++ value->v.cardinal_list.cardinals[0], ++ value->v.cardinal_list.cardinals[1], ++ value->v.cardinal_list.cardinals[2], ++ value->v.cardinal_list.cardinals[3], ++ &left, ++ &right, ++ &top, ++ &bottom); ++ ++ extents.left = left; ++ extents.right = right; ++ extents.top = top; ++ extents.bottom = bottom; ++ + meta_window_set_custom_frame_extents (window, &extents, initial); + } + } +@@ -678,10 +696,16 @@ reload_opaque_region (MetaWindow *window, + { + MtkRectangle *rect = &rects[rect_index]; + +- rect->x = region[i++]; +- rect->y = region[i++]; +- rect->width = region[i++]; +- rect->height = region[i++]; ++ meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), ++ region[i + 0], ++ region[i + 1], ++ region[i + 2], ++ region[i + 3], ++ &rect->x, ++ &rect->y, ++ &rect->width, ++ &rect->height); ++ i += 4; + + rect_index++; + } +@@ -1245,7 +1269,61 @@ meta_set_normal_hints (MetaWindow *window, + * as if flags were zero + */ + if (hints) +- window->size_hints = *hints; ++ { ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); ++ ++ window->size_hints = *hints; ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->x, hints->y, ++ hints->width, hints->height, ++ &window->size_hints.x, ++ &window->size_hints.y, ++ &window->size_hints.width, ++ &window->size_hints.height); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->min_width, hints->min_height, ++ 0, 0, ++ &window->size_hints.min_width, ++ &window->size_hints.min_height, ++ NULL, NULL); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->max_width, hints->max_height, ++ 0, 0, ++ &window->size_hints.max_width, ++ &window->size_hints.max_height, ++ NULL, NULL); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->width_inc, hints->height_inc, ++ 0, 0, ++ &window->size_hints.width_inc, ++ &window->size_hints.height_inc, ++ NULL, NULL); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->min_aspect.x, hints->min_aspect.y, ++ 0, 0, ++ &window->size_hints.min_aspect.x, ++ &window->size_hints.min_aspect.y, ++ NULL, NULL); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->max_aspect.x, hints->max_aspect.y, ++ 0, 0, ++ &window->size_hints.max_aspect.x, ++ &window->size_hints.max_aspect.y, ++ NULL, NULL); ++ ++ meta_window_x11_protocol_to_stage (window_x11, ++ hints->base_width, hints->base_height, ++ 0, 0, ++ &window->size_hints.base_width, ++ &window->size_hints.base_height, ++ NULL, NULL); ++ } + else + window->size_hints.flags = 0; + +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index 42981584cce..491d49e5c29 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) + return meta_window_x11_get_instance_private (window_x11); + } + ++static void ++meta_window_x11_real_stage_to_protocol (MetaWindowX11 *window_x11, ++ int stage_x, ++ int stage_y, ++ int stage_width, ++ int stage_height, ++ int *protocol_x, ++ int *protocol_y, ++ int *protocol_width, ++ int *protocol_height) ++{ ++ if (protocol_x) ++ *protocol_x = stage_x; ++ if (protocol_y) ++ *protocol_y = stage_y; ++ if (protocol_width) ++ *protocol_width = stage_width; ++ if (protocol_height) ++ *protocol_height = stage_height; ++} ++ ++static void ++meta_window_x11_real_protocol_to_stage (MetaWindowX11 *window_x11, ++ int protocol_x, ++ int protocol_y, ++ int protocol_width, ++ int protocol_height, ++ int *stage_x, ++ int *stage_y, ++ int *stage_width, ++ int *stage_height) ++{ ++ if (stage_x) ++ *stage_x = protocol_x; ++ if (stage_y) ++ *stage_y = protocol_y; ++ if (stage_width) ++ *stage_width = protocol_width; ++ if (stage_height) ++ *stage_height = protocol_height; ++} ++ ++void ++meta_window_x11_stage_to_protocol (MetaWindowX11 *window_x11, ++ int stage_x, ++ int stage_y, ++ int stage_width, ++ int stage_height, ++ int *protocol_x, ++ int *protocol_y, ++ int *protocol_width, ++ int *protocol_height) ++{ ++ MetaWindowX11Class *klass = META_WINDOW_X11_GET_CLASS (window_x11); ++ ++ klass->stage_to_protocol (window_x11, ++ stage_x, stage_y, ++ stage_width, stage_height, ++ protocol_x, protocol_y, ++ protocol_width, protocol_height); ++} ++ ++void ++meta_window_x11_protocol_to_stage (MetaWindowX11 *window_x11, ++ int protocol_x, ++ int protocol_y, ++ int protocol_width, ++ int protocol_height, ++ int *stage_x, ++ int *stage_y, ++ int *stage_width, ++ int *stage_height) ++{ ++ MetaWindowX11Class *klass = META_WINDOW_X11_GET_CLASS (window_x11); ++ ++ klass->protocol_to_stage (window_x11, ++ protocol_x, protocol_y, ++ protocol_width, protocol_height, ++ stage_x, stage_y, ++ stage_width, stage_height); ++} ++ ++static MtkRegion * ++region_protocol_to_stage (MtkRegion *region, ++ MetaWindowX11 *window_x11) ++{ ++ int n_rects, i; ++ MtkRectangle *rects; ++ MtkRegion *scaled_region; ++ ++ n_rects = mtk_region_num_rectangles (region); ++ MTK_RECTANGLE_CREATE_ARRAY_SCOPED (n_rects, rects); ++ for (i = 0; i < n_rects; i++) ++ { ++ rects[i] = mtk_region_get_rectangle (region, i); ++ meta_window_x11_protocol_to_stage (window_x11, ++ rects[i].x, rects[i].y, ++ rects[i].width, rects[i].height, ++ &rects[i].x, &rects[i].y, ++ &rects[i].width, &rects[i].height); ++ } ++ ++ scaled_region = mtk_region_create_rectangles (rects, n_rects); ++ ++ return scaled_region; ++} ++ + static void + send_icccm_message (MetaWindow *window, + Atom atom, +@@ -254,8 +361,13 @@ send_configure_notify (MetaWindow *window) + event.xconfigure.display = x11_display->xdisplay; + event.xconfigure.event = priv->xwindow; + event.xconfigure.window = priv->xwindow; +- event.xconfigure.x = priv->client_rect.x - priv->border_width; +- event.xconfigure.y = priv->client_rect.y - priv->border_width; ++ meta_window_x11_stage_to_protocol (window_x11, ++ priv->client_rect.x - priv->border_width, ++ priv->client_rect.y - priv->border_width, ++ 0, 0, ++ &event.xconfigure.x, ++ &event.xconfigure.y, ++ NULL, NULL); + if (window->frame) + { + if (window->withdrawn) +@@ -267,19 +379,42 @@ send_configure_notify (MetaWindow *window) + + meta_frame_calc_borders (window->frame, &borders); + +- event.xconfigure.x = window->frame->rect.x + borders.invisible.left; +- event.xconfigure.y = window->frame->rect.y + borders.invisible.top; ++ meta_window_x11_stage_to_protocol (window_x11, ++ window->frame->rect.x + borders.invisible.left, ++ window->frame->rect.y + borders.invisible.top, ++ 0, 0, ++ &event.xconfigure.x, ++ &event.xconfigure.y, ++ NULL, NULL); + } + else + { ++ int dx, dy; ++ + /* Need to be in root window coordinates */ +- event.xconfigure.x += window->frame->rect.x; +- event.xconfigure.y += window->frame->rect.y; ++ meta_window_x11_stage_to_protocol (window_x11, ++ window->frame->rect.x, ++ window->frame->rect.y, ++ 0, 0, ++ &dx, ++ &dy, ++ NULL, NULL); ++ event.xconfigure.x += dx; ++ event.xconfigure.y += dy; + } + } +- event.xconfigure.width = priv->client_rect.width; +- event.xconfigure.height = priv->client_rect.height; +- event.xconfigure.border_width = priv->border_width; /* requested not actual */ ++ meta_window_x11_stage_to_protocol (window_x11, ++ priv->client_rect.width, ++ priv->client_rect.height, ++ 0, 0, ++ &event.xconfigure.width, ++ &event.xconfigure.height, ++ NULL, NULL); ++ meta_window_x11_stage_to_protocol (window_x11, ++ priv->border_width, ++ 0, 0, 0, ++ &event.xconfigure.border_width, ++ NULL, NULL, NULL); + event.xconfigure.above = None; /* FIXME */ + event.xconfigure.override_redirect = False; + +@@ -1137,20 +1272,26 @@ static void + update_net_frame_extents (MetaWindow *window) + { + MetaX11Display *x11_display = window->display->x11_display; +- ++ int left, right, top, bottom; + unsigned long data[4]; + MetaFrameBorders borders; + Window xwindow = meta_window_x11_get_xwindow (window); + + meta_frame_calc_borders (window->frame, &borders); +- /* Left */ +- data[0] = borders.visible.left; +- /* Right */ +- data[1] = borders.visible.right; +- /* Top */ +- data[2] = borders.visible.top; +- /* Bottom */ +- data[3] = borders.visible.bottom; ++ meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), ++ borders.visible.left, ++ borders.visible.right, ++ borders.visible.top, ++ borders.visible.bottom, ++ &left, ++ &right, ++ &top, ++ &bottom); ++ ++ data[0] = left; ++ data[1] = right; ++ data[2] = top; ++ data[3] = bottom; + + meta_topic (META_DEBUG_GEOMETRY, + "Setting _NET_FRAME_EXTENTS on managed window 0x%lx " +@@ -1482,10 +1623,11 @@ meta_window_x11_move_resize_internal (MetaWindow *window, + configure_frame_first = size_dx + size_dy >= 0; + + values.border_width = 0; +- values.x = client_rect.x; +- values.y = client_rect.y; +- values.width = client_rect.width; +- values.height = client_rect.height; ++ meta_window_x11_stage_to_protocol (window_x11, ++ client_rect.x, client_rect.y, ++ client_rect.width, client_rect.height, ++ &values.x, &values.y, ++ &values.width, &values.height); + + mask = 0; + if (is_configure_request && priv->border_width != 0) +@@ -1591,6 +1733,10 @@ meta_window_x11_update_struts (MetaWindow *window) + strut_begin = struts[4+(i*2)]; + strut_end = struts[4+(i*2)+1]; + ++ meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), ++ strut_begin, strut_end, thickness, 0, ++ &strut_begin, &strut_end, &thickness, NULL); ++ + temp = g_new0 (MetaStrut, 1); + temp->side = 1 << i; /* See MetaSide def. Matches nicely, eh? */ + meta_display_get_size (window->display, +@@ -1655,6 +1801,10 @@ meta_window_x11_update_struts (MetaWindow *window) + if (thickness == 0) + continue; + ++ meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), ++ thickness, 0, 0, 0, ++ &thickness, NULL, NULL, NULL); ++ + temp = g_new0 (MetaStrut, 1); + temp->side = 1 << i; + meta_display_get_size (window->display, +@@ -2048,9 +2198,10 @@ static void + meta_window_x11_constructed (GObject *object) + { + MetaWindow *window = META_WINDOW (object); +- MetaWindowX11 *x11_window = META_WINDOW_X11 (object); +- MetaWindowX11Private *priv = meta_window_x11_get_instance_private (x11_window); ++ MetaWindowX11 *window_x11 = META_WINDOW_X11 (object); ++ MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); + XWindowAttributes attrs = priv->attributes; ++ MtkRectangle rect; + + meta_verbose ("attrs->map_state = %d (%s)", + attrs.map_state, +@@ -2065,16 +2216,17 @@ meta_window_x11_constructed (GObject *object) + window->client_type = META_WINDOW_CLIENT_TYPE_X11; + window->override_redirect = attrs.override_redirect; + +- window->rect.x = attrs.x; +- window->rect.y = attrs.y; +- window->rect.width = attrs.width; +- window->rect.height = attrs.height; ++ meta_window_x11_protocol_to_stage (window_x11, ++ attrs.x, attrs.y, attrs.width, attrs.height, ++ &rect.x, &rect.y, &rect.width, &rect.height); ++ ++ window->rect = rect; + + /* size_hints are the "request" */ +- window->size_hints.x = attrs.x; +- window->size_hints.y = attrs.y; +- window->size_hints.width = attrs.width; +- window->size_hints.height = attrs.height; ++ window->size_hints.x = rect.x; ++ window->size_hints.y = rect.y; ++ window->size_hints.width = rect.width; ++ window->size_hints.height = rect.height; + + window->depth = attrs.depth; + priv->xvisual = attrs.visual; +@@ -2084,11 +2236,11 @@ meta_window_x11_constructed (GObject *object) + + window->decorated = TRUE; + window->hidden = FALSE; +- priv->border_width = attrs.border_width; + priv->xclient_leader = None; + +- priv->keys_grabbed = FALSE; +- priv->grab_on_frame = FALSE; ++ meta_window_x11_protocol_to_stage (window_x11, ++ attrs.border_width, 0, 0, 0, ++ &priv->border_width, NULL, NULL, NULL); + + g_signal_connect (window, "notify::decorated", + G_CALLBACK (meta_window_x11_update_input_region), +@@ -2200,6 +2352,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) + klass->thaw_commits = meta_window_x11_impl_thaw_commits; + klass->always_update_shape = meta_window_x11_impl_always_update_shape; + klass->process_property_notify = meta_window_x11_impl_process_property_notify; ++ klass->stage_to_protocol = meta_window_x11_real_stage_to_protocol; ++ klass->protocol_to_stage = meta_window_x11_real_protocol_to_stage; + + obj_props[PROP_ATTRIBUTES] = + g_param_spec_pointer ("attributes", NULL, NULL, +@@ -2476,7 +2630,10 @@ meta_window_x11_update_input_region (MetaWindow *window) + else + { + /* Window has a custom shape. */ +- region = region_create_from_x_rectangles (rects, n_rects); ++ g_autoptr (MtkRegion) protocol_region = NULL; ++ ++ protocol_region = region_create_from_x_rectangles (rects, n_rects); ++ region = region_protocol_to_stage (protocol_region, window_x11); + } + + meta_XFree (rects); +@@ -2560,7 +2717,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) + + if (rects) + { +- region = region_create_from_x_rectangles (rects, n_rects); ++ g_autoptr (MtkRegion) protocol_region = NULL; ++ ++ protocol_region = region_create_from_x_rectangles (rects, n_rects); ++ region = region_protocol_to_stage (protocol_region, window_x11); + XFree (rects); + } + } +@@ -2829,6 +2989,7 @@ meta_window_x11_configure_request (MetaWindow *window, + { + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); ++ int new_x, new_y, new_width, new_height; + + /* Note that x, y is the corner of the window border, + * and width, height is the size of the window inside +@@ -2837,15 +2998,25 @@ meta_window_x11_configure_request (MetaWindow *window, + * requested border here. + */ + if (event->xconfigurerequest.value_mask & CWBorderWidth) +- priv->border_width = event->xconfigurerequest.border_width; ++ { ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->xconfigurerequest.border_width, 0, 0, 0, ++ &priv->border_width, NULL, NULL, NULL); ++ } + +- meta_window_move_resize_request(window, +- event->xconfigurerequest.value_mask, +- window->size_hints.win_gravity, +- event->xconfigurerequest.x, +- event->xconfigurerequest.y, +- event->xconfigurerequest.width, +- event->xconfigurerequest.height); ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->xconfigurerequest.x, event->xconfigurerequest.y, ++ event->xconfigurerequest.width, event->xconfigurerequest.height, ++ &new_x, &new_y, ++ &new_width, &new_height); ++ ++ meta_window_move_resize_request (window, ++ event->xconfigurerequest.value_mask, ++ window->size_hints.win_gravity, ++ new_x, ++ new_y, ++ new_width, ++ new_height); + + /* Handle stacking. We only handle raises/lowers, mostly because + * stack.c really can't deal with anything else. I guess we'll fix +@@ -3340,8 +3511,13 @@ meta_window_x11_client_message (MetaWindow *window, + guint32 timestamp; + MetaWindowDrag *window_drag; + +- x_root = event->xclient.data.l[0]; +- y_root = event->xclient.data.l[1]; ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->xclient.data.l[0], ++ event->xclient.data.l[1], ++ 0, 0, ++ &x_root, ++ &y_root, ++ NULL, NULL); + action = event->xclient.data.l[2]; + button = event->xclient.data.l[3]; + +@@ -3503,6 +3679,7 @@ meta_window_x11_client_message (MetaWindow *window, + { + MetaGravity gravity; + guint value_mask; ++ int x, y, width, height; + + gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); + value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; +@@ -3511,13 +3688,20 @@ meta_window_x11_client_message (MetaWindow *window, + if (gravity == 0) + gravity = window->size_hints.win_gravity; + ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->xclient.data.l[1], ++ event->xclient.data.l[2], ++ event->xclient.data.l[3], ++ event->xclient.data.l[4], ++ &x, &y, &width, &height); ++ + meta_window_move_resize_request(window, + value_mask, + gravity, +- event->xclient.data.l[1], /* x */ +- event->xclient.data.l[2], /* y */ +- event->xclient.data.l[3], /* width */ +- event->xclient.data.l[4]); /* height */ ++ x, ++ y, ++ width, ++ height); + } + else if (event->xclient.message_type == + x11_display->atom__NET_ACTIVE_WINDOW && +@@ -3574,11 +3758,15 @@ meta_window_x11_client_message (MetaWindow *window, + else if (event->xclient.message_type == + x11_display->atom__GTK_SHOW_WINDOW_MENU) + { +- gulong x, y; ++ int x, y; + + /* l[0] is device_id, which we don't use */ +- x = event->xclient.data.l[1]; +- y = event->xclient.data.l[2]; ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->xclient.data.l[1], ++ event->xclient.data.l[2], ++ 0, 0, ++ &x, &y, ++ NULL, NULL); + + meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); + } +@@ -4100,10 +4288,11 @@ meta_window_x11_configure_notify (MetaWindow *window, + g_assert (window->override_redirect); + g_assert (window->frame == NULL); + +- window->rect.x = event->x; +- window->rect.y = event->y; +- window->rect.width = event->width; +- window->rect.height = event->height; ++ meta_window_x11_protocol_to_stage (window_x11, ++ event->x, event->y, ++ event->width, event->height, ++ &window->rect.x, &window->rect.y, ++ &window->rect.width, &window->rect.height); + + priv->client_rect = window->rect; + window->buffer_rect = window->rect; +diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h +index 205eaaa632b..fa3fbea6a84 100644 +--- a/src/x11/window-x11.h ++++ b/src/x11/window-x11.h +@@ -45,6 +45,24 @@ struct _MetaWindowX11Class + gboolean (*always_update_shape) (MetaWindow *window); + void (*process_property_notify) (MetaWindow *window, + XPropertyEvent *event); ++ void (*stage_to_protocol) (MetaWindowX11 *window_x11, ++ int stage_x, ++ int stage_y, ++ int stage_width, ++ int stage_height, ++ int *protocol_x, ++ int *protocol_y, ++ int *protocol_width, ++ int *protocol_height); ++ void (*protocol_to_stage) (MetaWindowX11 *window_x11, ++ int protocol_x, ++ int protocol_y, ++ int protocol_width, ++ int protocol_height, ++ int *stage_x, ++ int *stage_y, ++ int *stage_width, ++ int *stage_height); + }; + + MetaWindow * meta_window_x11_new (MetaDisplay *display, +@@ -112,3 +130,23 @@ gboolean meta_window_x11_has_alpha_channel (MetaWindow *window); + + META_EXPORT + Window meta_window_x11_get_xwindow (MetaWindow *window); ++ ++void meta_window_x11_stage_to_protocol (MetaWindowX11 *window_x11, ++ int stage_x, ++ int stage_y, ++ int stage_width, ++ int stage_heigth, ++ int *protocol_x, ++ int *protocol_y, ++ int *protocol_width, ++ int *protocol_height); ++ ++void meta_window_x11_protocol_to_stage (MetaWindowX11 *window_x11, ++ int protocol_x, ++ int protocol_y, ++ int protocol_width, ++ int protocol_height, ++ int *stage_x, ++ int *stage_y, ++ int *stage_width, ++ int *stage_heigth); +-- +GitLab + diff --git a/staging/mutter/mutter-42.alpha-disable-tegra.patch b/staging/mutter/mutter-42.alpha-disable-tegra.patch new file mode 100644 index 0000000..3225c8f --- /dev/null +++ b/staging/mutter/mutter-42.alpha-disable-tegra.patch @@ -0,0 +1,25 @@ +From a5c67e0debaa89f7a73452560664cdc5c581ab95 Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Tue, 9 Mar 2021 17:21:59 -0800 +Subject: [PATCH] Test: deny atomic KMS for "tegra" (RHBZ #1936991) + +Signed-off-by: Adam Williamson +--- + src/backends/native/meta-kms-impl-device-atomic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c +index 35837f7429..ffff7b8e23 100644 +--- a/src/backends/native/meta-kms-impl-device-atomic.c ++++ b/src/backends/native/meta-kms-impl-device-atomic.c +@@ -1352,6 +1352,7 @@ is_atomic_allowed (const char *driver_name) + { + const char *atomic_driver_deny_list[] = { + "xlnx", ++ "tegra", + NULL, + }; + +-- +2.43.0 + diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec new file mode 100644 index 0000000..6f8792f --- /dev/null +++ b/staging/mutter/mutter.spec @@ -0,0 +1,218 @@ +%global glib_version 2.75.1 +%global gtk3_version 3.19.8 +%global gtk4_version 4.0.0 +%global gsettings_desktop_schemas_version 40~alpha +%global json_glib_version 0.12.0 +%global libinput_version 1.19.0 +%global pipewire_version 0.3.33 +%global lcms2_version 2.6 +%global colord_version 1.4.5 +%global libei_version 1.0.0 +%global mutter_api_version 14 + +%global gnome_major_version 46 +%global gnome_version %{gnome_major_version}.0 +%global tarball_version %%(echo %{version} | tr '~' '.') +%global _default_patch_fuzz 2 + +Name: mutter +Version: %{gnome_version}.xscaling.1 +Release: %autorelease +Summary: Window and compositing manager based on Clutter + +License: GPLv2+ +URL: http://www.gnome.org +Source0: https://download.gnome.org/sources/%{name}/%{gnome_major_version}/%{name}-%{tarball_version}.tar.xz + +# Work-around for OpenJDK's compliance test +Patch: 0001-window-actor-Special-case-shaped-Java-windows.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1936991 +Patch: mutter-42.alpha-disable-tegra.patch + +# https://pagure.io/fedora-workstation/issue/79 +Patch: 0001-place-Always-center-initial-setup-fedora-welcome.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=2239128 +# https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 +# not upstreamed because for upstream we'd really want to find a way +# to fix *both* problems +Patch: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch + +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329 +# Modified to add the change from +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329#note_1874837 +# which solves the problems reported with #3329 alone +Patch: 0001-modified-3329.patch + +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 +# Scaling for Xwayland applications +Patch: 3567.patch + +BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 +BuildRequires: pkgconfig(sm) +BuildRequires: pkgconfig(libwacom) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xdamage) +BuildRequires: pkgconfig(xext) +BuildRequires: pkgconfig(xfixes) +BuildRequires: pkgconfig(xi) +BuildRequires: pkgconfig(xrandr) +BuildRequires: pkgconfig(xrender) +BuildRequires: pkgconfig(xcursor) +BuildRequires: pkgconfig(xcomposite) +BuildRequires: pkgconfig(x11-xcb) +BuildRequires: pkgconfig(xkbcommon) +BuildRequires: pkgconfig(xkbcommon-x11) +BuildRequires: pkgconfig(xkbfile) +BuildRequires: pkgconfig(xtst) +BuildRequires: mesa-libEGL-devel +BuildRequires: mesa-libGLES-devel +BuildRequires: mesa-libGL-devel +BuildRequires: mesa-libgbm-devel +BuildRequires: pkgconfig(glesv2) +BuildRequires: pkgconfig(graphene-gobject-1.0) +BuildRequires: pam-devel +BuildRequires: pkgconfig(libdisplay-info) +BuildRequires: pkgconfig(libpipewire-0.3) >= %{pipewire_version} +BuildRequires: pkgconfig(sysprof-capture-4) +BuildRequires: sysprof-devel +BuildRequires: pkgconfig(libsystemd) +BuildRequires: xorg-x11-server-Xorg +BuildRequires: xorg-x11-server-Xvfb +BuildRequires: pkgconfig(xkeyboard-config) +BuildRequires: desktop-file-utils +# Bootstrap requirements +BuildRequires: gettext-devel git-core +BuildRequires: pkgconfig(libcanberra) +BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} +BuildRequires: pkgconfig(gnome-settings-daemon) +BuildRequires: meson +BuildRequires: pkgconfig(gbm) +BuildRequires: pkgconfig(gnome-desktop-4) +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(libstartup-notification-1.0) +BuildRequires: pkgconfig(wayland-eglstream) +BuildRequires: pkgconfig(wayland-protocols) +BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(lcms2) >= %{lcms2_version} +BuildRequires: pkgconfig(colord) >= %{colord_version} +BuildRequires: pkgconfig(libei-1.0) >= %{libei_version} +BuildRequires: pkgconfig(libeis-1.0) >= %{libei_version} + +BuildRequires: pkgconfig(json-glib-1.0) >= %{json_glib_version} +BuildRequires: pkgconfig(libinput) >= %{libinput_version} +BuildRequires: pkgconfig(xwayland) + +BuildRequires: python3-dbusmock + +Requires: control-center-filesystem +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gnome-settings-daemon +Requires: gtk4%{?_isa} >= %{gtk4_version} +Requires: json-glib%{?_isa} >= %{json_glib_version} +Requires: libinput%{?_isa} >= %{libinput_version} +Requires: pipewire%{_isa} >= %{pipewire_version} +Requires: startup-notification +Requires: dbus + +# Need common +Requires: %{name}-common = %{version}-%{release} + +Recommends: mesa-dri-drivers%{?_isa} + +Provides: firstboot(windowmanager) = mutter + +# Cogl and Clutter were forked at these versions, but have diverged +# significantly since then. +Provides: bundled(cogl) = 1.22.0 +Provides: bundled(clutter) = 1.26.0 + +Conflicts: mutter < 45~beta.1-2 + +# Make sure dnf updates gnome-shell together with this package; otherwise we +# might end up with broken gnome-shell installations due to mutter ABI changes. +Conflicts: gnome-shell < 45~rc + +%description +Mutter is a window and compositing manager that displays and manages +your desktop via OpenGL. Mutter combines a sophisticated display engine +using the Clutter toolkit with solid window-management logic inherited +from the Metacity window manager. + +While Mutter can be used stand-alone, it is primarily intended to be +used as the display core of a larger system such as GNOME Shell. For +this reason, Mutter is very extensible via plugins, which are used both +to add fancy visual effects and to rework the window management +behaviors to meet the needs of the environment. + +%package common +Summary: Common files used by %{name} and forks of %{name} +BuildArch: noarch +Conflicts: mutter < 45~beta.1-2 + +%description common +Common files used by Mutter and soft forks of Mutter + +%package devel +Summary: Development package for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} +# for EGL/eglmesaext.h that's included from public cogl-egl-defines.h header +Requires: mesa-libEGL-devel + +%description devel +Header files and libraries for developing Mutter plugins. Also includes +utilities for testing Metacity/Mutter themes. + +%package tests +Summary: Tests for the %{name} package +Requires: %{name}-devel%{?_isa} = %{version}-%{release} +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: gtk3%{?_isa} >= %{gtk3_version} + +%description tests +The %{name}-tests package contains tests that can be used to verify +the functionality of the installed %{name} package. + +%prep +%autosetup -S git -n %{name}-%{tarball_version} + +%build +%meson -Degl_device=true -Dwayland_eglstream=true +%meson_build + +%install +%meson_install + +%find_lang %{name} + +%files -f %{name}.lang +%license COPYING +%doc NEWS +%{_bindir}/mutter +%{_libdir}/lib*.so.* +%{_libdir}/mutter-%{mutter_api_version}/ +%{_libexecdir}/mutter-restart-helper +%{_libexecdir}/mutter-x11-frames +%{_mandir}/man1/mutter.1* + +%files common +%{_datadir}/GConf/gsettings/mutter-schemas.convert +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.wayland.gschema.xml +%{_datadir}/gnome-control-center/keybindings/50-mutter-*.xml +%{_udevrulesdir}/61-mutter.rules + +%files devel +%{_includedir}/* +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/* + +%files tests +%{_libexecdir}/installed-tests/mutter-%{mutter_api_version} +%{_datadir}/installed-tests/mutter-%{mutter_api_version} +%{_datadir}/mutter-%{mutter_api_version}/tests + +%changelog +%autochangelog From c2168038c925bf6b7e19e92a5904a1116896ab3c Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 08:27:52 -0700 Subject: [PATCH 03/41] chore: Fix tarball version --- staging/mutter/mutter.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 6f8792f..8aa8fc3 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -12,7 +12,7 @@ %global gnome_major_version 46 %global gnome_version %{gnome_major_version}.0 -%global tarball_version %%(echo %{version} | tr '~' '.') +%global tarball_version %%(echo %{gnome_version} | tr '~' '.') %global _default_patch_fuzz 2 Name: mutter From 5c91541b97c7cf103b142ff66a2d6818dd1aa7d3 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 08:39:09 -0700 Subject: [PATCH 04/41] chore: Update patch, rebase on to current Mutter 46 --- staging/mutter/3567.patch | 711 ++++++++++++++++---------------------- 1 file changed, 291 insertions(+), 420 deletions(-) diff --git a/staging/mutter/3567.patch b/staging/mutter/3567.patch index ebfe6d4..e4fa0c3 100644 --- a/staging/mutter/3567.patch +++ b/staging/mutter/3567.patch @@ -1,25 +1,8 @@ -From d577df46a223fc821595b113bd89cfeb19a29014 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 12 Dec 2023 22:41:20 +0100 -Subject: [PATCH 1/4] x11-display: Expose UI scaling factor via D-Bus - -This replaces the `legacy-ui-scaling-factor` entry in -`org.gnome.Mutter.DisplayConfig`, with the motivation being to no longer -expose X11 specific state via the monitor configuration API. ---- - .../org.gnome.Mutter.DisplayConfig.xml | 4 -- - data/dbus-interfaces/org.gnome.Mutter.X11.xml | 8 +++ - src/backends/meta-monitor-manager.c | 7 -- - src/meson.build | 5 ++ - src/x11/meta-x11-display.c | 64 ++++++++++++++++++- - 5 files changed, 76 insertions(+), 12 deletions(-) - create mode 100644 data/dbus-interfaces/org.gnome.Mutter.X11.xml - diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index af78ec0517d..7f1957529f0 100644 +index 2fe8450a8..86421b7b0 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -@@ -420,10 +420,6 @@ +@@ -426,10 +426,6 @@ always use the same scale. Absence of this means logical monitor scales can differ. @@ -32,7 +15,7 @@ index af78ec0517d..7f1957529f0 100644 diff --git a/data/dbus-interfaces/org.gnome.Mutter.X11.xml b/data/dbus-interfaces/org.gnome.Mutter.X11.xml new file mode 100644 -index 00000000000..3d3c8a42f87 +index 000000000..3d3c8a42f --- /dev/null +++ b/data/dbus-interfaces/org.gnome.Mutter.X11.xml @@ -0,0 +1,8 @@ @@ -44,11 +27,47 @@ index 00000000000..3d3c8a42f87 + + + +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index 92c97b12e..54f286daa 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -5,6 +5,7 @@ + + + ++ + + + + + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index 0760a341a..6ed3fc2c3 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * + MetaMonitorsConfig *config, + MetaMonitorsConfigMethod method, + GError **error); ++ ++MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index 24995edb6fc..94512cef3e5 100644 +index 77743bc72..45033d966 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c -@@ -2048,14 +2048,12 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -2051,14 +2051,12 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, GDBusMethodInvocation *invocation, MetaMonitorManager *manager) { @@ -63,7 +82,7 @@ index 24995edb6fc..94512cef3e5 100644 int max_screen_width, max_screen_height; g_variant_builder_init (&monitors_builder, -@@ -2244,11 +2242,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -2261,11 +2259,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, g_variant_new_boolean (TRUE)); } @@ -75,337 +94,43 @@ index 24995edb6fc..94512cef3e5 100644 if (meta_monitor_manager_get_max_screen_size (manager, &max_screen_width, &max_screen_height)) -diff --git a/src/meson.build b/src/meson.build -index 47ee8f570eb..f6079fd8a85 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -943,6 +943,11 @@ dbus_interfaces = [ - 'interface': 'org.gnome.Mutter.DebugControl.xml', - 'prefix': 'org.gnome.Mutter', - }, -+ { -+ 'name': 'meta-dbus-x11', -+ 'interface': 'org.gnome.Mutter.X11.xml', -+ 'prefix': 'org.gnome.Mutter', -+ }, - ] - - if have_profiler -diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c -index 3c3a65061bb..fa2a33f6eca 100644 ---- a/src/x11/meta-x11-display.c -+++ b/src/x11/meta-x11-display.c -@@ -70,7 +70,7 @@ - #include "wayland/meta-xwayland-private.h" - #endif - --G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) -+#include "meta-dbus-x11.h" +@@ -4123,3 +4116,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) - static GQuark quark_x11_display_logical_monitor_data = 0; - -@@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData - int xinerama_index; - } MetaX11DisplayLogicalMonitorData; - -+typedef struct _MetaX11DisplayPrivate -+{ -+ MetaDBusX11 *dbus_api; -+ guint dbus_name_id; -+} MetaX11DisplayPrivate; -+ -+G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) -+ - static char *get_screen_name (Display *xdisplay, - int number); - -@@ -151,13 +159,46 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) - g_free (filter); + return priv->virtual_monitors; } - -+static void -+on_bus_acquired (GDBusConnection *connection, -+ const char *name, -+ gpointer user_data) -+{ -+ MetaX11Display *x11_display = user_data; -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ -+ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), -+ connection, -+ "/org/gnome/Mutter/X11", -+ NULL); -+} -+ -+static void -+update_ui_scaling_factor (MetaX11Display *x11_display) -+{ -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ MetaBackend *backend = backend_from_x11_display (x11_display); -+ MetaSettings *settings = meta_backend_get_settings (backend); -+ int ui_scaling_factor; + -+ ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); -+ meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); -+} -+ - static void - meta_x11_display_dispose (GObject *object) - { - MetaX11Display *x11_display = META_X11_DISPLAY (object); -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); - - x11_display->closing = TRUE; - -+ g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); -+ g_clear_object (&priv->dbus_api); -+ - g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); - - g_clear_list (&x11_display->event_funcs, -@@ -1196,6 +1237,23 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) - on_frames_client_died, x11_display); - } - -+static void -+initialize_dbus_interface (MetaX11Display *x11_display) ++MetaLogicalMonitorLayoutMode ++meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) +{ -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ -+ priv->dbus_api = meta_dbus_x11_skeleton_new (); -+ priv->dbus_name_id = -+ g_bus_own_name (G_BUS_TYPE_SESSION, -+ "org.gnome.Mutter.X11", -+ G_BUS_NAME_OWNER_FLAGS_NONE, -+ on_bus_acquired, -+ NULL, NULL, -+ x11_display, NULL); -+ update_ui_scaling_factor (x11_display); ++ return manager->layout_mode; +} -+ - /** - * meta_x11_display_new: - * -@@ -1290,6 +1348,8 @@ meta_x11_display_new (MetaDisplay *display, - x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); - x11_display->display = display; - -+ initialize_dbus_interface (x11_display); -+ - /* here we use XDisplayName which is what the user - * probably put in, vs. DisplayString(display) which is - * canonicalized by XOpenDisplay() -@@ -1947,6 +2007,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - } - - x11_display->has_xinerama_indices = FALSE; -+ -+ update_ui_scaling_factor (x11_display); - } - - static Bool --- -GitLab - - -From 9a329a024bc2f9de3415fdc7a4ba9d8152b27e5c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Tue, 20 Feb 2024 23:51:48 +0100 -Subject: [PATCH 2/4] Add an experimental feature for letting Xwayland clients - scale natively - -With the next commits we'll introduce a new mode for scaling of Xwayland apps, -we'll want to put this mode behind an experimental setting though, so add -that setting. ---- - data/org.gnome.mutter.gschema.xml.in | 8 ++++++++ - src/backends/meta-settings-private.h | 1 + - src/backends/meta-settings.c | 2 ++ - 3 files changed, 11 insertions(+) - -diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in -index fa8cf95dd87..cb60308b6e2 100644 ---- a/data/org.gnome.mutter.gschema.xml.in -+++ b/data/org.gnome.mutter.gschema.xml.in -@@ -4,6 +4,7 @@ - - - -+ - - - - - diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h -index ca14ce67cb4..90e6998187e 100644 +index afbba054a..2081a81b1 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h -@@ -31,6 +31,7 @@ typedef enum _MetaExperimentalFeature - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0), +@@ -32,6 +32,7 @@ typedef enum _MetaExperimentalFeature META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1), META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND = (1 << 2), -+ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING = (1 << 3), + META_EXPERIMENTAL_FEATURE_VARIABLE_REFRESH_RATE = (1 << 3), ++ META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING = (1 << 4), } MetaExperimentalFeature; typedef enum _MetaXwaylandExtension diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c -index 486ac5abb7f..1042c845b9c 100644 +index 3703b23b0..1ae59d636 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c -@@ -294,6 +294,8 @@ experimental_features_handler (GVariant *features_variant, - feature = META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS; - else if (g_str_equal (feature_str, "autoclose-xwayland")) +@@ -296,6 +296,8 @@ experimental_features_handler (GVariant *features_variant, feature = META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND; + else if (g_str_equal (feature_str, "variable-refresh-rate")) + feature = META_EXPERIMENTAL_FEATURE_VARIABLE_REFRESH_RATE; + else if (g_str_equal (feature_str, "xwayland-native-scaling")) + feature = META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING; if (feature) g_message ("Enabling experimental feature '%s'", feature_str); --- -GitLab - - -From 2c3832f66550d62fd733686d7b956c3f9b8a12b1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 12 Dec 2023 22:42:46 +0100 -Subject: [PATCH 3/4] context: Put Wayland compositor getter in the context - header - ---- - src/meta/meta-context.h | 5 +++++ - src/meta/meta-wayland-compositor.h | 3 --- - src/meta/types.h | 4 ++++ - 3 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h -index ef36bd2c303..2adb9b07e0f 100644 ---- a/src/meta/meta-context.h -+++ b/src/meta/meta-context.h -@@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, - META_EXPORT - gboolean meta_context_restore_rlimit_nofile (MetaContext *context, - GError **error); -+ -+#ifdef HAVE_WAYLAND -+META_EXPORT -+MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); -+#endif -diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h -index 7f4a507057c..3df92fda57d 100644 ---- a/src/meta/meta-wayland-compositor.h -+++ b/src/meta/meta-wayland-compositor.h -@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, - META, WAYLAND_COMPOSITOR, - GObject) - --META_EXPORT --MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); -- - META_EXPORT - struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); - -diff --git a/src/meta/types.h b/src/meta/types.h -index cbe2a9a3d7f..8fba4a839ef 100644 ---- a/src/meta/types.h -+++ b/src/meta/types.h -@@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; - - typedef struct _MetaWorkspaceManager MetaWorkspaceManager; - typedef struct _MetaSelection MetaSelection; -+ -+#ifdef HAVE_WAYLAND -+typedef struct _MetaWaylandCompositor MetaWaylandCompositor; -+#endif --- -GitLab - - -From 24f445e20f7da35df4e53cef13578b91dd372c6a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 12 Dec 2023 22:52:44 +0100 -Subject: [PATCH 4/4] Add experimental mode to use native scaling of Xwayland - clients - -Allow scale-aware Xwayland clients to scale by an integer scale -themselves, instead of letting them render them at 1x scale and then -scaling up the texture, making it look blurry. - -When monitor framebuffers are scaled, this special cases Xwayland and -sends output regions in a way that Xwayland think everything is N times -as large as the logical region, where N is the ceil of the max monitor -scale. - -This is done by introducing a "stage" vs "protocol" coordinate space for -X11, where the "protocol" coordinate space is "stage" multiplied by a -scaling factor. - -We're guarding this behind a new experimental feature -"xwayland-native-scaling", which can only come into effect when enabled -together with "scale-monitor-framebuffer". ---- - src/backends/meta-monitor-manager-private.h | 2 + - src/backends/meta-monitor-manager.c | 6 + - src/compositor/meta-window-actor-x11.c | 22 +- - src/core/frame.c | 106 +++++-- - src/wayland/meta-wayland-cursor-surface.c | 52 ++-- - src/wayland/meta-wayland-outputs.c | 46 ++- - src/wayland/meta-wayland-pointer.c | 14 + - src/wayland/meta-wayland-private.h | 2 + - src/wayland/meta-wayland-surface.c | 30 +- - src/wayland/meta-window-xwayland.c | 71 ++++- - src/wayland/meta-xwayland-private.h | 1 + - src/wayland/meta-xwayland-surface.c | 10 +- - src/wayland/meta-xwayland.c | 56 ++++ - src/wayland/meta-xwayland.h | 2 + - src/x11/meta-x11-display.c | 200 +++++++++++-- - src/x11/window-props.c | 104 ++++++- - src/x11/window-x11.c | 305 ++++++++++++++++---- - src/x11/window-x11.h | 38 +++ - 18 files changed, 898 insertions(+), 169 deletions(-) - -diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h -index 0760a341a86..6ed3fc2c3f5 100644 ---- a/src/backends/meta-monitor-manager-private.h -+++ b/src/backends/meta-monitor-manager-private.h -@@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error); -+ -+MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); -diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index 94512cef3e5..c8e42a87539 100644 ---- a/src/backends/meta-monitor-manager.c -+++ b/src/backends/meta-monitor-manager.c -@@ -4099,3 +4099,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) - - return priv->virtual_monitors; - } -+ -+MetaLogicalMonitorLayoutMode -+meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) -+{ -+ return manager->layout_mode; -+} diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c -index 19827af331c..7df10e6c151 100644 +index 19827af33..7df10e6c1 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c @@ -688,11 +688,23 @@ meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, @@ -438,18 +163,18 @@ index 19827af331c..7df10e6c151 100644 meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); } diff --git a/src/core/frame.c b/src/core/frame.c -index 914b144b89d..592d2df8982 100644 +index 145f0b7bd..502622598 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -33,6 +33,7 @@ #include "x11/meta-x11-display-private.h" - #include "x11/window-x11.h" + #include "x11/window-x11-private.h" #include "x11/window-props.h" +#include "x11/window-x11.h" #include #include -@@ -66,6 +67,7 @@ meta_window_set_frame_xwindow (MetaWindow *window, +@@ -66,6 +67,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, XSetWindowAttributes attrs; gulong create_serial = 0; MetaFrame *frame; @@ -457,7 +182,7 @@ index 914b144b89d..592d2df8982 100644 if (window->frame) return; -@@ -127,11 +129,19 @@ meta_window_set_frame_xwindow (MetaWindow *window, +@@ -127,11 +129,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, meta_stack_tracker_record_remove (window->display->stack_tracker, meta_window_x11_get_xwindow (window), XNextRequest (x11_display->xdisplay)); @@ -644,8 +369,63 @@ index 914b144b89d..592d2df8982 100644 event.xconfigure.border_width = 0; event.xconfigure.above = None; event.xconfigure.override_redirect = False; +diff --git a/src/meson.build b/src/meson.build +index a8cf7e197..ea2dcb2dd 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -943,6 +943,11 @@ dbus_interfaces = [ + 'interface': 'org.gnome.Mutter.DebugControl.xml', + 'prefix': 'org.gnome.Mutter', + }, ++ { ++ 'name': 'meta-dbus-x11', ++ 'interface': 'org.gnome.Mutter.X11.xml', ++ 'prefix': 'org.gnome.Mutter', ++ }, + ] + + if have_profiler +diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h +index ef36bd2c3..2adb9b07e 100644 +--- a/src/meta/meta-context.h ++++ b/src/meta/meta-context.h +@@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, + META_EXPORT + gboolean meta_context_restore_rlimit_nofile (MetaContext *context, + GError **error); ++ ++#ifdef HAVE_WAYLAND ++META_EXPORT ++MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); ++#endif +diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h +index 7f4a50705..3df92fda5 100644 +--- a/src/meta/meta-wayland-compositor.h ++++ b/src/meta/meta-wayland-compositor.h +@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, + META, WAYLAND_COMPOSITOR, + GObject) + +-META_EXPORT +-MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); +- + META_EXPORT + struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); + +diff --git a/src/meta/types.h b/src/meta/types.h +index cbe2a9a3d..8fba4a839 100644 +--- a/src/meta/types.h ++++ b/src/meta/types.h +@@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; + + typedef struct _MetaWorkspaceManager MetaWorkspaceManager; + typedef struct _MetaSelection MetaSelection; ++ ++#ifdef HAVE_WAYLAND ++typedef struct _MetaWaylandCompositor MetaWaylandCompositor; ++#endif diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c -index 87a8895c886..5a16ce7d879 100644 +index 87a8895c8..5a16ce7d8 100644 --- a/src/wayland/meta-wayland-cursor-surface.c +++ b/src/wayland/meta-wayland-cursor-surface.c @@ -92,37 +92,29 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, @@ -709,7 +489,7 @@ index 87a8895c886..5a16ce7d879 100644 meta_wayland_surface_update_outputs (surface); diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c -index f7a56f2f274..23398eb45b6 100644 +index 89ae86445..6a05e887e 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -31,6 +31,10 @@ @@ -730,9 +510,9 @@ index f7a56f2f274..23398eb45b6 100644 + MetaWaylandCompositor *compositor; + struct wl_global *global; - uint32_t mode_flags; - float refresh_rate; -@@ -427,6 +433,7 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor, + GList *resources; + GList *xdg_output_resources; +@@ -422,6 +428,7 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor, MetaWaylandOutput *wayland_output; wayland_output = g_object_new (META_TYPE_WAYLAND_OUTPUT, NULL); @@ -740,7 +520,7 @@ index f7a56f2f274..23398eb45b6 100644 wayland_output->global = wl_global_create (compositor->wayland_display, &wl_output_interface, META_WL_OUTPUT_VERSION, -@@ -601,6 +608,19 @@ static const struct zxdg_output_v1_interface +@@ -596,6 +603,19 @@ static const struct zxdg_output_v1_interface meta_xdg_output_destroy, }; @@ -760,14 +540,14 @@ index f7a56f2f274..23398eb45b6 100644 static void send_xdg_output_events (struct wl_resource *resource, MetaWaylandOutput *wayland_output, -@@ -615,8 +635,28 @@ send_xdg_output_events (struct wl_resource *resource, - logical_monitor = meta_monitor_get_logical_monitor (monitor); +@@ -613,18 +633,27 @@ send_xdg_output_events (struct wl_resource *resource, layout = meta_logical_monitor_get_layout (logical_monitor); + old_layout = wayland_output->layout; -- zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); -- zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); +- if (need_all_events || +- old_layout.x != layout.x || old_layout.y != layout.y) + if (is_xwayland_resource (wayland_output, resource)) -+ { + { +#ifdef HAVE_XWAYLAND + MetaXWaylandManager *xwayland_manager = + &wayland_output->compositor->xwayland_manager; @@ -779,19 +559,23 @@ index f7a56f2f274..23398eb45b6 100644 + layout.width *= xwayland_scale; + layout.height *= xwayland_scale; + -+ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); + zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); +- need_done = TRUE; + zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); +#endif -+ } + } +- +- if (need_all_events || +- old_layout.width != layout.width || old_layout.height != layout.height) + else -+ { + { + zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); -+ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); -+ } - - version = wl_resource_get_version (resource); + zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); +- need_done = TRUE; + } -@@ -736,7 +776,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) + if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) +@@ -745,7 +774,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); @@ -801,10 +585,10 @@ index f7a56f2f274..23398eb45b6 100644 compositor->outputs = diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c -index 98534953930..7ceb6a3daa8 100644 +index 88b27f84d..324092970 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c -@@ -1190,6 +1190,20 @@ pointer_set_cursor (struct wl_client *client, +@@ -1244,6 +1244,20 @@ pointer_set_cursor (struct wl_client *client, cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); meta_wayland_cursor_surface_set_renderer (cursor_surface, cursor_renderer); @@ -826,7 +610,7 @@ index 98534953930..7ceb6a3daa8 100644 hot_x, hot_y); diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h -index e8d442c0398..834753ffdd3 100644 +index e8d442c03..834753ffd 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -77,6 +77,8 @@ struct _MetaXWaylandManager @@ -839,10 +623,10 @@ index e8d442c0398..834753ffdd3 100644 struct _MetaWaylandCompositor diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index 3761c7b725d..0c06020bb8b 100644 +index b132504d3..0012798df 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c -@@ -773,8 +773,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, +@@ -770,8 +770,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL)); } @@ -864,7 +648,7 @@ index 3761c7b725d..0c06020bb8b 100644 if (state->has_new_buffer_transform) surface->buffer_transform = state->buffer_transform; -@@ -962,8 +973,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -959,8 +970,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaMultiTexture *committed_texture = surface->committed_state.texture; int committed_scale = surface->committed_state.scale; @@ -876,7 +660,7 @@ index 3761c7b725d..0c06020bb8b 100644 { if (!surface->role || !META_IS_WAYLAND_CURSOR_SURFACE (surface->role)) { -@@ -1497,6 +1509,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) +@@ -1488,6 +1500,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) g_hash_table_foreach (surface->compositor->outputs, update_surface_output_state, surface); @@ -894,7 +678,7 @@ index 3761c7b725d..0c06020bb8b 100644 void diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c -index 1299a351ca7..5fb00696267 100644 +index 1299a351c..5fb006962 100644 --- a/src/wayland/meta-window-xwayland.c +++ b/src/wayland/meta-window-xwayland.c @@ -27,8 +27,9 @@ @@ -991,7 +775,7 @@ index 1299a351ca7..5fb00696267 100644 gobject_class->get_property = meta_window_xwayland_get_property; gobject_class->set_property = meta_window_xwayland_set_property; diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h -index 7a9cb73fdf9..9e06f03155f 100644 +index 7a9cb73fd..9e06f0315 100644 --- a/src/wayland/meta-xwayland-private.h +++ b/src/wayland/meta-xwayland-private.h @@ -20,6 +20,7 @@ @@ -1003,7 +787,7 @@ index 7a9cb73fdf9..9e06f03155f 100644 gboolean meta_xwayland_init (MetaXWaylandManager *manager, diff --git a/src/wayland/meta-xwayland-surface.c b/src/wayland/meta-xwayland-surface.c -index 8fa1c72a969..c6daf9b2670 100644 +index 8fa1c72a9..c6daf9b26 100644 --- a/src/wayland/meta-xwayland-surface.c +++ b/src/wayland/meta-xwayland-surface.c @@ -163,13 +163,19 @@ meta_xwayland_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_ @@ -1029,7 +813,7 @@ index 8fa1c72a969..c6daf9b2670 100644 static MetaWaylandSurface * diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c -index ea9c27d74a0..828e6f64efe 100644 +index ea9c27d74..828e6f64e 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -1051,6 +1051,29 @@ meta_xwayland_shutdown (MetaWaylandCompositor *compositor) @@ -1114,7 +898,7 @@ index ea9c27d74a0..828e6f64efe 100644 + return 1; +} diff --git a/src/wayland/meta-xwayland.h b/src/wayland/meta-xwayland.h -index daf9d1abb03..ae7a06977e4 100644 +index daf9d1abb..ae7a06977 100644 --- a/src/wayland/meta-xwayland.h +++ b/src/wayland/meta-xwayland.h @@ -48,3 +48,5 @@ META_EXPORT_TEST @@ -1124,10 +908,34 @@ index daf9d1abb03..ae7a06977e4 100644 + +int meta_xwayland_get_effective_scale (MetaXWaylandManager *manager); diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c -index fa2a33f6eca..84e639c1b01 100644 +index 438f3bd1e..f2a613392 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c -@@ -130,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) +@@ -70,7 +70,7 @@ + #include "wayland/meta-xwayland-private.h" + #endif + +-G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++#include "meta-dbus-x11.h" + + static GQuark quark_x11_display_logical_monitor_data = 0; + +@@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData + int xinerama_index; + } MetaX11DisplayLogicalMonitorData; + ++typedef struct _MetaX11DisplayPrivate ++{ ++ MetaDBusX11 *dbus_api; ++ guint dbus_name_id; ++} MetaX11DisplayPrivate; ++ ++G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++ + static char *get_screen_name (Display *xdisplay, + int number); + +@@ -122,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) return meta_context_get_backend (context); } @@ -1170,12 +978,31 @@ index fa2a33f6eca..84e639c1b01 100644 static void meta_x11_display_unmanage_windows (MetaX11Display *x11_display) { -@@ -180,10 +216,32 @@ update_ui_scaling_factor (MetaX11Display *x11_display) - MetaX11DisplayPrivate *priv = - meta_x11_display_get_instance_private (x11_display); - MetaBackend *backend = backend_from_x11_display (x11_display); -- MetaSettings *settings = meta_backend_get_settings (backend); -- int ui_scaling_factor; +@@ -151,13 +195,68 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) + g_free (filter); + } + ++static void ++on_bus_acquired (GDBusConnection *connection, ++ const char *name, ++ gpointer user_data) ++{ ++ MetaX11Display *x11_display = user_data; ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ ++ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), ++ connection, ++ "/org/gnome/Mutter/X11", ++ NULL); ++} ++ ++static void ++update_ui_scaling_factor (MetaX11Display *x11_display) ++{ ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ MetaBackend *backend = backend_from_x11_display (x11_display); + MetaContext *context = meta_backend_get_context (backend); + int ui_scaling_factor = 1; + @@ -1201,12 +1028,26 @@ index fa2a33f6eca..84e639c1b01 100644 + break; + } + } ++ ++ meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); ++} ++ + static void + meta_x11_display_dispose (GObject *object) + { + MetaX11Display *x11_display = META_X11_DISPLAY (object); ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); -- ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); - meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); - } + x11_display->closing = TRUE; -@@ -613,6 +671,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) ++ g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); ++ g_clear_object (&priv->dbus_api); ++ + g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); + + g_clear_list (&x11_display->event_funcs, +@@ -572,6 +671,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) return; meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); @@ -1216,24 +1057,22 @@ index fa2a33f6eca..84e639c1b01 100644 data[0] = monitor_width; data[1] = monitor_height; -@@ -1022,14 +1083,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, +@@ -981,14 +1083,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, for (l = logical_monitors; l; l = l->next) { - MtkRectangle area; -- ++ MtkRectangle stage_area; ++ MtkRectangle protocol_area; + - meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, &area); -- ++ meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, ++ &stage_area); + - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; -+ MtkRectangle stage_area; -+ MtkRectangle protocol_area; -+ -+ meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, -+ &stage_area); -+ + stage_to_protocol (x11_display, + stage_area.x, stage_area.y, + &protocol_area.x, &protocol_area.y); @@ -1247,7 +1086,7 @@ index fa2a33f6eca..84e639c1b01 100644 tmp += 4; } -@@ -1058,7 +1127,6 @@ set_work_area_hint (MetaDisplay *display, +@@ -1017,7 +1127,6 @@ set_work_area_hint (MetaDisplay *display, int num_workspaces; GList *l; unsigned long *data, *tmp; @@ -1255,7 +1094,7 @@ index fa2a33f6eca..84e639c1b01 100644 num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); data = g_new (unsigned long, num_workspaces * 4); -@@ -1067,14 +1135,22 @@ set_work_area_hint (MetaDisplay *display, +@@ -1026,14 +1135,22 @@ set_work_area_hint (MetaDisplay *display, for (l = workspace_manager->workspaces; l; l = l->next) { MetaWorkspace *workspace = l->data; @@ -1283,10 +1122,27 @@ index fa2a33f6eca..84e639c1b01 100644 tmp += 4; } -@@ -1254,6 +1330,41 @@ initialize_dbus_interface (MetaX11Display *x11_display) - update_ui_scaling_factor (x11_display); +@@ -1196,6 +1313,58 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) + on_frames_client_died, x11_display); } ++static void ++initialize_dbus_interface (MetaX11Display *x11_display) ++{ ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ ++ priv->dbus_api = meta_dbus_x11_skeleton_new (); ++ priv->dbus_name_id = ++ g_bus_own_name (G_BUS_TYPE_SESSION, ++ "org.gnome.Mutter.X11", ++ G_BUS_NAME_OWNER_FLAGS_NONE, ++ on_bus_acquired, ++ NULL, NULL, ++ x11_display, NULL); ++ update_ui_scaling_factor (x11_display); ++} ++ +static void +experimental_features_changed (MetaSettings *settings, + MetaExperimentalFeature old_experimental_features, @@ -1325,7 +1181,7 @@ index fa2a33f6eca..84e639c1b01 100644 /** * meta_x11_display_new: * -@@ -1272,6 +1383,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1214,6 +1383,7 @@ meta_x11_display_new (MetaDisplay *display, MetaBackend *backend = meta_context_get_backend (context); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); @@ -1333,7 +1189,16 @@ index fa2a33f6eca..84e639c1b01 100644 g_autoptr (MetaX11Display) x11_display = NULL; Display *xdisplay; Screen *xscreen; -@@ -1442,7 +1554,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1290,6 +1460,8 @@ meta_x11_display_new (MetaDisplay *display, + x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); + x11_display->display = display; + ++ initialize_dbus_interface (x11_display); ++ + /* here we use XDisplayName which is what the user + * probably put in, vs. DisplayString(display) which is + * canonicalized by XOpenDisplay() +@@ -1382,7 +1554,7 @@ meta_x11_display_new (MetaDisplay *display, "monitors-changed-internal", G_CALLBACK (on_monitors_changed_internal), x11_display, @@ -1342,7 +1207,7 @@ index fa2a33f6eca..84e639c1b01 100644 init_leader_window (x11_display, ×tamp); x11_display->timestamp = timestamp; -@@ -1535,6 +1647,11 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1475,6 +1647,11 @@ meta_x11_display_new (MetaDisplay *display, meta_prefs_add_listener (prefs_changed_callback, x11_display); @@ -1354,7 +1219,7 @@ index fa2a33f6eca..84e639c1b01 100644 set_work_area_hint (display, x11_display); g_signal_connect_object (display, "workareas-changed", -@@ -1744,16 +1861,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) +@@ -1683,16 +1860,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) } static void @@ -1376,7 +1241,7 @@ index fa2a33f6eca..84e639c1b01 100644 } static void -@@ -1805,8 +1918,37 @@ static void +@@ -1744,8 +1917,37 @@ static void update_cursor_theme (MetaX11Display *x11_display) { MetaBackend *backend = backend_from_x11_display (x11_display); @@ -1395,7 +1260,8 @@ index fa2a33f6eca..84e639c1b01 100644 + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = + &wayland_compositor->xwayland_manager; -+ + +- set_cursor_theme (x11_display->xdisplay, backend); + scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + break; @@ -1409,13 +1275,12 @@ index fa2a33f6eca..84e639c1b01 100644 + size = meta_prefs_get_cursor_size () * scale; + + theme = meta_prefs_get_cursor_theme (); - -- set_cursor_theme (x11_display->xdisplay, backend); ++ + set_cursor_theme (x11_display->xdisplay, theme, size); schedule_reload_x11_cursor (x11_display); if (META_IS_BACKEND_X11 (backend)) -@@ -1814,7 +1956,7 @@ update_cursor_theme (MetaX11Display *x11_display) +@@ -1753,7 +1955,7 @@ update_cursor_theme (MetaX11Display *x11_display) MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); @@ -1424,8 +1289,17 @@ index fa2a33f6eca..84e639c1b01 100644 meta_backend_x11_reload_cursor (backend_x11); } } +@@ -1946,6 +2148,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, + } + + x11_display->has_xinerama_indices = FALSE; ++ ++ update_ui_scaling_factor (x11_display); + } + + static Bool diff --git a/src/x11/window-props.c b/src/x11/window-props.c -index 73f80395b0c..2c67e91f486 100644 +index c18b3eab5..55c7b8b98 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -305,10 +305,15 @@ reload_icon_geometry (MetaWindow *window, @@ -1502,7 +1376,7 @@ index 73f80395b0c..2c67e91f486 100644 * as if flags were zero */ if (hints) -- window->size_hints = *hints; +- window->size_hints = *(MetaSizeHints*)(hints); + { + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + @@ -1562,7 +1436,7 @@ index 73f80395b0c..2c67e91f486 100644 window->size_hints.flags = 0; diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index 42981584cce..491d49e5c29 100644 +index e57bc8622..8d2388d2e 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) @@ -1819,7 +1693,7 @@ index 42981584cce..491d49e5c29 100644 temp = g_new0 (MetaStrut, 1); temp->side = 1 << i; meta_display_get_size (window->display, -@@ -2048,9 +2198,10 @@ static void +@@ -2040,9 +2190,10 @@ static void meta_window_x11_constructed (GObject *object) { MetaWindow *window = META_WINDOW (object); @@ -1832,7 +1706,7 @@ index 42981584cce..491d49e5c29 100644 meta_verbose ("attrs->map_state = %d (%s)", attrs.map_state, -@@ -2065,16 +2216,17 @@ meta_window_x11_constructed (GObject *object) +@@ -2057,16 +2208,17 @@ meta_window_x11_constructed (GObject *object) window->client_type = META_WINDOW_CLIENT_TYPE_X11; window->override_redirect = attrs.override_redirect; @@ -1858,7 +1732,7 @@ index 42981584cce..491d49e5c29 100644 window->depth = attrs.depth; priv->xvisual = attrs.visual; -@@ -2084,11 +2236,11 @@ meta_window_x11_constructed (GObject *object) +@@ -2076,11 +2228,11 @@ meta_window_x11_constructed (GObject *object) window->decorated = TRUE; window->hidden = FALSE; @@ -1873,7 +1747,7 @@ index 42981584cce..491d49e5c29 100644 g_signal_connect (window, "notify::decorated", G_CALLBACK (meta_window_x11_update_input_region), -@@ -2200,6 +2352,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) +@@ -2192,6 +2344,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) klass->thaw_commits = meta_window_x11_impl_thaw_commits; klass->always_update_shape = meta_window_x11_impl_always_update_shape; klass->process_property_notify = meta_window_x11_impl_process_property_notify; @@ -1882,7 +1756,7 @@ index 42981584cce..491d49e5c29 100644 obj_props[PROP_ATTRIBUTES] = g_param_spec_pointer ("attributes", NULL, NULL, -@@ -2476,7 +2630,10 @@ meta_window_x11_update_input_region (MetaWindow *window) +@@ -2468,7 +2622,10 @@ meta_window_x11_update_input_region (MetaWindow *window) else { /* Window has a custom shape. */ @@ -1894,7 +1768,7 @@ index 42981584cce..491d49e5c29 100644 } meta_XFree (rects); -@@ -2560,7 +2717,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) +@@ -2552,7 +2709,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) if (rects) { @@ -1906,7 +1780,7 @@ index 42981584cce..491d49e5c29 100644 XFree (rects); } } -@@ -2829,6 +2989,7 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2821,6 +2981,7 @@ meta_window_x11_configure_request (MetaWindow *window, { MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); @@ -1914,7 +1788,7 @@ index 42981584cce..491d49e5c29 100644 /* Note that x, y is the corner of the window border, * and width, height is the size of the window inside -@@ -2837,15 +2998,25 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2829,15 +2990,25 @@ meta_window_x11_configure_request (MetaWindow *window, * requested border here. */ if (event->xconfigurerequest.value_mask & CWBorderWidth) @@ -1948,7 +1822,7 @@ index 42981584cce..491d49e5c29 100644 /* Handle stacking. We only handle raises/lowers, mostly because * stack.c really can't deal with anything else. I guess we'll fix -@@ -3340,8 +3511,13 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3332,8 +3503,13 @@ meta_window_x11_client_message (MetaWindow *window, guint32 timestamp; MetaWindowDrag *window_drag; @@ -1964,7 +1838,7 @@ index 42981584cce..491d49e5c29 100644 action = event->xclient.data.l[2]; button = event->xclient.data.l[3]; -@@ -3503,6 +3679,7 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3497,6 +3673,7 @@ meta_window_x11_client_message (MetaWindow *window, { MetaGravity gravity; guint value_mask; @@ -1972,7 +1846,7 @@ index 42981584cce..491d49e5c29 100644 gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; -@@ -3511,13 +3688,20 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3505,13 +3682,20 @@ meta_window_x11_client_message (MetaWindow *window, if (gravity == 0) gravity = window->size_hints.win_gravity; @@ -1997,7 +1871,7 @@ index 42981584cce..491d49e5c29 100644 } else if (event->xclient.message_type == x11_display->atom__NET_ACTIVE_WINDOW && -@@ -3574,11 +3758,15 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3568,11 +3752,15 @@ meta_window_x11_client_message (MetaWindow *window, else if (event->xclient.message_type == x11_display->atom__GTK_SHOW_WINDOW_MENU) { @@ -2016,7 +1890,7 @@ index 42981584cce..491d49e5c29 100644 meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); } -@@ -4100,10 +4288,11 @@ meta_window_x11_configure_notify (MetaWindow *window, +@@ -4094,10 +4282,11 @@ meta_window_x11_configure_notify (MetaWindow *window, g_assert (window->override_redirect); g_assert (window->frame == NULL); @@ -2033,7 +1907,7 @@ index 42981584cce..491d49e5c29 100644 priv->client_rect = window->rect; window->buffer_rect = window->rect; diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h -index 205eaaa632b..fa3fbea6a84 100644 +index 205eaaa63..fa3fbea6a 100644 --- a/src/x11/window-x11.h +++ b/src/x11/window-x11.h @@ -45,6 +45,24 @@ struct _MetaWindowX11Class @@ -2085,6 +1959,3 @@ index 205eaaa632b..fa3fbea6a84 100644 + int *stage_y, + int *stage_width, + int *stage_heigth); --- -GitLab - From 3b52bd4db1baeab83a6abd065612a0890da61f9a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 08:52:21 -0700 Subject: [PATCH 05/41] chore: Modify patch to consider previous Fedora patches --- staging/mutter/3567.patch | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/staging/mutter/3567.patch b/staging/mutter/3567.patch index e4fa0c3..694913a 100644 --- a/staging/mutter/3567.patch +++ b/staging/mutter/3567.patch @@ -130,10 +130,10 @@ index 3703b23b0..1ae59d636 100644 if (feature) g_message ("Enabling experimental feature '%s'", feature_str); diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c -index 19827af33..7df10e6c1 100644 +index 7d5e46ac7..577ed2760 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c -@@ -688,11 +688,23 @@ meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, +@@ -696,11 +696,23 @@ meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); if (surface) @@ -163,7 +163,7 @@ index 19827af33..7df10e6c1 100644 meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); } diff --git a/src/core/frame.c b/src/core/frame.c -index 145f0b7bd..502622598 100644 +index 1c90ce423..dbd111d76 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -33,6 +33,7 @@ @@ -173,8 +173,8 @@ index 145f0b7bd..502622598 100644 +#include "x11/window-x11.h" #include - #include -@@ -66,6 +67,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, + +@@ -65,6 +66,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, XSetWindowAttributes attrs; gulong create_serial = 0; MetaFrame *frame; @@ -182,7 +182,7 @@ index 145f0b7bd..502622598 100644 if (window->frame) return; -@@ -127,11 +129,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, +@@ -123,11 +125,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, meta_stack_tracker_record_remove (window->display->stack_tracker, meta_window_x11_get_xwindow (window), XNextRequest (x11_display->xdisplay)); @@ -204,7 +204,7 @@ index 145f0b7bd..502622598 100644 window->reparents_pending += 1; /* FIXME handle this error */ mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -201,6 +211,8 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -197,6 +207,8 @@ meta_window_destroy_frame (MetaWindow *window) if (!x11_display->closing) { @@ -213,7 +213,7 @@ index 145f0b7bd..502622598 100644 if (!window->unmanaging) { meta_stack_tracker_record_add (window->display->stack_tracker, -@@ -208,6 +220,14 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -204,6 +216,14 @@ meta_window_destroy_frame (MetaWindow *window) XNextRequest (x11_display->xdisplay)); } @@ -228,7 +228,7 @@ index 145f0b7bd..502622598 100644 XReparentWindow (x11_display->xdisplay, meta_window_x11_get_xwindow (window), x11_display->xroot, -@@ -215,8 +235,7 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -211,8 +231,7 @@ meta_window_destroy_frame (MetaWindow *window) * coordinates here means we'll need to ensure a configure * notify event is sent; see bug 399552. */ @@ -238,7 +238,7 @@ index 145f0b7bd..502622598 100644 window->reparents_pending += 1; } -@@ -270,6 +289,7 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -263,6 +282,7 @@ meta_frame_query_borders (MetaFrame *frame, MetaFrameBorders *borders) { MetaWindow *window = frame->window; @@ -246,7 +246,7 @@ index 145f0b7bd..502622598 100644 MetaX11Display *x11_display = window->display->x11_display; int format, res; Atom type; -@@ -295,12 +315,22 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -288,12 +308,22 @@ meta_frame_query_borders (MetaFrame *frame, if (res == Success && nitems == 4) { @@ -275,7 +275,7 @@ index 145f0b7bd..502622598 100644 } g_clear_pointer (&data, XFree); -@@ -321,12 +351,21 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -314,12 +344,21 @@ meta_frame_query_borders (MetaFrame *frame, if (res == Success && nitems == 4) { @@ -303,7 +303,7 @@ index 145f0b7bd..502622598 100644 } g_clear_pointer (&data, XFree); -@@ -370,7 +409,9 @@ meta_frame_sync_to_window (MetaFrame *frame, +@@ -363,7 +402,9 @@ meta_frame_sync_to_window (MetaFrame *frame, gboolean need_resize) { MetaWindow *window = frame->window; @@ -313,7 +313,7 @@ index 145f0b7bd..502622598 100644 meta_topic (META_DEBUG_GEOMETRY, "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", -@@ -381,12 +422,22 @@ meta_frame_sync_to_window (MetaFrame *frame, +@@ -374,12 +415,22 @@ meta_frame_sync_to_window (MetaFrame *frame, mtk_x11_error_trap_push (x11_display->xdisplay); @@ -340,7 +340,7 @@ index 145f0b7bd..502622598 100644 mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -423,6 +474,7 @@ static void +@@ -416,6 +467,7 @@ static void send_configure_notify (MetaFrame *frame) { MetaX11Display *x11_display = frame->window->display->x11_display; @@ -348,7 +348,7 @@ index 145f0b7bd..502622598 100644 XEvent event = { 0 }; /* We never get told by the frames client, just reassert the -@@ -432,10 +484,16 @@ send_configure_notify (MetaFrame *frame) +@@ -425,10 +477,16 @@ send_configure_notify (MetaFrame *frame) event.xconfigure.display = x11_display->xdisplay; event.xconfigure.event = frame->xwindow; event.xconfigure.window = frame->xwindow; @@ -908,7 +908,7 @@ index daf9d1abb..ae7a06977 100644 + +int meta_xwayland_get_effective_scale (MetaXWaylandManager *manager); diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c -index 438f3bd1e..f2a613392 100644 +index 5c0760daa..f67e9e427 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -70,7 +70,7 @@ @@ -1047,7 +1047,7 @@ index 438f3bd1e..f2a613392 100644 g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); g_clear_list (&x11_display->event_funcs, -@@ -572,6 +671,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) +@@ -600,6 +699,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) return; meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); @@ -1057,7 +1057,7 @@ index 438f3bd1e..f2a613392 100644 data[0] = monitor_width; data[1] = monitor_height; -@@ -981,14 +1083,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, +@@ -1009,14 +1111,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, for (l = logical_monitors; l; l = l->next) { @@ -1086,7 +1086,7 @@ index 438f3bd1e..f2a613392 100644 tmp += 4; } -@@ -1017,7 +1127,6 @@ set_work_area_hint (MetaDisplay *display, +@@ -1045,7 +1155,6 @@ set_work_area_hint (MetaDisplay *display, int num_workspaces; GList *l; unsigned long *data, *tmp; @@ -1094,7 +1094,7 @@ index 438f3bd1e..f2a613392 100644 num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); data = g_new (unsigned long, num_workspaces * 4); -@@ -1026,14 +1135,22 @@ set_work_area_hint (MetaDisplay *display, +@@ -1054,14 +1163,22 @@ set_work_area_hint (MetaDisplay *display, for (l = workspace_manager->workspaces; l; l = l->next) { MetaWorkspace *workspace = l->data; @@ -1122,7 +1122,7 @@ index 438f3bd1e..f2a613392 100644 tmp += 4; } -@@ -1196,6 +1313,58 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) +@@ -1224,6 +1341,58 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) on_frames_client_died, x11_display); } @@ -1181,7 +1181,7 @@ index 438f3bd1e..f2a613392 100644 /** * meta_x11_display_new: * -@@ -1214,6 +1383,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1242,6 +1411,7 @@ meta_x11_display_new (MetaDisplay *display, MetaBackend *backend = meta_context_get_backend (context); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); @@ -1189,7 +1189,7 @@ index 438f3bd1e..f2a613392 100644 g_autoptr (MetaX11Display) x11_display = NULL; Display *xdisplay; Screen *xscreen; -@@ -1290,6 +1460,8 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1318,6 +1488,8 @@ meta_x11_display_new (MetaDisplay *display, x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); x11_display->display = display; @@ -1198,7 +1198,7 @@ index 438f3bd1e..f2a613392 100644 /* here we use XDisplayName which is what the user * probably put in, vs. DisplayString(display) which is * canonicalized by XOpenDisplay() -@@ -1382,7 +1554,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1410,7 +1582,7 @@ meta_x11_display_new (MetaDisplay *display, "monitors-changed-internal", G_CALLBACK (on_monitors_changed_internal), x11_display, @@ -1207,7 +1207,7 @@ index 438f3bd1e..f2a613392 100644 init_leader_window (x11_display, ×tamp); x11_display->timestamp = timestamp; -@@ -1475,6 +1647,11 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1503,6 +1675,11 @@ meta_x11_display_new (MetaDisplay *display, meta_prefs_add_listener (prefs_changed_callback, x11_display); @@ -1219,7 +1219,7 @@ index 438f3bd1e..f2a613392 100644 set_work_area_hint (display, x11_display); g_signal_connect_object (display, "workareas-changed", -@@ -1683,16 +1860,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) +@@ -1711,16 +1888,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) } static void @@ -1241,7 +1241,7 @@ index 438f3bd1e..f2a613392 100644 } static void -@@ -1744,8 +1917,37 @@ static void +@@ -1772,8 +1945,37 @@ static void update_cursor_theme (MetaX11Display *x11_display) { MetaBackend *backend = backend_from_x11_display (x11_display); @@ -1280,7 +1280,7 @@ index 438f3bd1e..f2a613392 100644 schedule_reload_x11_cursor (x11_display); if (META_IS_BACKEND_X11 (backend)) -@@ -1753,7 +1955,7 @@ update_cursor_theme (MetaX11Display *x11_display) +@@ -1781,7 +1983,7 @@ update_cursor_theme (MetaX11Display *x11_display) MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); @@ -1289,7 +1289,7 @@ index 438f3bd1e..f2a613392 100644 meta_backend_x11_reload_cursor (backend_x11); } } -@@ -1946,6 +2148,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, +@@ -1974,6 +2176,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, } x11_display->has_xinerama_indices = FALSE; @@ -1436,7 +1436,7 @@ index c18b3eab5..55c7b8b98 100644 window->size_hints.flags = 0; diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index e57bc8622..8d2388d2e 100644 +index c2ae6bad7..45506120e 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) @@ -1745,9 +1745,9 @@ index e57bc8622..8d2388d2e 100644 + attrs.border_width, 0, 0, 0, + &priv->border_width, NULL, NULL, NULL); - g_signal_connect (window, "notify::decorated", - G_CALLBACK (meta_window_x11_update_input_region), -@@ -2192,6 +2344,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) + G_OBJECT_CLASS (meta_window_x11_parent_class)->constructed (object); + } +@@ -2188,6 +2340,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) klass->thaw_commits = meta_window_x11_impl_thaw_commits; klass->always_update_shape = meta_window_x11_impl_always_update_shape; klass->process_property_notify = meta_window_x11_impl_process_property_notify; @@ -1756,7 +1756,7 @@ index e57bc8622..8d2388d2e 100644 obj_props[PROP_ATTRIBUTES] = g_param_spec_pointer ("attributes", NULL, NULL, -@@ -2468,7 +2622,10 @@ meta_window_x11_update_input_region (MetaWindow *window) +@@ -2459,7 +2613,10 @@ meta_window_x11_update_input_region (MetaWindow *window) else { /* Window has a custom shape. */ @@ -1768,7 +1768,7 @@ index e57bc8622..8d2388d2e 100644 } meta_XFree (rects); -@@ -2552,7 +2709,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) +@@ -2543,7 +2700,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) if (rects) { From 349c64410e15443161e7fb1de65cac0f576ae470 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 08:58:48 -0700 Subject: [PATCH 06/41] chore: Fix type conversion error in patch set --- staging/mutter/3567.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/3567.patch b/staging/mutter/3567.patch index 694913a..b4eaaef 100644 --- a/staging/mutter/3567.patch +++ b/staging/mutter/3567.patch @@ -1380,7 +1380,7 @@ index c18b3eab5..55c7b8b98 100644 + { + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + -+ window->size_hints = *hints; ++ window->size_hints = *(MetaSizeHints*)(hints); + + meta_window_x11_protocol_to_stage (window_x11, + hints->x, hints->y, From 0a459f923f738df332995d00e80fc53549115d40 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 11:21:46 -0700 Subject: [PATCH 07/41] feat: Add triple buffering and nvidia secondary copy acceleration patches to Mutter --- .../mutter/{3567.patch => 0002-3567.patch} | 0 staging/mutter/0003-3304.patch | 854 ++ staging/mutter/0004-1441.patch | 8396 +++++++++++++++++ staging/mutter/mutter.spec | 12 +- 4 files changed, 9260 insertions(+), 2 deletions(-) rename staging/mutter/{3567.patch => 0002-3567.patch} (100%) create mode 100644 staging/mutter/0003-3304.patch create mode 100644 staging/mutter/0004-1441.patch diff --git a/staging/mutter/3567.patch b/staging/mutter/0002-3567.patch similarity index 100% rename from staging/mutter/3567.patch rename to staging/mutter/0002-3567.patch diff --git a/staging/mutter/0003-3304.patch b/staging/mutter/0003-3304.patch new file mode 100644 index 0000000..745e6b1 --- /dev/null +++ b/staging/mutter/0003-3304.patch @@ -0,0 +1,854 @@ +diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c +index 9a57c52de..2f8247b3a 100644 +--- a/src/backends/meta-egl.c ++++ b/src/backends/meta-egl.c +@@ -260,6 +260,14 @@ meta_egl_has_extensions (MetaEgl *egl, + return has_extensions; + } + ++const char * ++meta_egl_query_string (MetaEgl *egl, ++ EGLDisplay display, ++ EGLint name) ++{ ++ return eglQueryString (display, name); ++} ++ + gboolean + meta_egl_initialize (MetaEgl *egl, + EGLDisplay display, +diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h +index 09bee954a..8b955c90c 100644 +--- a/src/backends/meta-egl.h ++++ b/src/backends/meta-egl.h +@@ -47,6 +47,10 @@ gboolean meta_egl_has_extensions (MetaEgl *egl, + const char *first_extension, + ...); + ++const char * meta_egl_query_string (MetaEgl *egl, ++ EGLDisplay display, ++ EGLint name); ++ + gboolean meta_egl_initialize (MetaEgl *egl, + EGLDisplay display, + GError **error); +diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c +index 405ce80a4..086e217cb 100644 +--- a/src/backends/native/meta-onscreen-native.c ++++ b/src/backends/native/meta-onscreen-native.c +@@ -841,6 +841,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, + "copy_shared_framebuffer_gpu()"); + ++ if (renderer_gpu_data->secondary.needs_explicit_sync) ++ cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); ++ + render_device = renderer_gpu_data->render_device; + egl_display = meta_render_device_get_egl_display (render_device); + +@@ -948,8 +951,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre + COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, + "copy_shared_framebuffer_primary_gpu()"); + +- if (!secondary_gpu_state || +- secondary_gpu_state->egl_surface == EGL_NO_SURFACE) ++ if (!secondary_gpu_state) + return NULL; + + primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); +@@ -2418,6 +2420,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat + width, height, + format, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); ++ ++ if (!gbm_surface) ++ { ++ gbm_surface = gbm_surface_create (gbm_device, ++ width, height, ++ format, ++ 0); ++ } ++ + if (!gbm_surface) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, +diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c +index cf27ba8d4..0d50de177 100644 +--- a/src/backends/native/meta-renderer-native-gles3.c ++++ b/src/backends/native/meta-renderer-native-gles3.c +@@ -3,6 +3,7 @@ + /* + * Copyright (C) 2017 Red Hat + * Copyright (c) 2018 DisplayLink (UK) Ltd. ++ * Copyright (c) 2023 Canonical Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as +@@ -34,6 +35,7 @@ + #include "backends/meta-egl-ext.h" + #include "backends/meta-gles3.h" + #include "backends/meta-gles3-table.h" ++#include "meta/meta-debug.h" + + /* + * GL/gl.h being included may conflict with gl3.h on some architectures. +@@ -43,17 +45,240 @@ + #error "Somehow included OpenGL headers when we shouldn't have" + #endif + ++typedef struct _ContextData ++{ ++ GArray *buffer_support; ++ GLuint shader_program; ++} ContextData; ++ ++typedef struct ++{ ++ uint32_t drm_format; ++ uint64_t drm_modifier; ++ gboolean can_blit; ++} BufferTypeSupport; ++ + static void +-paint_egl_image (MetaGles3 *gles3, +- EGLImageKHR egl_image, +- int width, +- int height) ++context_data_free (ContextData *context_data) ++{ ++ g_array_free (context_data->buffer_support, TRUE); ++ g_free (context_data); ++} ++ ++static GQuark ++get_quark_for_egl_context (EGLContext egl_context) ++{ ++ char key[128]; ++ ++ g_snprintf (key, sizeof key, "EGLContext %p", egl_context); ++ ++ return g_quark_from_string (key); ++} ++ ++static gboolean ++can_blit_buffer (ContextData *context_data, ++ MetaEgl *egl, ++ EGLDisplay egl_display, ++ uint32_t drm_format, ++ uint64_t drm_modifier) ++{ ++ EGLint num_modifiers; ++ EGLuint64KHR *modifiers; ++ EGLBoolean *external_only; ++ g_autoptr (GError) error = NULL; ++ int i; ++ gboolean can_blit; ++ BufferTypeSupport support; ++ ++ can_blit = drm_modifier == DRM_FORMAT_MOD_LINEAR; ++ ++ for (i = 0; i < context_data->buffer_support->len; i++) ++ { ++ BufferTypeSupport *support = ++ &g_array_index (context_data->buffer_support, BufferTypeSupport, i); ++ ++ if (support->drm_format == drm_format && ++ support->drm_modifier == drm_modifier) ++ return support->can_blit; ++ } ++ ++ if (!meta_egl_has_extensions (egl, egl_display, NULL, ++ "EGL_EXT_image_dma_buf_import_modifiers", ++ NULL)) ++ { ++ meta_topic (META_DEBUG_RENDER, ++ "No support for EGL_EXT_image_dma_buf_import_modifiers, " ++ "assuming blitting linearly will still work."); ++ goto out; ++ } ++ ++ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, ++ drm_format, 0, NULL, NULL, ++ &num_modifiers, &error)) ++ { ++ meta_topic (META_DEBUG_RENDER, ++ "Failed to query supported DMA buffer modifiers (%s), " ++ "assuming blitting linearly will still work.", ++ error->message); ++ goto out; ++ } ++ ++ if (num_modifiers == 0) ++ goto out; ++ ++ modifiers = g_alloca0 (sizeof (EGLuint64KHR) * num_modifiers); ++ external_only = g_alloca0 (sizeof (EGLBoolean) * num_modifiers); ++ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, ++ drm_format, num_modifiers, ++ modifiers, external_only, ++ &num_modifiers, &error)) ++ { ++ g_warning ("Failed to requery supported DMA buffer modifiers: %s", ++ error->message); ++ can_blit = FALSE; ++ goto out; ++ } ++ ++ can_blit = FALSE; ++ for (i = 0; i < num_modifiers; i++) ++ { ++ if (drm_modifier == modifiers[i]) ++ { ++ can_blit = !external_only[i]; ++ goto out; ++ } ++ } ++ ++out: ++ support = (BufferTypeSupport) { ++ .drm_format = drm_format, ++ .drm_modifier = drm_modifier, ++ .can_blit = can_blit, ++ }; ++ g_array_append_val (context_data->buffer_support, support); ++ return can_blit; ++} ++ ++static GLuint ++load_shader (const char *src, ++ GLenum type) ++{ ++ GLuint shader = glCreateShader (type); ++ ++ if (shader) ++ { ++ GLint compiled; ++ ++ glShaderSource (shader, 1, &src, NULL); ++ glCompileShader (shader); ++ glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); ++ if (!compiled) ++ { ++ GLchar log[1024]; ++ ++ glGetShaderInfoLog (shader, sizeof (log) - 1, NULL, log); ++ log[sizeof (log) - 1] = '\0'; ++ g_warning ("load_shader compile failed: %s", log); ++ glDeleteShader (shader); ++ shader = 0; ++ } ++ } ++ ++ return shader; ++} ++ ++static void ++ensure_shader_program (ContextData *context_data, ++ MetaGles3 *gles3) ++{ ++ static const char vertex_shader_source[] = ++ "#version 100\n" ++ "attribute vec2 position;\n" ++ "attribute vec2 texcoord;\n" ++ "varying vec2 v_texcoord;\n" ++ "\n" ++ "void main()\n" ++ "{\n" ++ " gl_Position = vec4(position, 0.0, 1.0);\n" ++ " v_texcoord = texcoord;\n" ++ "}\n"; ++ ++ static const char fragment_shader_source[] = ++ "#version 100\n" ++ "#extension GL_OES_EGL_image_external : require\n" ++ "precision mediump float;\n" ++ "uniform samplerExternalOES s_texture;\n" ++ "varying vec2 v_texcoord;\n" ++ "\n" ++ " void main()\n" ++ "{\n" ++ " gl_FragColor = texture2D(s_texture, v_texcoord);\n" ++ "}\n"; ++ ++ static const GLfloat box[] = ++ { /* position texcoord */ ++ -1.0f, +1.0f, 0.0f, 0.0f, ++ +1.0f, +1.0f, 1.0f, 0.0f, ++ +1.0f, -1.0f, 1.0f, 1.0f, ++ -1.0f, -1.0f, 0.0f, 1.0f, ++ }; ++ GLint linked; ++ GLuint vertex_shader, fragment_shader; ++ GLint position_attrib, texcoord_attrib; ++ GLuint shader_program; ++ ++ if (context_data->shader_program) ++ return; ++ ++ shader_program = glCreateProgram (); ++ g_return_if_fail (shader_program); ++ context_data->shader_program = shader_program; ++ ++ vertex_shader = load_shader (vertex_shader_source, GL_VERTEX_SHADER); ++ g_return_if_fail (vertex_shader); ++ fragment_shader = load_shader (fragment_shader_source, GL_FRAGMENT_SHADER); ++ g_return_if_fail (fragment_shader); ++ ++ GLBAS (gles3, glAttachShader, (shader_program, vertex_shader)); ++ GLBAS (gles3, glAttachShader, (shader_program, fragment_shader)); ++ GLBAS (gles3, glLinkProgram, (shader_program)); ++ GLBAS (gles3, glGetProgramiv, (shader_program, GL_LINK_STATUS, &linked)); ++ if (!linked) ++ { ++ GLchar log[1024]; ++ ++ glGetProgramInfoLog (shader_program, sizeof (log) - 1, NULL, log); ++ log[sizeof (log) - 1] = '\0'; ++ g_warning ("Link failed: %s", log); ++ return; ++ } ++ ++ GLBAS (gles3, glUseProgram, (shader_program)); ++ ++ position_attrib = glGetAttribLocation (shader_program, "position"); ++ GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (position_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box)); ++ ++ texcoord_attrib = glGetAttribLocation (shader_program, "texcoord"); ++ GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box + 2)); ++} ++ ++static void ++blit_egl_image (MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height) + { + GLuint texture; + GLuint framebuffer; + + meta_gles3_clear_error (gles3); + ++ GLBAS (gles3, glViewport, (0, 0, width, height)); ++ + GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); + GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); + +@@ -85,6 +310,43 @@ paint_egl_image (MetaGles3 *gles3, + GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); + } + ++static void ++paint_egl_image (ContextData *context_data, ++ MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height) ++{ ++ GLuint texture; ++ ++ meta_gles3_clear_error (gles3); ++ ensure_shader_program (context_data, gles3); ++ ++ GLBAS (gles3, glViewport, (0, 0, width, height)); ++ ++ GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); ++ GLBAS (gles3, glGenTextures, (1, &texture)); ++ GLBAS (gles3, glBindTexture, (GL_TEXTURE_EXTERNAL_OES, texture)); ++ GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_EXTERNAL_OES, ++ egl_image)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_MAG_FILTER, ++ GL_NEAREST)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_MIN_FILTER, ++ GL_NEAREST)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_WRAP_S, ++ GL_CLAMP_TO_EDGE)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_WRAP_T, ++ GL_CLAMP_TO_EDGE)); ++ ++ GLBAS (gles3, glDrawArrays, (GL_TRIANGLE_FAN, 0, 4)); ++ ++ GLBAS (gles3, glDeleteTextures, (1, &texture)); ++} ++ + gboolean + meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + MetaGles3 *gles3, +@@ -105,6 +367,28 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + uint32_t format; + EGLImageKHR egl_image; + gboolean use_modifiers; ++ GQuark context_data_quark; ++ ContextData *context_data; ++ gboolean can_blit; ++ ++ context_data_quark = get_quark_for_egl_context (egl_context); ++ context_data = g_object_get_qdata (G_OBJECT (gles3), context_data_quark); ++ if (!context_data) ++ { ++ context_data = g_new0 (ContextData, 1); ++ context_data->buffer_support = g_array_new (FALSE, FALSE, ++ sizeof (BufferTypeSupport)); ++ ++ g_object_set_qdata_full (G_OBJECT (gles3), ++ context_data_quark, ++ context_data, ++ (GDestroyNotify) context_data_free); ++ } ++ ++ can_blit = can_blit_buffer (context_data, ++ egl, egl_display, ++ gbm_bo_get_format (shared_bo), ++ gbm_bo_get_modifier (shared_bo)); + + shared_bo_fd = gbm_bo_get_fd (shared_bo); + if (shared_bo_fd < 0) +@@ -150,9 +434,21 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + if (!egl_image) + return FALSE; + +- paint_egl_image (gles3, egl_image, width, height); ++ if (can_blit) ++ blit_egl_image (gles3, egl_image, width, height); ++ else ++ paint_egl_image (context_data, gles3, egl_image, width, height); + + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + + return TRUE; + } ++ ++void ++meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, ++ EGLContext egl_context) ++{ ++ GQuark context_data_quark = get_quark_for_egl_context (egl_context); ++ ++ g_object_set_qdata (G_OBJECT (gles3), context_data_quark, NULL); ++} +diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h +index 591ff82e1..f5791a171 100644 +--- a/src/backends/native/meta-renderer-native-gles3.h ++++ b/src/backends/native/meta-renderer-native-gles3.h +@@ -26,10 +26,13 @@ + #include "backends/meta-egl.h" + #include "backends/meta-gles3.h" + +-gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, +- MetaGles3 *gles3, +- EGLDisplay egl_display, +- EGLContext egl_context, +- EGLSurface egl_surface, +- struct gbm_bo *shared_bo, +- GError **error); ++gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, ++ MetaGles3 *gles3, ++ EGLDisplay egl_display, ++ EGLContext egl_context, ++ EGLSurface egl_surface, ++ struct gbm_bo *shared_bo, ++ GError **error); ++ ++void meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, ++ EGLContext egl_context); +diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h +index 997fe6f69..2d3fe1971 100644 +--- a/src/backends/native/meta-renderer-native-private.h ++++ b/src/backends/native/meta-renderer-native-private.h +@@ -60,6 +60,7 @@ typedef struct _MetaRendererNativeGpuData + struct { + MetaSharedFramebufferCopyMode copy_mode; + gboolean has_EGL_EXT_image_dma_buf_import_modifiers; ++ gboolean needs_explicit_sync; + + /* For GPU blit mode */ + EGLContext egl_context; +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 5ffbafb58..aa76d018c 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -63,6 +63,7 @@ + #include "backends/native/meta-output-kms.h" + #include "backends/native/meta-render-device-gbm.h" + #include "backends/native/meta-render-device-surfaceless.h" ++#include "backends/native/meta-renderer-native-gles3.h" + #include "backends/native/meta-renderer-native-private.h" + #include "backends/native/meta-renderer-view-native.h" + #include "cogl/cogl.h" +@@ -137,6 +138,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data + MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; + MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); + ++ meta_renderer_native_gles3_forget_context (renderer_native->gles3, ++ renderer_gpu_data->secondary.egl_context); ++ + meta_egl_destroy_context (egl, + egl_display, + renderer_gpu_data->secondary.egl_context, +@@ -1806,6 +1810,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, + CoglContext *cogl_context; + CoglDisplay *cogl_display; + const char **missing_gl_extensions; ++ const char *egl_vendor; + + egl_display = meta_render_device_get_egl_display (render_device); + if (egl_display == EGL_NO_DISPLAY) +@@ -1872,6 +1877,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, + meta_egl_has_extensions (egl, egl_display, NULL, + "EGL_EXT_image_dma_buf_import_modifiers", + NULL); ++ ++ egl_vendor = meta_egl_query_string (egl, egl_display, EGL_VENDOR); ++ if (!g_strcmp0 (egl_vendor, "NVIDIA")) ++ renderer_gpu_data->secondary.needs_explicit_sync = TRUE; ++ + ret = TRUE; + out: + maybe_restore_cogl_egl_api (renderer_native); +diff --git a/src/meta/common.h b/src/meta/common.h +index ee978ac6a..ed3aa81ef 100644 +--- a/src/meta/common.h ++++ b/src/meta/common.h +@@ -27,6 +27,7 @@ + #include + + #include "clutter/clutter.h" ++#include "meta/meta-base.h" + #include "meta/meta-enums.h" + + /** +@@ -42,8 +43,6 @@ + /* Replacement for X11 CurrentTime */ + #define META_CURRENT_TIME 0L + +-#define META_EXPORT __attribute__((visibility("default"))) extern +- + #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST + + /* Keep array size in sync with MAX_BUTTONS_PER_CORNER */ +diff --git a/src/meta/meson.build b/src/meta/meson.build +index 655dedeaf..bc3910408 100644 +--- a/src/meta/meson.build ++++ b/src/meta/meson.build +@@ -9,6 +9,7 @@ mutter_public_headers = [ + 'keybindings.h', + 'main.h', + 'meta-backend.h', ++ 'meta-base.h', + 'meta-background.h', + 'meta-background-actor.h', + 'meta-background-content.h', +@@ -17,6 +18,7 @@ mutter_public_headers = [ + 'meta-close-dialog.h', + 'meta-cursor-tracker.h', + 'meta-context.h', ++ 'meta-debug.h', + 'meta-dnd.h', + 'meta-enums.h', + 'meta-idle-monitor.h', +diff --git a/src/meta/meta-base.h b/src/meta/meta-base.h +new file mode 100644 +index 000000000..e344b2221 +--- /dev/null ++++ b/src/meta/meta-base.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2001 Havoc Pennington ++ * Copyright (C) 2005 Elijah Newren ++ * ++ * 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 ++ ++#define META_EXPORT __attribute__((visibility("default"))) extern +diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h +new file mode 100644 +index 000000000..b4c70144b +--- /dev/null ++++ b/src/meta/meta-debug.h +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (C) 2001 Havoc Pennington ++ * Copyright (C) 2005 Elijah Newren ++ * ++ * 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 "meta/meta-base.h" ++ ++/** ++ * MetaDebugTopic: ++ * @META_DEBUG_VERBOSE: verbose logging ++ * @META_DEBUG_FOCUS: focus ++ * @META_DEBUG_WORKAREA: workarea ++ * @META_DEBUG_STACK: stack ++ * @META_DEBUG_SM: session management ++ * @META_DEBUG_EVENTS: events ++ * @META_DEBUG_WINDOW_STATE: window state ++ * @META_DEBUG_WINDOW_OPS: window operations ++ * @META_DEBUG_GEOMETRY: geometry ++ * @META_DEBUG_PLACEMENT: window placement ++ * @META_DEBUG_PING: ping ++ * @META_DEBUG_KEYBINDINGS: keybindings ++ * @META_DEBUG_SYNC: sync ++ * @META_DEBUG_STARTUP: startup ++ * @META_DEBUG_PREFS: preferences ++ * @META_DEBUG_GROUPS: groups ++ * @META_DEBUG_RESIZING: resizing ++ * @META_DEBUG_SHAPES: shapes ++ * @META_DEBUG_EDGE_RESISTANCE: edge resistance ++ * @META_DEBUG_WAYLAND: Wayland ++ * @META_DEBUG_KMS: kernel mode setting ++ * @META_DEBUG_SCREEN_CAST: screencasting ++ * @META_DEBUG_REMOTE_DESKTOP: remote desktop ++ * @META_DEBUG_BACKEND: backend ++ * @META_DEBUG_RENDER: native backend rendering ++ * @META_DEBUG_COLOR: color management ++ * @META_DEBUG_INPUT_EVENTS: input events ++ * @META_DEBUG_EIS: eis state ++ */ ++typedef enum ++{ ++ META_DEBUG_VERBOSE = -1, ++ META_DEBUG_FOCUS = 1 << 0, ++ META_DEBUG_WORKAREA = 1 << 1, ++ META_DEBUG_STACK = 1 << 2, ++ META_DEBUG_SM = 1 << 3, ++ META_DEBUG_EVENTS = 1 << 4, ++ META_DEBUG_WINDOW_STATE = 1 << 5, ++ META_DEBUG_WINDOW_OPS = 1 << 6, ++ META_DEBUG_GEOMETRY = 1 << 7, ++ META_DEBUG_PLACEMENT = 1 << 8, ++ META_DEBUG_PING = 1 << 9, ++ META_DEBUG_KEYBINDINGS = 1 << 10, ++ META_DEBUG_SYNC = 1 << 11, ++ META_DEBUG_STARTUP = 1 << 12, ++ META_DEBUG_PREFS = 1 << 13, ++ META_DEBUG_GROUPS = 1 << 14, ++ META_DEBUG_RESIZING = 1 << 15, ++ META_DEBUG_SHAPES = 1 << 16, ++ META_DEBUG_EDGE_RESISTANCE = 1 << 17, ++ META_DEBUG_DBUS = 1 << 18, ++ META_DEBUG_INPUT = 1 << 19, ++ META_DEBUG_WAYLAND = 1 << 20, ++ META_DEBUG_KMS = 1 << 21, ++ META_DEBUG_SCREEN_CAST = 1 << 22, ++ META_DEBUG_REMOTE_DESKTOP = 1 << 23, ++ META_DEBUG_BACKEND = 1 << 24, ++ META_DEBUG_RENDER = 1 << 25, ++ META_DEBUG_COLOR = 1 << 26, ++ META_DEBUG_INPUT_EVENTS = 1 << 27, ++ META_DEBUG_EIS = 1 << 28, ++} MetaDebugTopic; ++ ++META_EXPORT ++gboolean meta_is_topic_enabled (MetaDebugTopic topic); ++ ++/* To disable verbose mode, we make these functions into no-ops */ ++#ifdef WITH_VERBOSE_MODE ++ ++const char * meta_topic_to_string (MetaDebugTopic topic); ++ ++META_EXPORT ++void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); ++ ++#define meta_topic(debug_topic, ...) \ ++ G_STMT_START \ ++ { \ ++ if (meta_is_topic_enabled (debug_topic)) \ ++ { \ ++ g_autofree char *_topic_message = NULL; \ ++\ ++ _topic_message = g_strdup_printf (__VA_ARGS__); \ ++ meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ ++ _topic_message); \ ++ } \ ++ } \ ++ G_STMT_END ++ ++#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) ++ ++#else ++ ++# ifdef G_HAVE_ISO_VARARGS ++# define meta_verbose(...) ++# define meta_topic(...) ++# elif defined(G_HAVE_GNUC_VARARGS) ++# define meta_verbose(format...) ++# define meta_topic(format...) ++# else ++# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" ++# endif ++ ++#endif /* !WITH_VERBOSE_MODE */ +diff --git a/src/meta/util.h b/src/meta/util.h +index 0019c8078..ca8ca2ade 100644 +--- a/src/meta/util.h ++++ b/src/meta/util.h +@@ -26,6 +26,7 @@ + #include + + #include "meta/common.h" ++#include "meta/meta-debug.h" + #include "meta/meta-later.h" + + META_EXPORT +@@ -46,71 +47,6 @@ META_EXPORT + void meta_fatal (const char *format, + ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN G_ANALYZER_NORETURN; + +-/** +- * MetaDebugTopic: +- * @META_DEBUG_VERBOSE: verbose logging +- * @META_DEBUG_FOCUS: focus +- * @META_DEBUG_WORKAREA: workarea +- * @META_DEBUG_STACK: stack +- * @META_DEBUG_SM: session management +- * @META_DEBUG_EVENTS: events +- * @META_DEBUG_WINDOW_STATE: window state +- * @META_DEBUG_WINDOW_OPS: window operations +- * @META_DEBUG_GEOMETRY: geometry +- * @META_DEBUG_PLACEMENT: window placement +- * @META_DEBUG_PING: ping +- * @META_DEBUG_KEYBINDINGS: keybindings +- * @META_DEBUG_SYNC: sync +- * @META_DEBUG_STARTUP: startup +- * @META_DEBUG_PREFS: preferences +- * @META_DEBUG_GROUPS: groups +- * @META_DEBUG_RESIZING: resizing +- * @META_DEBUG_SHAPES: shapes +- * @META_DEBUG_EDGE_RESISTANCE: edge resistance +- * @META_DEBUG_WAYLAND: Wayland +- * @META_DEBUG_KMS: kernel mode setting +- * @META_DEBUG_SCREEN_CAST: screencasting +- * @META_DEBUG_REMOTE_DESKTOP: remote desktop +- * @META_DEBUG_BACKEND: backend +- * @META_DEBUG_RENDER: native backend rendering +- * @META_DEBUG_COLOR: color management +- * @META_DEBUG_INPUT_EVENTS: input events +- * @META_DEBUG_EIS: eis state +- */ +-typedef enum +-{ +- META_DEBUG_VERBOSE = -1, +- META_DEBUG_FOCUS = 1 << 0, +- META_DEBUG_WORKAREA = 1 << 1, +- META_DEBUG_STACK = 1 << 2, +- META_DEBUG_SM = 1 << 3, +- META_DEBUG_EVENTS = 1 << 4, +- META_DEBUG_WINDOW_STATE = 1 << 5, +- META_DEBUG_WINDOW_OPS = 1 << 6, +- META_DEBUG_GEOMETRY = 1 << 7, +- META_DEBUG_PLACEMENT = 1 << 8, +- META_DEBUG_PING = 1 << 9, +- META_DEBUG_KEYBINDINGS = 1 << 10, +- META_DEBUG_SYNC = 1 << 11, +- META_DEBUG_STARTUP = 1 << 12, +- META_DEBUG_PREFS = 1 << 13, +- META_DEBUG_GROUPS = 1 << 14, +- META_DEBUG_RESIZING = 1 << 15, +- META_DEBUG_SHAPES = 1 << 16, +- META_DEBUG_EDGE_RESISTANCE = 1 << 17, +- META_DEBUG_DBUS = 1 << 18, +- META_DEBUG_INPUT = 1 << 19, +- META_DEBUG_WAYLAND = 1 << 20, +- META_DEBUG_KMS = 1 << 21, +- META_DEBUG_SCREEN_CAST = 1 << 22, +- META_DEBUG_REMOTE_DESKTOP = 1 << 23, +- META_DEBUG_BACKEND = 1 << 24, +- META_DEBUG_RENDER = 1 << 25, +- META_DEBUG_COLOR = 1 << 26, +- META_DEBUG_INPUT_EVENTS = 1 << 27, +- META_DEBUG_EIS = 1 << 28, +-} MetaDebugTopic; +- + /** + * MetaDebugPaintFlag: + * @META_DEBUG_PAINT_NONE: default +@@ -122,9 +58,6 @@ typedef enum + META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, + } MetaDebugPaintFlag; + +-META_EXPORT +-gboolean meta_is_topic_enabled (MetaDebugTopic topic); +- + META_EXPORT + void meta_add_verbose_topic (MetaDebugTopic topic); + +@@ -155,44 +88,6 @@ char* meta_external_binding_name_for_action (guint keybinding_action); + META_EXPORT + char* meta_g_utf8_strndup (const gchar *src, gsize n); + +-/* To disable verbose mode, we make these functions into no-ops */ +-#ifdef WITH_VERBOSE_MODE +- +-const char * meta_topic_to_string (MetaDebugTopic topic); +- +-META_EXPORT +-void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); +- +-#define meta_topic(debug_topic, ...) \ +- G_STMT_START \ +- { \ +- if (meta_is_topic_enabled (debug_topic)) \ +- { \ +- g_autofree char *_topic_message = NULL; \ +-\ +- _topic_message = g_strdup_printf (__VA_ARGS__); \ +- meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ +- _topic_message); \ +- } \ +- } \ +- G_STMT_END +- +-#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) +- +-#else +- +-# ifdef G_HAVE_ISO_VARARGS +-# define meta_verbose(...) +-# define meta_topic(...) +-# elif defined(G_HAVE_GNUC_VARARGS) +-# define meta_verbose(format...) +-# define meta_topic(format...) +-# else +-# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" +-# endif +- +-#endif /* !WITH_VERBOSE_MODE */ +- + typedef enum + { + META_LOCALE_DIRECTION_LTR, diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch new file mode 100644 index 0000000..ce61d92 --- /dev/null +++ b/staging/mutter/0004-1441.patch @@ -0,0 +1,8396 @@ +diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml +index 7aadfceb2..5020c9bed 100644 +--- a/.gitlab-ci.yml ++++ b/.gitlab-ci.yml +@@ -237,6 +237,29 @@ workflow: + - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + when: on_success + ++repo-sanity: ++ extends: ++ - .fdo.ci-fairy ++ stage: review ++ variables: ++ GIT_DEPTH: "1" ++ script: ++ - > ++ if [[ -z "$CI_REGISTRY_IMAGE" ]] ; ++ then ++ .gitlab-ci/simple-junit-report.sh check-junit-report.xml \ ++ repo-sanity "The container registry should be enabled in the project general settings panel at $CI_PROJECT_URL/edit" ; ++ exit 1 ; ++ fi ++ artifacts: ++ expire_in: 1 week ++ paths: ++ - check-junit-report.xml ++ reports: ++ junit: check-junit-report.xml ++ rules: ++ - !reference [.only-merge-requests, rules] ++ + check-commit-log: + extends: + - .fdo.ci-fairy +diff --git a/.gitlab-ci/simple-junit-report.sh b/.gitlab-ci/simple-junit-report.sh +new file mode 100755 +index 000000000..3a60324d3 +--- /dev/null ++++ b/.gitlab-ci/simple-junit-report.sh +@@ -0,0 +1,18 @@ ++#!/bin/bash ++OUTFILE=$1 ++NAME=$2 ++MESSAGE=$3 ++ ++cat >$OUTFILE < ++ ++ ++ ++ ++ ++ ++ ++EOF ++ ++# Also echo the message in stdout for good measure ++echo $MESSAGE +diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c +index 93e4c9329..a6c7ecea2 100644 +--- a/clutter/clutter/clutter-frame-clock.c ++++ b/clutter/clutter/clutter-frame-clock.c +@@ -42,6 +42,15 @@ enum + + static guint signals[N_SIGNALS]; + ++typedef enum ++{ ++ TRIPLE_BUFFERING_MODE_NEVER, ++ TRIPLE_BUFFERING_MODE_AUTO, ++ TRIPLE_BUFFERING_MODE_ALWAYS, ++} TripleBufferingMode; ++ ++static TripleBufferingMode triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO; ++ + #define SYNC_DELAY_FALLBACK_FRACTION 0.875 + + #define MINIMUM_REFRESH_RATE 30.f +@@ -70,8 +79,10 @@ typedef enum _ClutterFrameClockState + CLUTTER_FRAME_CLOCK_STATE_IDLE, + CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, + CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW, +- CLUTTER_FRAME_CLOCK_STATE_DISPATCHING, +- CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED, ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE, ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED, ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW, ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO, + } ClutterFrameClockState; + + struct _ClutterFrameClock +@@ -92,6 +103,7 @@ struct _ClutterFrameClock + ClutterFrameClockMode mode; + + int64_t last_dispatch_time_us; ++ int64_t prev_last_dispatch_time_us; + int64_t last_dispatch_lateness_us; + int64_t last_presentation_time_us; + int64_t next_update_time_us; +@@ -111,6 +123,9 @@ struct _ClutterFrameClock + int64_t vblank_duration_us; + /* Last KMS buffer submission time. */ + int64_t last_flip_time_us; ++ int64_t prev_last_flip_time_us; ++ ++ ClutterFrameHint last_flip_hints; + + /* Last time we promoted short-term maximum to long-term one */ + int64_t longterm_promotion_us; +@@ -245,10 +260,6 @@ static void + maybe_update_longterm_max_duration_us (ClutterFrameClock *frame_clock, + ClutterFrameInfo *frame_info) + { +- /* Do not update long-term max if there has been no measurement */ +- if (!frame_clock->shortterm_max_update_duration_us) +- return; +- + if ((frame_info->presentation_time - frame_clock->longterm_promotion_us) < + G_USEC_PER_SEC) + return; +@@ -275,6 +286,12 @@ void + clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, + ClutterFrameInfo *frame_info) + { ++#ifdef CLUTTER_ENABLE_DEBUG ++ const char *debug_state = ++ frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO ? ++ "Triple buffering" : "Double buffering"; ++#endif ++ + COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented, + "Clutter::FrameClock::presented()"); + COGL_TRACE_DESCRIBE (ClutterFrameClockNotifyPresented, +@@ -361,22 +378,52 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, + + frame_clock->got_measurements_last_frame = FALSE; + +- if (frame_info->cpu_time_before_buffer_swap_us != 0 && +- frame_info->has_valid_gpu_rendering_duration) ++ if ((frame_info->cpu_time_before_buffer_swap_us != 0 && ++ frame_info->has_valid_gpu_rendering_duration) || ++ frame_clock->ever_got_measurements) + { + int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us; ++ int64_t dispatch_time_us = 0, flip_time_us = 0; + +- dispatch_to_swap_us = +- frame_info->cpu_time_before_buffer_swap_us - +- frame_clock->last_dispatch_time_us; ++ switch (frame_clock->state) ++ { ++ case CLUTTER_FRAME_CLOCK_STATE_INIT: ++ case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ g_warn_if_reached (); ++ G_GNUC_FALLTHROUGH; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ dispatch_time_us = frame_clock->last_dispatch_time_us; ++ flip_time_us = frame_clock->last_flip_time_us; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ dispatch_time_us = frame_clock->prev_last_dispatch_time_us; ++ flip_time_us = frame_clock->prev_last_flip_time_us; ++ break; ++ } ++ ++ if (frame_info->cpu_time_before_buffer_swap_us == 0) ++ { ++ /* Cursor-only updates with no "swap" or "flip" */ ++ dispatch_to_swap_us = 0; ++ swap_to_flip_us = 0; ++ } ++ else ++ { ++ dispatch_to_swap_us = frame_info->cpu_time_before_buffer_swap_us - ++ dispatch_time_us; ++ swap_to_flip_us = flip_time_us - ++ frame_info->cpu_time_before_buffer_swap_us; ++ } + swap_to_rendering_done_us = + frame_info->gpu_rendering_duration_ns / 1000; +- swap_to_flip_us = +- frame_clock->last_flip_time_us - +- frame_info->cpu_time_before_buffer_swap_us; + + CLUTTER_NOTE (FRAME_TIMINGS, +- "update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", ++ "%s: update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", ++ debug_state, + frame_clock->last_dispatch_lateness_us, + dispatch_to_swap_us, + swap_to_rendering_done_us, +@@ -386,7 +433,7 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, + CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us + + MAX (swap_to_rendering_done_us, swap_to_flip_us), + frame_clock->shortterm_max_update_duration_us, +- frame_clock->refresh_interval_us); ++ 2 * frame_clock->refresh_interval_us); + + maybe_update_longterm_max_duration_us (frame_clock, frame_info); + +@@ -395,7 +442,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, + } + else + { +- CLUTTER_NOTE (FRAME_TIMINGS, "update2dispatch %ld µs", ++ CLUTTER_NOTE (FRAME_TIMINGS, "%s: update2dispatch %ld µs", ++ debug_state, + frame_clock->last_dispatch_lateness_us); + } + +@@ -413,11 +461,22 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: + g_warn_if_reached (); + break; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; + maybe_reschedule_update (frame_clock); + break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ maybe_reschedule_update (frame_clock); ++ break; + } + } + +@@ -435,26 +494,37 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: + g_warn_if_reached (); + break; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; + maybe_reschedule_update (frame_clock); + break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ maybe_reschedule_update (frame_clock); ++ break; + } + } + +-static int64_t +-clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) ++static gboolean ++clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock, ++ int64_t *max_render_time_us) + { + int64_t refresh_interval_us; +- int64_t max_render_time_us; + + refresh_interval_us = frame_clock->refresh_interval_us; + + if (!frame_clock->ever_got_measurements || + G_UNLIKELY (clutter_paint_debug_flags & + CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME)) +- return refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; ++ return FALSE; + + /* Max render time shows how early the frame clock needs to be dispatched + * to make it to the predicted next presentation time. It is an estimate of +@@ -468,15 +538,15 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) + * - The duration of vertical blank. + * - A constant to account for variations in the above estimates. + */ +- max_render_time_us = ++ *max_render_time_us = + MAX (frame_clock->longterm_max_update_duration_us, + frame_clock->shortterm_max_update_duration_us) + + frame_clock->vblank_duration_us + + clutter_max_render_time_constant_us; + +- max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us); ++ *max_render_time_us = CLAMP (*max_render_time_us, 0, 2 * refresh_interval_us); + +- return max_render_time_us; ++ return TRUE; + } + + static void +@@ -491,7 +561,9 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, + int64_t min_render_time_allowed_us; + int64_t max_render_time_allowed_us; + int64_t next_presentation_time_us; ++ int64_t next_smooth_presentation_time_us = 0; + int64_t next_update_time_us; ++ gboolean max_render_time_is_known; + + now_us = g_get_monotonic_time (); + +@@ -511,10 +583,13 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, + } + + min_render_time_allowed_us = refresh_interval_us / 2; +- max_render_time_allowed_us = +- clutter_frame_clock_compute_max_render_time_us (frame_clock); + +- if (min_render_time_allowed_us > max_render_time_allowed_us) ++ max_render_time_is_known = ++ clutter_frame_clock_compute_max_render_time_us (frame_clock, ++ &max_render_time_allowed_us); ++ ++ if (max_render_time_is_known && ++ min_render_time_allowed_us > max_render_time_allowed_us) + min_render_time_allowed_us = max_render_time_allowed_us; + + /* +@@ -535,7 +610,28 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, + * + */ + last_presentation_time_us = frame_clock->last_presentation_time_us; +- next_presentation_time_us = last_presentation_time_us + refresh_interval_us; ++ switch (frame_clock->state) ++ { ++ case CLUTTER_FRAME_CLOCK_STATE_INIT: ++ case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ next_smooth_presentation_time_us = last_presentation_time_us + ++ refresh_interval_us; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ next_smooth_presentation_time_us = last_presentation_time_us + ++ 2 * refresh_interval_us; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ next_smooth_presentation_time_us = last_presentation_time_us + ++ 3 * refresh_interval_us; ++ break; ++ } ++ ++ next_presentation_time_us = next_smooth_presentation_time_us; + + /* + * However, the last presentation could have happened more than a frame ago. +@@ -601,7 +697,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, + } + } + +- if (next_presentation_time_us != last_presentation_time_us + refresh_interval_us) ++ if (next_presentation_time_us != next_smooth_presentation_time_us) + { + /* There was an idle period since the last presentation, so there seems + * be no constantly updating actor. In this case it's best to start +@@ -613,6 +709,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, + } + else + { ++ /* If the max render time isn't known then using the current value of ++ * next_presentation_time_us is suboptimal. Targeting always one frame ++ * prior to that we'd lose the ability to scale up to triple buffering ++ * on late presentation. But targeting two frames prior we would be ++ * always triple buffering even when not required. ++ * So the algorithm for deciding when to scale up to triple buffering ++ * in the absence of render time measurements is to simply target full ++ * frame rate. If we're keeping up then we'll stay double buffering. If ++ * we're not keeping up then this will switch us to triple buffering. ++ */ ++ if (!max_render_time_is_known) ++ { ++ max_render_time_allowed_us = ++ refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; ++ next_presentation_time_us = ++ last_presentation_time_us + refresh_interval_us; ++ } ++ + while (next_presentation_time_us - min_render_time_allowed_us < now_us) + next_presentation_time_us += refresh_interval_us; + +@@ -644,7 +758,9 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock, + + refresh_interval_us = frame_clock->refresh_interval_us; + +- if (frame_clock->last_presentation_time_us == 0) ++ if (frame_clock->last_presentation_time_us == 0 || ++ !clutter_frame_clock_compute_max_render_time_us (frame_clock, ++ &max_render_time_allowed_us)) + { + *out_next_update_time_us = + frame_clock->last_dispatch_time_us ? +@@ -657,9 +773,6 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock, + return; + } + +- max_render_time_allowed_us = +- clutter_frame_clock_compute_max_render_time_us (frame_clock); +- + last_presentation_time_us = frame_clock->last_presentation_time_us; + next_presentation_time_us = last_presentation_time_us + refresh_interval_us; + +@@ -733,8 +846,17 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) + frame_clock->pending_reschedule_now = TRUE; + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; + break; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ frame_clock->pending_reschedule = TRUE; ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->pending_reschedule = TRUE; ++ frame_clock->pending_reschedule_now = TRUE; ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + break; + } + +@@ -770,11 +892,18 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; + break; + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: + return; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ next_update_time_us = g_get_monotonic_time (); ++ frame_clock->state = ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + frame_clock->pending_reschedule = TRUE; + frame_clock->pending_reschedule_now = TRUE; + return; +@@ -803,13 +932,18 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) + + frame_clock->next_update_time_us = next_update_time_us; + g_source_set_ready_time (frame_clock->source, next_update_time_us); +- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; + } + + void + clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) + { + int64_t next_update_time_us = -1; ++ TripleBufferingMode current_mode = triple_buffering_mode; ++ ++ if (current_mode == TRIPLE_BUFFERING_MODE_AUTO && ++ (frame_clock->last_flip_hints & ++ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)) ++ current_mode = TRIPLE_BUFFERING_MODE_NEVER; + + if (frame_clock->inhibit_count > 0) + { +@@ -825,12 +959,41 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + return; + case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + break; + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: + return; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ switch (current_mode) ++ { ++ case TRIPLE_BUFFERING_MODE_NEVER: ++ frame_clock->pending_reschedule = TRUE; ++ return; ++ case TRIPLE_BUFFERING_MODE_AUTO: ++ calculate_next_update_time_us (frame_clock, ++ &next_update_time_us, ++ &frame_clock->next_presentation_time_us, ++ &frame_clock->next_frame_deadline_us); ++ frame_clock->is_next_presentation_time_valid = ++ (frame_clock->next_presentation_time_us != 0); ++ frame_clock->has_next_frame_deadline = ++ (frame_clock->next_frame_deadline_us != 0); ++ frame_clock->state = ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; ++ break; ++ case TRIPLE_BUFFERING_MODE_ALWAYS: ++ next_update_time_us = g_get_monotonic_time (); ++ frame_clock->next_presentation_time_us = 0; ++ frame_clock->is_next_presentation_time_valid = FALSE; ++ frame_clock->state = ++ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; ++ break; ++ } ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + frame_clock->pending_reschedule = TRUE; + return; + } +@@ -859,7 +1022,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) + + frame_clock->next_update_time_us = next_update_time_us; + g_source_set_ready_time (frame_clock->source, next_update_time_us); +- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + } + + void +@@ -875,6 +1037,8 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, + { + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + break; + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + frame_clock->pending_reschedule = TRUE; +@@ -885,8 +1049,14 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, + frame_clock->pending_reschedule_now = TRUE; + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; + break; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ frame_clock->pending_reschedule = TRUE; ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->pending_reschedule = TRUE; ++ frame_clock->pending_reschedule_now = TRUE; ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + break; + } + +@@ -922,7 +1092,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, + frame_clock->refresh_interval_us; + + lateness_us = time_us - ideal_dispatch_time_us; +- if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us) ++ if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us / 4) + frame_clock->last_dispatch_lateness_us = 0; + else + frame_clock->last_dispatch_lateness_us = lateness_us; +@@ -943,10 +1113,27 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, + } + #endif + ++ frame_clock->prev_last_dispatch_time_us = frame_clock->last_dispatch_time_us; + frame_clock->last_dispatch_time_us = time_us; + g_source_set_ready_time (frame_clock->source, -1); + +- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING; ++ switch (frame_clock->state) ++ { ++ case CLUTTER_FRAME_CLOCK_STATE_INIT: ++ case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ g_warn_if_reached (); ++ return; ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO; ++ break; ++ } + + frame_count = frame_clock->frame_count++; + +@@ -977,26 +1164,36 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, + result = iface->frame (frame_clock, frame, frame_clock->listener.user_data); + COGL_TRACE_END (ClutterFrameClockFrame); + +- switch (frame_clock->state) ++ switch (result) + { +- case CLUTTER_FRAME_CLOCK_STATE_INIT: +- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: +- g_warn_if_reached (); ++ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: + break; +- case CLUTTER_FRAME_CLOCK_STATE_IDLE: +- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: +- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: +- break; +- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: +- switch (result) ++ case CLUTTER_FRAME_RESULT_IDLE: ++ /* The frame was aborted; nothing to paint/present */ ++ switch (frame_clock->state) + { +- case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: +- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED; ++ case CLUTTER_FRAME_CLOCK_STATE_INIT: ++ case CLUTTER_FRAME_CLOCK_STATE_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: ++ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: ++ g_warn_if_reached (); + break; +- case CLUTTER_FRAME_RESULT_IDLE: ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; + maybe_reschedule_update (frame_clock); + break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; ++ maybe_reschedule_update (frame_clock); ++ break; ++ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: ++ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; ++ maybe_reschedule_update (frame_clock); ++ break; + } + break; + } +@@ -1029,21 +1226,31 @@ frame_clock_source_dispatch (GSource *source, + } + + void +-clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, +- int64_t flip_time_us) ++clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, ++ int64_t flip_time_us, ++ ClutterFrameHint hints) + { ++ frame_clock->prev_last_flip_time_us = frame_clock->last_flip_time_us; + frame_clock->last_flip_time_us = flip_time_us; ++ frame_clock->last_flip_hints = hints; + } + + GString * + clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock) + { ++ int64_t max_render_time_us; + int64_t max_update_duration_us; + GString *string; + +- string = g_string_new (NULL); +- g_string_append_printf (string, "Max render time: %ld µs", +- clutter_frame_clock_compute_max_render_time_us (frame_clock)); ++ string = g_string_new ("Max render time: "); ++ if (!clutter_frame_clock_compute_max_render_time_us (frame_clock, ++ &max_render_time_us)) ++ { ++ g_string_append (string, "unknown"); ++ return string; ++ } ++ ++ g_string_append_printf (string, "%ld µs", max_render_time_us); + + if (frame_clock->got_measurements_last_frame) + g_string_append_printf (string, " ="); +@@ -1210,8 +1417,6 @@ clutter_frame_clock_dispose (GObject *object) + { + ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object); + +- g_warn_if_fail (frame_clock->state != CLUTTER_FRAME_CLOCK_STATE_DISPATCHING); +- + if (frame_clock->source) + { + g_signal_emit (frame_clock, signals[DESTROY], 0); +@@ -1235,6 +1440,15 @@ static void + clutter_frame_clock_class_init (ClutterFrameClockClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ const char *mode_str; ++ ++ mode_str = g_getenv ("MUTTER_DEBUG_TRIPLE_BUFFERING"); ++ if (!g_strcmp0 (mode_str, "never")) ++ triple_buffering_mode = TRIPLE_BUFFERING_MODE_NEVER; ++ else if (!g_strcmp0 (mode_str, "auto")) ++ triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO; ++ else if (!g_strcmp0 (mode_str, "always")) ++ triple_buffering_mode = TRIPLE_BUFFERING_MODE_ALWAYS; + + object_class->dispose = clutter_frame_clock_dispose; + +diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h +index a7be5ef31..bfc89bde0 100644 +--- a/clutter/clutter/clutter-frame-clock.h ++++ b/clutter/clutter/clutter-frame-clock.h +@@ -33,6 +33,12 @@ typedef enum _ClutterFrameResult + CLUTTER_FRAME_RESULT_IDLE, + } ClutterFrameResult; + ++typedef enum _ClutterFrameHint ++{ ++ CLUTTER_FRAME_HINT_NONE = 0, ++ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED = 1 << 0, ++} ClutterFrameHint; ++ + #define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ()) + CLUTTER_EXPORT + G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock, +@@ -102,7 +108,8 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock, + CLUTTER_EXPORT + float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock); + +-void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, +- int64_t flip_time_us); ++void clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, ++ int64_t flip_time_us, ++ ClutterFrameHint hints); + + GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); +diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h +index ef66b874e..ce140560a 100644 +--- a/clutter/clutter/clutter-frame-private.h ++++ b/clutter/clutter/clutter-frame-private.h +@@ -36,6 +36,7 @@ struct _ClutterFrame + + gboolean has_result; + ClutterFrameResult result; ++ ClutterFrameHint hints; + }; + + CLUTTER_EXPORT +diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c +index 7436f9f18..53c289b2c 100644 +--- a/clutter/clutter/clutter-frame.c ++++ b/clutter/clutter/clutter-frame.c +@@ -115,3 +115,16 @@ clutter_frame_set_result (ClutterFrame *frame, + frame->result = result; + frame->has_result = TRUE; + } ++ ++void ++clutter_frame_set_hint (ClutterFrame *frame, ++ ClutterFrameHint hint) ++{ ++ frame->hints |= hint; ++} ++ ++ClutterFrameHint ++clutter_frame_get_hints (ClutterFrame *frame) ++{ ++ return frame->hints; ++} +diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h +index 34f0770bd..c7b3d02ac 100644 +--- a/clutter/clutter/clutter-frame.h ++++ b/clutter/clutter/clutter-frame.h +@@ -54,4 +54,11 @@ void clutter_frame_set_result (ClutterFrame *frame, + CLUTTER_EXPORT + gboolean clutter_frame_has_result (ClutterFrame *frame); + ++CLUTTER_EXPORT ++void clutter_frame_set_hint (ClutterFrame *frame, ++ ClutterFrameHint hint); ++ ++CLUTTER_EXPORT ++ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame); ++ + G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFrame, clutter_frame_unref) +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index b503ef839..1fbe3ae7a 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -902,14 +902,21 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, + + _clutter_stage_window_redraw_view (stage_window, view, frame); + +- clutter_frame_clock_record_flip_time (frame_clock, +- g_get_monotonic_time ()); ++ clutter_frame_clock_record_flip (frame_clock, ++ g_get_monotonic_time (), ++ clutter_frame_get_hints (frame)); + + clutter_stage_emit_after_paint (stage, view, frame); + + if (_clutter_context_get_show_fps ()) + end_frame_timing_measurement (view); + } ++ else ++ { ++ clutter_frame_clock_record_flip (frame_clock, ++ g_get_monotonic_time (), ++ clutter_frame_get_hints (frame)); ++ } + + _clutter_stage_window_finish_frame (stage_window, view, frame); + +diff --git a/cogl/cogl/cogl-attribute-buffer.c b/cogl/cogl/cogl-attribute-buffer.c +index 55e296dd3..ee89e500a 100644 +--- a/cogl/cogl/cogl-attribute-buffer.c ++++ b/cogl/cogl/cogl-attribute-buffer.c +@@ -51,13 +51,13 @@ cogl_attribute_buffer_init (CoglAttributeBuffer *buffer) + + CoglAttributeBuffer * + cogl_attribute_buffer_new_with_size (CoglContext *context, +- size_t bytes) ++ size_t bytes) + { + CoglAttributeBuffer *buffer; + + buffer = g_object_new (COGL_TYPE_ATTRIBUTE_BUFFER, + "context", context, +- "size", bytes, ++ "size", (uint64_t) bytes, + "default-target", COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER, + "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, + NULL); +@@ -67,8 +67,8 @@ cogl_attribute_buffer_new_with_size (CoglContext *context, + + CoglAttributeBuffer * + cogl_attribute_buffer_new (CoglContext *context, +- size_t bytes, +- const void *data) ++ size_t bytes, ++ const void *data) + { + CoglAttributeBuffer *buffer; + +diff --git a/cogl/cogl/cogl-attribute-buffer.h b/cogl/cogl/cogl-attribute-buffer.h +index 45040f7d9..59876a112 100644 +--- a/cogl/cogl/cogl-attribute-buffer.h ++++ b/cogl/cogl/cogl-attribute-buffer.h +@@ -92,7 +92,7 @@ GType cogl_attribute_buffer_get_type (void) G_GNUC_CONST; + */ + COGL_EXPORT CoglAttributeBuffer * + cogl_attribute_buffer_new_with_size (CoglContext *context, +- size_t bytes); ++ size_t bytes); + + /** + * cogl_attribute_buffer_new: +@@ -122,7 +122,7 @@ cogl_attribute_buffer_new_with_size (CoglContext *context, + */ + COGL_EXPORT CoglAttributeBuffer * + cogl_attribute_buffer_new (CoglContext *context, +- size_t bytes, +- const void *data); ++ size_t bytes, ++ const void *data); + + G_END_DECLS +diff --git a/cogl/cogl/cogl-context-private.h b/cogl/cogl/cogl-context-private.h +index 4c0bc4bea..cd5db0ee3 100644 +--- a/cogl/cogl/cogl-context-private.h ++++ b/cogl/cogl/cogl-context-private.h +@@ -311,3 +311,6 @@ _cogl_context_set_current_projection_entry (CoglContext *context, + void + _cogl_context_set_current_modelview_entry (CoglContext *context, + CoglMatrixEntry *entry); ++ ++void ++_cogl_context_update_sync (CoglContext *context); +diff --git a/cogl/cogl/cogl-context.c b/cogl/cogl/cogl-context.c +index be13933ec..492d49542 100644 +--- a/cogl/cogl/cogl-context.c ++++ b/cogl/cogl/cogl-context.c +@@ -463,6 +463,28 @@ _cogl_context_set_current_modelview_entry (CoglContext *context, + context->current_modelview_entry = entry; + } + ++void ++_cogl_context_update_sync (CoglContext *context) ++{ ++ const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); ++ ++ if (!winsys->update_sync) ++ return; ++ ++ winsys->update_sync (context); ++} ++ ++int ++cogl_context_get_latest_sync_fd (CoglContext *context) ++{ ++ const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); ++ ++ if (!winsys->get_sync_fd) ++ return -1; ++ ++ return winsys->get_sync_fd (context); ++} ++ + CoglGraphicsResetStatus + cogl_get_graphics_reset_status (CoglContext *context) + { +diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h +index 614a351fe..fba7bedf2 100644 +--- a/cogl/cogl/cogl-context.h ++++ b/cogl/cogl/cogl-context.h +@@ -367,4 +367,18 @@ cogl_context_timestamp_query_get_time_ns (CoglContext *context, + COGL_EXPORT int64_t + cogl_context_get_gpu_time_ns (CoglContext *context); + ++/** ++ * cogl_context_get_latest_sync_fd ++ * @context: a #CoglContext pointer ++ * ++ * This function is used to get support for waiting on previous ++ * GPU work through sync fds. It will return a sync fd which will ++ * signal when the previous work has completed. ++ * ++ * Return value: sync fd for latest GPU submission if available, ++ * returns -1 if not. ++ */ ++COGL_EXPORT int ++cogl_context_get_latest_sync_fd (CoglContext *context); ++ + G_END_DECLS +diff --git a/cogl/cogl/cogl-index-buffer.c b/cogl/cogl/cogl-index-buffer.c +index 4de5205d3..1e4309436 100644 +--- a/cogl/cogl/cogl-index-buffer.c ++++ b/cogl/cogl/cogl-index-buffer.c +@@ -53,13 +53,14 @@ cogl_index_buffer_init (CoglIndexBuffer *buffer) + * indices buffer should be able to contain multiple ranges of indices + * which the wiki design doesn't currently consider. */ + CoglIndexBuffer * +-cogl_index_buffer_new (CoglContext *context, size_t bytes) ++cogl_index_buffer_new (CoglContext *context, ++ size_t bytes) + { + CoglIndexBuffer *indices; + + indices = g_object_new (COGL_TYPE_INDEX_BUFFER, + "context", context, +- "size", bytes, ++ "size", (uint64_t) bytes, + "default-target", COGL_BUFFER_BIND_TARGET_INDEX_BUFFER, + "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, + NULL); +diff --git a/cogl/cogl/cogl-index-buffer.h b/cogl/cogl/cogl-index-buffer.h +index 23b75d837..ec7418318 100644 +--- a/cogl/cogl/cogl-index-buffer.h ++++ b/cogl/cogl/cogl-index-buffer.h +@@ -78,6 +78,6 @@ GType cogl_index_buffer_get_type (void) G_GNUC_CONST; + */ + COGL_EXPORT CoglIndexBuffer * + cogl_index_buffer_new (CoglContext *context, +- size_t bytes); ++ size_t bytes); + + G_END_DECLS +diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h +index 959a60533..86d8ea2d5 100644 +--- a/cogl/cogl/cogl-onscreen-private.h ++++ b/cogl/cogl/cogl-onscreen-private.h +@@ -78,4 +78,7 @@ COGL_EXPORT CoglFrameInfo * + cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen); + + COGL_EXPORT CoglFrameInfo * +-cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen); ++cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen); ++ ++COGL_EXPORT unsigned int ++cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen); +diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c +index f4b460a83..086be7ed7 100644 +--- a/cogl/cogl/cogl-onscreen.c ++++ b/cogl/cogl/cogl-onscreen.c +@@ -325,6 +325,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + { + CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen); + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); ++ CoglContext *context = cogl_framebuffer_get_context (framebuffer); + CoglOnscreenClass *klass = COGL_ONSCREEN_GET_CLASS (onscreen); + + g_return_if_fail (COGL_IS_ONSCREEN (framebuffer)); +@@ -334,6 +335,9 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + + _cogl_framebuffer_flush_journal (framebuffer); + ++ /* Update our "latest" sync fd to contain all previous work */ ++ _cogl_context_update_sync (context); ++ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME))) + cogl_framebuffer_finish (framebuffer); + +@@ -511,6 +515,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen) + return g_queue_pop_head (&priv->pending_frame_infos); + } + ++unsigned int ++cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen) ++{ ++ CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen); ++ ++ return g_queue_get_length (&priv->pending_frame_infos); ++} ++ + CoglFrameClosure * + cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, + CoglFrameCallback callback, +diff --git a/cogl/cogl/cogl-pixel-buffer.c b/cogl/cogl/cogl-pixel-buffer.c +index fc238580a..392460933 100644 +--- a/cogl/cogl/cogl-pixel-buffer.c ++++ b/cogl/cogl/cogl-pixel-buffer.c +@@ -63,15 +63,15 @@ cogl_pixel_buffer_init (CoglPixelBuffer *buffer) + + static CoglPixelBuffer * + _cogl_pixel_buffer_new (CoglContext *context, +- size_t size, +- const void *data, +- GError **error) ++ size_t size, ++ const void *data, ++ GError **error) + { + CoglPixelBuffer *pixel_buffer; + + pixel_buffer = g_object_new (COGL_TYPE_PIXEL_BUFFER, + "context", context, +- "size", size, ++ "size", (uint64_t) size, + "default-target", COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, + "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, + NULL); +@@ -94,8 +94,8 @@ _cogl_pixel_buffer_new (CoglContext *context, + + CoglPixelBuffer * + cogl_pixel_buffer_new (CoglContext *context, +- size_t size, +- const void *data) ++ size_t size, ++ const void *data) + { + GError *ignore_error = NULL; + CoglPixelBuffer *buffer = +diff --git a/cogl/cogl/cogl-pixel-buffer.h b/cogl/cogl/cogl-pixel-buffer.h +index e7abe0888..cf26a61b2 100644 +--- a/cogl/cogl/cogl-pixel-buffer.h ++++ b/cogl/cogl/cogl-pixel-buffer.h +@@ -87,7 +87,7 @@ GType cogl_pixel_buffer_get_type (void) G_GNUC_CONST; + */ + COGL_EXPORT CoglPixelBuffer * + cogl_pixel_buffer_new (CoglContext *context, +- size_t size, +- const void *data); ++ size_t size, ++ const void *data); + + G_END_DECLS +diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build +index d1aa6ef1d..261edbd86 100644 +--- a/cogl/cogl/meson.build ++++ b/cogl/cogl/meson.build +@@ -407,6 +407,7 @@ libmutter_cogl = shared_library(libmutter_cogl_name, + install: true, + ) + libmutter_cogl_dep = declare_dependency( ++ sources: [cogl_enums[1]], + dependencies: [cogl_deps], + link_with: libmutter_cogl, + ) +diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.c b/cogl/cogl/winsys/cogl-onscreen-egl.c +index 6c5bf2654..44010969c 100644 +--- a/cogl/cogl/winsys/cogl-onscreen-egl.c ++++ b/cogl/cogl/winsys/cogl-onscreen-egl.c +@@ -281,6 +281,27 @@ cogl_onscreen_egl_queue_damage_region (CoglOnscreen *onscreen, + g_warning ("Error reported by eglSetDamageRegion"); + } + ++void ++cogl_onscreen_egl_maybe_create_timestamp_query (CoglOnscreen *onscreen, ++ CoglFrameInfo *info) ++{ ++ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); ++ CoglContext *context = cogl_framebuffer_get_context (framebuffer); ++ ++ if (!cogl_has_feature (context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) ++ return; ++ ++ info->gpu_time_before_buffer_swap_ns = ++ cogl_context_get_gpu_time_ns (context); ++ info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); ++ ++ /* Set up a timestamp query for when all rendering will be finished. */ ++ info->timestamp_query = ++ cogl_framebuffer_create_timestamp_query (framebuffer); ++ ++ info->has_valid_gpu_rendering_duration = TRUE; ++} ++ + static void + cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, +@@ -309,19 +330,6 @@ cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, + COGL_FRAMEBUFFER (onscreen), + COGL_FRAMEBUFFER_STATE_BIND); + +- if (cogl_has_feature (context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) +- { +- info->gpu_time_before_buffer_swap_ns = +- cogl_context_get_gpu_time_ns (context); +- info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); +- +- /* Set up a timestamp query for when all rendering will be finished. */ +- info->timestamp_query = +- cogl_framebuffer_create_timestamp_query (COGL_FRAMEBUFFER (onscreen)); +- +- info->has_valid_gpu_rendering_duration = TRUE; +- } +- + if (n_rectangles && priv->pf_eglSwapBuffersWithDamage) + { + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); +diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.h b/cogl/cogl/winsys/cogl-onscreen-egl.h +index 13662be60..d4dda6636 100644 +--- a/cogl/cogl/winsys/cogl-onscreen-egl.h ++++ b/cogl/cogl/winsys/cogl-onscreen-egl.h +@@ -40,6 +40,10 @@ struct _CoglOnscreenEglClass + CoglOnscreenClass parent_class; + }; + ++COGL_EXPORT void ++cogl_onscreen_egl_maybe_create_timestamp_query (CoglOnscreen *onscreen, ++ CoglFrameInfo *info); ++ + COGL_EXPORT void + cogl_onscreen_egl_set_egl_surface (CoglOnscreenEgl *onscreen_egl, + EGLSurface egl_surface); +diff --git a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h +index 4b74e2088..a0d03a3c4 100644 +--- a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h ++++ b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h +@@ -162,6 +162,15 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroySync, + (EGLDisplay dpy, + EGLSyncKHR sync)) + COGL_WINSYS_FEATURE_END () ++ ++COGL_WINSYS_FEATURE_BEGIN (native_fence_sync, ++ "ANDROID\0", ++ "native_fence_sync\0", ++ COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC) ++COGL_WINSYS_FEATURE_FUNCTION (EGLint, eglDupNativeFenceFD, ++ (EGLDisplay dpy, ++ EGLSyncKHR sync)) ++COGL_WINSYS_FEATURE_END () + #endif + + COGL_WINSYS_FEATURE_BEGIN (surfaceless_context, +diff --git a/cogl/cogl/winsys/cogl-winsys-egl-private.h b/cogl/cogl/winsys/cogl-winsys-egl-private.h +index 9b0b168b4..6a31d1ab2 100644 +--- a/cogl/cogl/winsys/cogl-winsys-egl-private.h ++++ b/cogl/cogl/winsys/cogl-winsys-egl-private.h +@@ -101,6 +101,7 @@ typedef enum _CoglEGLWinsysFeature + COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT = 1L << 6, + COGL_EGL_WINSYS_FEATURE_CONTEXT_PRIORITY = 1L << 7, + COGL_EGL_WINSYS_FEATURE_NO_CONFIG_CONTEXT = 1L << 8, ++ COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC = 1L << 9, + } CoglEGLWinsysFeature; + + typedef struct _CoglRendererEGL +@@ -119,6 +120,9 @@ typedef struct _CoglRendererEGL + /* vtable for platform specific parts */ + const CoglWinsysEGLVtable *platform_vtable; + ++ /* Sync for latest submitted work */ ++ EGLSyncKHR sync; ++ + /* Function pointers for EGL specific extensions */ + #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d) + +diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c +index 5472ba9d9..7a52129c2 100644 +--- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c ++++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c +@@ -243,6 +243,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; ++ egl_renderer->sync = EGL_NO_SYNC_KHR; + + if (!_cogl_xlib_renderer_connect (renderer, error)) + goto error; +diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c +index ee7c1df54..66b9940c0 100644 +--- a/cogl/cogl/winsys/cogl-winsys-egl.c ++++ b/cogl/cogl/winsys/cogl-winsys-egl.c +@@ -441,6 +441,9 @@ _cogl_winsys_display_destroy (CoglDisplay *display) + + g_return_if_fail (egl_display != NULL); + ++ if (egl_renderer->sync != EGL_NO_SYNC_KHR) ++ egl_renderer->pf_eglDestroySync (egl_renderer->edpy, egl_renderer->sync); ++ + cleanup_context (display); + + if (egl_renderer->platform_vtable->display_destroy) +@@ -573,6 +576,37 @@ _cogl_winsys_fence_destroy (CoglContext *context, void *fence) + + renderer->pf_eglDestroySync (renderer->edpy, fence); + } ++ ++static int ++_cogl_winsys_get_sync_fd (CoglContext *context) ++{ ++ CoglRendererEGL *renderer = context->display->renderer->winsys; ++ int fd; ++ ++ if (!renderer->pf_eglDupNativeFenceFD) ++ return -1; ++ ++ fd = renderer->pf_eglDupNativeFenceFD (renderer->edpy, renderer->sync); ++ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) ++ return -1; ++ ++ return fd; ++} ++ ++static void ++_cogl_winsys_update_sync (CoglContext *context) ++{ ++ CoglRendererEGL *renderer = context->display->renderer->winsys; ++ ++ if (!renderer->pf_eglDestroySync || !renderer->pf_eglCreateSync) ++ return; ++ ++ if (renderer->sync != EGL_NO_SYNC_KHR) ++ renderer->pf_eglDestroySync (renderer->edpy, renderer->sync); ++ ++ renderer->sync = renderer->pf_eglCreateSync (renderer->edpy, ++ EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); ++} + #endif + + static CoglWinsysVtable _cogl_winsys_vtable = +@@ -595,6 +629,8 @@ static CoglWinsysVtable _cogl_winsys_vtable = + .fence_add = _cogl_winsys_fence_add, + .fence_is_complete = _cogl_winsys_fence_is_complete, + .fence_destroy = _cogl_winsys_fence_destroy, ++ .get_sync_fd = _cogl_winsys_get_sync_fd, ++ .update_sync = _cogl_winsys_update_sync, + #endif + }; + +diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h +index 7dfbd13ed..d627617d6 100644 +--- a/cogl/cogl/winsys/cogl-winsys-private.h ++++ b/cogl/cogl/winsys/cogl-winsys-private.h +@@ -141,6 +141,12 @@ typedef struct _CoglWinsysVtable + (*fence_destroy) (CoglContext *ctx, + void *fence); + ++ void ++ (*update_sync) (CoglContext *ctx); ++ ++ int ++ (*get_sync_fd) (CoglContext *ctx); ++ + } CoglWinsysVtable; + + typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void); +diff --git a/config.h.meson b/config.h.meson +index 094d79616..9919bd4d0 100644 +--- a/config.h.meson ++++ b/config.h.meson +@@ -135,3 +135,6 @@ + + /* Supports malloc_trim */ + #mesondefine HAVE_MALLOC_TRIM ++ ++/* Supports eventfd */ ++#mesondefine HAVE_EVENTFD +diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +index 86421b7b0..7294c57a8 100644 +--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml ++++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +@@ -396,8 +396,8 @@ + @layout_mode current layout mode represents the way logical monitors + are laid out on the screen. Possible modes include: + +- 1 : physical +- 2 : logical ++ 1 : logical ++ 2 : physical + + With physical layout mode, each logical monitor has the same dimensions + as the monitor modes of the associated monitors assigned to it, no +diff --git a/meson.build b/meson.build +index c5ec57395..9732d8460 100644 +--- a/meson.build ++++ b/meson.build +@@ -541,6 +541,8 @@ endif + + cc.compiles('void main (void) { __builtin_ffsl (0); __builtin_popcountl (0); }') + ++have_eventfd = cc.has_header('sys/eventfd.h') ++ + cdata = configuration_data() + cdata.set_quoted('GETTEXT_PACKAGE', gettext_package) + cdata.set_quoted('VERSION', meson.project_version()) +@@ -573,6 +575,7 @@ cdata.set('HAVE_LIBDISPLAY_INFO', have_libdisplay_info) + cdata.set('HAVE_PANGO_FT2', have_pango_ft2) + cdata.set('HAVE_TIMERFD', have_timerfd) + cdata.set('HAVE_MALLOC_TRIM', have_malloc_trim) ++cdata.set('HAVE_EVENTFD', have_eventfd) + + if have_x11_client + xkb_base = xkeyboard_config_dep.get_variable('xkb_base') +diff --git a/mtk/mtk/mtk-rectangle.c b/mtk/mtk/mtk-rectangle.c +index 55626d8e2..4f5927ccc 100644 +--- a/mtk/mtk/mtk-rectangle.c ++++ b/mtk/mtk/mtk-rectangle.c +@@ -65,6 +65,12 @@ mtk_rectangle_new (int x, + return rect; + } + ++MtkRectangle * ++mtk_rectangle_new_empty (void) ++{ ++ return g_new0 (MtkRectangle, 1); ++} ++ + /** + * mtk_rectangle_area: + * @rect: A rectangle +diff --git a/mtk/mtk/mtk-rectangle.h b/mtk/mtk/mtk-rectangle.h +index 2463d3b08..1cb598fce 100644 +--- a/mtk/mtk/mtk-rectangle.h ++++ b/mtk/mtk/mtk-rectangle.h +@@ -86,6 +86,9 @@ MtkRectangle * mtk_rectangle_new (int x, + int width, + int height); + ++MTK_EXPORT ++MtkRectangle * mtk_rectangle_new_empty (void); ++ + /* Basic comparison functions */ + MTK_EXPORT + int mtk_rectangle_area (const MtkRectangle *rect); +@@ -149,3 +152,5 @@ void mtk_rectangle_scale_double (const MtkRectangle *rect, + MTK_EXPORT + gboolean mtk_rectangle_is_adjacent_to (const MtkRectangle *rect, + const MtkRectangle *other); ++ ++G_DEFINE_AUTOPTR_CLEANUP_FUNC (MtkRectangle, mtk_rectangle_free) +diff --git a/po/LINGUAS b/po/LINGUAS +index 02ae4c496..b89761cb3 100644 +--- a/po/LINGUAS ++++ b/po/LINGUAS +@@ -47,6 +47,7 @@ is + it + ja + ka ++kab + kk + kn + ko +diff --git a/po/kab.po b/po/kab.po +new file mode 100644 +index 000000000..5cc29556c +--- /dev/null ++++ b/po/kab.po +@@ -0,0 +1,793 @@ ++# Kabyle translation for mutter. ++# Copyright (C) 2024 mutter's COPYRIGHT HOLDER ++# This file is distributed under the same license as the mutter package. ++# FIRST AUTHOR , YEAR. ++# ButterflyOfFire , 2024. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: mutter main\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" ++"POT-Creation-Date: 2024-04-04 12:25+0000\n" ++"PO-Revision-Date: 2024-04-08 06:56+0200\n" ++"Last-Translator: sa\n" ++"Language-Team: Kabyle <>\n" ++"Language: kab\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=n>1;\n" ++"X-DL-Team: kab\n" ++"X-DL-Module: mutter\n" ++"X-DL-Branch: main\n" ++"X-DL-Domain: po\n" ++"X-DL-State: Translating\n" ++"X-Generator: Poedit 3.4.2\n" ++ ++#: data/50-mutter-navigation.xml:6 ++msgid "Navigation" ++msgstr "Tunigin" ++ ++#: data/50-mutter-navigation.xml:9 ++msgid "Move window to workspace 1" ++msgstr "Smutti asfaylu ɣer tallunt umahil tis 1" ++ ++#: data/50-mutter-navigation.xml:12 ++msgid "Move window to workspace 2" ++msgstr "Smutti asfaylu ɣer tallunt umahil tis 2" ++ ++#: data/50-mutter-navigation.xml:15 ++msgid "Move window to workspace 3" ++msgstr "Smutti asfaylu ɣer tallunt umahil tis 3" ++ ++#: data/50-mutter-navigation.xml:18 ++msgid "Move window to workspace 4" ++msgstr "Smutti asfaylu ɣer tallunt umahil tis 3" ++ ++#: data/50-mutter-navigation.xml:21 ++msgid "Move window to last workspace" ++msgstr "Smutti asfaylu ɣer tallunt umahil" ++ ++#: data/50-mutter-navigation.xml:24 ++msgid "Move window one workspace to the left" ++msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan ɣer tama tazelmaḍt" ++ ++#: data/50-mutter-navigation.xml:27 ++msgid "Move window one workspace to the right" ++msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan ɣer tama tayeffust" ++ ++#: data/50-mutter-navigation.xml:31 ++msgid "Move window one workspace up" ++msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan d asawen" ++ ++#: data/50-mutter-navigation.xml:35 ++msgid "Move window one workspace down" ++msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan d akessar" ++ ++#: data/50-mutter-navigation.xml:38 ++msgid "Move window one monitor to the left" ++msgstr "Senkez asfaylu s yiwen usefrak ɣer uzelmaḍ" ++ ++#: data/50-mutter-navigation.xml:41 ++msgid "Move window one monitor to the right" ++msgstr "Senkez asfaylu s yiwen usefrak ɣer uyeffus" ++ ++#: data/50-mutter-navigation.xml:44 ++msgid "Move window one monitor up" ++msgstr "Senkez asfaylu s yiwen usefrak d asawen" ++ ++#: data/50-mutter-navigation.xml:47 ++msgid "Move window one monitor down" ++msgstr "Senkez asfaylu s yiwen usefrak d akessar" ++ ++#: data/50-mutter-navigation.xml:51 ++msgid "Switch applications" ++msgstr "Senfel isnasen" ++ ++#: data/50-mutter-navigation.xml:56 ++msgid "Switch to previous application" ++msgstr "Uɣal ɣer usnas yezrin" ++ ++#: data/50-mutter-navigation.xml:60 ++msgid "Switch windows" ++msgstr "Senfel isfuyla" ++ ++#: data/50-mutter-navigation.xml:65 ++msgid "Switch to previous window" ++msgstr "Uɣal ɣer usfaylu yezrin" ++ ++#: data/50-mutter-navigation.xml:69 ++msgid "Switch windows of an application" ++msgstr "Senfel isfuyla n usnas" ++ ++#: data/50-mutter-navigation.xml:74 ++msgid "Switch to previous window of an application" ++msgstr "Uɣal ɣer usfaylu yezrin n usnas" ++ ++#: data/50-mutter-navigation.xml:78 ++msgid "Switch system controls" ++msgstr "Senfel isenqaden n unagraw" ++ ++#: data/50-mutter-navigation.xml:83 ++msgid "Switch to previous system control" ++msgstr "Uɣal ɣer usenqad n unagraw yezrin" ++ ++#: data/50-mutter-navigation.xml:87 ++msgid "Switch windows directly" ++msgstr "Senfel srid isfuyla" ++ ++#: data/50-mutter-navigation.xml:92 ++msgid "Switch directly to previous window" ++msgstr "Uɣam srid ɣer usfaylu yezrin" ++ ++#: data/50-mutter-navigation.xml:96 ++msgid "Switch windows of an app directly" ++msgstr "Senfel srid isfuyla n usnas" ++ ++#: data/50-mutter-navigation.xml:101 ++msgid "Switch directly to previous window of an app" ++msgstr "Uɣal srid usfaylu yezrin n usnas" ++ ++#: data/50-mutter-navigation.xml:105 ++msgid "Switch system controls directly" ++msgstr "Senfel srid isenqaden n ungraw" ++ ++#: data/50-mutter-navigation.xml:110 ++msgid "Switch directly to previous system control" ++msgstr "Uɣal srid ɣer usenqad n ungraw yezrin" ++ ++#: data/50-mutter-navigation.xml:113 ++msgid "Hide all normal windows" ++msgstr "Ffer akk isfuyla imugna" ++ ++#: data/50-mutter-navigation.xml:116 ++msgid "Switch to workspace 1" ++msgstr "Ddu ɣer tallunt n umahil tis 1" ++ ++#: data/50-mutter-navigation.xml:119 ++msgid "Switch to workspace 2" ++msgstr "Ddu ɣer tallunt n umahil tis 2" ++ ++#: data/50-mutter-navigation.xml:122 ++msgid "Switch to workspace 3" ++msgstr "Ddu ɣer tallunt n umahil tis 3" ++ ++#: data/50-mutter-navigation.xml:125 ++msgid "Switch to workspace 4" ++msgstr "Ddu ɣer tallunt n umahil tis 4" ++ ++#: data/50-mutter-navigation.xml:128 ++msgid "Switch to last workspace" ++msgstr "Ddu ɣer tallunt n umahil taneggarut" ++ ++#: data/50-mutter-navigation.xml:131 ++msgid "Switch to workspace on the left" ++msgstr "Ddu ɣer tallunt n umahil deg tama taẓelmaḍt" ++ ++#: data/50-mutter-navigation.xml:134 ++msgid "Switch to workspace on the right" ++msgstr "Ddu ɣer tallunt n umahil deg tama tayeffust" ++ ++#: data/50-mutter-navigation.xml:138 ++msgid "Switch to workspace above" ++msgstr "Ddu ɣer tallunt n umahil ufella" ++ ++#: data/50-mutter-navigation.xml:142 ++msgid "Switch to workspace below" ++msgstr "Ddu ɣer tallunt n umahil wadda" ++ ++#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6 ++msgid "System" ++msgstr "Anagraw" ++ ++#: data/50-mutter-system.xml:8 ++msgid "Show the run command prompt" ++msgstr "Sken aneftay n tladna n uselkem" ++ ++#: data/50-mutter-wayland.xml:8 ++msgid "Restore the keyboard shortcuts" ++msgstr "Err-d inegzumen n unasiw" ++ ++#: data/50-mutter-windows.xml:6 ++msgid "Windows" ++msgstr "Isfuyla" ++ ++#: data/50-mutter-windows.xml:8 ++msgid "Activate the window menu" ++msgstr "Rmed umuɣ n usfaylu" ++ ++#: data/50-mutter-windows.xml:10 ++msgid "Toggle fullscreen mode" ++msgstr "Ldi/Mdel askar n ugdil aččuran" ++ ++#: data/50-mutter-windows.xml:12 ++msgid "Toggle maximization state" ++msgstr "Ldi/Mdel addad n usumɣer" ++ ++#: data/50-mutter-windows.xml:14 ++msgid "Maximize window" ++msgstr "Semɣer asfaylu" ++ ++#: data/50-mutter-windows.xml:16 ++msgid "Restore window" ++msgstr "Err-d asfaylu" ++ ++#: data/50-mutter-windows.xml:18 ++msgid "Close window" ++msgstr "Mdel asfaylu" ++ ++#: data/50-mutter-windows.xml:20 ++msgid "Hide window" ++msgstr "Ffer asfaylu" ++ ++#: data/50-mutter-windows.xml:22 ++msgid "Move window" ++msgstr "Senkez asfaylu" ++ ++#: data/50-mutter-windows.xml:24 ++msgid "Resize window" ++msgstr "Semsawi teɣzi n usfaylu" ++ ++#: data/50-mutter-windows.xml:27 ++msgid "Toggle window on all workspaces or one" ++msgstr "Ldi/Mdel asfaylu deg meṛṛa tallunin n umahil neɣ deg yiwet kan" ++ ++#: data/50-mutter-windows.xml:29 ++msgid "Raise window if covered, otherwise lower it" ++msgstr "Sali asfaylu ma yella iɣumm, neɣ ṣbb-it" ++ ++#: data/50-mutter-windows.xml:31 ++msgid "Raise window above other windows" ++msgstr "Sezmer asfaylu yellan nnig yisfuyla niḍen" ++ ++#: data/50-mutter-windows.xml:33 ++msgid "Lower window below other windows" ++msgstr "Asfaylu n wadda ddaw n yisfuyla niḍen" ++ ++#: data/50-mutter-windows.xml:35 ++msgid "Maximize window vertically" ++msgstr "Semɣer asfaylu s wudem ubdid" ++ ++#: data/50-mutter-windows.xml:37 ++msgid "Maximize window horizontally" ++msgstr "Semɣer asfaylu s wudem aglawan" ++ ++#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 ++msgid "View split on left" ++msgstr "Sken beṭṭu ɣer uzelmaḍ" ++ ++#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 ++msgid "View split on right" ++msgstr "Sken beṭṭu ɣer uyeffus" ++ ++#: data/org.gnome.mutter.gschema.xml.in:15 ++msgid "Modifier to use for extended window management operations" ++msgstr "Aneglam ara yettwasqedcen i temhilin ɣezzifen n usefrek n yisfuyla" ++ ++#: data/org.gnome.mutter.gschema.xml.in:16 ++msgid "" ++"This key will initiate the “overlay”, which is a combination window overview " ++"and application launching system. The default is intended to be the “Windows " ++"key” on PC hardware. It’s expected that this binding either the default or " ++"set to the empty string." ++msgstr "" ++"Tasarut-a ad twennez \"asembibbi\", d anagraw n usuddes n teskant n yisfuyla " ++"akked uskar n usnas. Azal amezwer d \"tasarut n Windows\" ɣef warrum PC. " ++"Yetturaǧu tasarut-a ad tettusbadu s wudem amezwer neɣ ad tettusbadu ɣer " ++"uzrir ilem." ++ ++#: data/org.gnome.mutter.gschema.xml.in:28 ++msgid "Attach modal dialogs" ++msgstr "Seddu idiwenniyen iskaranen" ++ ++#: data/org.gnome.mutter.gschema.xml.in:29 ++msgid "" ++"When true, instead of having independent titlebars, modal dialogs appear " ++"attached to the titlebar of the parent window and are moved together with " ++"the parent window." ++msgstr "" ++"Mi ara yili d tidet, deg wadeg n yifeggagen n yizwal ilelliyen, idiwenniyen " ++"iskaranen ad d-banen ddan deg ufeggag n uzwel n usfaylu maraw, ad " ++"ttwasnekzen akken akkedd usfaylu amaraw." ++ ++#: data/org.gnome.mutter.gschema.xml.in:38 ++msgid "Enable edge tiling when dropping windows on screen edges" ++msgstr "Rmed aburset n tamiwin mi ara tserseḍ isfuyla ɣef tamiwin n ugdil" ++ ++#: data/org.gnome.mutter.gschema.xml.in:39 ++msgid "" ++"If enabled, dropping windows on vertical screen edges maximizes them " ++"vertically and resizes them horizontally to cover half of the available " ++"area. Dropping windows on the top screen edge maximizes them completely." ++msgstr "" ++"Ma yella tettwarmed textiṛt-a, tarusi yisfuyla ɣef tamiwin tiratakin n ugdil " ++"ad ttwasmeɣren s wudem aglawan, akken ara ččaren azgen n temnaḍt i yellan. " ++"Azuɣer n yisfuyla ɣef tama tafellayt n ugdil ad ten-issemɣer s wudem ummid." ++ ++#: data/org.gnome.mutter.gschema.xml.in:48 ++msgid "Workspaces are managed dynamically" ++msgstr "Tallunin n umahil ttwasefrakent s wudem asmussan" ++ ++#: data/org.gnome.mutter.gschema.xml.in:49 ++msgid "" ++"Determines whether workspaces are managed dynamically or whether there’s a " ++"static number of workspaces (determined by the num-workspaces key in org." ++"gnome.desktop.wm.preferences)." ++msgstr "" ++"Yettguccul ma yella tallunin n umahil ttwasefrakent s wudem asmussan neɣ ma " ++"yella amḍan udmis n tallunin n umahil (yettwaguccel s tsarut num-workspaces " ++"deg org.gnome.desktop.wm.preferences)." ++ ++#: data/org.gnome.mutter.gschema.xml.in:58 ++msgid "Workspaces only on primary" ++msgstr "Tallunin n umahil ɣef umezwaru kan" ++ ++#: data/org.gnome.mutter.gschema.xml.in:59 ++msgid "" ++"Determines whether workspace switching should happen for windows on all " ++"monitors or only for windows on the primary monitor." ++msgstr "" ++"Yesguccul ma yella tallunin n umahil ttwasefrakent s wudem asmussan neɣ ma " ++"yella amḍan udmis n tallunin n umahil (yettwaguccel s tsarut num-workspaces " ++"deg org.gnome.desktop.wm.preferences)." ++ ++#: data/org.gnome.mutter.gschema.xml.in:67 ++msgid "Delay focus changes until the pointer stops moving" ++msgstr "Saẓey isenfal n usaḍes alamma asewwar ad iḥbes asenkez" ++ ++#: data/org.gnome.mutter.gschema.xml.in:68 ++msgid "" ++"If set to true, and the focus mode is either “sloppy” or “mouse” then the " ++"focus will not be changed immediately when entering a window, but only after " ++"the pointer stops moving." ++msgstr "" ++"Ma yella yettusbadu s tidet, askar asaḍes \"sloppy\" neɣ \"d taɣerdayt\", " ++"asiḍes ur yettwasenfal ara mi ara d-yekcem usfaylu, maca ma yeḥbes kan " ++"usewwar asenkez." ++ ++#: data/org.gnome.mutter.gschema.xml.in:78 ++msgid "Draggable border width" ++msgstr "Tehri n tama yettwazuɣaren" ++ ++#: data/org.gnome.mutter.gschema.xml.in:79 ++msgid "" ++"The amount of total draggable borders. If the theme’s visible borders are " ++"not enough, invisible borders will be added to meet this value." ++msgstr "" ++"Tasmekta tasemdayt n tamiwin i izmeren ad tettwaszuɣarent. Ma yella tamiwin " ++"ibanen n usentel d timagdazin, tamiwin ur nban ara ad ttwarnunt i wakken ad " ++"yaweḍ wazal-nni." ++ ++#: data/org.gnome.mutter.gschema.xml.in:88 ++msgid "Auto maximize nearly monitor sized windows" ++msgstr "Asemɣer awurman i yisfuyla n teɣzi i iqerben ɣer teɣzi n ugdil" ++ ++#: data/org.gnome.mutter.gschema.xml.in:89 ++msgid "" ++"If enabled, new windows that are initially the size of the monitor " ++"automatically get maximized." ++msgstr "" ++"Ma yella yettwarmed, isfuyla imaynuten i yesεan teɣzi am tin n ugdil " ++"yettnernin s wudem awurman." ++ ++#: data/org.gnome.mutter.gschema.xml.in:97 ++msgid "Place new windows in the center" ++msgstr "Sers isfuyla imaynuten deg tlemmast" ++ ++#: data/org.gnome.mutter.gschema.xml.in:98 ++msgid "" ++"When true, the new windows will always be put in the center of the active " ++"screen of the monitor." ++msgstr "" ++"Ma yella d tidet, isfuyla imaynuten zgan ttuɣalen deg tlemmast n ugdil urmid " ++"n usefrak." ++ ++#: data/org.gnome.mutter.gschema.xml.in:107 ++msgid "Enable experimental features" ++msgstr "Rmed timahilin tirmitanin" ++ ++#: data/org.gnome.mutter.gschema.xml.in:108 ++msgid "" ++"To enable experimental features, add the feature keyword to the list. " ++"Whether the feature requires restarting the compositor depends on the given " ++"feature. Any experimental feature is not required to still be available, or " ++"configurable. Don’t expect adding anything in this setting to be future " ++"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " ++"mutter default to layout logical monitors in a logical pixel coordinate " ++"space, while scaling monitor framebuffers instead of window content, to " ++"manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " ++"mutter always allocate scanout buffers with explicit modifiers, if supported " ++"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " ++"terminates Xwayland if all relevant X11 clients are gone. Requires a " ++"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " ++"refresh rate of the monitor when applicable if supported by the monitor, GPU " ++"and DRM driver. Configurable in Settings. Requires a restart." ++msgstr "" ++"I urmad n tmahilin tirmitanin, rnu awal n tsarut n tmahilt ɣer tebdart. " ++"Allus n usenker n usuddas yettwasra almend n tmahilt i d-yettwamudden. Ur " ++"tettwasra ara kra n tmahilt tarmitant ad teqqim tella kan neɣ tezmer ad " ++"tettuswal. Mačči yal timerna n kra deg uɣewwar-a yeskanay-d imal. Awalen n " ++"tsura yettwaqbalen akka tura: • “scale-monitor-framebuffer” — yettarra " ++"mutter ad yesεu s wudem amezwer isefraken imeẓẓulen deg wadeg ameẓẓul n " ++"yimsidag n yipiksilen, lawan n usemɣer n yikataren n usefrak deg wadeg n " ++"ugbur n usfaylu, i usefrek n HiDPI. Ur yesra allus n usenker. • “kms-" ++"modifiers” — yettarra mutter yezga yettḥerri aḥrazen n uḍummu s yisenfalayen " ++"iflayanen, ma yella yettwasefrak sɣur unuḍaf. Yesra allus n usenkar. • " ++"“autoclose-xwayland” — yettfakk s wudem awurman Xwayland ma yella akk " ++"imsaɣen X11 yesεan azal ruḥen. Yesra allus n usenker. • “variable-refresh-" ++"rate” — yettarra mutter yezmer ad isemsawi s wudem asmussan aktum n usismeḍ " ++"n usefrak, ma yella tettunefk tegnit, ma yella yettwasefrak sɣur usefrak, " ++"GPU akked unuḍaf DRM. Yettwaswal deg yiɣewwaren. Yesra alluas n usenker." ++ ++#: data/org.gnome.mutter.gschema.xml.in:144 ++msgid "Modifier to use to locate the pointer" ++msgstr "Senfel ara yettwasqedcen i usideg n usewwaṛ" ++ ++#: data/org.gnome.mutter.gschema.xml.in:145 ++msgid "This key will initiate the “locate pointer” action." ++msgstr "Tasarut-a ad twennez tigawt n \"usideg n usewwaṛ\"." ++ ++#: data/org.gnome.mutter.gschema.xml.in:152 ++msgid "Timeout for check-alive ping" ++msgstr "Tanzagt n keffu n ping n usenqed" ++ ++#: data/org.gnome.mutter.gschema.xml.in:153 ++msgid "" ++"Number of milliseconds a client has to respond to a ping request in order to " ++"not be detected as frozen. Using 0 will disable the alive check completely." ++msgstr "" ++"Amḍan n yiliten tsinin i yesεa umsaɣ i wakken ad yerr ɣef ussuter ping akken " ++"ur yettuneḥsab ara yegres. Aseqdec n 0 yesnusuy s wudem ummid asenqed n " ++"tiltin n umsaɣ." ++ ++#: data/org.gnome.mutter.gschema.xml.in:177 ++msgid "Switch monitor configurations" ++msgstr "Senfel tiwila n usefrak" ++ ++#: data/org.gnome.mutter.gschema.xml.in:182 ++msgid "Rotates the built-in monitor configuration" ++msgstr "Sezzi tawila n usefrak usliɣ" ++ ++#: data/org.gnome.mutter.gschema.xml.in:187 ++msgid "Cancel any active input capture session" ++msgstr "Sefsex akk n tɣimiyin n tuṭṭfa n unekcum yettwaremden" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:12 ++msgid "Switch to VT 1" ++msgstr "Ddu ɣer VT 1" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:16 ++msgid "Switch to VT 2" ++msgstr "Ddu ɣer VT 2" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:20 ++msgid "Switch to VT 3" ++msgstr "Ddu ɣer VT 3" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:24 ++msgid "Switch to VT 4" ++msgstr "Ddu ɣer VT 4" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:28 ++msgid "Switch to VT 5" ++msgstr "Ddu ɣer VT 5" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:32 ++msgid "Switch to VT 6" ++msgstr "Ddu ɣer VT 6" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:36 ++msgid "Switch to VT 7" ++msgstr "Ddu ɣer VT 7" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:40 ++msgid "Switch to VT 8" ++msgstr "Ddu ɣer VT 8" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:44 ++msgid "Switch to VT 9" ++msgstr "Ddu ɣer VT 9" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:48 ++msgid "Switch to VT 10" ++msgstr "Ddu ɣer VT 10" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:52 ++msgid "Switch to VT 11" ++msgstr "Ddu ɣer VT 11" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:56 ++msgid "Switch to VT 12" ++msgstr "Ddu ɣer VT 12" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:60 ++msgid "Re-enable shortcuts" ++msgstr "Ales armad n yinegzumen n unasiw" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:70 ++msgid "Allow X11 grabs to lock keyboard focus with Xwayland" ++msgstr "Sireg tuṭṭfiwin X11 ad sekkṛent afukus n unasiw s Xwayland" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:71 ++msgid "" ++"Allow all keyboard events to be routed to X11 “override redirect” windows " ++"with a grab when running in Xwayland. This option is to support X11 clients " ++"which map an “override redirect” window (which do not receive keyboard " ++"focus) and issue a keyboard grab to force all keyboard events to that " ++"window. This option is seldom used and has no effect on regular X11 windows " ++"which can receive keyboard focus under normal circumstances. For a X11 grab " ++"to be taken into account under Wayland, the client must also either send a " ++"specific X11 ClientMessage to the root window or be among the applications " ++"allowed in key “xwayland-grab-access-rules”." ++msgstr "" ++"Asireg n usezzi n meṛṛa tidyanin n unasiw ɣer yisfuyla X11 \"override " ++"redirect\" s uzuɣer lawan n uselkem deg Xwayland. Taxtiṛt-a tettaǧǧa imsaɣen " ++"X11 azuɣer n usfaylu \"override redirect\" (ur nremmes ara asiḍes n unasiw) " ++"akked useqdec n uzuɣer i uḥettem n meṛṛa tidyanin n unasiw ɣer usfaylu-a. " ++"Taxtiṛt-a ur tettwaseqdac ara s waṭas, ur txeddem kra i yisfuyla X11 i " ++"izemren ad remsen asiḍes n unasiw deg tegnatin timugna. I uzuɣer n X11 ad " ++"tettwaṭṭef deg Wayland, amsaɣ ilaq ad yazen daɣen X11 ClientMessage ɣer " ++"usfaylu aẓar neɣ ad yili seg yisnasen yettwasirgen deg tsarut “xwayland-grab-" ++"access-rules”." ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:90 ++msgid "Xwayland applications allowed to issue keyboard grabs" ++msgstr "Isnasen Xwayland ttusirgent ad gent tuṭṭfiwin n unasiw" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:91 ++msgid "" ++"List the resource names or resource class of X11 windows either allowed or " ++"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " ++"resource class of a given X11 window can be obtained using the command " ++"“xprop WM_CLASS”. Wildcards “*” and jokers “?” in the values are supported. " ++"Values starting with “!” are denied, which has precedence over the list of " ++"values allowed, to revoke applications from the default system list. The " ++"default system list includes the following applications: " ++"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Users can break an existing grab by " ++"using the specific keyboard shortcut defined by the keybinding key “restore-" ++"shortcuts”." ++msgstr "" ++"Bder ismawen n yiɣbula neɣ ismilen n yiɣbula n yisfuyla X11 yettwasirgen neɣ " ++"uhu, ad gen tuṭṭfiwin n unasiw X11 deg Wayland. Isem neɣ asmel n uɣbalu n " ++"usfaylu X11 i yettwamudden zemren ad d-ttwawin s useqdec n tladna “xprop " ++"WM_CLASS”. Isekkilen imcettlen “*” akked ijukiṛen “?” deg wazalen " ++"yettwasferken. Azalen i ibeddun s \"!\" ttwagin, i yellan deg tebdart " ++"yettwasirgen yakan, i usefsex n yisnasen seg tebdart n unagraw amezwer. " ++"Tabdart n unagraw amezwer deg-s isnasen-a: " ++"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Iseqdacen zemren ad sḥebsen tira " ++"yellan yakan s useqdec n unegzum n unasiw uzzig yettusbadun s tsarut n " ++"tuqqna \"restore-shortcuts\"." ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:116 ++msgid "Disable selected X extensions in Xwayland" ++msgstr "Sens isiɣzaf X i yettwafernen deg Xwayland" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:117 ++msgid "" ++"This option disables the selected X extensions in Xwayland if Xwayland was " ++"built with support for those X extensions. This option has no effect if " ++"Xwayland was built without support for the selected extensions. Xwayland " ++"needs to be restarted for this setting to take effect." ++msgstr "" ++"Taxtiṛt-a tesnusuy isiɣzaf X i yettwafernen deg Xwayland ma yella Xwayland " ++"yebna s usefrek i yisiɣzaf-a X. Taxtiṛt-a ur d-tgellu s wecemma ma yella " ++"Xwayland yebna war asefrek n yisiɣzaf i yettwafernen. Xwayland yesra ad " ++"yales asenker i uɣewwar-a i wakken ad yeddu." ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:130 ++msgid "Allow X11 clients with a different endianness to connect to Xwayland" ++msgstr "Sireg imsaɣen X11 s at taggara yemgaraden i tuqqna ɣer Xwayland" ++ ++#: data/org.gnome.mutter.wayland.gschema.xml.in:131 ++msgid "" ++"Allow connections from clients with an endianness different to that of " ++"Xwayland. The X server byte-swapping code is a huge attack surface, much of " ++"that code in Xwayland is prone to security issues. The use-case of byte-" ++"swapped clients is very niche, and disabled by default in Xwayland. Enable " ++"this option to instruct Xwayland to accept connections from X11 clients with " ++"a different endianness. This option has no effect if Xwayland does not " ++"support the command line option +byteswappedclients/-byteswappedclients to " ++"control that setting. Xwayland needs to be restarted for this setting to " ++"take effect." ++msgstr "" ++"Asireg n tuqqniwin seg yimsaɣen ideg endianness yemgarad ɣef win n Xwayland. " ++"Tangalt n umyibedel n yibiten n uqeddac X d tajumma meqqren n uzḍam, amur " ++"ameqqran seg tengalt-a deg Xwayland yezmer ad yesεu uguren n tɣellist. " ++"Addaden n useqdec n yimsaɣen yettmyibeddalen ibiten drus maḍi, yettwasens s " ++"wudem amezwer deg Xwayland. Armad n textiṛt-a i ussuter deg Xwayland aqbal n " ++"tuqqniwin n yimsaɣen X11 s endianness yemgaraden. Taxtiṛt-a ur txeddem " ++"acemma ma yella Xwayland ur yessefrak ara taxtiṛt n yizirig n tiludna " ++"+byteswappedclients/-byteswappedclients i usenqed n uɣewwar-a. Xwayland " ++"yesra ad yales asenker i uɣewwar-a i wakken ad yeṭṭef." ++ ++#: src/backends/meta-monitor.c:251 ++msgid "Built-in display" ++msgstr "Agdil usliɣ" ++ ++#: src/backends/meta-monitor.c:278 ++msgid "Unknown" ++msgstr "Arussin" ++ ++#: src/backends/meta-monitor.c:280 ++msgid "Unknown Display" ++msgstr "Agdil arussin" ++ ++#: src/backends/meta-monitor.c:288 ++#, c-format ++msgctxt "" ++"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" ++msgid "%s %s" ++msgstr "%s %s" ++ ++#: src/backends/meta-monitor.c:296 ++#, c-format ++msgctxt "" ++"This is a monitor vendor name followed by product/model name where size in " ++"inches could not be calculated, e.g. Dell U2414H" ++msgid "%s %s" ++msgstr "%s %s" ++ ++#: src/core/bell.c:193 ++msgid "Bell event" ++msgstr "Tadyant n unayna" ++ ++#: src/core/display.c:734 ++msgid "Privacy Screen Enabled" ++msgstr "Agdil n tbaḍnit yermed" ++ ++#: src/core/display.c:735 ++msgid "Privacy Screen Disabled" ++msgstr "Agdil n tbaḍnit yensa" ++ ++#: src/core/meta-context-main.c:601 ++msgid "Replace the running window manager" ++msgstr "Semselsi amsefrak n usfaylu yettwaselkamen" ++ ++#: src/core/meta-context-main.c:607 ++msgid "X Display to use" ++msgstr "Taskant X ara yettusqedcen" ++ ++#: src/core/meta-context-main.c:613 ++msgid "Disable connection to session manager" ++msgstr "Sens tuqqna i umsefrak n tɣimit" ++ ++#: src/core/meta-context-main.c:619 ++msgid "Specify session management ID" ++msgstr "Asulay n usefrek n tɣimit tuzzigt" ++ ++#: src/core/meta-context-main.c:625 ++msgid "Initialize session from savefile" ++msgstr "Wennez tiɣimit seg ufaylu i yettwaskelsen" ++ ++#: src/core/meta-context-main.c:631 ++msgid "Make X calls synchronous" ++msgstr "Err isawalen X mtawan" ++ ++#: src/core/meta-context-main.c:639 ++msgid "Run as a wayland compositor" ++msgstr "Selkem am umsuddas Wayland" ++ ++#: src/core/meta-context-main.c:645 ++msgid "Run as a nested compositor" ++msgstr "Selkem am umsuddas yemyekcamen" ++ ++#: src/core/meta-context-main.c:651 ++msgid "Run wayland compositor without starting Xwayland" ++msgstr "Selkem amsuddas wayland war asenker n Xwayland" ++ ++#: src/core/meta-context-main.c:657 ++msgid "Specify Wayland display name to use" ++msgstr "Sded agdil Wayland i useqdec" ++ ++#: src/core/meta-context-main.c:665 ++msgid "Run as a full display server, rather than nested" ++msgstr "Selkem am uqeddac n uskan aččuran, deg wadeg n umyikcam" ++ ++#: src/core/meta-context-main.c:670 ++msgid "Run as a headless display server" ++msgstr "Selkem am uqeddac n uskan war aqerru" ++ ++#: src/core/meta-context-main.c:675 ++msgid "Add persistent virtual monitor (WxH or WxH@R)" ++msgstr "Rnu asefrak uhlis amaɣlal (WxH neɣ WxH@R)" ++ ++#: src/core/meta-context-main.c:687 ++msgid "Run with X11 backend" ++msgstr "Selkem s ugdil n deffir X11" ++ ++#: src/core/meta-context-main.c:693 ++msgid "Profile performance using trace instrumentation" ++msgstr "Timellit n umaɣnu s useqdec n ifecka n uḍfar" ++ ++#: src/core/meta-context-main.c:699 ++msgid "Enable debug control D-Bus interface" ++msgstr "Rmed agrudem D-Bus n usenqed n tseɣtayt" ++ ++#. TRANSLATORS: This string refers to a button that switches between ++#. * different modes. ++#. ++#: src/core/meta-pad-action-mapper.c:826 ++#, c-format ++msgid "Mode Switch (Group %d)" ++msgstr "Asenfel n uskar (Agraw %d)" ++ ++#. TRANSLATORS: This string refers to an action, cycles drawing tablets' ++#. * mapping through the available outputs. ++#. ++#: src/core/meta-pad-action-mapper.c:848 ++msgid "Switch monitor" ++msgstr "Senfel asefrak" ++ ++#: src/core/meta-pad-action-mapper.c:850 ++msgid "Show on-screen help" ++msgstr "Sken tallalt ɣef ugdil" ++ ++#. Translators: this string will appear in Sysprof ++#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 ++msgid "Compositor" ++msgstr "Amsuddas" ++ ++#: src/core/mutter.c:74 ++msgid "Print version" ++msgstr "Sken lqem" ++ ++#: src/core/mutter.c:80 ++msgid "Mutter plugin to use" ++msgstr "Azegrir Mutter ara yettwasqedcen" ++ ++#: src/core/prefs.c:1842 ++#, c-format ++msgid "Workspace %d" ++msgstr "Tallunt n umahil %d" ++ ++#: src/core/util.c:139 ++msgid "Mutter was compiled without support for verbose mode" ++msgstr "Mutter yettwasefsu war asefrek n uskar ɣezzifen" ++ ++#: src/core/workspace.c:510 ++msgid "Workspace switched" ++msgstr "Tallunt n umahil tettwasenfel" ++ ++#: src/wayland/meta-wayland-tablet-pad.c:532 ++#, c-format ++msgid "Mode Switch: Mode %d" ++msgstr "Asenfel n uskar: Askar %d" ++ ++#: src/x11/meta-x11-display.c:723 ++#, c-format ++msgid "" ++"Display “%s” already has a window manager; try using the --replace option to " ++"replace the current window manager." ++msgstr "" ++"Sken \"%s\" yesεa yakan asefrak n usfaylu; εreḍ seqdec taxtiṛt --replace i " ++"usemselsi n usefrak n yisfuyla amiran." ++ ++#: src/x11/meta-x11-display.c:1088 ++#, c-format ++msgid "Failed to open X Window System display “%s”" ++msgstr "Yecceḍ ulday n uskan n n yifuyla X Window \"%s\"" ++ ++#: src/x11/meta-x11-display.c:1268 ++#, c-format ++msgid "Screen %d on display “%s” is invalid" ++msgstr "Agdil %d ɣef uskan \"%s\" d arameɣtu" ++ ++#. This probably means that a non-WM compositor like xcompmgr is running; ++#. * we have no way to get it to exit ++#: src/x11/meta-x11-display.c:2547 ++#, c-format ++msgid "" ++"Another compositing manager is already running on screen %i on display “%s”." ++msgstr "" ++"Asefrak niḍen n usuddes yella yakan yettwaselkam ɣef ugdil %i ɣef uskan " ++"\"%s\"." ++ ++#: src/x11/meta-x11-selection-input-stream.c:475 ++#, c-format ++msgid "Format %s not supported" ++msgstr "Amasal %s ur yettwasefrak ara" ++ ++#: src/x11/window-props.c:528 ++#, c-format ++msgid "%s (on %s)" ++msgstr "%s (ɣef %s)" +diff --git a/po/ko.po b/po/ko.po +index 558c6c5ca..3ac430f08 100644 +--- a/po/ko.po ++++ b/po/ko.po +@@ -7,7 +7,7 @@ + # + # Updated in mutter: + # Changwoo Ryu , 2011-2017. +-# Gwan-gyeong Mun , 2018-2023. ++# Gwan-gyeong Mun , 2018-2024. + # + # + # 주의: +@@ -17,8 +17,8 @@ + msgid "" + msgstr "" + "Project-Id-Version: mutter\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" +-"POT-Creation-Date: 2023-08-23 16:49+0000\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" ++"POT-Creation-Date: 2024-03-11 11:31+0000\n" + "PO-Revision-Date: 2023-03-15 18:43+0200\n" + "Last-Translator: Gwan-gyeong Mun \n" + "Language-Team: GNOME Korea \n" +@@ -257,11 +257,11 @@ msgstr "창을 세로 방향으로 최대화" + msgid "Maximize window horizontally" + msgstr "창을 가로 방향으로 최대화" + +-#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 ++#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 + msgid "View split on left" + msgstr "왼쪽 나눔창 보기" + +-#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 ++#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 + msgid "View split on right" + msgstr "오른쪽 나눔창 보기" + +@@ -394,10 +394,11 @@ msgid "" + "space, while scaling monitor framebuffers instead of window content, to " + "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " + "mutter always allocate scanout buffers with explicit modifiers, if supported " +-"by the driver. Requires a restart. • “rt-scheduler” — makes mutter request a " +-"low priority real-time scheduling. Requires a restart. • “autoclose-" +-"xwayland” — automatically terminates Xwayland if all relevant X11 clients " +-"are gone. Requires a restart." ++"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " ++"terminates Xwayland if all relevant X11 clients are gone. Requires a " ++"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " ++"refresh rate of the monitor when applicable if supported by the monitor, GPU " ++"and DRM driver. Configurable in Settings. Requires a restart." + msgstr "" + "실험적인 기능을 사용하려면, 해당 기능 키워드를 목록에 추가하십시오. 기능에 따" + "라 컴포지터를 다시 시작해야 할 수도 있습니다. 실험적인 기능은 사용할 수 없을 " +@@ -407,24 +408,25 @@ msgstr "" + "를 배치하고, HiDPI 모니터를 관리하기 위해 창 내용 대신 모니터 프레임 버퍼를 " + "스케일링합니다. 재시작은 필요하지 않습니다. • “kms-modifiers” — 드라이버에서 " + "지원하는 경우 머터가 항상 명시적 한정자를 사용하여 스캔아웃 버퍼를 할당 합니" +-"다. 재시작이 필요합니다. • “rt-scheduler” — 머터 요청을 우선순위가 낮은 실시" +-"간 스케줄링으로 만듭니다. 재시작이 필요합니다. • “autoclose-xwayland” — 모든 " +-"X11 관련 클라이언트가 종료되면 X웨일랜드를 자동으로 종료합니다. 재시작이 필요" +-"하지 않습니다." ++"다. 재시작이 필요합니다. • “autoclose-xwayland” — 모든 X11 관련 클라이언트가 " ++"종료되면 X웨일랜드를 자동으로 종료합니다. 재시작이 필요하지 않습니다. • " ++"“variable-refresh-rate” — 모니터, GPU 및 DRM 드라이버에서 지원하는 경우 모니" ++"터의 새로 고침 빈도를 동적으로 조정합니다. 설정에서 구성 가능하며, 재시작이 " ++"필요합니다." + +-#: data/org.gnome.mutter.gschema.xml.in:141 ++#: data/org.gnome.mutter.gschema.xml.in:144 + msgid "Modifier to use to locate the pointer" + msgstr "포인터 위치 찾기에 사용할 키" + +-#: data/org.gnome.mutter.gschema.xml.in:142 ++#: data/org.gnome.mutter.gschema.xml.in:145 + msgid "This key will initiate the “locate pointer” action." + msgstr "이 키는 “포인터 위치 찾기” 동작을 합니다." + +-#: data/org.gnome.mutter.gschema.xml.in:149 ++#: data/org.gnome.mutter.gschema.xml.in:152 + msgid "Timeout for check-alive ping" + msgstr "활성 확인 핑 시간 초과" + +-#: data/org.gnome.mutter.gschema.xml.in:150 ++#: data/org.gnome.mutter.gschema.xml.in:153 + msgid "" + "Number of milliseconds a client has to respond to a ping request in order to " + "not be detected as frozen. Using 0 will disable the alive check completely." +@@ -432,15 +434,15 @@ msgstr "" + "중지된 것으로 감지되지 않도록 클라이언트가 핑 요청에 응답해야 하는 시간 (밀리" + "초). 0을 사용하면 활성 확인이 완전히 비활성화됩니다." + +-#: data/org.gnome.mutter.gschema.xml.in:174 ++#: data/org.gnome.mutter.gschema.xml.in:177 + msgid "Switch monitor configurations" + msgstr "모니터 설정 전환" + +-#: data/org.gnome.mutter.gschema.xml.in:179 ++#: data/org.gnome.mutter.gschema.xml.in:182 + msgid "Rotates the built-in monitor configuration" + msgstr "내장된 모니터 설정을 돌아가면서 전환합니다" + +-#: data/org.gnome.mutter.gschema.xml.in:184 ++#: data/org.gnome.mutter.gschema.xml.in:187 + msgid "Cancel any active input capture session" + msgstr "활성화된 입력 캡처 세션 취소" + +@@ -587,26 +589,26 @@ msgstr "" + "byteswappedclients을 지원하지 않는 경우 효과가 없습니다. 이 설정을 적용하려" + "면 X웨일랜드를 다시 시작해야 합니다." + +-#: src/backends/meta-monitor.c:253 ++#: src/backends/meta-monitor.c:251 + msgid "Built-in display" + msgstr "내장 디스플레이" + +-#: src/backends/meta-monitor.c:280 ++#: src/backends/meta-monitor.c:278 + msgid "Unknown" + msgstr "알 수 없음" + +-#: src/backends/meta-monitor.c:282 ++#: src/backends/meta-monitor.c:280 + msgid "Unknown Display" + msgstr "알 수 없는 디스플레이" + +-#: src/backends/meta-monitor.c:290 ++#: src/backends/meta-monitor.c:288 + #, c-format + msgctxt "" + "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" + msgid "%s %s" + msgstr "%s %s" + +-#: src/backends/meta-monitor.c:298 ++#: src/backends/meta-monitor.c:296 + #, c-format + msgctxt "" + "This is a monitor vendor name followed by product/model name where size in " +@@ -618,78 +620,82 @@ msgstr "%s %s" + msgid "Bell event" + msgstr "삑소리 이벤트" + +-#: src/core/display.c:723 ++#: src/core/display.c:734 + msgid "Privacy Screen Enabled" + msgstr "사생활 보호 화면 사용" + +-#: src/core/display.c:724 ++#: src/core/display.c:735 + msgid "Privacy Screen Disabled" + msgstr "사생활 보호 화면 해제" + +-#: src/core/meta-context-main.c:581 ++#: src/core/meta-context-main.c:601 + msgid "Replace the running window manager" + msgstr "실행 중인 창 관리자를 바꿉니다" + +-#: src/core/meta-context-main.c:587 ++#: src/core/meta-context-main.c:607 + msgid "X Display to use" + msgstr "사용할 X 디스플레이" + +-#: src/core/meta-context-main.c:593 ++#: src/core/meta-context-main.c:613 + msgid "Disable connection to session manager" + msgstr "세션 관리자와 연결 하지 않습니다" + +-#: src/core/meta-context-main.c:599 ++#: src/core/meta-context-main.c:619 + msgid "Specify session management ID" + msgstr "세션 관리 ID를 지정합니다" + +-#: src/core/meta-context-main.c:605 ++#: src/core/meta-context-main.c:625 + msgid "Initialize session from savefile" + msgstr "저장 파일에서 세션을 초기화 합니다" + +-#: src/core/meta-context-main.c:611 ++#: src/core/meta-context-main.c:631 + msgid "Make X calls synchronous" + msgstr "동기 X 호출을 합니다" + +-#: src/core/meta-context-main.c:619 ++#: src/core/meta-context-main.c:639 + msgid "Run as a wayland compositor" + msgstr "웨일랜드 컴포지터로 실행합니다" + +-#: src/core/meta-context-main.c:625 ++#: src/core/meta-context-main.c:645 + msgid "Run as a nested compositor" + msgstr "중첩 컴포지터로 실행합니다" + +-#: src/core/meta-context-main.c:631 ++#: src/core/meta-context-main.c:651 + msgid "Run wayland compositor without starting Xwayland" + msgstr "웨일랜드 컴포지터를 X웨일랜드 시작없이 실행합니다" + +-#: src/core/meta-context-main.c:637 ++#: src/core/meta-context-main.c:657 + msgid "Specify Wayland display name to use" + msgstr "사용할 웨일랜드 디스플레이 이름 지정" + +-#: src/core/meta-context-main.c:645 ++#: src/core/meta-context-main.c:665 + msgid "Run as a full display server, rather than nested" + msgstr "전체 디스플레이 서버로 실행, 중첩 컴포지터가 아님" + +-#: src/core/meta-context-main.c:650 ++#: src/core/meta-context-main.c:670 + msgid "Run as a headless display server" + msgstr "헤드리스 디스플레이 서버로 실행" + +-#: src/core/meta-context-main.c:655 ++#: src/core/meta-context-main.c:675 + msgid "Add persistent virtual monitor (WxH or WxH@R)" + msgstr "영구적인 가상 모니터 추가 (WxH or WxH@R)" + +-#: src/core/meta-context-main.c:667 ++#: src/core/meta-context-main.c:687 + msgid "Run with X11 backend" + msgstr "X11 백 엔드로 실행 합니다" + +-#: src/core/meta-context-main.c:673 ++#: src/core/meta-context-main.c:693 + msgid "Profile performance using trace instrumentation" + msgstr "추적 계측을 사용한 성능 프로파일" + ++#: src/core/meta-context-main.c:699 ++msgid "Enable debug control D-Bus interface" ++msgstr "디버깅 제어 D-Bus 인터페이스 사용" ++ + #. TRANSLATORS: This string refers to a button that switches between + #. * different modes. + #. +-#: src/core/meta-pad-action-mapper.c:807 ++#: src/core/meta-pad-action-mapper.c:826 + #, c-format + msgid "Mode Switch (Group %d)" + msgstr "모드 전환 (그룹 %d)" +@@ -697,16 +703,16 @@ msgstr "모드 전환 (그룹 %d)" + #. TRANSLATORS: This string refers to an action, cycles drawing tablets' + #. * mapping through the available outputs. + #. +-#: src/core/meta-pad-action-mapper.c:829 ++#: src/core/meta-pad-action-mapper.c:848 + msgid "Switch monitor" + msgstr "모니터 전환" + +-#: src/core/meta-pad-action-mapper.c:831 ++#: src/core/meta-pad-action-mapper.c:850 + msgid "Show on-screen help" + msgstr "화면 도움말 표시" + + #. Translators: this string will appear in Sysprof +-#: src/core/meta-profiler.c:111 src/core/meta-profiler.c:301 ++#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 + msgid "Compositor" + msgstr "컴포지터" + +@@ -718,7 +724,7 @@ msgstr "버전을 출력합니다" + msgid "Mutter plugin to use" + msgstr "사용할 머터 플러그인" + +-#: src/core/prefs.c:1843 ++#: src/core/prefs.c:1842 + #, c-format + msgid "Workspace %d" + msgstr "작업 공간 %d" +@@ -727,16 +733,16 @@ msgstr "작업 공간 %d" + msgid "Mutter was compiled without support for verbose mode" + msgstr "머터가 자세한 정보 표시 모드를 지원하지 않게 컴파일되었습니다" + +-#: src/core/workspace.c:535 ++#: src/core/workspace.c:510 + msgid "Workspace switched" + msgstr "작업 공간 전환" + +-#: src/wayland/meta-wayland-tablet-pad.c:534 ++#: src/wayland/meta-wayland-tablet-pad.c:532 + #, c-format + msgid "Mode Switch: Mode %d" + msgstr "모드 전환: 모드 %d" + +-#: src/x11/meta-x11-display.c:708 ++#: src/x11/meta-x11-display.c:723 + #, c-format + msgid "" + "Display “%s” already has a window manager; try using the --replace option to " +@@ -745,19 +751,19 @@ msgstr "" + "디스플레이 “%s”에 이미 창 관리자가 있습니다. 현재 창 관리자를 바꾸려면 --" + "replace 옵션을 써보십시오." + +-#: src/x11/meta-x11-display.c:1073 ++#: src/x11/meta-x11-display.c:1088 + #, c-format + msgid "Failed to open X Window System display “%s”" + msgstr "X 윈도 시스템 디스플레이 “%s”을(를) 여는데 실패하였습니다" + +-#: src/x11/meta-x11-display.c:1219 ++#: src/x11/meta-x11-display.c:1268 + #, c-format + msgid "Screen %d on display “%s” is invalid" + msgstr "디스플레이 “%2$s”의 화면 %1$d은(는) 잘못되었습니다" + + #. This probably means that a non-WM compositor like xcompmgr is running; + #. * we have no way to get it to exit +-#: src/x11/meta-x11-display.c:2540 ++#: src/x11/meta-x11-display.c:2547 + #, c-format + msgid "" + "Another compositing manager is already running on screen %i on display “%s”." +@@ -771,7 +777,7 @@ msgid "Format %s not supported" + msgstr "%s 형식은 지원하지 않습니다" + + # <창제목> (on <기계>) +-#: src/x11/window-props.c:548 ++#: src/x11/window-props.c:528 + #, c-format + msgid "%s (on %s)" + msgstr "%s (%s에서)" +diff --git a/po/nl.po b/po/nl.po +index 1aae5aca9..9f4d33e05 100644 +--- a/po/nl.po ++++ b/po/nl.po +@@ -10,8 +10,8 @@ msgid "" + msgstr "" + "Project-Id-Version: mutter\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" +-"POT-Creation-Date: 2024-02-12 13:12+0000\n" +-"PO-Revision-Date: 2024-02-18 17:09+0100\n" ++"POT-Creation-Date: 2024-03-16 16:36+0000\n" ++"PO-Revision-Date: 2024-03-31 12:12+0200\n" + "Last-Translator: Nathan Follens \n" + "Language-Team: GNOME-NL https://matrix.to/#/#nl:gnome.org\n" + "Language: nl\n" +@@ -250,19 +250,19 @@ msgstr "Venster verticaal maximaliseren" + msgid "Maximize window horizontally" + msgstr "Venster horizontaal maximaliseren" + +-#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:160 ++#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 + msgid "View split on left" + msgstr "Weergave gesplitst op links" + +-#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:165 ++#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 + msgid "View split on right" + msgstr "Weergave gesplitst op rechts" + +-#: data/org.gnome.mutter.gschema.xml.in:14 ++#: data/org.gnome.mutter.gschema.xml.in:15 + msgid "Modifier to use for extended window management operations" + msgstr "Controletoets voor uitgebreide vensterbeheerfunctionaliteit" + +-#: data/org.gnome.mutter.gschema.xml.in:15 ++#: data/org.gnome.mutter.gschema.xml.in:16 + msgid "" + "This key will initiate the “overlay”, which is a combination window overview " + "and application launching system. The default is intended to be the “Windows " +@@ -274,11 +274,11 @@ msgstr "" + "toets’ en de bedoeling is dat deze sneltoets ofwel de standaardwaarde bevat " + "ofwel leeggemaakt is." + +-#: data/org.gnome.mutter.gschema.xml.in:27 ++#: data/org.gnome.mutter.gschema.xml.in:28 + msgid "Attach modal dialogs" + msgstr "Blokkerende dialoogvensters vastmaken" + +-#: data/org.gnome.mutter.gschema.xml.in:28 ++#: data/org.gnome.mutter.gschema.xml.in:29 + msgid "" + "When true, instead of having independent titlebars, modal dialogs appear " + "attached to the titlebar of the parent window and are moved together with " +@@ -288,11 +288,11 @@ msgstr "" + "maar vastgekoppeld aan het achterliggende venster en bewegen daardoor ook " + "mee met het achterliggende venster." + +-#: data/org.gnome.mutter.gschema.xml.in:37 ++#: data/org.gnome.mutter.gschema.xml.in:38 + msgid "Enable edge tiling when dropping windows on screen edges" + msgstr "Randtegels inschakelen bij het slepen van vensters naar schermranden" + +-#: data/org.gnome.mutter.gschema.xml.in:38 ++#: data/org.gnome.mutter.gschema.xml.in:39 + msgid "" + "If enabled, dropping windows on vertical screen edges maximizes them " + "vertically and resizes them horizontally to cover half of the available " +@@ -303,11 +303,11 @@ msgstr "" + "schermgrootte brengen. Het laten vallen van vensters op de bovenrand van het " + "scherm maximaliseert ze helemaal." + +-#: data/org.gnome.mutter.gschema.xml.in:47 ++#: data/org.gnome.mutter.gschema.xml.in:48 + msgid "Workspaces are managed dynamically" + msgstr "Werkbladen worden dynamisch beheerd" + +-#: data/org.gnome.mutter.gschema.xml.in:48 ++#: data/org.gnome.mutter.gschema.xml.in:49 + msgid "" + "Determines whether workspaces are managed dynamically or whether there’s a " + "static number of workspaces (determined by the num-workspaces key in org." +@@ -317,11 +317,11 @@ msgstr "" + "werkbladen is (gegeven door de sleutel num-workspaces in org.gnome.desktop." + "wm.preferences)." + +-#: data/org.gnome.mutter.gschema.xml.in:57 ++#: data/org.gnome.mutter.gschema.xml.in:58 + msgid "Workspaces only on primary" + msgstr "Werkbladen alleen voor primaire venster" + +-#: data/org.gnome.mutter.gschema.xml.in:58 ++#: data/org.gnome.mutter.gschema.xml.in:59 + msgid "" + "Determines whether workspace switching should happen for windows on all " + "monitors or only for windows on the primary monitor." +@@ -329,11 +329,11 @@ msgstr "" + "Geeft aan of wisselen van werkblad voor vensters op alle schermen of alleen " + "voor vensters op het hoofdscherm moet gebeuren." + +-#: data/org.gnome.mutter.gschema.xml.in:66 ++#: data/org.gnome.mutter.gschema.xml.in:67 + msgid "Delay focus changes until the pointer stops moving" + msgstr "Aandacht vertragen totdat de muispijl stopt met bewegen" + +-#: data/org.gnome.mutter.gschema.xml.in:67 ++#: data/org.gnome.mutter.gschema.xml.in:68 + msgid "" + "If set to true, and the focus mode is either “sloppy” or “mouse” then the " + "focus will not be changed immediately when entering a window, but only after " +@@ -343,11 +343,11 @@ msgstr "" + "‘mouse’, dan zal de aandacht niet direct veranderd worden bij het binnengaan " + "van een venster, maar slechts wanneer de muispijl stopt met bewegen." + +-#: data/org.gnome.mutter.gschema.xml.in:77 ++#: data/org.gnome.mutter.gschema.xml.in:78 + msgid "Draggable border width" + msgstr "Sleepbare randbreedte" + +-#: data/org.gnome.mutter.gschema.xml.in:78 ++#: data/org.gnome.mutter.gschema.xml.in:79 + msgid "" + "The amount of total draggable borders. If the theme’s visible borders are " + "not enough, invisible borders will be added to meet this value." +@@ -356,11 +356,11 @@ msgstr "" + "onvoldoende zijn, worden onzichtbare randen toegevoegd om deze waarde te " + "bereiken." + +-#: data/org.gnome.mutter.gschema.xml.in:87 ++#: data/org.gnome.mutter.gschema.xml.in:88 + msgid "Auto maximize nearly monitor sized windows" + msgstr "Vensters van bijna-monitorformaat auto-maximaliseren" + +-#: data/org.gnome.mutter.gschema.xml.in:88 ++#: data/org.gnome.mutter.gschema.xml.in:89 + msgid "" + "If enabled, new windows that are initially the size of the monitor " + "automatically get maximized." +@@ -368,11 +368,11 @@ msgstr "" + "Indien ingeschakeld, worden vensters die initieel ongeveer even groot zijn " + "als de monitor automatisch gemaximaliseerd." + +-#: data/org.gnome.mutter.gschema.xml.in:96 ++#: data/org.gnome.mutter.gschema.xml.in:97 + msgid "Place new windows in the center" + msgstr "Plaats nieuwe vensters in het midden" + +-#: data/org.gnome.mutter.gschema.xml.in:97 ++#: data/org.gnome.mutter.gschema.xml.in:98 + msgid "" + "When true, the new windows will always be put in the center of the active " + "screen of the monitor." +@@ -380,11 +380,11 @@ msgstr "" + "Indien waar zullen nieuwe vensters steeds in het midden van het actieve " + "scherm van de monitor geplaatst worden." + +-#: data/org.gnome.mutter.gschema.xml.in:106 ++#: data/org.gnome.mutter.gschema.xml.in:107 + msgid "Enable experimental features" + msgstr "Experimentele functies inschakelen" + +-#: data/org.gnome.mutter.gschema.xml.in:107 ++#: data/org.gnome.mutter.gschema.xml.in:108 + msgid "" + "To enable experimental features, add the feature keyword to the list. " + "Whether the feature requires restarting the compositor depends on the given " +@@ -396,7 +396,10 @@ msgid "" + "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " + "mutter always allocate scanout buffers with explicit modifiers, if supported " + "by the driver. Requires a restart. • “autoclose-xwayland” — automatically " +-"terminates Xwayland if all relevant X11 clients are gone. Requires a restart." ++"terminates Xwayland if all relevant X11 clients are gone. Requires a " ++"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " ++"refresh rate of the monitor when applicable if supported by the monitor, GPU " ++"and DRM driver. Configurable in Settings. Requires a restart." + msgstr "" + "Voeg het sleutelwoord van een experimentele functie toe aan de lijst om deze " + "in te schakelen. Of de compositor herstart moet worden vooraleer de functie " +@@ -411,21 +414,25 @@ msgstr "" + "scanoutbuffers steeds toewijst met uitdrukkelijke modifiers, indien dit " + "ondersteund wordt door het stuurprogramma. Hiervoor is opnieuw opstarten " + "vereist. • “autoclose-xwayland” — beëindigt Xwayland automatisch wanneer er " +-"geen relevante X11-cliënten meer zijn. Hiervoor is opnieuw opstarten vereist." ++"geen relevante X11-cliënten meer zijn. Hiervoor is opnieuw opstarten " ++"vereist. • “variable-refresh-rate” — laat mutter de verversingsfrequentie " ++"van het beeldscherm dynamisch aanpassen wanneer van toepassing en wanneer " ++"het beeldscherm, de GPU en het DRM-stuurprogramma dit ondersteunt. " ++"Instelbaar via Instellingen. Hiervoor is opnieuw opstarten vereist." + +-#: data/org.gnome.mutter.gschema.xml.in:137 ++#: data/org.gnome.mutter.gschema.xml.in:144 + msgid "Modifier to use to locate the pointer" + msgstr "Controletoets om de muispijl te lokaliseren" + +-#: data/org.gnome.mutter.gschema.xml.in:138 ++#: data/org.gnome.mutter.gschema.xml.in:145 + msgid "This key will initiate the “locate pointer” action." + msgstr "Deze sleutel activeert de actie ‘muispijl lokaliseren’." + +-#: data/org.gnome.mutter.gschema.xml.in:145 ++#: data/org.gnome.mutter.gschema.xml.in:152 + msgid "Timeout for check-alive ping" + msgstr "Time-out voor levenscontroleping" + +-#: data/org.gnome.mutter.gschema.xml.in:146 ++#: data/org.gnome.mutter.gschema.xml.in:153 + msgid "" + "Number of milliseconds a client has to respond to a ping request in order to " + "not be detected as frozen. Using 0 will disable the alive check completely." +@@ -434,15 +441,15 @@ msgstr "" + "verzoek om niet als bevroren beschouwd te worden. Stel dit in op 0 om de " + "levenscontrole volledig uit te schakelen." + +-#: data/org.gnome.mutter.gschema.xml.in:170 ++#: data/org.gnome.mutter.gschema.xml.in:177 + msgid "Switch monitor configurations" + msgstr "Tussen beeldschermconfiguraties schakelen" + +-#: data/org.gnome.mutter.gschema.xml.in:175 ++#: data/org.gnome.mutter.gschema.xml.in:182 + msgid "Rotates the built-in monitor configuration" + msgstr "Roteert de ingebouwde beeldschermconfiguratie" + +-#: data/org.gnome.mutter.gschema.xml.in:180 ++#: data/org.gnome.mutter.gschema.xml.in:187 + msgid "Cancel any active input capture session" + msgstr "Alle actieve sessies voor opvang van invoer annuleren" + +@@ -632,76 +639,76 @@ msgstr "%s %s" + msgid "Bell event" + msgstr "Bel-gebeurtenis" + +-#: src/core/display.c:733 ++#: src/core/display.c:734 + msgid "Privacy Screen Enabled" + msgstr "Privacyscherm ingeschakeld" + +-#: src/core/display.c:734 ++#: src/core/display.c:735 + msgid "Privacy Screen Disabled" + msgstr "Privacyscherm uitgeschakeld" + +-#: src/core/meta-context-main.c:594 ++#: src/core/meta-context-main.c:601 + msgid "Replace the running window manager" + msgstr "De huidige toepassing voor vensterbeheer vervangen" + +-#: src/core/meta-context-main.c:600 ++#: src/core/meta-context-main.c:607 + msgid "X Display to use" + msgstr "De te gebruiken X-weergave" + +-#: src/core/meta-context-main.c:606 ++#: src/core/meta-context-main.c:613 + msgid "Disable connection to session manager" + msgstr "Schakel de verbinding met het sessiebeheer uit" + +-#: src/core/meta-context-main.c:612 ++#: src/core/meta-context-main.c:619 + msgid "Specify session management ID" + msgstr "Bepaal de ID van het sessiebeheer" + +-#: src/core/meta-context-main.c:618 ++#: src/core/meta-context-main.c:625 + msgid "Initialize session from savefile" + msgstr "Initialiseer de sessie middels een opslagbestand" + +-#: src/core/meta-context-main.c:624 ++#: src/core/meta-context-main.c:631 + msgid "Make X calls synchronous" + msgstr "X-aanroepen synchroon maken" + +-#: src/core/meta-context-main.c:632 ++#: src/core/meta-context-main.c:639 + msgid "Run as a wayland compositor" + msgstr "Uitvoeren als een wayland compositor" + +-#: src/core/meta-context-main.c:638 ++#: src/core/meta-context-main.c:645 + msgid "Run as a nested compositor" + msgstr "Uitvoeren als een geneste compositor" + +-#: src/core/meta-context-main.c:644 ++#: src/core/meta-context-main.c:651 + msgid "Run wayland compositor without starting Xwayland" + msgstr "Wayland-compositor uitvoeren zonder Xwayland te starten" + +-#: src/core/meta-context-main.c:650 ++#: src/core/meta-context-main.c:657 + msgid "Specify Wayland display name to use" + msgstr "Bepaal de te gebruiken Wayland-weergavenaam" + +-#: src/core/meta-context-main.c:658 ++#: src/core/meta-context-main.c:665 + msgid "Run as a full display server, rather than nested" + msgstr "Uitvoeren als een volledige displayserver, in plaats van genest" + +-#: src/core/meta-context-main.c:663 ++#: src/core/meta-context-main.c:670 + msgid "Run as a headless display server" + msgstr "Uitvoeren als een ‘headless’ displayserver" + +-#: src/core/meta-context-main.c:668 ++#: src/core/meta-context-main.c:675 + msgid "Add persistent virtual monitor (WxH or WxH@R)" + msgstr "Blijvend virtueel beeldscherm toevoegen (BxH of BxH@V)" + +-#: src/core/meta-context-main.c:680 ++#: src/core/meta-context-main.c:687 + msgid "Run with X11 backend" + msgstr "Uitvoeren met X11-backend" + + # Onduidelijk of 'profile' hier een naamwoord of werkwoord is - Nathan +-#: src/core/meta-context-main.c:686 ++#: src/core/meta-context-main.c:693 + msgid "Profile performance using trace instrumentation" + msgstr "Prestaties profileren met trace-hulpmiddelen" + +-#: src/core/meta-context-main.c:692 ++#: src/core/meta-context-main.c:699 + msgid "Enable debug control D-Bus interface" + msgstr "Debugbesturing van D-Bus-interface inschakelen" + +@@ -737,7 +744,7 @@ msgstr "Versie-informatie tonen" + msgid "Mutter plugin to use" + msgstr "Te gebruiken Mutter-plug-in" + +-#: src/core/prefs.c:1843 ++#: src/core/prefs.c:1842 + #, c-format + msgid "Workspace %d" + msgstr "Werkblad %d" +@@ -746,7 +753,7 @@ msgstr "Werkblad %d" + msgid "Mutter was compiled without support for verbose mode" + msgstr "Mutter is gecompileerd zonder ondersteuning voor verbose-mode" + +-#: src/core/workspace.c:511 ++#: src/core/workspace.c:510 + msgid "Workspace switched" + msgstr "Werkblad gewisseld" + +@@ -776,7 +783,7 @@ msgstr "Scherm %d op beeldscherm ‘%s’ is ongeldig" + + #. This probably means that a non-WM compositor like xcompmgr is running; + #. * we have no way to get it to exit +-#: src/x11/meta-x11-display.c:2539 ++#: src/x11/meta-x11-display.c:2547 + #, c-format + msgid "" + "Another compositing manager is already running on screen %i on display “%s”." +@@ -789,7 +796,7 @@ msgstr "" + msgid "Format %s not supported" + msgstr "Formaat %s wordt niet ondersteund" + +-#: src/x11/window-props.c:524 ++#: src/x11/window-props.c:528 + #, c-format + msgid "%s (on %s)" + msgstr "%s (op %s)" +diff --git a/po/pa.po b/po/pa.po +index 29df49a3f..aeaed0f6d 100644 +--- a/po/pa.po ++++ b/po/pa.po +@@ -5,23 +5,23 @@ + # + # Amanpreet_Singh , 2004. + # Amanpreet Singh Alam , 2004. +-# A S Alam , 2006. ++# SPDX-FileCopyrightText: 2006, 2024 A S Alam + # A S Alam , 2007, 2009, 2010, 2011, 2021, 2023. + # ASB , 2007. + # Amanpreet Singh Alam , 2009, 2012, 2013, 2014, 2015, 2017, 2020. + msgid "" + msgstr "" + "Project-Id-Version: metacity.gnome-2-26\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" +-"POT-Creation-Date: 2023-07-15 01:02+0000\n" +-"PO-Revision-Date: 2023-09-02 08:25-0700\n" +-"Last-Translator: A S Alam \n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" ++"POT-Creation-Date: 2024-03-02 12:22+0000\n" ++"PO-Revision-Date: 2024-03-18 08:12-0500\n" ++"Last-Translator: A S Alam \n" + "Language-Team: Punjabi \n" + "Language: pa\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" +-"X-Generator: Lokalize 23.04.3\n" ++"X-Generator: Lokalize 23.08.5\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "\n" + +@@ -162,22 +162,18 @@ msgid "Switch to last workspace" + msgstr "ਪਿਛਲੇ ਵਰਕਸਪੇਸ ਵਿੱਚ ਜਾਓ" + + #: data/50-mutter-navigation.xml:131 +-#| msgid "Move to workspace on the left" + msgid "Switch to workspace on the left" + msgstr "ਖੱਬੇ ਪਾਸੇ ਆਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" + + #: data/50-mutter-navigation.xml:134 +-#| msgid "Move to workspace on the right" + msgid "Switch to workspace on the right" + msgstr "ਸੱਜੇ ਪਾਸੇ ਆਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" + + #: data/50-mutter-navigation.xml:138 +-#| msgid "Switch to workspace 1" + msgid "Switch to workspace above" + msgstr "ਉੱਤਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" + + #: data/50-mutter-navigation.xml:142 +-#| msgid "Switch to workspace 1" + msgid "Switch to workspace below" + msgstr "ਹੇਠਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" + +@@ -257,11 +253,11 @@ msgstr "ਵਿੰਡੋ ਖੜਵੇਂ ਰੂਪ ਵਿੱਚ ਵੱਧੋ-ਵ + msgid "Maximize window horizontally" + msgstr "ਵਿੰਡੋ ਲੇਟਵੇਂ ਰੂਪ ਵਿੱਚ ਵੱਧੋ-ਵੱਧ" + +-#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 ++#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 + msgid "View split on left" + msgstr "ਖੱਬੇ ਪਾਸੇ ਵੰਡ ਵੇਖੋ" + +-#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 ++#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 + msgid "View split on right" + msgstr "ਸੱਜੇ ਪਾਸੇ ਵੰਡ ਵੇਖੋ" + +@@ -404,13 +400,12 @@ msgstr "ਤਜਰਬੇ ਅਧੀਨ ਫ਼ੀਚਰਾਂ ਨੂੰ ਸਮਰ + #| "framebuffer” — makes mutter default to layout logical monitors in a " + #| "logical pixel coordinate space, while scaling monitor framebuffers " + #| "instead of window content, to manage HiDPI monitors. Does not require a " +-#| "restart. • “rt-scheduler” — makes mutter request a low priority real-time " +-#| "scheduling. The executable or user must have CAP_SYS_NICE. Requires a " +-#| "restart. • “dma-buf-screen-sharing\" — enables DMA buffered screen " +-#| "sharing. This is already enabled by default when using the i915 driver, " +-#| "but disabled for everything else. Requires a restart. • “autoclose-" +-#| "xwayland” — automatically terminates Xwayland if all relevant X11 clients " +-#| "are gone. Does not require a restart." ++#| "restart. • “kms-modifiers” — makes mutter always allocate scanout buffers " ++#| "with explicit modifiers, if supported by the driver. Requires a restart. " ++#| "• “rt-scheduler” — makes mutter request a low priority real-time " ++#| "scheduling. Requires a restart. • “autoclose-xwayland” — automatically " ++#| "terminates Xwayland if all relevant X11 clients are gone. Requires a " ++#| "restart." + msgid "" + "To enable experimental features, add the feature keyword to the list. " + "Whether the feature requires restarting the compositor depends on the given " +@@ -421,10 +416,11 @@ msgid "" + "space, while scaling monitor framebuffers instead of window content, to " + "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " + "mutter always allocate scanout buffers with explicit modifiers, if supported " +-"by the driver. Requires a restart. • “rt-scheduler” — makes mutter request a " +-"low priority real-time scheduling. Requires a restart. • “autoclose-" +-"xwayland” — automatically terminates Xwayland if all relevant X11 clients " +-"are gone. Requires a restart." ++"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " ++"terminates Xwayland if all relevant X11 clients are gone. Requires a " ++"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " ++"refresh rate of the monitor when applicable if supported by the monitor, GPU " ++"and DRM driver. Configurable in Settings. Requires a restart." + msgstr "" + "ਤਜਰਬੇ ਅਧੀਨ ਫ਼ੀਚਰ ਸਮਰੱਥ ਕਰਨ ਲਈ, ਫੀਚਰ ਕੀਵਰਡ ਸੂਚੀ ਵਿੱਚ ਜੋੜੋ। ਕੀ ਫ਼ੀਚਰ ਲਈ" + " ਕੰਪੋਜ਼ੀਟਰ ਮੁੜ-ਚਾਲੂ " +@@ -437,24 +433,29 @@ msgstr "" + "ਲਾਜ਼ੀਕਲ ਮਾਨੀਟਰਾਂ ਦੇ ਖਾਕੇ ਲਈ ਮਟਰ ਨੂੰ ਮੂਲ ਬਣਾਉਣਾ, ਜਦੋਂ ਕਿ HiDPI ਮਾਨੀਟਰਾਂ ਦੇ" + " ਇੰਤਜ਼ਾਮ ਲਈ ਵਿੰਡੋ " + "ਸਮੱਗਰੀ ਦੀ ਬਜਾਏ ਸਕੇਲਿੰਗ ਮਾਨੀਟਰ ਫਰੇਮਬਰਫ਼ ਹੋਣ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ। •" +-" “kms-modifiers” — ਜੇ ਡਰਾਇਵਰ ਰਾਹੀਂ ਸਹਾਇਕ ਹੋਵੇ ਤਾਂ ਮਟਰ ਖਾਸ ਸੋਧਕਾਂ ਲਈ ਸਕੈਨ-ਆਉਟ" +-" ਬਫ਼ਰ ਹਮੇਸ਼ਾਂ ਜਾਰੀ ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। • “autoclose-xwayland” — ਜੇ" +-" ਸਾਰੇ ਵਾਜਬ X11 ਕਲਾਈਂਟ ਖਤਮ ਹੋ ਜਾਣ ਤਾਂ ਆਪਣੇ-ਆਪ Xwayland ਨੂੰ ਖਤਮ ਕਰਦਾ ਹੈ।" +-" ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।" +- +-#: data/org.gnome.mutter.gschema.xml.in:141 ++" “kms-" ++"modifiers” — ਜੇ ਡਰਾਇਵਰ ਰਾਹੀਂ ਸਹਾਇਕ ਹੋਵੇ ਤਾਂ ਮਟਰ ਖਾਸ ਸੋਧਕਾਂ ਲਈ ਸਕੈਨ-ਆਉਟ ਬਫ਼ਰ" ++" ਹਮੇਸ਼ਾਂ ਜਾਰੀ " ++"ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। • “autoclose-xwayland” — ਜੇ ਸਾਰੇ ਵਾਜਬ X11" ++" ਕਲਾਈਂਟ " ++"ਖਤਮ ਹੋ ਜਾਣ ਤਾਂ ਆਪਣੇ-ਆਪ Xwayland ਨੂੰ ਖਤਮ ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। •" ++" “variable-refresh-rate” — ਜੇ ਮਾਨੀਟਰ, GPU ਅਤੇ DRM ਡਰਾਇਵਰ ਸਹਾਇਕ ਹੋਣ ਤਾਂ ਮਟਰ" ++" ਮਾਨੀਟਰ ਦੇ ਡਾਇਨੈਮਿਕ ਰੂਪ ਵਿੱਚ ਰੀ-ਫਰੈਸ਼ ਰੇਟ ਨੂੰ ਅਡਜੱਸਟ ਕਰ ਸਕਦਾ ਹੈ। ਸੈਟਿੰਗਾਂ ਵਿੱਚ" ++" ਸੰਰਚਨਾ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।" ++ ++#: data/org.gnome.mutter.gschema.xml.in:144 + msgid "Modifier to use to locate the pointer" + msgstr "ਪੁਆਇੰਟਰ ਲੱਭਣ ਲਈ ਵਰਤਣ ਵਾਸਤੇ ਸੋਧਣ" + +-#: data/org.gnome.mutter.gschema.xml.in:142 ++#: data/org.gnome.mutter.gschema.xml.in:145 + msgid "This key will initiate the “locate pointer” action." + msgstr "ਇਹ ਕੁੰਜੀ “ਪੁਆਇੰਟਰ ਲੱਭੋ“ ਕਾਰਵਾਈ ਸ਼ੁਰੂ ਕਰਦੀ ਹੈ।" + +-#: data/org.gnome.mutter.gschema.xml.in:149 ++#: data/org.gnome.mutter.gschema.xml.in:152 + msgid "Timeout for check-alive ping" + msgstr "ਚੈਕ-ਸਰਗਰਮ ਪਿੰਗ ਲਈ ਸਮਾਂ-ਅੰਤਰਾਲ" + +-#: data/org.gnome.mutter.gschema.xml.in:150 ++#: data/org.gnome.mutter.gschema.xml.in:153 + msgid "" + "Number of milliseconds a client has to respond to a ping request in order to " + "not be detected as frozen. Using 0 will disable the alive check completely." +@@ -464,15 +465,15 @@ msgstr "" + "ਜਕੜਿਆ ਨਾ ਖੋਜਿਆ ਜਾਵੇ। 0 ਵਰਤਣ ਨਾਲ ਸਰਗਰਮੀ ਦੀ ਜਾਂਚ ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਅਸਮਰੱਥ ਕੀਤਾ" + " ਜਾਵੇਗਾ।" + +-#: data/org.gnome.mutter.gschema.xml.in:174 ++#: data/org.gnome.mutter.gschema.xml.in:177 + msgid "Switch monitor configurations" + msgstr "ਮਾਨੀਟਰ ਸੰਰਚਨਾ ਨੂੰ ਬਦਲੋ" + +-#: data/org.gnome.mutter.gschema.xml.in:179 ++#: data/org.gnome.mutter.gschema.xml.in:182 + msgid "Rotates the built-in monitor configuration" + msgstr "ਬਿਲਟ-ਇਨ ਮਾਨੀਟਰ ਸੰਰਚਨਾ ਨੂੰ ਘੁੰਮਾਓ" + +-#: data/org.gnome.mutter.gschema.xml.in:184 ++#: data/org.gnome.mutter.gschema.xml.in:187 + msgid "Cancel any active input capture session" + msgstr "ਕਿਸੇ ਵੀ ਸਰਗਰਮ ਇਨਪੁਟ ਸਕਰੀਨ ਕੈਪਚਰ ਕਰਨ ਵਾਲੇ ਸ਼ੈਸ਼ਨ ਨੂੰ ਰੱਦ ਕਰੋ" + +@@ -614,7 +615,8 @@ msgstr "" + msgid "Allow X11 clients with a different endianness to connect to Xwayland" + msgstr "" + "ਵੱਖਰੀ ਏਂਡੀਨੈਸਸ (endianess) ਵਾਲੇ X11 ਵਾਲੇ ਕਲਾਈਂਟਾਂ ਨੂੰ Xwayland ਨਾਲ ਕਨੈਕਟ ਹੋਣ" +-" ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ" ++" ਦੀ ਇਜਾਜ਼ਤ " ++"ਦਿਓ" + + #: data/org.gnome.mutter.wayland.gschema.xml.in:131 + msgid "" +@@ -629,26 +631,26 @@ msgid "" + "take effect." + msgstr "" + +-#: src/backends/meta-monitor.c:253 ++#: src/backends/meta-monitor.c:251 + msgid "Built-in display" + msgstr "ਬਿਲਟ-ਇਨ ਡਿਸਪਲੇਅ" + +-#: src/backends/meta-monitor.c:280 ++#: src/backends/meta-monitor.c:278 + msgid "Unknown" + msgstr "ਅਣਜਾਣ" + +-#: src/backends/meta-monitor.c:282 ++#: src/backends/meta-monitor.c:280 + msgid "Unknown Display" + msgstr "ਅਣਜਾਣ ਡਿਸਪਲੇਅ" + +-#: src/backends/meta-monitor.c:290 ++#: src/backends/meta-monitor.c:288 + #, c-format + msgctxt "" + "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" + msgid "%s %s" + msgstr "%s %s" + +-#: src/backends/meta-monitor.c:298 ++#: src/backends/meta-monitor.c:296 + #, c-format + msgctxt "" + "This is a monitor vendor name followed by product/model name where size in " +@@ -660,78 +662,82 @@ msgstr "%s %s" + msgid "Bell event" + msgstr "ਘੰਟੀ ਈਵੈਂਟ" + +-#: src/core/display.c:718 ++#: src/core/display.c:734 + msgid "Privacy Screen Enabled" + msgstr "ਪਰਦੇਦਾਰੀ ਸਕਰੀਨ ਸਮਰੱਥ ਹੈ" + +-#: src/core/display.c:719 ++#: src/core/display.c:735 + msgid "Privacy Screen Disabled" + msgstr "ਪਰਦੇਦਾਰੀ ਸਕਰੀਨ ਅਸਮਰੱਥ ਹੈ" + +-#: src/core/meta-context-main.c:581 ++#: src/core/meta-context-main.c:601 + msgid "Replace the running window manager" + msgstr "ਚੱਲ ਰਹੇ ਵਿੰਡੋ ਮੈਨੇਜਰ ਨੂੰ ਬਦਲੋ" + +-#: src/core/meta-context-main.c:587 ++#: src/core/meta-context-main.c:607 + msgid "X Display to use" + msgstr "ਵਰਤਣ ਲਈ X ਡਿਸਪਲੇਅ" + +-#: src/core/meta-context-main.c:593 ++#: src/core/meta-context-main.c:613 + msgid "Disable connection to session manager" + msgstr "ਸ਼ੈਸ਼ਨ ਮੈਨੇਜਰ ਨਾਲ ਕੁਨੈਕਸ਼ਨ ਅਯੋਗ" + +-#: src/core/meta-context-main.c:599 ++#: src/core/meta-context-main.c:619 + msgid "Specify session management ID" + msgstr "ਸ਼ੈਸ਼ਨ ਪਰਬੰਧਨ ID ਦਿਓ" + +-#: src/core/meta-context-main.c:605 ++#: src/core/meta-context-main.c:625 + msgid "Initialize session from savefile" + msgstr "ਸੰਭਾਲੀ ਫਾਇਲ ਤੋਂ ਸ਼ੈਸ਼ਨ ਸ਼ੁਰੂ" + +-#: src/core/meta-context-main.c:611 ++#: src/core/meta-context-main.c:631 + msgid "Make X calls synchronous" + msgstr "X ਕਾਲ ਸੈਕਰੋਨਸ ਬਣਾਓ" + +-#: src/core/meta-context-main.c:619 ++#: src/core/meta-context-main.c:639 + msgid "Run as a wayland compositor" + msgstr "ਵੇਲੈਂਡ ਕੰਪੋਜ਼ਰ ਵਜੋਂ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:625 ++#: src/core/meta-context-main.c:645 + msgid "Run as a nested compositor" + msgstr "ਨੈਸਟਡ ਕੰਪੋਜ਼ਰ ਵਜੋਂ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:631 ++#: src/core/meta-context-main.c:651 + msgid "Run wayland compositor without starting Xwayland" + msgstr "Xwayland ਸ਼ੁਰੂ ਕੀਤੇ ਬਿਨਾਂ ਵੇਲੈਂਡ ਕੰਪੋਜ਼ੀਟਰ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:637 ++#: src/core/meta-context-main.c:657 + msgid "Specify Wayland display name to use" + msgstr "ਵਰਤਣ ਲਈ ਵੇਅਲੈਂਡ ਡਿਸਪਲੇਅ ਨਾਂ ਦਿਓ" + +-#: src/core/meta-context-main.c:645 ++#: src/core/meta-context-main.c:665 + msgid "Run as a full display server, rather than nested" + msgstr "ਅੰਦਰੂਨੀ ਰੂਪ ਵਿੱਚ ਚਲਾਉਣ ਦੀ ਬਜਾਏ ਪੂਰੇ ਡਿਸਪਲੇਅ ਸਰਵਰ ਵਜੋਂ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:650 ++#: src/core/meta-context-main.c:670 + msgid "Run as a headless display server" + msgstr "ਹੈੱਡਲੈੱਸ ਡਿਸਪਲੇਅ ਸਰਵਰ ਵਜੋਂ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:655 ++#: src/core/meta-context-main.c:675 + msgid "Add persistent virtual monitor (WxH or WxH@R)" + msgstr "ਸਥਿਰ ਵਰਚੁਅਲ ਮਾਨੀਟਰ ਜੋੜੋ (WxH or WxH@R)" + +-#: src/core/meta-context-main.c:667 ++#: src/core/meta-context-main.c:687 + msgid "Run with X11 backend" + msgstr "X11 ਬੈਕਐਡ ਨਾਲ ਚਲਾਓ" + +-#: src/core/meta-context-main.c:673 ++#: src/core/meta-context-main.c:693 + msgid "Profile performance using trace instrumentation" + msgstr "ਟਰੇਸ ਸਾਧਨ ਵਰਤ ਕੇ ਕਾਰਗੁਜ਼ਾਰੀ ਦਾ ਪਰੋਫ਼ਾਇਲ ਬਣਾਓ" + ++#: src/core/meta-context-main.c:699 ++msgid "Enable debug control D-Bus interface" ++msgstr "ਡੀਬੱਗ ਕੰਟਰੋਲ ਡੀ-ਬੱਸ ਇੰਟਰਫੇਸ ਸਮਰੱਥ ਕਰੋ" ++ + #. TRANSLATORS: This string refers to a button that switches between + #. * different modes. + #. +-#: src/core/meta-pad-action-mapper.c:861 ++#: src/core/meta-pad-action-mapper.c:826 + #, c-format + msgid "Mode Switch (Group %d)" + msgstr "ਮੋਡ ਬਦਲੋ (ਗਰੁੱਪ %d)" +@@ -739,16 +745,16 @@ msgstr "ਮੋਡ ਬਦਲੋ (ਗਰੁੱਪ %d)" + #. TRANSLATORS: This string refers to an action, cycles drawing tablets' + #. * mapping through the available outputs. + #. +-#: src/core/meta-pad-action-mapper.c:884 ++#: src/core/meta-pad-action-mapper.c:848 + msgid "Switch monitor" + msgstr "ਮਾਨੀਟਰ ਨੂੰ ਬਦਲੋ" + +-#: src/core/meta-pad-action-mapper.c:886 ++#: src/core/meta-pad-action-mapper.c:850 + msgid "Show on-screen help" + msgstr "ਆਨ-ਸਕਰੀਨ ਮਦਦ ਵੇਖੋ" + + #. Translators: this string will appear in Sysprof +-#: src/core/meta-profiler.c:111 src/core/meta-profiler.c:301 ++#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 + msgid "Compositor" + msgstr "ਕੰਪੋਜੀਟਰ" + +@@ -760,7 +766,7 @@ msgstr "ਵਰਜਨ ਛਾਪੋ" + msgid "Mutter plugin to use" + msgstr "ਵਰਤਣ ਲਈ ਮੁੱਟਰ ਪਲੱਗਇਨ" + +-#: src/core/prefs.c:1843 ++#: src/core/prefs.c:1842 + #, c-format + msgid "Workspace %d" + msgstr "ਵਰਕਸਪੇਸ %d" +@@ -769,17 +775,16 @@ msgstr "ਵਰਕਸਪੇਸ %d" + msgid "Mutter was compiled without support for verbose mode" + msgstr "ਮੱਟਰ, ਵਰਬੋਜ਼ ਮੋਡ ਲਈ ਸਹਾਰੇ ਤੋਂ ਬਿਨਾਂ ਕੰਪਾਇਲ ਹੋਇਆ" + +-#: src/core/workspace.c:541 +-#| msgid "Workspace %s%d" ++#: src/core/workspace.c:510 + msgid "Workspace switched" + msgstr "ਵਰਕਸਪੇਸ ਬਦਲਿਆ" + +-#: src/wayland/meta-wayland-tablet-pad.c:530 ++#: src/wayland/meta-wayland-tablet-pad.c:532 + #, c-format + msgid "Mode Switch: Mode %d" + msgstr "ਮੋਡ ਬਦਲੋ: ਮੋਡ %d" + +-#: src/x11/meta-x11-display.c:708 ++#: src/x11/meta-x11-display.c:723 + #, c-format + msgid "" + "Display “%s” already has a window manager; try using the --replace option to " +@@ -789,19 +794,19 @@ msgstr "" + " ਬਦਲਣ ਲਈ --replace ਚੋਣ " + "ਵਰਤ ਕੇ ਦੇਖੋ।" + +-#: src/x11/meta-x11-display.c:1073 ++#: src/x11/meta-x11-display.c:1088 + #, c-format + msgid "Failed to open X Window System display “%s”" + msgstr "X ਵਿੰਡੋ ਸਿਸਟਮ ਡਿਸਪਲੇਅ ”%s” ਨੂੰ ਖੋਲਣ ਵਿੱਚ ਅਸਮਰਥ" + +-#: src/x11/meta-x11-display.c:1219 ++#: src/x11/meta-x11-display.c:1268 + #, c-format + msgid "Screen %d on display “%s” is invalid" + msgstr "ਡਿਸਪਲੇਅ ”%2$s” ਉੱਤੇ ਸਕਰੀਨ %1$d ਗਲਤ ਹੈ" + + #. This probably means that a non-WM compositor like xcompmgr is running; + #. * we have no way to get it to exit +-#: src/x11/meta-x11-display.c:2550 ++#: src/x11/meta-x11-display.c:2538 + #, c-format + msgid "" + "Another compositing manager is already running on screen %i on display “%s”." +@@ -814,7 +819,7 @@ msgstr "" + msgid "Format %s not supported" + msgstr "ਫਾਰਮੈਟ %s ਸਹਾਇਕ ਨਹੀਂ ਹੈ" + +-#: src/x11/window-props.c:548 ++#: src/x11/window-props.c:528 + #, c-format + msgid "%s (on %s)" + msgstr "%s (%s ਉੱਤੇ)" +@@ -2463,3 +2468,4 @@ msgstr "%s (%s ਉੱਤੇ)" + + #~ msgid "Theme file %s did not contain a root element" + #~ msgstr "ਥੀਮ ਫਾਇਲ %s root ਐਲੀਮੈਂਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਨਹੀਂ ਸੀ" ++ +diff --git a/src/backends/meta-color-device.c b/src/backends/meta-color-device.c +index 3032d34c2..0d6cf40db 100644 +--- a/src/backends/meta-color-device.c ++++ b/src/backends/meta-color-device.c +@@ -963,56 +963,62 @@ static void + create_device_profile_from_edid (MetaColorDevice *color_device, + GTask *task) + { +- const MetaEdidInfo *edid_info; ++ const MetaEdidInfo *edid_info = ++ meta_monitor_get_edid_info (color_device->monitor); ++ GenerateProfileData *data = g_task_get_task_data (task); ++ g_autoptr (CdIcc) cd_icc = NULL; ++ g_autoptr (GBytes) bytes = NULL; ++ g_autofree char *file_md5_checksum = NULL; ++ g_autoptr (GError) error = NULL; + +- edid_info = meta_monitor_get_edid_info (color_device->monitor); + if (edid_info) + { +- g_autoptr (CdIcc) cd_icc = NULL; +- GBytes *bytes; +- g_autoptr (GError) error = NULL; +- GenerateProfileData *data = g_task_get_task_data (task); +- const char *file_path = data->file_path; +- g_autofree char *file_md5_checksum = NULL; +- + meta_topic (META_DEBUG_COLOR, + "Generating ICC profile for '%s' from EDID", + meta_color_device_get_id (color_device)); + + cd_icc = create_icc_profile_from_edid (color_device, +- edid_info, file_path, ++ edid_info, data->file_path, + &error); +- if (!cd_icc) +- { +- g_task_return_error (task, g_steal_pointer (&error)); +- g_object_unref (task); +- return; +- } ++ } ++ else ++ { ++ meta_topic (META_DEBUG_COLOR, ++ "Generating sRGB ICC profile for '%s' because EDID is missing", ++ meta_color_device_get_id (color_device)); + +- bytes = cd_icc_save_data (cd_icc, CD_ICC_SAVE_FLAGS_NONE, &error); +- if (!bytes) +- { +- g_task_return_error (task, g_steal_pointer (&error)); +- g_object_unref (task); +- return; +- } ++ cd_icc = cd_icc_new (); + +- file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes); +- cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, +- file_md5_checksum); ++ if (!cd_icc_create_default_full (cd_icc, ++ CD_ICC_LOAD_FLAGS_PRIMARIES, ++ &error)) ++ g_clear_object (&cd_icc); ++ } + +- data->color_calibration = +- meta_color_calibration_new (cd_icc, NULL); +- data->cd_icc = g_steal_pointer (&cd_icc); +- data->bytes = bytes; +- save_icc_profile (file_path, task); ++ if (!cd_icc) ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ g_object_unref (task); ++ return; + } +- else ++ ++ bytes = cd_icc_save_data (cd_icc, CD_ICC_SAVE_FLAGS_NONE, &error); ++ if (!bytes) + { +- g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, +- "No EDID available"); ++ g_task_return_error (task, g_steal_pointer (&error)); + g_object_unref (task); ++ return; + } ++ ++ file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes); ++ cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, ++ file_md5_checksum); ++ ++ data->color_calibration = ++ meta_color_calibration_new (cd_icc, NULL); ++ data->cd_icc = g_steal_pointer (&cd_icc); ++ data->bytes = g_steal_pointer (&bytes); ++ save_icc_profile (data->file_path, task); + } + + static void +diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c +index 7aa24439d..727e1a5f3 100644 +--- a/src/backends/meta-stage-impl.c ++++ b/src/backends/meta-stage-impl.c +@@ -774,6 +774,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, + { + g_autoptr (GError) error = NULL; + ++ clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED); ++ + if (meta_stage_impl_scanout_view (stage_impl, + stage_view, + scanout, +diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c +index 588caab28..83458cfe6 100644 +--- a/src/backends/native/meta-cursor-renderer-native.c ++++ b/src/backends/native/meta-cursor-renderer-native.c +@@ -454,7 +454,8 @@ create_cursor_drm_buffer_gbm (MetaGpuKms *gpu_kms, + GError **error) + { + struct gbm_bo *bo; +- uint8_t buf[4 * cursor_width * cursor_height]; ++ uint32_t bo_stride; ++ uint8_t *buf; + int i; + MetaDrmBufferFlags flags; + MetaDrmBufferGbm *buffer_gbm; +@@ -476,10 +477,16 @@ create_cursor_drm_buffer_gbm (MetaGpuKms *gpu_kms, + return NULL; + } + +- memset (buf, 0, sizeof (buf)); ++ bo_stride = gbm_bo_get_stride (bo); ++ buf = g_alloca0 (bo_stride * cursor_height); ++ + for (i = 0; i < height; i++) +- memcpy (buf + i * 4 * cursor_width, pixels + i * stride, width * 4); +- if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0) ++ { ++ memcpy (buf + i * bo_stride, ++ pixels + i * stride, ++ MIN (bo_stride, stride)); ++ } ++ if (gbm_bo_write (bo, buf, bo_stride * cursor_height) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Failed write to gbm_bo: %s", g_strerror (errno)); +diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c +index 161d43957..4ca8fb0f4 100644 +--- a/src/backends/native/meta-drm-buffer-gbm.c ++++ b/src/backends/native/meta-drm-buffer-gbm.c +@@ -186,7 +186,7 @@ lock_front_buffer (MetaDrmBufferGbm *buffer_gbm, + return FALSE; + } + +- return meta_drm_buffer_gbm_ensure_fb_id (META_DRM_BUFFER (buffer_gbm), error); ++ return TRUE; + } + + MetaDrmBufferGbm * +diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c +index b15eee14d..05bc89e83 100644 +--- a/src/backends/native/meta-kms-impl-device.c ++++ b/src/backends/native/meta-kms-impl-device.c +@@ -1559,9 +1559,11 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, + meta_kms_update_merge_from (crtc_frame->pending_update, update); + meta_kms_update_free (update); + update = g_steal_pointer (&crtc_frame->pending_update); +- disarm_crtc_frame_deadline_timer (crtc_frame); + } + ++ if (crtc_frame->deadline.armed) ++ disarm_crtc_frame_deadline_timer (crtc_frame); ++ + meta_kms_device_handle_flush (priv->device, latch_crtc); + + feedback = do_process (impl_device, latch_crtc, update, flags); +diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c +index 795008b21..70d1e792c 100644 +--- a/src/backends/native/meta-kms.c ++++ b/src/backends/native/meta-kms.c +@@ -63,6 +63,8 @@ struct _MetaKms + int kernel_thread_inhibit_count; + + MetaKmsCursorManager *cursor_manager; ++ ++ gboolean shutting_down; + }; + + G_DEFINE_TYPE (MetaKms, meta_kms, META_TYPE_THREAD) +@@ -354,6 +356,7 @@ static void + on_prepare_shutdown (MetaBackend *backend, + MetaKms *kms) + { ++ kms->shutting_down = TRUE; + meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); + meta_thread_flush_callbacks (META_THREAD (kms)); + +@@ -408,6 +411,12 @@ meta_kms_new (MetaBackend *backend, + return kms; + } + ++gboolean ++meta_kms_is_shutting_down (MetaKms *kms) ++{ ++ return kms->shutting_down; ++} ++ + static void + meta_kms_finalize (GObject *object) + { +diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h +index 743401406..f6b19520b 100644 +--- a/src/backends/native/meta-kms.h ++++ b/src/backends/native/meta-kms.h +@@ -60,6 +60,8 @@ MetaKmsDevice * meta_kms_create_device (MetaKms *kms, + MetaKmsDeviceFlag flags, + GError **error); + ++gboolean meta_kms_is_shutting_down (MetaKms *kms); ++ + MetaKms * meta_kms_new (MetaBackend *backend, + MetaKmsFlags flags, + GError **error); +diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c +index 086e217cb..9836663d0 100644 +--- a/src/backends/native/meta-onscreen-native.c ++++ b/src/backends/native/meta-onscreen-native.c +@@ -76,7 +76,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState + + struct { + MetaDrmBufferDumb *current_dumb_fb; +- MetaDrmBufferDumb *dumb_fbs[2]; ++ MetaDrmBufferDumb *dumb_fbs[3]; + } cpu; + + gboolean noted_primary_gpu_copy_ok; +@@ -98,9 +98,13 @@ struct _MetaOnscreenNative + struct { + struct gbm_surface *surface; + MetaDrmBuffer *current_fb; ++ MetaDrmBuffer *posted_fb; + MetaDrmBuffer *next_fb; ++ MetaDrmBuffer *stalled_fb; + CoglScanout *current_scanout; ++ CoglScanout *posted_scanout; + CoglScanout *next_scanout; ++ CoglScanout *stalled_scanout; + } gbm; + + #ifdef HAVE_EGL_DEVICE +@@ -125,6 +129,16 @@ struct _MetaOnscreenNative + gulong privacy_screen_changed_handler_id; + gulong color_space_changed_handler_id; + gulong hdr_metadata_changed_handler_id; ++ ++ gboolean needs_flush; ++ ++ unsigned int swaps_pending; ++ ++ struct { ++ int *rectangles; /* 4 x n_rectangles */ ++ int n_rectangles; ++ ClutterFrame *frame; ++ } next_post; + }; + + G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, +@@ -132,44 +146,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, + + static GQuark blit_source_quark = 0; + ++static void ++try_post_latest_swap (CoglOnscreen *onscreen); ++ ++static void ++post_finish_frame (MetaOnscreenNative *onscreen_native, ++ MetaKmsUpdate *kms_update); ++ + static gboolean + init_secondary_gpu_state (MetaRendererNative *renderer_native, + CoglOnscreen *onscreen, + GError **error); + +-static void +-free_current_bo (CoglOnscreen *onscreen) +-{ +- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); +- +- g_clear_object (&onscreen_native->gbm.current_fb); +- g_clear_object (&onscreen_native->gbm.current_scanout); +-} +- + static void + meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) + { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + +- if (!onscreen_native->gbm.next_fb) ++ if (!onscreen_native->gbm.posted_fb) + return; + +- free_current_bo (onscreen); ++ g_set_object (&onscreen_native->gbm.current_fb, ++ onscreen_native->gbm.posted_fb); ++ g_clear_object (&onscreen_native->gbm.posted_fb); + +- g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); +- g_clear_object (&onscreen_native->gbm.next_fb); + g_set_object (&onscreen_native->gbm.current_scanout, +- onscreen_native->gbm.next_scanout); +- g_clear_object (&onscreen_native->gbm.next_scanout); ++ onscreen_native->gbm.posted_scanout); ++ g_clear_object (&onscreen_native->gbm.posted_scanout); + } + + static void +-meta_onscreen_native_clear_next_fb (CoglOnscreen *onscreen) ++meta_onscreen_native_clear_posted_fb (CoglOnscreen *onscreen) + { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + +- g_clear_object (&onscreen_native->gbm.next_fb); +- g_clear_object (&onscreen_native->gbm.next_scanout); ++ g_clear_object (&onscreen_native->gbm.posted_fb); ++ g_clear_object (&onscreen_native->gbm.posted_scanout); + } + + static void +@@ -207,7 +219,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) + + info = cogl_onscreen_pop_head_frame_info (onscreen); + +- g_assert (!cogl_onscreen_peek_head_frame_info (onscreen)); ++ g_return_if_fail (info); + + _cogl_onscreen_notify_frame_sync (onscreen, info); + _cogl_onscreen_notify_complete (onscreen, info); +@@ -243,6 +255,7 @@ notify_view_crtc_presented (MetaRendererView *view, + + meta_onscreen_native_notify_frame_complete (onscreen); + meta_onscreen_native_swap_drm_fb (onscreen); ++ try_post_latest_swap (onscreen); + } + + static void +@@ -292,15 +305,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, + CoglFramebuffer *framebuffer = + clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); +- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + CoglFrameInfo *frame_info; + + frame_info = cogl_onscreen_peek_head_frame_info (onscreen); + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + +- g_warn_if_fail (!onscreen_native->gbm.next_fb); +- + meta_onscreen_native_notify_frame_complete (onscreen); ++ try_post_latest_swap (onscreen); + } + + static void +@@ -350,7 +361,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + + meta_onscreen_native_notify_frame_complete (onscreen); +- meta_onscreen_native_clear_next_fb (onscreen); ++ meta_onscreen_native_clear_posted_fb (onscreen); ++ try_post_latest_swap (onscreen); + } + + static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { +@@ -411,18 +423,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, + } + #endif /* HAVE_EGL_DEVICE */ + +-void +-meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) ++static void ++drop_stalled_swap (CoglOnscreen *onscreen) + { + CoglFrameInfo *frame_info; ++ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + +- meta_onscreen_native_swap_drm_fb (onscreen); ++ /* Remember we can't compare stalled_fb because it's not used by ++ * META_RENDERER_NATIVE_MODE_EGL_DEVICE. So we judge stalled to be whenever ++ * swaps_pending > 1. ++ */ ++ if (onscreen_native->swaps_pending <= 1) ++ return; ++ ++ onscreen_native->swaps_pending--; ++ ++ g_clear_object (&onscreen_native->gbm.stalled_fb); ++ g_clear_object (&onscreen_native->gbm.stalled_scanout); + + frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + meta_onscreen_native_notify_frame_complete (onscreen); + } + ++void ++meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) ++{ ++ drop_stalled_swap (onscreen); ++ ++ /* If the monitor just woke up and the shell is fully idle (has nothing ++ * more to swap) then we just woke to an indefinitely black screen. Let's ++ * fix that using the last swap (which is never classified as "stalled"). ++ */ ++ try_post_latest_swap (onscreen); ++} ++ + static void + apply_transform (MetaCrtcKms *crtc_kms, + MetaKmsPlaneAssignment *kms_plane_assignment, +@@ -506,6 +541,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, + MetaGpuKms *gpu_kms; + MetaDrmBuffer *buffer; + MetaKmsPlaneAssignment *plane_assignment; ++ graphene_rect_t src_rect; ++ MtkRectangle dst_rect; + + COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, + "Meta::OnscreenNative::flip_crtc()"); +@@ -519,16 +556,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, + switch (renderer_gpu_data->mode) + { + case META_RENDERER_NATIVE_MODE_GBM: +- graphene_rect_t src_rect; +- MtkRectangle dst_rect; ++ g_set_object (&onscreen_native->gbm.posted_fb, ++ onscreen_native->gbm.next_fb); ++ g_clear_object (&onscreen_native->gbm.next_fb); ++ ++ buffer = onscreen_native->gbm.posted_fb; + +- buffer = onscreen_native->gbm.next_fb; ++ g_set_object (&onscreen_native->gbm.posted_scanout, ++ onscreen_native->gbm.next_scanout); ++ g_clear_object (&onscreen_native->gbm.next_scanout); + +- if (onscreen_native->gbm.next_scanout) ++ if (onscreen_native->gbm.posted_scanout) + { +- cogl_scanout_get_src_rect (onscreen_native->gbm.next_scanout, ++ cogl_scanout_get_src_rect (onscreen_native->gbm.posted_scanout, + &src_rect); +- cogl_scanout_get_dst_rect (onscreen_native->gbm.next_scanout, ++ cogl_scanout_get_dst_rect (onscreen_native->gbm.posted_scanout, + &dst_rect); + } + else +@@ -919,12 +961,17 @@ static MetaDrmBufferDumb * + secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) + { + MetaDrmBufferDumb *current_dumb_fb; ++ const int n_dumb_fbs = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); ++ int i; + + current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb; +- if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0]) +- return secondary_gpu_state->cpu.dumb_fbs[1]; +- else +- return secondary_gpu_state->cpu.dumb_fbs[0]; ++ for (i = 0; i < n_dumb_fbs; i++) ++ { ++ if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[i]) ++ return secondary_gpu_state->cpu.dumb_fbs[(i + 1) % n_dumb_fbs]; ++ } ++ ++ return secondary_gpu_state->cpu.dumb_fbs[0]; + } + + static MetaDrmBuffer * +@@ -1256,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, + g_warning ("Page flip failed: %s", error->message); + + frame_info = cogl_onscreen_peek_head_frame_info (onscreen); +- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + +- meta_onscreen_native_notify_frame_complete (onscreen); +- meta_onscreen_native_clear_next_fb (onscreen); ++ /* After resuming from suspend, drop_stalled_swap might have done this ++ * already and emptied the frame_info queue. ++ */ ++ if (frame_info) ++ { ++ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; ++ meta_onscreen_native_notify_frame_complete (onscreen); ++ } ++ ++ meta_onscreen_native_clear_posted_fb (onscreen); + } + + static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { +@@ -1280,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; + MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; + MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; +- MetaRenderer *renderer = META_RENDERER (renderer_native); +- MetaBackend *backend = meta_renderer_get_backend (renderer); +- MetaMonitorManager *monitor_manager = +- meta_backend_get_monitor_manager (backend); + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); ++ MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; + MetaGpuKms *render_gpu = onscreen_native->render_gpu; + MetaDeviceFile *render_device_file; + ClutterFrame *frame = user_data; +- MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); +- MetaKmsUpdate *kms_update; + CoglOnscreenClass *parent_class; ++ gboolean create_timestamp_query = TRUE; + gboolean egl_context_changed = FALSE; +- MetaPowerSave power_save_mode; + g_autoptr (GError) error = NULL; + MetaDrmBufferFlags buffer_flags; + MetaDrmBufferGbm *buffer_gbm; + g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL; + g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; +- MetaKmsCrtc *kms_crtc; +- MetaKmsDevice *kms_device; ++ size_t rectangles_size; + + COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, + "Meta::OnscreenNative::swap_buffers_with_damage()"); + ++ if (meta_is_topic_enabled (META_DEBUG_KMS)) ++ { ++ unsigned int frames_pending = ++ cogl_onscreen_count_pending_frames (onscreen); ++ ++ meta_topic (META_DEBUG_KMS, ++ "Swap buffers: %u frames pending (%s-buffering)", ++ frames_pending, ++ frames_pending == 1 ? "double" : ++ frames_pending == 2 ? "triple" : ++ "?"); ++ } ++ + secondary_gpu_fb = + update_secondary_gpu_state_pre_swap_buffers (onscreen, + rectangles, + n_rectangles); + ++ secondary_gpu_state = onscreen_native->secondary_gpu_state; ++ if (secondary_gpu_state) ++ { ++ MetaRendererNativeGpuData *secondary_gpu_data; ++ ++ secondary_gpu_data = ++ meta_renderer_native_get_gpu_data (renderer_native, ++ secondary_gpu_state->gpu_kms); ++ if (secondary_gpu_data->secondary.copy_mode == ++ META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU) ++ create_timestamp_query = FALSE; ++ } ++ ++ if (create_timestamp_query) ++ cogl_onscreen_egl_maybe_create_timestamp_query (onscreen, frame_info); ++ + parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); + parent_class->swap_buffers_with_damage (onscreen, + rectangles, +@@ -1362,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + switch (renderer_gpu_data->mode) + { + case META_RENDERER_NATIVE_MODE_GBM: +- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); ++ if (onscreen_native->gbm.next_fb != NULL) ++ { ++ g_warn_if_fail (onscreen_native->gbm.stalled_fb == NULL); ++ drop_stalled_swap (onscreen); ++ g_assert (onscreen_native->gbm.stalled_fb == NULL); ++ onscreen_native->gbm.stalled_fb = ++ g_steal_pointer (&onscreen_native->gbm.next_fb); ++ onscreen_native->gbm.stalled_scanout = ++ g_steal_pointer (&onscreen_native->gbm.next_scanout); ++ } ++ + if (onscreen_native->secondary_gpu_state) + g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); + else + g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb); ++ ++ if (!meta_drm_buffer_ensure_fb_id (onscreen_native->gbm.next_fb, &error)) ++ { ++ g_warning ("Failed to ensure KMS FB ID on %s: %s", ++ meta_device_file_get_path (render_device_file), ++ error->message); ++ ++ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; ++ meta_onscreen_native_notify_frame_complete (onscreen); ++ return; ++ } + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + break; +@@ -1376,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + #endif + } + ++ clutter_frame_set_result (frame, ++ CLUTTER_FRAME_RESULT_PENDING_PRESENTED); ++ + /* + * If we changed EGL context, cogl will have the wrong idea about what is + * current, making it fail to set it when it needs to. Avoid that by making +@@ -1385,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + if (egl_context_changed) + _cogl_winsys_egl_ensure_current (cogl_display); + +- kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); +- kms_device = meta_kms_crtc_get_device (kms_crtc); ++ rectangles_size = n_rectangles * 4 * sizeof (int); ++ onscreen_native->next_post.rectangles = ++ g_realloc (onscreen_native->next_post.rectangles, rectangles_size); ++ memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size); ++ onscreen_native->next_post.n_rectangles = n_rectangles; ++ ++ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); ++ onscreen_native->next_post.frame = clutter_frame_ref (frame); ++ ++ onscreen_native->swaps_pending++; ++ try_post_latest_swap (onscreen); ++} ++ ++static void ++try_post_latest_swap (CoglOnscreen *onscreen) ++{ ++ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); ++ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); ++ CoglRenderer *cogl_renderer = cogl_context->display->renderer; ++ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; ++ MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; ++ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; ++ MetaRenderer *renderer = META_RENDERER (renderer_native); ++ MetaBackend *backend = meta_renderer_get_backend (renderer); ++ MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); ++ MetaKms *kms = meta_backend_native_get_kms (backend_native); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); ++ MetaPowerSave power_save_mode; ++ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); ++ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); ++ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); ++ MetaKmsUpdate *kms_update; ++ g_autoptr (MetaKmsFeedback) kms_feedback = NULL; ++ g_autoptr (ClutterFrame) frame = NULL; ++ MetaFrameNative *frame_native; ++ ++ if (onscreen_native->next_post.frame == NULL || ++ onscreen_native->view == NULL || ++ meta_kms_is_shutting_down (kms)) ++ return; + + power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); + if (power_save_mode == META_POWER_SAVE_ON) + { ++ unsigned int frames_pending = ++ cogl_onscreen_count_pending_frames (onscreen); ++ unsigned int posts_pending; ++ ++ g_assert (frames_pending >= onscreen_native->swaps_pending); ++ posts_pending = frames_pending - onscreen_native->swaps_pending; ++ if (posts_pending > 0) ++ return; /* wait for the next frame notification and then try again */ ++ ++ frame = g_steal_pointer (&onscreen_native->next_post.frame); ++ frame_native = meta_frame_native_from_frame (frame); ++ ++ if (onscreen_native->swaps_pending == 0) ++ { ++ if (frame_native) ++ { ++ kms_update = meta_frame_native_steal_kms_update (frame_native); ++ if (kms_update) ++ post_finish_frame (onscreen_native, kms_update); ++ } ++ return; ++ } ++ ++ drop_stalled_swap (onscreen); ++ onscreen_native->swaps_pending--; ++ + kms_update = meta_frame_native_ensure_kms_update (frame_native, + kms_device); + meta_kms_update_add_result_listener (kms_update, +@@ -1405,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + onscreen_native->crtc, + kms_update, + META_KMS_ASSIGN_PLANE_FLAG_NONE, +- rectangles, +- n_rectangles); ++ onscreen_native->next_post.rectangles, ++ onscreen_native->next_post.n_rectangles); + } + else + { + meta_renderer_native_queue_power_save_page_flip (renderer_native, + onscreen); +- clutter_frame_set_result (frame, +- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + return; + } + +@@ -1433,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + kms_update = meta_frame_native_steal_kms_update (frame_native); + meta_renderer_native_queue_mode_set_update (renderer_native, + kms_update); +- clutter_frame_set_result (frame, +- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + return; + } + else if (meta_renderer_native_has_pending_mode_set (renderer_native)) +@@ -1448,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + + meta_frame_native_steal_kms_update (frame_native); + meta_renderer_native_post_mode_set_updates (renderer_native); +- clutter_frame_set_result (frame, +- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + return; + } + break; +@@ -1465,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + kms_update); + + meta_renderer_native_post_mode_set_updates (renderer_native); +- clutter_frame_set_result (frame, +- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + return; + } + break; +@@ -1481,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + kms_update = meta_frame_native_steal_kms_update (frame_native); + meta_kms_device_post_update (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); +- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + } + + gboolean +@@ -1552,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, + + g_warning ("Direct scanout page flip failed: %s", error->message); + +- cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout, ++ cogl_scanout_notify_failed (onscreen_native->gbm.posted_scanout, + onscreen); + clutter_stage_view_add_redraw_clip (view, NULL); + clutter_stage_view_schedule_update_now (view); +@@ -1562,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + + meta_onscreen_native_notify_frame_complete (onscreen); +- meta_onscreen_native_clear_next_fb (onscreen); ++ meta_onscreen_native_clear_posted_fb (onscreen); + } + + static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { +@@ -1614,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, + return FALSE; + } + ++ /* Our direct scanout frame counts as 1, so more than that means we would ++ * be jumping the queue (and post would fail). ++ */ ++ if (cogl_onscreen_count_pending_frames (onscreen) > 1) ++ { ++ g_set_error_literal (error, ++ COGL_SCANOUT_ERROR, ++ COGL_SCANOUT_ERROR_INHIBITED, ++ "Direct scanout is inhibited during triple buffering"); ++ return FALSE; ++ } ++ + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + render_gpu); + +@@ -1729,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, + ClutterFrame *frame) + { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); +- MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); +- MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + +- meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), +- kms_crtc); + maybe_update_frame_sync (onscreen_native, frame); + } + +@@ -1849,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + MetaKmsUpdate *kms_update; ++ unsigned int frames_pending = cogl_onscreen_count_pending_frames (onscreen); ++ unsigned int swaps_pending = onscreen_native->swaps_pending; ++ unsigned int posts_pending = frames_pending - swaps_pending; + +- kms_update = meta_frame_native_steal_kms_update (frame_native); +- if (!kms_update) ++ onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, ++ kms_crtc); ++ ++ if (!meta_frame_native_has_kms_update (frame_native)) + { +- if (meta_kms_device_handle_flush (kms_device, kms_crtc)) +- { +- kms_update = meta_kms_update_new (kms_device); +- meta_kms_update_set_flushing (kms_update, kms_crtc); +- } +- else ++ if (!onscreen_native->needs_flush || posts_pending) + { + clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); + return; + } + } + ++ if (posts_pending && !swaps_pending) ++ { ++ g_return_if_fail (meta_frame_native_has_kms_update (frame_native)); ++ g_warn_if_fail (onscreen_native->next_post.frame == NULL); ++ ++ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); ++ onscreen_native->next_post.frame = clutter_frame_ref (frame); ++ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); ++ return; ++ } ++ ++ kms_update = meta_frame_native_steal_kms_update (frame_native); ++ ++ if (posts_pending && swaps_pending) ++ { ++ MetaFrameNative *older_frame_native; ++ MetaKmsUpdate *older_kms_update; ++ ++ g_return_if_fail (kms_update); ++ g_return_if_fail (onscreen_native->next_post.frame != NULL); ++ ++ older_frame_native = ++ meta_frame_native_from_frame (onscreen_native->next_post.frame); ++ older_kms_update = ++ meta_frame_native_ensure_kms_update (older_frame_native, kms_device); ++ meta_kms_update_merge_from (older_kms_update, kms_update); ++ meta_kms_update_free (kms_update); ++ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); ++ return; ++ } ++ ++ if (!kms_update) ++ { ++ kms_update = meta_kms_update_new (kms_device); ++ g_warn_if_fail (onscreen_native->needs_flush); ++ } ++ ++ if (onscreen_native->needs_flush) ++ { ++ meta_kms_update_set_flushing (kms_update, kms_crtc); ++ onscreen_native->needs_flush = FALSE; ++ } ++ ++ post_finish_frame (onscreen_native, kms_update); ++ ++ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); ++} ++ ++static void ++post_finish_frame (MetaOnscreenNative *onscreen_native, ++ MetaKmsUpdate *kms_update) ++{ ++ MetaCrtc *crtc = onscreen_native->crtc; ++ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); ++ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); ++ g_autoptr (MetaKmsFeedback) kms_feedback = NULL; ++ + meta_kms_update_add_result_listener (kms_update, + &finish_frame_result_listener_vtable, + NULL, +@@ -1887,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, + meta_kms_update_set_flushing (kms_update, kms_crtc); + meta_kms_device_post_update (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); +- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); ++} ++ ++void ++meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen) ++{ ++ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); ++ ++ onscreen_native->swaps_pending = 0; ++ ++ g_clear_object (&onscreen_native->gbm.stalled_fb); ++ g_clear_object (&onscreen_native->gbm.stalled_scanout); ++ g_clear_object (&onscreen_native->gbm.next_fb); ++ g_clear_object (&onscreen_native->gbm.next_scanout); + } + + static gboolean +@@ -2802,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) + { + case META_RENDERER_NATIVE_MODE_GBM: + g_clear_object (&onscreen_native->gbm.next_fb); ++ g_clear_object (&onscreen_native->gbm.posted_fb); ++ g_clear_object (&onscreen_native->gbm.current_fb); + g_clear_object (&onscreen_native->gbm.next_scanout); +- free_current_bo (onscreen); ++ g_clear_object (&onscreen_native->gbm.posted_scanout); ++ g_clear_object (&onscreen_native->gbm.current_scanout); + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); +@@ -2837,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) + + g_clear_object (&onscreen_native->output); + g_clear_object (&onscreen_native->crtc); ++ ++ g_clear_pointer (&onscreen_native->next_post.rectangles, g_free); ++ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); ++ onscreen_native->next_post.n_rectangles = 0; + } + + static void +diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h +index 0e1193325..e30357d19 100644 +--- a/src/backends/native/meta-onscreen-native.h ++++ b/src/backends/native/meta-onscreen-native.h +@@ -48,6 +48,8 @@ void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); + gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, + CoglScanout *scanout); + ++void meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen); ++ + void meta_onscreen_native_set_view (CoglOnscreen *onscreen, + MetaRendererView *view); + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index aa76d018c..3c22b4e86 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -731,12 +731,18 @@ static gboolean + dummy_power_save_page_flip_cb (gpointer user_data) + { + MetaRendererNative *renderer_native = user_data; ++ GList *old_list = ++ g_steal_pointer (&renderer_native->power_save_page_flip_onscreens); + +- g_list_foreach (renderer_native->power_save_page_flip_onscreens, ++ g_list_foreach (old_list, + (GFunc) meta_onscreen_native_dummy_power_save_page_flip, + NULL); +- g_clear_list (&renderer_native->power_save_page_flip_onscreens, ++ g_clear_list (&old_list, + g_object_unref); ++ ++ if (renderer_native->power_save_page_flip_onscreens != NULL) ++ return G_SOURCE_CONTINUE; ++ + renderer_native->power_save_page_flip_source_id = 0; + + return G_SOURCE_REMOVE; +@@ -748,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na + { + const unsigned int timeout_ms = 100; + ++ if (g_list_find (renderer_native->power_save_page_flip_onscreens, onscreen)) ++ return; ++ + if (!renderer_native->power_save_page_flip_source_id) + { + renderer_native->power_save_page_flip_source_id = +@@ -1529,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) + } + } + ++static void ++discard_pending_swaps (MetaRenderer *renderer) ++{ ++ GList *views = meta_renderer_get_views (renderer);; ++ GList *l; ++ ++ for (l = views; l; l = l->next) ++ { ++ ClutterStageView *stage_view = l->data; ++ CoglFramebuffer *fb = clutter_stage_view_get_onscreen (stage_view); ++ CoglOnscreen *onscreen; ++ ++ if (!COGL_IS_ONSCREEN (fb)) ++ continue; ++ ++ onscreen = COGL_ONSCREEN (fb); ++ meta_onscreen_native_discard_pending_swaps (onscreen); ++ } ++} ++ + static void + meta_renderer_native_rebuild_views (MetaRenderer *renderer) + { +@@ -1539,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) + MetaRendererClass *parent_renderer_class = + META_RENDERER_CLASS (meta_renderer_native_parent_class); + ++ discard_pending_swaps (renderer); + meta_kms_discard_pending_page_flips (kms); + g_hash_table_remove_all (renderer_native->mode_set_updates); + +diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c +index 41b78ec18..02eccc77d 100644 +--- a/src/backends/x11/nested/meta-stage-x11-nested.c ++++ b/src/backends/x11/nested/meta-stage-x11-nested.c +@@ -186,6 +186,8 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window, + } + + frame_info = cogl_frame_info_new (context, 0); ++ cogl_onscreen_egl_maybe_create_timestamp_query (stage_x11->onscreen, ++ frame_info); + cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info, frame); + + if (!clutter_frame_has_result (frame)) +diff --git a/src/compositor/edge-resistance.c b/src/compositor/edge-resistance.c +index f3005714b..338886255 100644 +--- a/src/compositor/edge-resistance.c ++++ b/src/compositor/edge-resistance.c +@@ -29,17 +29,6 @@ + #include "core/meta-workspace-manager-private.h" + #include "core/workspace-private.h" + +-/* A simple macro for whether a given window's edges are potentially +- * relevant for resistance/snapping during a move/resize operation +- */ +-#define WINDOW_EDGES_RELEVANT(window, display) \ +- meta_window_should_be_showing (window) && \ +- (!meta_compositor_get_current_window_drag (display->compositor) || \ +- window != meta_window_drag_get_window (meta_compositor_get_current_window_drag (display->compositor))) && \ +- window->type != META_WINDOW_DESKTOP && \ +- window->type != META_WINDOW_MENU && \ +- window->type != META_WINDOW_SPLASHSCREEN +- + typedef struct _MetaEdgeResistanceData MetaEdgeResistanceData; + + struct _MetaEdgeResistanceData +@@ -52,6 +41,29 @@ struct _MetaEdgeResistanceData + + static GQuark edge_resistance_data_quark = 0; + ++static gboolean ++is_window_relevant_for_edges (MetaWindow *window) ++{ ++ MetaWindowDrag *drag; ++ ++ if (!meta_window_should_be_showing (window)) ++ return FALSE; ++ ++ drag = meta_compositor_get_current_window_drag (window->display->compositor); ++ if (drag && window == meta_window_drag_get_window (drag)) ++ return FALSE; ++ ++ switch (window->type) ++ { ++ case META_WINDOW_DESKTOP: ++ case META_WINDOW_MENU: ++ case META_WINDOW_SPLASHSCREEN: ++ return FALSE; ++ default: ++ return TRUE; ++ } ++} ++ + /* !WARNING!: this function can return invalid indices (namely, either -1 or + * edges->len); this is by design, but you need to remember this. + */ +@@ -879,12 +891,13 @@ static MetaEdgeResistanceData * + compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + { + MetaEdgeResistanceData *edge_data; +- GList *stacked_windows; +- GList *cur_window_iter; +- GList *edges; ++ GList *l; + /* Lists of window positions (rects) and their relative stacking positions */ + int stack_position; +- GSList *obscuring_windows, *window_stacking; ++ g_autoslist (MtkRectangle) obscuring_windows = NULL; ++ g_autoptr (GList) stacked_windows = NULL; ++ g_autoptr (GSList) window_stacking = NULL; ++ g_autoptr (GList) edges = NULL; + /* The portions of the above lists that still remain at the stacking position + * in the layer that we are working on + */ +@@ -910,16 +923,16 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + * those below it instead of going both ways, we also need to keep a + * counter list. Messy, I know. + */ +- obscuring_windows = window_stacking = NULL; +- cur_window_iter = stacked_windows; + stack_position = 0; +- while (cur_window_iter != NULL) ++ for (l = stacked_windows; l; l = l->next) + { +- MetaWindow *cur_window = cur_window_iter->data; +- if (WINDOW_EDGES_RELEVANT (cur_window, display)) ++ MetaWindow *cur_window = l->data; ++ ++ if (is_window_relevant_for_edges (cur_window)) + { + MtkRectangle *new_rect; +- new_rect = g_new (MtkRectangle, 1); ++ ++ new_rect = mtk_rectangle_new_empty (); + meta_window_get_frame_rect (cur_window, new_rect); + obscuring_windows = g_slist_prepend (obscuring_windows, new_rect); + window_stacking = +@@ -927,7 +940,6 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + } + + stack_position++; +- cur_window_iter = cur_window_iter->next; + } + /* Put 'em in bottom to top order */ + rem_windows = obscuring_windows = g_slist_reverse (obscuring_windows); +@@ -940,18 +952,17 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + */ + edges = NULL; + stack_position = 0; +- cur_window_iter = stacked_windows; +- while (cur_window_iter != NULL) ++ for (l = stacked_windows; l; l = l->next) + { ++ MetaWindow *cur_window = l->data; + MtkRectangle cur_rect; +- MetaWindow *cur_window = cur_window_iter->data; + meta_window_get_frame_rect (cur_window, &cur_rect); + + /* Check if we want to use this window's edges for edge + * resistance (note that dock edges are considered screen edges + * which are handled separately + */ +- if (WINDOW_EDGES_RELEVANT (cur_window, display) && ++ if (is_window_relevant_for_edges (cur_window) && + cur_window->type != META_WINDOW_DOCK) + { + GList *new_edges; +@@ -1035,17 +1046,8 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + } + + stack_position++; +- cur_window_iter = cur_window_iter->next; + } + +- /* +- * 4th: Free the extra memory not needed and sort the list +- */ +- g_list_free (stacked_windows); +- /* Free the memory used by the obscuring windows/docks lists */ +- g_slist_free (window_stacking); +- g_slist_free_full (obscuring_windows, g_free); +- + /* Sort the list. FIXME: Should I bother with this sorting? I just + * sort again later in cache_edges() anyway... + */ +@@ -1060,7 +1062,6 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) + edges, + workspace_manager->active_workspace->monitor_edges, + workspace_manager->active_workspace->screen_edges); +- g_list_free (edges); + + return edge_data; + } +diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c +index 8f5d1a046..1267dd4f2 100644 +--- a/src/compositor/meta-sync-ring.c ++++ b/src/compositor/meta-sync-ring.c +@@ -544,20 +544,29 @@ gboolean + meta_sync_ring_insert_wait (void) + { + MetaSyncRing *ring = meta_sync_ring_get (); ++ MetaSync *sync; + + if (!ring) + return FALSE; + + g_return_val_if_fail (ring->xdisplay != NULL, FALSE); + +- if (ring->current_sync->state != META_SYNC_STATE_READY) ++ sync = ring->current_sync; ++ ++ if (sync->state == META_SYNC_STATE_WAITING) ++ { ++ meta_gl_delete_sync (sync->gpu_fence); ++ sync->gpu_fence = 0; ++ sync->state = META_SYNC_STATE_READY; ++ } ++ else if (sync->state != META_SYNC_STATE_READY) + { + meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?"); + if (!meta_sync_ring_reboot (ring->xdisplay)) + return FALSE; + } + +- meta_sync_insert (ring->current_sync); ++ meta_sync_insert (sync); + + return TRUE; + } +diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c +index 24597bbf7..0b43f8eb1 100644 +--- a/src/compositor/meta-window-actor-wayland.c ++++ b/src/compositor/meta-window-actor-wayland.c +@@ -350,7 +350,7 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) + ClutterActor *child_actor; + ClutterActorIter iter; + MetaSurfaceActor *topmost_surface_actor = NULL; +- int n_mapped_surfaces = 0; ++ int n_visible_surface_actors = 0; + MetaWindow *window; + ClutterActorBox window_box; + ClutterActorBox surface_box; +@@ -365,11 +365,17 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) + clutter_actor_iter_init (&iter, surface_container); + while (clutter_actor_iter_next (&iter, &child_actor)) + { ++ MetaSurfaceActor *surface_actor; ++ + if (!clutter_actor_is_mapped (child_actor)) + continue; + +- topmost_surface_actor = META_SURFACE_ACTOR (child_actor); +- n_mapped_surfaces++; ++ surface_actor = META_SURFACE_ACTOR (child_actor); ++ if (meta_surface_actor_is_obscured (surface_actor)) ++ continue; ++ ++ topmost_surface_actor = surface_actor; ++ n_visible_surface_actors++; + } + + if (!topmost_surface_actor) +@@ -380,10 +386,10 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) + } + + window = meta_window_actor_get_meta_window (actor); +- if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 1) ++ if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 1) + return topmost_surface_actor; + +- if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 2) ++ if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 2) + { + MetaSurfaceActorWayland *bg_surface_actor = NULL; + MetaWaylandSurface *bg_surface; +@@ -393,10 +399,16 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) + clutter_actor_iter_init (&iter, surface_container); + while (clutter_actor_iter_next (&iter, &child_actor)) + { ++ MetaSurfaceActor *surface_actor; ++ + if (!clutter_actor_is_mapped (child_actor)) + continue; + +- bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (child_actor); ++ surface_actor = META_SURFACE_ACTOR (child_actor); ++ if (meta_surface_actor_is_obscured (surface_actor)) ++ continue; ++ ++ bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (surface_actor); + break; + } + g_assert (bg_surface_actor); +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 9af0f0004..4bd2bc471 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -1154,6 +1154,9 @@ constrain_modal_dialog (MetaWindow *window, + meta_window_get_placement_rule (window)) + return TRUE; + ++ if (window->fullscreen) ++ return TRUE; ++ + /* We want to center the dialog on the parent, including the decorations + for both of them. info->current is in client X window coordinates, so we need + to convert them to frame coordinates, apply the centering and then +diff --git a/src/core/window.c b/src/core/window.c +index 47c29d94a..c6c23708e 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2227,7 +2227,7 @@ meta_window_show (MetaWindow *window) + window->has_maximize_func) + { + MtkRectangle work_area; +- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); ++ meta_window_get_work_area_current_monitor (window, &work_area); + /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */ + if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) + { +@@ -3101,7 +3101,7 @@ meta_window_unmaximize (MetaWindow *window, + MtkRectangle old_frame_rect, old_buffer_rect; + gboolean has_target_size; + +- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); ++ meta_window_get_work_area_current_monitor (window, &work_area); + meta_window_get_frame_rect (window, &old_frame_rect); + meta_window_get_buffer_rect (window, &old_buffer_rect); + +@@ -5837,9 +5837,7 @@ void + meta_window_get_work_area_current_monitor (MetaWindow *window, + MtkRectangle *area) + { +- meta_window_get_work_area_for_monitor (window, +- window->monitor->number, +- area); ++ meta_window_get_work_area_for_logical_monitor (window, window->monitor, area); + } + + /** +diff --git a/src/meson.build b/src/meson.build +index f7797ff9c..e658f98ca 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -579,6 +579,8 @@ if have_wayland + 'core/meta-service-channel.h', + 'wayland/meta-cursor-sprite-wayland.c', + 'wayland/meta-cursor-sprite-wayland.h', ++ 'wayland/meta-drm-timeline.c', ++ 'wayland/meta-drm-timeline.h', + 'wayland/meta-pointer-confinement-wayland.c', + 'wayland/meta-pointer-confinement-wayland.h', + 'wayland/meta-pointer-lock-wayland.c', +@@ -633,6 +635,8 @@ if have_wayland + 'wayland/meta-wayland-keyboard.h', + 'wayland/meta-wayland-legacy-xdg-foreign.c', + 'wayland/meta-wayland-legacy-xdg-foreign.h', ++ 'wayland/meta-wayland-linux-drm-syncobj.c', ++ 'wayland/meta-wayland-linux-drm-syncobj.h', + 'wayland/meta-wayland-outputs.c', + 'wayland/meta-wayland-outputs.h', + 'wayland/meta-wayland-pointer.c', +@@ -1084,6 +1088,7 @@ if have_wayland + ['xdg-output', 'unstable', 'v1', ], + ['xdg-shell', 'stable', ], + ['xwayland-keyboard-grab', 'unstable', 'v1', ], ++ ['linux-drm-syncobj-v1', 'private', ], + ] + if have_wayland_eglstream + wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable('pkgdatadir') +diff --git a/src/tests/mtk/region-tests.c b/src/tests/mtk/region-tests.c +index 7e41a53f0..c9ebc2adb 100644 +--- a/src/tests/mtk/region-tests.c ++++ b/src/tests/mtk/region-tests.c +@@ -26,7 +26,7 @@ test_contains_point (void) + { + g_autoptr (MtkRegion) r1 = NULL; + +- r1 = mtk_region_create_rectangle (mtk_rectangle_new (0, 0, 100, 100)); ++ r1 = mtk_region_create_rectangle (&MTK_RECTANGLE_INIT (0, 0, 100, 100)); + + g_assert (!mtk_region_contains_point (r1, 200, 200)); + g_assert (mtk_region_contains_point (r1, 50, 50)); +diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c +index f5ebc23fe..2f870fdc3 100644 +--- a/src/tests/native-kms-render.c ++++ b/src/tests/native-kms-render.c +@@ -39,6 +39,8 @@ + #include "tests/meta-wayland-test-driver.h" + #include "tests/meta-wayland-test-utils.h" + ++#define N_FRAMES_PER_TEST 30 ++ + typedef struct + { + int number_of_frames_left; +@@ -46,12 +48,15 @@ typedef struct + + struct { + int n_paints; +- uint32_t fb_id; ++ int n_presentations; ++ int n_direct_scanouts; ++ GList *fb_ids; + } scanout; + + gboolean wait_for_scanout; + + struct { ++ int scanouts_attempted; + gboolean scanout_sabotaged; + gboolean fallback_painted; + guint repaint_guard_id; +@@ -101,7 +106,7 @@ meta_test_kms_render_basic (void) + gulong handler_id; + + test = (KmsRenderingTest) { +- .number_of_frames_left = 10, ++ .number_of_frames_left = N_FRAMES_PER_TEST, + .loop = g_main_loop_new (NULL, FALSE), + }; + handler_id = g_signal_connect (stage, "after-update", +@@ -123,7 +128,6 @@ on_scanout_before_update (ClutterStage *stage, + KmsRenderingTest *test) + { + test->scanout.n_paints = 0; +- test->scanout.fb_id = 0; + } + + static void +@@ -135,6 +139,7 @@ on_scanout_before_paint (ClutterStage *stage, + CoglScanout *scanout; + CoglScanoutBuffer *scanout_buffer; + MetaDrmBuffer *buffer; ++ uint32_t fb_id; + + scanout = clutter_stage_view_peek_scanout (stage_view); + if (!scanout) +@@ -143,8 +148,13 @@ on_scanout_before_paint (ClutterStage *stage, + scanout_buffer = cogl_scanout_get_buffer (scanout); + g_assert_true (META_IS_DRM_BUFFER (scanout_buffer)); + buffer = META_DRM_BUFFER (scanout_buffer); +- test->scanout.fb_id = meta_drm_buffer_get_fb_id (buffer); +- g_assert_cmpuint (test->scanout.fb_id, >, 0); ++ fb_id = meta_drm_buffer_get_fb_id (buffer); ++ g_assert_cmpuint (fb_id, >, 0); ++ test->scanout.fb_ids = g_list_append (test->scanout.fb_ids, ++ GUINT_TO_POINTER (fb_id)); ++ ++ /* Triple buffering, but no higher */ ++ g_assert_cmpuint (g_list_length (test->scanout.fb_ids), <=, 2); + } + + static void +@@ -173,12 +183,12 @@ on_scanout_presented (ClutterStage *stage, + MetaDeviceFile *device_file; + GError *error = NULL; + drmModeCrtc *drm_crtc; ++ uint32_t first_fb_id_expected; + +- if (test->wait_for_scanout && test->scanout.n_paints > 0) ++ if (test->wait_for_scanout && test->scanout.fb_ids == NULL) + return; + +- if (test->wait_for_scanout && test->scanout.fb_id == 0) +- return; ++ test->scanout.n_presentations++; + + device_pool = meta_backend_native_get_device_pool (backend_native); + +@@ -197,15 +207,41 @@ 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); +- if (test->scanout.fb_id == 0) +- g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id); ++ ++ if (test->scanout.fb_ids) ++ { ++ test->scanout.n_direct_scanouts++; ++ first_fb_id_expected = GPOINTER_TO_UINT (test->scanout.fb_ids->data); ++ test->scanout.fb_ids = g_list_delete_link (test->scanout.fb_ids, ++ test->scanout.fb_ids); ++ } + else +- g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id); ++ { ++ first_fb_id_expected = 0; ++ } ++ ++ /* The buffer ID won't match on the first frame because switching from ++ * triple buffered compositing to double buffered direct scanout takes ++ * an extra frame to drain the queue. Thereafter we are in direct scanout ++ * mode and expect the buffer IDs to match. ++ */ ++ if (test->scanout.n_presentations > 1) ++ { ++ if (first_fb_id_expected == 0) ++ g_assert_cmpuint (drm_crtc->buffer_id, !=, first_fb_id_expected); ++ else ++ g_assert_cmpuint (drm_crtc->buffer_id, ==, first_fb_id_expected); ++ } ++ + drmModeFreeCrtc (drm_crtc); + + meta_device_file_release (device_file); + +- g_main_loop_quit (test->loop); ++ test->number_of_frames_left--; ++ if (test->number_of_frames_left <= 0) ++ g_main_loop_quit (test->loop); ++ else ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + } + + typedef enum +@@ -244,7 +280,9 @@ meta_test_kms_render_client_scanout (void) + g_assert_nonnull (wayland_test_client); + + test = (KmsRenderingTest) { ++ .number_of_frames_left = N_FRAMES_PER_TEST, + .loop = g_main_loop_new (NULL, FALSE), ++ .scanout = {0}, + .wait_for_scanout = TRUE, + }; + +@@ -270,7 +308,8 @@ meta_test_kms_render_client_scanout (void) + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + g_main_loop_run (test.loop); + +- g_assert_cmpuint (test.scanout.fb_id, >, 0); ++ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); ++ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); + + g_debug ("Unmake fullscreen"); + window = meta_find_window_from_title (test_context, "dma-buf-scanout-test"); +@@ -292,10 +331,15 @@ meta_test_kms_render_client_scanout (void) + g_assert_cmpint (buffer_rect.y, ==, 10); + + test.wait_for_scanout = FALSE; ++ test.number_of_frames_left = N_FRAMES_PER_TEST; ++ test.scanout.n_presentations = 0; ++ test.scanout.n_direct_scanouts = 0; ++ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + g_main_loop_run (test.loop); + +- g_assert_cmpuint (test.scanout.fb_id, ==, 0); ++ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); ++ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, 0); + + g_debug ("Moving back to 0, 0"); + meta_window_move_frame (window, TRUE, 0, 0); +@@ -307,10 +351,15 @@ meta_test_kms_render_client_scanout (void) + g_assert_cmpint (buffer_rect.y, ==, 0); + + test.wait_for_scanout = TRUE; ++ test.number_of_frames_left = N_FRAMES_PER_TEST; ++ test.scanout.n_presentations = 0; ++ test.scanout.n_direct_scanouts = 0; ++ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + g_main_loop_run (test.loop); + +- g_assert_cmpuint (test.scanout.fb_id, >, 0); ++ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); ++ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); + + g_signal_handler_disconnect (stage, before_update_handler_id); + g_signal_handler_disconnect (stage, before_paint_handler_id); +@@ -364,6 +413,15 @@ on_scanout_fallback_before_paint (ClutterStage *stage, + if (!scanout) + return; + ++ test->scanout_fallback.scanouts_attempted++; ++ ++ /* The first scanout candidate frame will get composited due to triple ++ * buffering draining the queue to drop to double buffering. So don't ++ * sabotage that first frame. ++ */ ++ if (test->scanout_fallback.scanouts_attempted < 2) ++ return; ++ + g_assert_false (test->scanout_fallback.scanout_sabotaged); + + if (is_atomic_mode_setting (kms_device)) +@@ -401,6 +459,15 @@ on_scanout_fallback_paint_view (ClutterStage *stage, + g_clear_handle_id (&test->scanout_fallback.repaint_guard_id, + g_source_remove); + test->scanout_fallback.fallback_painted = TRUE; ++ test->scanout_fallback.scanout_sabotaged = FALSE; ++ } ++ else if (test->scanout_fallback.scanouts_attempted == 1) ++ { ++ /* Now that we've seen the first scanout attempt that was inhibited by ++ * triple buffering, try a second frame. The second one should scanout ++ * and will be sabotaged. ++ */ ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + } + } + +@@ -410,11 +477,11 @@ on_scanout_fallback_presented (ClutterStage *stage, + ClutterFrameInfo *frame_info, + KmsRenderingTest *test) + { +- if (!test->scanout_fallback.scanout_sabotaged) +- return; ++ if (test->scanout_fallback.fallback_painted) ++ g_main_loop_quit (test->loop); + +- g_assert_true (test->scanout_fallback.fallback_painted); +- g_main_loop_quit (test->loop); ++ test->number_of_frames_left--; ++ g_assert_cmpint (test->number_of_frames_left, >, 0); + } + + static void +@@ -443,6 +510,7 @@ meta_test_kms_render_client_scanout_fallback (void) + g_assert_nonnull (wayland_test_client); + + test = (KmsRenderingTest) { ++ .number_of_frames_left = N_FRAMES_PER_TEST, + .loop = g_main_loop_new (NULL, FALSE), + }; + +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png +new file mode 100644 +index 000000000..c2b0c2ff5 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png +new file mode 100644 +index 000000000..28fc7b266 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ +diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c +index cb78489b4..8591e88d6 100644 +--- a/src/tests/wayland-test-clients/buffer-transform.c ++++ b/src/tests/wayland-test-clients/buffer-transform.c +@@ -22,11 +22,6 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +-static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; +- + static gboolean waiting_for_configure = FALSE; + static gboolean fullscreen = 0; + static uint32_t window_width = 0; +@@ -88,7 +83,9 @@ static const struct xdg_surface_listener xdg_surface_listener = { + }; + + static void +-draw_main (gboolean rotated) ++draw_main (WaylandDisplay *display, ++ struct wl_surface *surface, ++ gboolean rotated) + { + static uint32_t color0 = 0xffffffff; + static uint32_t color1 = 0xff00ffff; +@@ -139,7 +136,7 @@ draw_main (gboolean rotated) + } + + static void +-wait_for_configure (void) ++wait_for_configure (WaylandDisplay *display) + { + waiting_for_configure = TRUE; + while (waiting_for_configure || window_width == 0) +@@ -153,6 +150,11 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ struct wl_surface *surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); +@@ -163,9 +165,9 @@ main (int argc, + + xdg_toplevel_set_fullscreen(xdg_toplevel, NULL); + wl_surface_commit (surface); +- wait_for_configure (); ++ wait_for_configure (display); + +- draw_main (FALSE); ++ draw_main (display, surface, FALSE); + wl_surface_commit (surface); + wait_for_effects_completed (display, surface); + +@@ -185,7 +187,7 @@ main (int argc, + wl_surface_commit (surface); + wait_for_view_verified (display, 3); + +- draw_main (TRUE); ++ draw_main (display, surface, TRUE); + wl_surface_set_buffer_transform (surface, WL_OUTPUT_TRANSFORM_90); + wl_surface_commit (surface); + wait_for_view_verified (display, 4); +@@ -202,7 +204,5 @@ main (int argc, + wl_surface_commit (surface); + wait_for_view_verified (display, 7); + +- g_clear_object (&display); +- + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/dma-buf-scanout.c b/src/tests/wayland-test-clients/dma-buf-scanout.c +index bc499164e..d71763947 100644 +--- a/src/tests/wayland-test-clients/dma-buf-scanout.c ++++ b/src/tests/wayland-test-clients/dma-buf-scanout.c +@@ -55,11 +55,7 @@ typedef enum + WINDOW_STATE_FULLSCREEN, + } WindowState; + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static GList *active_buffers; + +@@ -84,7 +80,7 @@ static const struct wl_buffer_listener buffer_listener = { + }; + + static void +-init_surface (void) ++init_surface (struct xdg_toplevel *xdg_toplevel) + { + xdg_toplevel_set_title (xdg_toplevel, "dma-buf-scanout-test"); + xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); +@@ -92,8 +88,9 @@ init_surface (void) + } + + static void +-draw_main (int width, +- int height) ++draw_main (WaylandDisplay *display, ++ int width, ++ int height) + { + WaylandBuffer *buffer; + DmaBufFormat *format; +@@ -140,9 +137,11 @@ handle_xdg_toplevel_configure (void *user_data, + int32_t height, + struct wl_array *states) + { ++ WaylandDisplay *display; + g_assert (width > 0 || prev_width > 0); + g_assert (height > 0 || prev_width > 0); + ++ display = user_data; + if (width > 0 && height > 0) + { + prev_width = width; +@@ -156,7 +155,7 @@ handle_xdg_toplevel_configure (void *user_data, + + window_state = parse_xdg_toplevel_state (states); + +- draw_main (width, height); ++ draw_main (display, width, height); + } + + static void +@@ -196,6 +195,7 @@ handle_xdg_surface_configure (void *user_data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = user_data; + struct wl_callback *frame_callback; + + xdg_surface_ack_configure (xdg_surface, serial); +@@ -223,6 +223,10 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + wl_display_roundtrip (display->display); +@@ -230,11 +234,11 @@ main (int argc, + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); +- xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); ++ xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, display); + +- init_surface (); ++ init_surface (xdg_toplevel); + + running = TRUE; + while (running) +@@ -244,7 +248,6 @@ main (int argc, + } + + g_list_free_full (active_buffers, (GDestroyNotify) g_object_unref); +- g_object_unref (display); + + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/fractional-scale.c b/src/tests/wayland-test-clients/fractional-scale.c +index 4ed55ebe3..f62aa2033 100644 +--- a/src/tests/wayland-test-clients/fractional-scale.c ++++ b/src/tests/wayland-test-clients/fractional-scale.c +@@ -23,12 +23,8 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + static struct wp_viewport *viewport; +-static struct wp_fractional_scale_v1 *fractional_scale_obj; + + static gboolean running; + static gboolean waiting_for_configure; +@@ -43,6 +39,8 @@ handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; ++ + wl_callback_destroy (callback); + test_driver_sync_point (display->test_driver, sync_point++, NULL); + } +@@ -52,7 +50,7 @@ static const struct wl_callback_listener frame_listener = { + }; + + static void +-maybe_redraw (void) ++maybe_redraw (WaylandDisplay *display) + { + struct wl_callback *callback; + uint32_t buffer_width; +@@ -72,7 +70,7 @@ maybe_redraw (void) + wp_viewport_set_destination (viewport, logical_width, logical_height); + + callback = wl_surface_frame (surface); +- wl_callback_add_listener (callback, &frame_listener, NULL); ++ wl_callback_add_listener (callback, &frame_listener, display); + + wl_surface_commit (surface); + +@@ -112,10 +110,11 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; + xdg_surface_ack_configure (xdg_surface, serial); + waiting_for_configure = FALSE; + +- maybe_redraw (); ++ maybe_redraw (display); + } + + static const struct xdg_surface_listener xdg_surface_listener = { +@@ -126,6 +125,7 @@ static void handle_preferred_scale (void *data, + struct wp_fractional_scale_v1 *fractional_scale_obj, + uint32_t wire_scale) + { ++ WaylandDisplay *display = data; + float new_fractional_buffer_scale; + + new_fractional_buffer_scale = wire_scale / 120.0; +@@ -136,7 +136,7 @@ static void handle_preferred_scale (void *data, + + fractional_buffer_scale = new_fractional_buffer_scale; + waiting_for_scale = FALSE; +- maybe_redraw (); ++ maybe_redraw (display); + } + + static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { +@@ -147,11 +147,16 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ struct wp_fractional_scale_v1 *fractional_scale_obj; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "fractional-scale"); +@@ -163,7 +168,7 @@ main (int argc, + surface); + wp_fractional_scale_v1_add_listener (fractional_scale_obj, + &fractional_scale_listener, +- NULL); ++ display); + + wl_surface_commit (surface); + +diff --git a/src/tests/wayland-test-clients/fullscreen.c b/src/tests/wayland-test-clients/fullscreen.c +index 9690f6e85..804be4eb2 100644 +--- a/src/tests/wayland-test-clients/fullscreen.c ++++ b/src/tests/wayland-test-clients/fullscreen.c +@@ -24,11 +24,7 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static gboolean running; + +@@ -58,6 +54,8 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; ++ + draw_surface (display, surface, 10, 10, 0x1f109f20); + xdg_surface_ack_configure (xdg_surface, serial); + wl_surface_commit (surface); +@@ -81,12 +79,16 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "fullscreen"); +diff --git a/src/tests/wayland-test-clients/idle-inhibit.c b/src/tests/wayland-test-clients/idle-inhibit.c +index 23079e879..953db2b92 100644 +--- a/src/tests/wayland-test-clients/idle-inhibit.c ++++ b/src/tests/wayland-test-clients/idle-inhibit.c +@@ -24,7 +24,6 @@ + + #include "idle-inhibit-unstable-v1-client-protocol.h" + +-static WaylandDisplay *display; + struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; + + static void +@@ -59,7 +58,8 @@ main (int argc, + char **argv) + { + struct wl_registry *registry; +- WaylandSurface *surface; ++ g_autoptr (WaylandSurface) surface; ++ g_autoptr (WaylandDisplay) display = NULL; + struct zwp_idle_inhibitor_v1 *inhibitor; + + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); +diff --git a/src/tests/wayland-test-clients/invalid-subsurfaces.c b/src/tests/wayland-test-clients/invalid-subsurfaces.c +index 103456e93..2cf0d4ecf 100644 +--- a/src/tests/wayland-test-clients/invalid-subsurfaces.c ++++ b/src/tests/wayland-test-clients/invalid-subsurfaces.c +@@ -24,33 +24,16 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +- +-static void +-connect_to_display (void) +-{ +- g_assert_null (display); +- +- display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); +- g_assert_nonnull (display); +-} +- +-static void +-clean_up_display (void) +-{ +- g_clear_object (&display); +-} +- + static void + test_circular_subsurfaces1 (void) + { ++ g_autoptr (WaylandDisplay) display = NULL; + struct wl_surface *surface1; + struct wl_subsurface *subsurface1; + struct wl_surface *surface2; + struct wl_subsurface *subsurface2; + +- connect_to_display (); +- ++ display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); + surface1 = wl_compositor_create_surface (display->compositor); + surface2 = wl_compositor_create_surface (display->compositor); + g_assert_nonnull (surface1); +@@ -66,13 +49,12 @@ test_circular_subsurfaces1 (void) + g_assert_nonnull (subsurface2); + + g_assert_cmpint (wl_display_roundtrip (display->display), ==, -1); +- +- clean_up_display (); + } + + static void + test_circular_subsurfaces2 (void) + { ++ g_autoptr (WaylandDisplay) display = NULL; + struct wl_surface *surface1; + struct wl_subsurface *subsurface1; + struct wl_surface *surface2; +@@ -80,7 +62,7 @@ test_circular_subsurfaces2 (void) + struct wl_surface *surface3; + struct wl_subsurface *subsurface3; + +- connect_to_display (); ++ display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); + + surface1 = wl_compositor_create_surface (display->compositor); + surface2 = wl_compositor_create_surface (display->compositor); +@@ -103,8 +85,6 @@ test_circular_subsurfaces2 (void) + g_assert_nonnull (subsurface3); + + g_assert_cmpint (wl_display_roundtrip (display->display), ==, -1); +- +- clean_up_display (); + } + + int +diff --git a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c b/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c +index bd75dc995..4ffda8d5a 100644 +--- a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c ++++ b/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c +@@ -22,23 +22,19 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static gboolean running; + + static void +-init_surface (void) ++init_surface (struct xdg_toplevel *xdg_toplevel) + { + xdg_toplevel_set_title (xdg_toplevel, "bogus window geometry"); + wl_surface_commit (surface); + } + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, surface, 700, 500, 0xff00ff00); + } +@@ -69,13 +65,14 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; + static gboolean sent_invalid_once = FALSE; + + if (sent_invalid_once) + return; + + xdg_surface_set_window_geometry (xdg_surface, 0, 0, 0, 0); +- draw_main (); ++ draw_main (display); + wl_surface_commit (surface); + + sent_invalid_once = TRUE; +@@ -91,15 +88,19 @@ static const struct xdg_surface_listener xdg_surface_listener = { + static void + test_empty_window_geometry (void) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +- init_surface (); ++ init_surface (xdg_toplevel); + + running = TRUE; + while (running) +@@ -110,7 +111,6 @@ test_empty_window_geometry (void) + + g_clear_pointer (&xdg_toplevel, xdg_toplevel_destroy); + g_clear_pointer (&xdg_surface, xdg_surface_destroy); +- g_clear_object (&display); + } + + int +diff --git a/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c b/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c +index 0ddaa4a04..b46a88563 100644 +--- a/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c ++++ b/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c +@@ -23,33 +23,28 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +- +-static struct wl_registry *wl_registry; + static struct wl_seat *wl_seat; + static struct wl_pointer *wl_pointer; + static uint32_t enter_serial; + + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + struct wl_surface *cursor_surface; +-struct wl_cursor_theme *cursor_theme; + struct wl_cursor *cursor; + struct wl_cursor *cursor2; + + static gboolean running; + + static void +-init_surface (void) ++init_surface (struct xdg_toplevel *xdg_toplevel) + { + xdg_toplevel_set_title (xdg_toplevel, "kms-cursor-hotplug-helper"); + wl_surface_commit (surface); + } + + static void +-draw_main (int width, +- int height) ++draw_main (WaylandDisplay *display, ++ int width, ++ int height) + { + draw_surface (display, surface, width, height, 0xff00ff00); + } +@@ -89,7 +84,9 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { +- draw_main (100, 100); ++ WaylandDisplay *display = data; ++ ++ draw_main (display, 100, 100); + xdg_surface_ack_configure (xdg_surface, serial); + wl_surface_commit (surface); + } +@@ -251,6 +248,12 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct wl_registry *wl_registry; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ struct wl_cursor_theme *cursor_theme; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + wl_registry = wl_display_get_registry (display->display); + wl_registry_add_listener (wl_registry, ®istry_listener, display); +@@ -260,7 +263,7 @@ main (int argc, + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +@@ -271,7 +274,7 @@ main (int argc, + g_assert_nonnull (cursor); + g_assert_nonnull (cursor2); + +- init_surface (); ++ init_surface (xdg_toplevel); + wl_surface_commit (surface); + + running = TRUE; +diff --git a/src/tests/wayland-test-clients/single-pixel-buffer.c b/src/tests/wayland-test-clients/single-pixel-buffer.c +index ed98939a3..d350e4d8e 100644 +--- a/src/tests/wayland-test-clients/single-pixel-buffer.c ++++ b/src/tests/wayland-test-clients/single-pixel-buffer.c +@@ -22,13 +22,7 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +-static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + static struct wl_buffer *buffer; +-static struct wl_surface *subsurface_surface; +-static struct wl_subsurface *subsurface; + + static gboolean waiting_for_configure = FALSE; + static gboolean fullscreen = 0; +@@ -91,7 +85,7 @@ static const struct xdg_surface_listener xdg_surface_listener = { + }; + + static void +-wait_for_configure (void) ++wait_for_configure (WaylandDisplay *display) + { + waiting_for_configure = TRUE; + while (waiting_for_configure || window_width == 0) +@@ -114,7 +108,7 @@ static const struct wl_buffer_listener buffer_listener = { + }; + + static void +-wait_for_buffer_released (void) ++wait_for_buffer_released (WaylandDisplay *display) + { + while (buffer) + { +@@ -127,8 +121,14 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; + struct wp_viewport *viewport; + struct wp_viewport *subsurface_viewport; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ struct wl_surface *subsurface_surface; ++ struct wl_subsurface *subsurface; ++ struct wl_surface *surface; + + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + +@@ -140,7 +140,7 @@ main (int argc, + + xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); + wl_surface_commit (surface); +- wait_for_configure (); ++ wait_for_configure (display); + + viewport = wp_viewporter_get_viewport (display->viewporter, surface); + wp_viewport_set_destination (viewport, window_width, window_height); +@@ -157,7 +157,7 @@ main (int argc, + wait_for_effects_completed (display, surface); + wait_for_view_verified (display, 0); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + subsurface_surface = wl_compositor_create_surface (display->compositor); + subsurface = wl_subcompositor_get_subsurface (display->subcompositor, +@@ -184,7 +184,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 1); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -197,7 +197,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 0); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -210,7 +210,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 2); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -223,7 +223,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 3); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -236,7 +236,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 4); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -249,7 +249,7 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 5); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + + buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, +@@ -262,9 +262,43 @@ main (int argc, + wl_surface_commit (subsurface_surface); + wait_for_view_verified (display, 6); + +- wait_for_buffer_released (); ++ wait_for_buffer_released (display); + +- g_clear_object (&display); ++ /* Test reuse */ ++ ++ buffer = ++ wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, ++ 0x70707070, ++ 0x00000000, ++ 0x70707070, ++ 0x70707070); ++ wl_surface_attach (subsurface_surface, buffer, 0, 0); ++ wl_surface_commit (subsurface_surface); ++ wait_for_view_verified (display, 7); ++ ++ wl_subsurface_destroy (subsurface); ++ wl_surface_destroy (subsurface_surface); ++ ++ subsurface_surface = wl_compositor_create_surface (display->compositor); ++ subsurface = wl_subcompositor_get_subsurface (display->subcompositor, ++ subsurface_surface, ++ surface); ++ wl_subsurface_set_desync (subsurface); ++ wl_subsurface_set_position (subsurface, 30, 30); ++ wl_surface_commit (surface); ++ ++ subsurface_viewport = wp_viewporter_get_viewport (display->viewporter, ++ subsurface_surface); ++ wp_viewport_set_destination (subsurface_viewport, ++ window_width - 60, ++ window_height - 60); ++ ++ wl_buffer_add_listener (buffer, &buffer_listener, NULL); ++ wl_surface_attach (subsurface_surface, buffer, 0, 0); ++ wl_surface_commit (subsurface_surface); ++ wait_for_view_verified (display, 8); ++ ++ wait_for_buffer_released (display); + + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/subsurface-corner-cases.c b/src/tests/wayland-test-clients/subsurface-corner-cases.c +index c3b239b2c..449bcb83d 100644 +--- a/src/tests/wayland-test-clients/subsurface-corner-cases.c ++++ b/src/tests/wayland-test-clients/subsurface-corner-cases.c +@@ -22,12 +22,6 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +-static struct wl_surface *toplevel_surface, *child_surface, *grandchild_surface; +-static struct wl_subsurface *child, *grandchild; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; +- + static gboolean waiting_for_configure = FALSE; + static gboolean fullscreen = 0; + static uint32_t window_width = 0; +@@ -75,7 +69,8 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { + }; + + static void +-draw_toplevel (void) ++draw_toplevel (WaylandDisplay *display, ++ struct wl_surface *toplevel_surface) + { + draw_surface (display, toplevel_surface, + window_width, window_height, +@@ -97,7 +92,8 @@ static const struct xdg_surface_listener xdg_surface_listener = { + }; + + static void +-draw_child (void) ++draw_child (WaylandDisplay *display, ++ struct wl_surface *child_surface) + { + draw_surface (display, child_surface, + window_width / 2, window_height / 2, +@@ -105,7 +101,8 @@ draw_child (void) + } + + static void +-draw_grandchild (void) ++draw_grandchild (WaylandDisplay *display, ++ struct wl_surface *grandchild_surface) + { + draw_surface (display, grandchild_surface, + window_width / 2, window_height / 2, +@@ -113,7 +110,7 @@ draw_grandchild (void) + } + + static void +-wait_for_configure (void) ++wait_for_configure (WaylandDisplay *display) + { + waiting_for_configure = TRUE; + while (waiting_for_configure || window_width == 0) +@@ -127,6 +124,12 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ struct wl_surface *toplevel_surface, *child_surface, *grandchild_surface; ++ struct wl_subsurface *child, *grandchild; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + toplevel_surface = wl_compositor_create_surface (display->compositor); +@@ -138,9 +141,9 @@ main (int argc, + + xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); + wl_surface_commit (toplevel_surface); +- wait_for_configure (); ++ wait_for_configure (display); + +- draw_toplevel (); ++ draw_toplevel (display, toplevel_surface); + wl_surface_commit (toplevel_surface); + wait_for_effects_completed (display, toplevel_surface); + +@@ -148,7 +151,7 @@ main (int argc, + child = wl_subcompositor_get_subsurface (display->subcompositor, + child_surface, + toplevel_surface); +- draw_child (); ++ draw_child (display, child_surface); + wl_surface_commit (child_surface); + /* No toplevel commit → sub-surface must not be mapped yet */ + wait_for_view_verified (display, 0); +@@ -174,7 +177,7 @@ main (int argc, + /* Toplevel commit → sub-surface must be unmapped */ + wait_for_view_verified (display, 5); + +- draw_child (); ++ draw_child (display, child_surface); + wl_surface_commit (child_surface); + wl_subsurface_set_desync (child); + wl_surface_attach (child_surface, NULL, 0, 0); +@@ -182,7 +185,7 @@ main (int argc, + /* Desync sub-surface must have been unmapped */ + wait_for_view_verified (display, 6); + +- draw_child (); ++ draw_child (display, child_surface); + wl_surface_commit (child_surface); + wl_subsurface_set_sync (child); + wl_subsurface_destroy (child); +@@ -192,7 +195,7 @@ main (int argc, + child = wl_subcompositor_get_subsurface (display->subcompositor, + child_surface, + toplevel_surface); +- draw_child (); ++ draw_child (display, child_surface); + wl_surface_commit (child_surface); + /* No toplevel commit → sub-surface must not be mapped yet */ + wait_for_view_verified (display, 8); +@@ -209,7 +212,7 @@ main (int argc, + child = wl_subcompositor_get_subsurface (display->subcompositor, + child_surface, + toplevel_surface); +- draw_child (); ++ draw_child (display, child_surface); + wl_surface_commit (child_surface); + wl_surface_commit (toplevel_surface); + /* New sub-surface → placement below toplevel must not have taken effect */ +@@ -219,7 +222,7 @@ main (int argc, + grandchild = wl_subcompositor_get_subsurface (display->subcompositor, + grandchild_surface, + child_surface); +- draw_grandchild (); ++ draw_grandchild (display, grandchild_surface); + wl_subsurface_set_position (grandchild, window_width / 4, window_height / 4); + wl_surface_commit (grandchild_surface); + wl_surface_commit (child_surface); +@@ -236,7 +239,7 @@ main (int argc, + grandchild = wl_subcompositor_get_subsurface (display->subcompositor, + grandchild_surface, + child_surface); +- draw_grandchild (); ++ draw_grandchild (display, grandchild_surface); + wl_subsurface_set_position (grandchild, window_width / 4, window_height / 4); + wl_surface_commit (grandchild_surface); + wl_surface_commit (child_surface); +@@ -244,7 +247,5 @@ main (int argc, + /* New grandchild must be placed above its parent */ + wait_for_view_verified (display, 14); + +- g_clear_object (&display); +- + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/subsurface-parent-unmapped.c b/src/tests/wayland-test-clients/subsurface-parent-unmapped.c +index 7fc83b07d..40c72ea33 100644 +--- a/src/tests/wayland-test-clients/subsurface-parent-unmapped.c ++++ b/src/tests/wayland-test-clients/subsurface-parent-unmapped.c +@@ -23,36 +23,32 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +-static struct wl_registry *registry; + static struct wl_seat *seat; + static struct wl_pointer *pointer; + + static struct wl_surface *toplevel_surface; + static struct xdg_surface *toplevel_xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static struct wl_surface *popup_surface; + static struct xdg_surface *popup_xdg_surface; + static struct xdg_popup *xdg_popup; + + static struct wl_surface *subsurface_surface; +-static struct wl_subsurface *subsurface; + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, toplevel_surface, 200, 200, 0xff00ffff); + } + + static void +-draw_popup (void) ++draw_popup (WaylandDisplay *display) + { + draw_surface (display, popup_surface, 100, 100, 0xff005500); + } + + static void +-draw_subsurface (void) ++draw_subsurface (WaylandDisplay *display) + { + draw_surface (display, subsurface_surface, 100, 50, 0xff001f00); + } +@@ -83,8 +79,10 @@ handle_toplevel_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; ++ + xdg_surface_ack_configure (xdg_surface, serial); +- draw_main (); ++ draw_main (display); + wl_surface_commit (toplevel_surface); + wl_display_flush (display->display); + } +@@ -125,6 +123,8 @@ handle_popup_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; ++ + wl_callback_destroy (callback); + test_driver_sync_point (display->test_driver, 0, popup_surface); + } +@@ -138,16 +138,17 @@ handle_popup_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; + struct wl_callback *frame_callback; + +- draw_popup (); ++ draw_popup (display); + +- draw_subsurface (); ++ draw_subsurface (display); + wl_surface_commit (subsurface_surface); + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (popup_surface); +- wl_callback_add_listener (frame_callback, &frame_listener, NULL); ++ wl_callback_add_listener (frame_callback, &frame_listener, display); + wl_surface_commit (popup_surface); + wl_display_flush (display->display); + } +@@ -164,6 +165,7 @@ pointer_handle_button (void *data, + uint32_t button, + uint32_t state) + { ++ WaylandDisplay *display = data; + struct xdg_positioner *positioner; + static int click_count = 0; + +@@ -174,7 +176,7 @@ pointer_handle_button (void *data, + popup_xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, + popup_surface); + xdg_surface_add_listener (popup_xdg_surface, +- &popup_xdg_surface_listener, NULL); ++ &popup_xdg_surface_listener, display); + positioner = xdg_wm_base_create_positioner (display->xdg_wm_base); + xdg_positioner_set_size (positioner, 100, 100); + xdg_positioner_set_anchor_rect (positioner, 0, 0, 1, 1); +@@ -219,10 +221,12 @@ seat_handle_capabilities (void *data, + struct wl_seat *wl_seat, + enum wl_seat_capability caps) + { ++ WaylandDisplay *display = data; ++ + if (caps & WL_SEAT_CAPABILITY_POINTER) + { + pointer = wl_seat_get_pointer (wl_seat); +- wl_pointer_add_listener (pointer, &pointer_listener, NULL); ++ wl_pointer_add_listener (pointer, &pointer_listener, display); + } + } + +@@ -263,10 +267,12 @@ handle_registry_global (void *data, + const char *interface, + uint32_t version) + { ++ WaylandDisplay *display = data; ++ + if (strcmp (interface, "wl_seat") == 0) + { + seat = wl_registry_bind (registry, id, &wl_seat_interface, 1); +- wl_seat_add_listener (seat, &seat_listener, NULL); ++ wl_seat_add_listener (seat, &seat_listener, display); + } + } + +@@ -286,12 +292,17 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct wl_registry *registry; ++ struct xdg_toplevel *xdg_toplevel; ++ struct wl_subsurface *subsurface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + + registry = wl_display_get_registry (display->display); +- wl_registry_add_listener (registry, ®istry_listener, NULL); ++ wl_registry_add_listener (registry, ®istry_listener, display); + wl_display_roundtrip (display->display); + wl_display_roundtrip (display->display); + +@@ -311,7 +322,7 @@ main (int argc, + toplevel_xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, + toplevel_surface); + xdg_surface_add_listener (toplevel_xdg_surface, +- &toplevel_xdg_surface_listener, NULL); ++ &toplevel_xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (toplevel_xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "subsurface-parent-unmapped"); +@@ -331,7 +342,5 @@ main (int argc, + return EXIT_FAILURE; + } + +- g_clear_object (&display); +- + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c b/src/tests/wayland-test-clients/subsurface-remap-toplevel.c +index e23aacabb..c1bb90ea5 100644 +--- a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c ++++ b/src/tests/wayland-test-clients/subsurface-remap-toplevel.c +@@ -32,13 +32,9 @@ typedef enum _State + STATE_WAIT_FOR_FRAME_2 + } State; + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; + static struct xdg_toplevel *xdg_toplevel; + +-static struct wl_surface *subsurface_surface; + static struct wl_subsurface *subsurface; + + static struct wl_callback *frame_callback; +@@ -72,7 +68,7 @@ static const struct wl_callback_listener actor_destroy_listener = { + }; + + static void +-reset_surface (void) ++reset_surface (WaylandDisplay *display) + { + struct wl_callback *callback; + +@@ -86,13 +82,14 @@ reset_surface (void) + } + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, surface, 700, 500, 0xff00ff00); + } + + static void +-draw_subsurface (void) ++draw_subsurface (WaylandDisplay *display, ++ struct wl_surface *subsurface_surface) + { + draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); + } +@@ -123,10 +120,11 @@ handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; + switch (state) + { + case STATE_WAIT_FOR_FRAME_1: +- reset_surface (); ++ reset_surface (display); + break; + case STATE_WAIT_FOR_FRAME_2: + exit (EXIT_SUCCESS); +@@ -150,16 +148,17 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; + switch (state) + { + case STATE_INIT: + g_assert_not_reached (); + case STATE_WAIT_FOR_CONFIGURE_1: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_1; + break; + case STATE_WAIT_FOR_CONFIGURE_2: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_2; + break; + case STATE_WAIT_FOR_ACTOR_DESTROYED: +@@ -172,7 +171,7 @@ handle_xdg_surface_configure (void *data, + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (surface); +- wl_callback_add_listener (frame_callback, &frame_listener, NULL); ++ wl_callback_add_listener (frame_callback, &frame_listener, display); + wl_surface_commit (surface); + wl_display_flush (display->display); + } +@@ -185,11 +184,15 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_surface *xdg_surface; ++ struct wl_surface *subsurface_surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +@@ -198,7 +201,7 @@ main (int argc, + subsurface_surface, + surface); + wl_subsurface_set_position (subsurface, 100, 100); +- draw_subsurface (); ++ draw_subsurface (display, subsurface_surface); + wl_surface_commit (subsurface_surface); + + init_surface (); +@@ -211,7 +214,5 @@ main (int argc, + return EXIT_FAILURE; + } + +- g_clear_object (&display); +- + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/subsurface-reparenting.c b/src/tests/wayland-test-clients/subsurface-reparenting.c +index f537e0727..7a4c99577 100644 +--- a/src/tests/wayland-test-clients/subsurface-reparenting.c ++++ b/src/tests/wayland-test-clients/subsurface-reparenting.c +@@ -34,8 +34,6 @@ typedef enum _State + STATE_WAIT_FOR_FRAME_3 + } State; + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; + static struct xdg_surface *xdg_surface; + static struct xdg_toplevel *xdg_toplevel; +@@ -47,16 +45,16 @@ static struct wl_callback *frame_callback; + + static State state; + +-static void init_surfaces (void); ++static void init_surfaces (WaylandDisplay *display); + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, surface, 700, 500, 0xff00ff00); + } + + static void +-draw_subsurface (void) ++draw_subsurface (WaylandDisplay *display) + { + draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); + } +@@ -87,10 +85,11 @@ actor_destroyed (void *data, + struct wl_callback *callback, + uint32_t serial) + { ++ WaylandDisplay *display = data; + g_assert_cmpint (state, ==, STATE_WAIT_FOR_ACTOR_DESTROYED); + + wl_subsurface_destroy (subsurface); +- init_surfaces (); ++ init_surfaces (display); + state = STATE_WAIT_FOR_CONFIGURE_2; + + wl_callback_destroy (callback); +@@ -101,12 +100,12 @@ static const struct wl_callback_listener actor_destroy_listener = { + }; + + static void +-reset_surface (void) ++reset_surface (WaylandDisplay *display) + { + struct wl_callback *callback; + + callback = test_driver_sync_actor_destroyed (display->test_driver, surface); +- wl_callback_add_listener (callback, &actor_destroy_listener, NULL); ++ wl_callback_add_listener (callback, &actor_destroy_listener, display); + + xdg_toplevel_destroy (xdg_toplevel); + xdg_surface_destroy (xdg_surface); +@@ -120,10 +119,12 @@ handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_WAIT_FOR_FRAME_1: +- reset_surface (); ++ reset_surface (display); + break; + case STATE_WAIT_FOR_FRAME_2: + exit (EXIT_SUCCESS); +@@ -141,16 +142,18 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_INIT: + g_assert_not_reached (); + case STATE_WAIT_FOR_CONFIGURE_1: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_1; + break; + case STATE_WAIT_FOR_CONFIGURE_2: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_2; + break; + default: +@@ -160,7 +163,7 @@ handle_xdg_surface_configure (void *data, + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (surface); +- wl_callback_add_listener (frame_callback, &frame_listener, NULL); ++ wl_callback_add_listener (frame_callback, &frame_listener, display); + wl_surface_commit (surface); + wl_display_flush (display->display); + } +@@ -170,11 +173,11 @@ static const struct xdg_surface_listener xdg_surface_listener = { + }; + + static void +-init_surfaces (void) ++init_surfaces (WaylandDisplay *display) + { + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "subsurface-reparenting-test"); +@@ -190,13 +193,14 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + subsurface_surface = wl_compositor_create_surface (display->compositor); +- draw_subsurface (); ++ draw_subsurface (display); + wl_surface_commit (subsurface_surface); + +- init_surfaces (); ++ init_surfaces (display); + state = STATE_WAIT_FOR_CONFIGURE_1; + + while (TRUE) +diff --git a/src/tests/wayland-test-clients/xdg-activation.c b/src/tests/wayland-test-clients/xdg-activation.c +index a1e78758f..b97a599c2 100644 +--- a/src/tests/wayland-test-clients/xdg-activation.c ++++ b/src/tests/wayland-test-clients/xdg-activation.c +@@ -24,18 +24,15 @@ + + #include "xdg-activation-v1-client-protocol.h" + +-static WaylandDisplay *display; +-static struct wl_registry *registry; + static struct xdg_activation_v1 *activation; + + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static gboolean running; + + static void +-init_surface (const char *token) ++init_surface (struct xdg_toplevel *xdg_toplevel, ++ const char *token) + { + xdg_toplevel_set_title (xdg_toplevel, "startup notification client"); + xdg_activation_v1_activate (activation, token, surface); +@@ -43,7 +40,7 @@ init_surface (const char *token) + } + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, surface, 700, 500, 0xff00ff00); + } +@@ -74,7 +71,9 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { +- draw_main (); ++ WaylandDisplay *display = data; ++ ++ draw_main (display); + wl_surface_commit (surface); + + g_assert_cmpint (wl_display_roundtrip (display->display), !=, -1); +@@ -126,7 +125,7 @@ static const struct xdg_activation_token_v1_listener token_listener = { + }; + + static char * +-get_token (void) ++get_token (WaylandDisplay *display) + { + struct xdg_activation_token_v1 *token; + char *token_string = NULL; +@@ -151,6 +150,11 @@ get_token (void) + static void + test_startup_notifications (void) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct wl_registry *registry; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ + g_autofree char *token = NULL; + + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); +@@ -162,15 +166,15 @@ test_startup_notifications (void) + + wl_display_roundtrip (display->display); + +- token = get_token (); ++ token = get_token (display); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +- init_surface (token); ++ init_surface (xdg_toplevel, token); + + running = TRUE; + while (running) +@@ -185,7 +189,6 @@ test_startup_notifications (void) + g_clear_pointer (&xdg_surface, xdg_surface_destroy); + g_clear_pointer (&activation, xdg_activation_v1_destroy); + g_clear_pointer (®istry, wl_registry_destroy); +- g_clear_object (&display); + } + + int +diff --git a/src/tests/wayland-test-clients/xdg-apply-limits.c b/src/tests/wayland-test-clients/xdg-apply-limits.c +index c386af283..9c30bfe4a 100644 +--- a/src/tests/wayland-test-clients/xdg-apply-limits.c ++++ b/src/tests/wayland-test-clients/xdg-apply-limits.c +@@ -31,15 +31,9 @@ typedef enum _State + STATE_WAIT_FOR_FRAME_2 + } State; + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; + static struct xdg_toplevel *xdg_toplevel; + +-static struct wl_surface *subsurface_surface; +-static struct wl_subsurface *subsurface; +- + static struct wl_callback *frame_callback; + + static gboolean running; +@@ -71,7 +65,7 @@ static const struct wl_callback_listener actor_destroy_listener = { + }; + + static void +-reset_surface (void) ++reset_surface (WaylandDisplay *display) + { + struct wl_callback *callback; + +@@ -89,13 +83,14 @@ reset_surface (void) + } + + static void +-draw_main (void) ++draw_main (WaylandDisplay *display) + { + draw_surface (display, surface, 700, 500, 0xff00ff00); + } + + static void +-draw_subsurface (void) ++draw_subsurface (WaylandDisplay *display, ++ struct wl_surface *subsurface_surface) + { + draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); + } +@@ -126,10 +121,12 @@ handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_WAIT_FOR_FRAME_1: +- reset_surface (); ++ reset_surface (display); + test_driver_sync_point (display->test_driver, 1, NULL); + break; + case STATE_WAIT_FOR_FRAME_2: +@@ -154,16 +151,18 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_INIT: + g_assert_not_reached (); + case STATE_WAIT_FOR_CONFIGURE_1: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_1; + break; + case STATE_WAIT_FOR_CONFIGURE_2: +- draw_main (); ++ draw_main (display); + state = STATE_WAIT_FOR_FRAME_2; + break; + case STATE_WAIT_FOR_ACTOR_DESTROYED: +@@ -176,7 +175,7 @@ handle_xdg_surface_configure (void *data, + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (surface); +- wl_callback_add_listener (frame_callback, &frame_listener, NULL); ++ wl_callback_add_listener (frame_callback, &frame_listener, display); + wl_surface_commit (surface); + wl_display_flush (display->display); + } +@@ -189,11 +188,16 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_surface *xdg_surface; ++ struct wl_surface *subsurface_surface; ++ struct wl_subsurface *subsurface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +@@ -202,7 +206,7 @@ main (int argc, + subsurface_surface, + surface); + wl_subsurface_set_position (subsurface, 100, 100); +- draw_subsurface (); ++ draw_subsurface (display, subsurface_surface); + wl_surface_commit (subsurface_surface); + + init_surface (); +diff --git a/src/tests/wayland-test-clients/xdg-foreign.c b/src/tests/wayland-test-clients/xdg-foreign.c +index f2dbec151..fdc4f9f70 100644 +--- a/src/tests/wayland-test-clients/xdg-foreign.c ++++ b/src/tests/wayland-test-clients/xdg-foreign.c +@@ -24,8 +24,6 @@ + #include "xdg-foreign-unstable-v1-client-protocol.h" + #include "xdg-foreign-unstable-v2-client-protocol.h" + +-static WaylandDisplay *display; +- + static struct zxdg_exporter_v1 *exporter_v1; + static struct zxdg_exporter_v2 *exporter_v2; + static struct zxdg_importer_v1 *importer_v1; +@@ -130,10 +128,11 @@ int + main (int argc, + char **argv) + { +- g_autoptr (WaylandSurface) window1; +- g_autoptr (WaylandSurface) window2; +- g_autoptr (WaylandSurface) window3; +- g_autoptr (WaylandSurface) window4; ++ g_autoptr (WaylandSurface) window1 = NULL; ++ g_autoptr (WaylandSurface) window2 = NULL; ++ g_autoptr (WaylandSurface) window3 = NULL; ++ g_autoptr (WaylandSurface) window4 = NULL; ++ g_autoptr (WaylandDisplay) display = NULL; + g_autofree char *handle1 = NULL; + g_autofree char *handle3 = NULL; + struct wl_registry *registry; +@@ -222,7 +221,5 @@ main (int argc, + return EXIT_FAILURE; + } + +- g_object_unref (display); +- + return EXIT_SUCCESS; + } +diff --git a/src/tests/wayland-test-clients/xdg-toplevel-bounds.c b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c +index 861ae515b..d3c72dad6 100644 +--- a/src/tests/wayland-test-clients/xdg-toplevel-bounds.c ++++ b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c +@@ -29,11 +29,7 @@ typedef enum _State + STATE_WAIT_FOR_FRAME_1, + } State; + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; +-static struct xdg_surface *xdg_surface; +-static struct xdg_toplevel *xdg_toplevel; + + static struct wl_callback *frame_callback; + +@@ -44,15 +40,16 @@ static int32_t pending_bounds_width; + static int32_t pending_bounds_height; + + static void +-init_surface (void) ++init_surface (struct xdg_toplevel *xdg_toplevel) + { + xdg_toplevel_set_title (xdg_toplevel, "toplevel-bounds-test"); + wl_surface_commit (surface); + } + + static void +-draw_main (int width, +- int height) ++draw_main (WaylandDisplay *display, ++ int width, ++ int height) + { + draw_surface (display, surface, width, height, 0xff00ff00); + } +@@ -94,6 +91,8 @@ handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_WAIT_FOR_FRAME_1: +@@ -114,6 +113,8 @@ handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) + { ++ WaylandDisplay *display = data; ++ + switch (state) + { + case STATE_INIT: +@@ -122,7 +123,8 @@ handle_xdg_surface_configure (void *data, + g_assert (pending_bounds_width > 0); + g_assert (pending_bounds_height > 0); + +- draw_main (pending_bounds_width - 10, ++ draw_main (display, ++ pending_bounds_width - 10, + pending_bounds_height - 10); + state = STATE_WAIT_FOR_FRAME_1; + break; +@@ -132,7 +134,7 @@ handle_xdg_surface_configure (void *data, + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (surface); +- wl_callback_add_listener (frame_callback, &frame_listener, NULL); ++ wl_callback_add_listener (frame_callback, &frame_listener, display); + wl_surface_commit (surface); + wl_display_flush (display->display); + } +@@ -154,17 +156,21 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; ++ struct xdg_toplevel *xdg_toplevel; ++ struct xdg_surface *xdg_surface; ++ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER | + WAYLAND_DISPLAY_CAPABILITY_XDG_SHELL_V4); + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); +- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); ++ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + +- init_surface (); ++ init_surface (xdg_toplevel); + state = STATE_WAIT_FOR_CONFIGURE_1; + + wl_surface_commit (surface); +diff --git a/src/tests/wayland-test-clients/ycbcr.c b/src/tests/wayland-test-clients/ycbcr.c +index 1805abb8d..3ce3ec642 100644 +--- a/src/tests/wayland-test-clients/ycbcr.c ++++ b/src/tests/wayland-test-clients/ycbcr.c +@@ -24,8 +24,6 @@ + + #include "wayland-test-client-utils.h" + +-static WaylandDisplay *display; +- + static struct wl_surface *surface; + static struct xdg_surface *xdg_surface; + static struct xdg_toplevel *xdg_toplevel; +@@ -63,8 +61,9 @@ typedef void (*ShaderFunc) (float x, + float *out_cr); + + static void +-draw (uint32_t drm_format, +- ShaderFunc shader) ++draw (WaylandDisplay *display, ++ uint32_t drm_format, ++ ShaderFunc shader) + { + WaylandBuffer *buffer; + uint8_t *planes[4]; +@@ -180,7 +179,7 @@ static const struct xdg_surface_listener xdg_surface_listener = { + }; + + static void +-wait_for_configure (void) ++wait_for_configure (WaylandDisplay *display) + { + waiting_for_configure = TRUE; + while (waiting_for_configure) +@@ -194,6 +193,7 @@ int + main (int argc, + char **argv) + { ++ g_autoptr (WaylandDisplay) display = NULL; + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); +@@ -205,27 +205,25 @@ main (int argc, + xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); + wl_surface_commit (surface); + +- wait_for_configure (); ++ wait_for_configure (display); + +- draw (DRM_FORMAT_YUYV, shader_luma_gradient); ++ draw (display, DRM_FORMAT_YUYV, shader_luma_gradient); + wl_surface_commit (surface); + wait_for_effects_completed (display, surface); + wait_for_view_verified (display, 0); + +- draw (DRM_FORMAT_YUYV, shader_color_gradient); ++ draw (display, DRM_FORMAT_YUYV, shader_color_gradient); + wl_surface_commit (surface); + wait_for_view_verified (display, 1); + +- draw (DRM_FORMAT_YUV420, shader_luma_gradient); ++ draw (display, DRM_FORMAT_YUV420, shader_luma_gradient); + wl_surface_commit (surface); + wait_for_view_verified (display, 2); + +- draw (DRM_FORMAT_YUV420, shader_color_gradient); ++ draw (display, DRM_FORMAT_YUV420, shader_color_gradient); + wl_surface_commit (surface); + wait_for_view_verified (display, 3); + + g_clear_pointer (&xdg_toplevel, xdg_toplevel_destroy); + g_clear_pointer (&xdg_surface, xdg_surface_destroy); +- +- g_clear_object (&display); + } +diff --git a/src/wayland/meta-drm-timeline.c b/src/wayland/meta-drm-timeline.c +new file mode 100644 +index 000000000..6d86fd19f +--- /dev/null ++++ b/src/wayland/meta-drm-timeline.c +@@ -0,0 +1,269 @@ ++/* ++ * Copyright (C) 2023 NVIDIA Corporation. ++ * ++ * 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 . ++ * ++ * Written by: ++ * Austin Shafer ++ */ ++ ++/** ++ * MetaDrmTimeline ++ * ++ * MetaDrmTimeline is a helper for handling DRM syncobj operations. It ++ * can import DRM syncobjs and export eventfds at a particular point. ++ * ++ * This is heavily inspired by wlroot's wlr_render_timeline, written by ++ * Simon Ser. ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#ifdef HAVE_EVENTFD ++#include ++#endif ++ ++#include "meta/util.h" ++#include "wayland/meta-drm-timeline.h" ++ ++enum ++{ ++ PROP_0, ++ ++ PROP_DRM_FD, ++ PROP_SYNCOBJ_FD, ++ ++ N_PROPS ++}; ++ ++typedef struct _MetaDrmTimeline ++{ ++ GObject parent; ++ ++ int drm; ++ int drm_syncobj_fd; ++ uint32_t drm_syncobj; ++} MetaDrmTimeline; ++ ++static GParamSpec *obj_props[N_PROPS]; ++ ++static void initable_iface_init (GInitableIface *initable_iface); ++ ++G_DEFINE_FINAL_TYPE_WITH_CODE (MetaDrmTimeline, meta_drm_timeline, G_TYPE_OBJECT, ++ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, ++ initable_iface_init)) ++ ++static void ++meta_drm_timeline_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); ++ ++ switch (prop_id) ++ { ++ case PROP_DRM_FD: ++ g_value_set_int (value, timeline->drm); ++ break; ++ case PROP_SYNCOBJ_FD: ++ g_value_set_int (value, timeline->drm_syncobj_fd); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++meta_drm_timeline_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); ++ int fd; ++ ++ switch (prop_id) ++ { ++ case PROP_DRM_FD: ++ fd = g_value_get_int (value); ++ timeline->drm = fcntl (fd, F_DUPFD_CLOEXEC, 0); ++ break; ++ case PROP_SYNCOBJ_FD: ++ fd = g_value_get_int (value); ++ timeline->drm_syncobj_fd = fcntl (fd, F_DUPFD_CLOEXEC, 0); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static gboolean ++meta_drm_timeline_initable_init (GInitable *initable, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ MetaDrmTimeline *timeline = META_DRM_TIMELINE (initable); ++ ++ if (drmSyncobjFDToHandle (timeline->drm, ++ timeline->drm_syncobj_fd, ++ &timeline->drm_syncobj) != 0) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_FAILED, ++ "Failed to import DRM syncobj"); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static void ++initable_iface_init (GInitableIface *initable_iface) ++{ ++ initable_iface->init = meta_drm_timeline_initable_init; ++} ++ ++MetaDrmTimeline * ++meta_drm_timeline_import_syncobj (int fd, ++ int drm_syncobj, ++ GError **error) ++{ ++ MetaDrmTimeline *timeline = g_initable_new (META_TYPE_DRM_TIMELINE, ++ NULL, error, ++ "drm-fd", fd, ++ "syncobj-fd", drm_syncobj, ++ NULL); ++ ++ return timeline; ++} ++ ++int ++meta_drm_timeline_get_eventfd (MetaDrmTimeline *timeline, ++ uint64_t sync_point, ++ GError **error) ++{ ++ g_autofd int fd = -1; ++ ++#ifdef HAVE_EVENTFD ++ fd = eventfd (0, EFD_CLOEXEC); ++ if (fd < 0) ++ return -1; ++ ++ if (drmSyncobjEventfd (timeline->drm, timeline->drm_syncobj, ++ sync_point, fd, 0) != 0) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "DRM_IOCTL_SYNCOBJ_EVENTFD: Failed to export eventfd"); ++ return -1; ++ } ++#endif ++ ++ return g_steal_fd (&fd); ++} ++ ++gboolean ++meta_drm_timeline_set_sync_point (MetaDrmTimeline *timeline, ++ uint64_t sync_point, ++ int sync_fd, ++ GError **error) ++{ ++ uint32_t tmp; ++ ++ /* Import our syncfd at a new release point */ ++ if (drmSyncobjCreate (timeline->drm, 0, &tmp) != 0) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "Failed to create temporary syncobj"); ++ return FALSE; ++ } ++ ++ if (drmSyncobjImportSyncFile (timeline->drm, tmp, sync_fd) != 0) ++ goto end; ++ ++ if (drmSyncobjTransfer (timeline->drm, timeline->drm_syncobj, ++ sync_point, tmp, 0, 0) != 0) ++ goto end; ++ ++ drmSyncobjDestroy (timeline->drm, tmp); ++ return TRUE; ++ ++end: ++ drmSyncobjDestroy (timeline->drm, tmp); ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "Failed to import syncfd at specified point"); ++ return FALSE; ++} ++ ++static void ++meta_drm_timeline_finalize (GObject *object) ++{ ++ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); ++ ++ drmSyncobjDestroy (timeline->drm, timeline->drm_syncobj); ++ g_clear_fd (&timeline->drm_syncobj_fd, NULL); ++ g_clear_fd (&timeline->drm, NULL); ++ ++ G_OBJECT_CLASS (meta_drm_timeline_parent_class)->finalize (object); ++} ++ ++static void ++meta_drm_timeline_init (MetaDrmTimeline *timeline) ++{ ++ timeline->drm = -1; ++ timeline->drm_syncobj_fd = -1; ++ timeline->drm_syncobj = -1; ++} ++ ++static void ++meta_drm_timeline_class_init (MetaDrmTimelineClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->get_property = meta_drm_timeline_get_property; ++ object_class->set_property = meta_drm_timeline_set_property; ++ object_class->finalize = meta_drm_timeline_finalize; ++ ++ obj_props[PROP_DRM_FD] = ++ g_param_spec_int ("drm-fd", ++ NULL, ++ NULL, ++ 0, INT_MAX, 0, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ ++ obj_props[PROP_SYNCOBJ_FD] = ++ g_param_spec_int ("syncobj-fd", ++ NULL, ++ NULL, ++ 0, INT_MAX, 0, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ ++ g_object_class_install_properties (object_class, N_PROPS, obj_props); ++} +diff --git a/src/wayland/meta-drm-timeline.h b/src/wayland/meta-drm-timeline.h +new file mode 100644 +index 000000000..8206e3066 +--- /dev/null ++++ b/src/wayland/meta-drm-timeline.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2023 NVIDIA Corporation. ++ * ++ * 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 . ++ * ++ * Written by: ++ * Austin Shafer ++ */ ++ ++#pragma once ++ ++#include ++#include ++#include ++ ++#define META_TYPE_DRM_TIMELINE (meta_drm_timeline_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaDrmTimeline, meta_drm_timeline, ++ META, DRM_TIMELINE, GObject); ++ ++typedef struct _MetaDrmTimeline MetaDrmTimeline; ++ ++MetaDrmTimeline * meta_drm_timeline_create (int fd, ++ GError **error); ++ ++MetaDrmTimeline * meta_drm_timeline_import_syncobj (int fd, ++ int drm_syncobj, ++ GError **error); ++ ++int meta_drm_timeline_get_eventfd (MetaDrmTimeline *timeline, ++ uint64_t sync_point, ++ GError **error); ++ ++gboolean meta_drm_timeline_set_sync_point (MetaDrmTimeline *timeline, ++ uint64_t sync_point, ++ int sync_fd, ++ GError **error); +diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c +index 59360e30a..3f64758a5 100644 +--- a/src/wayland/meta-wayland-buffer.c ++++ b/src/wayland/meta-wayland-buffer.c +@@ -49,6 +49,7 @@ + #include "wayland/meta-wayland-buffer.h" + + #include ++#include + + #include "backends/meta-backend-private.h" + #include "clutter/clutter.h" +@@ -59,6 +60,8 @@ + #include "common/meta-cogl-drm-formats.h" + #include "common/meta-drm-format-helpers.h" + #include "compositor/meta-multi-texture-format-private.h" ++#include "wayland/meta-drm-timeline.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #ifdef HAVE_NATIVE_BACKEND + #include "backends/native/meta-drm-buffer-gbm.h" +@@ -712,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) + void + meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) + { ++ MetaContext *context = meta_wayland_compositor_get_context (buffer->compositor); ++ MetaBackend *backend = meta_context_get_backend (context); ++ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); ++ CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); ++ MetaWaylandSyncPoint *sync_point; ++ g_autoptr(GError) error = NULL; ++ g_autofd int sync_fd = -1; ++ + g_return_if_fail (buffer->use_count > 0); + + buffer->use_count--; + + if (buffer->use_count == 0 && buffer->resource) +- wl_buffer_send_release (buffer->resource); ++ { ++ wl_buffer_send_release (buffer->resource); ++ ++ sync_fd = cogl_context_get_latest_sync_fd (cogl_context); ++ if (sync_fd < 0) ++ { ++ meta_topic (META_DEBUG_WAYLAND, "Invalid Sync Fd returned by COGL"); ++ return; ++ } ++ ++ for (int i = 0; i < buffer->release_points->len; i++) ++ { ++ sync_point = g_ptr_array_index (buffer->release_points, i); ++ if (!meta_wayland_sync_timeline_set_sync_point (sync_point->timeline, ++ sync_point->sync_point, ++ sync_fd, ++ &error)) ++ { ++ g_warning ("Failed to import sync point: %s", error->message); ++ } ++ } ++ g_ptr_array_remove_range (buffer->release_points, 0, ++ buffer->release_points->len); ++ } + } + + gboolean +@@ -981,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) + + clear_tainted_scanout_onscreens (buffer); + g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); ++ g_clear_pointer (&buffer->release_points, g_ptr_array_unref); + + g_clear_object (&buffer->egl_image.texture); + #ifdef HAVE_WAYLAND_EGLSTREAM +@@ -999,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) + static void + meta_wayland_buffer_init (MetaWaylandBuffer *buffer) + { ++ buffer->release_points = g_ptr_array_new_with_free_func (g_free); + } + + static void +@@ -1091,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) + + drm_format = shm_to_drm_format (possible_formats[i]); + format_info = meta_format_info_from_drm_format (drm_format); +- g_assert (format_info); ++ ++ if (!format_info) ++ continue; + + if (!context_supports_format (cogl_context, format_info)) + continue; +diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h +index 23aea7cb2..a0d59f51b 100644 +--- a/src/wayland/meta-wayland-buffer.h ++++ b/src/wayland/meta-wayland-buffer.h +@@ -79,6 +79,8 @@ struct _MetaWaylandBuffer + } single_pixel; + + GHashTable *tainted_scanout_onscreens; ++ ++ GPtrArray *release_points; + }; + + #define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ()) +diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c +index 8b326ecfa..5e4ee671c 100644 +--- a/src/wayland/meta-wayland-dma-buf.c ++++ b/src/wayland/meta-wayland-dma-buf.c +@@ -57,6 +57,7 @@ + #include "wayland/meta-wayland-buffer.h" + #include "wayland/meta-wayland-private.h" + #include "wayland/meta-wayland-versions.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #ifdef HAVE_NATIVE_BACKEND + #include "backends/native/meta-drm-buffer-gbm.h" +@@ -1046,6 +1047,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, + return &source->base; + } + ++GSource * ++meta_wayland_drm_syncobj_create_source (MetaWaylandBuffer *buffer, ++ MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ MetaWaylandDmaBufSourceDispatch dispatch, ++ gpointer user_data) ++{ ++ MetaWaylandDmaBufSource *source = NULL; ++ g_autofd int sync_fd = -1; ++ g_autoptr(GError) error = NULL; ++ ++ sync_fd = meta_wayland_sync_timeline_get_eventfd (timeline, sync_point, &error); ++ if (sync_fd < 0) ++ { ++ g_warning ("Failed to get sync fd: %s", error->message); ++ return NULL; ++ } ++ ++ if (is_fd_readable (sync_fd)) ++ { ++ return NULL; ++ } ++ ++ source = create_source (buffer, dispatch, user_data); ++ if (!source) ++ return NULL; ++ ++ source->fd_tags[0] = g_source_add_unix_fd (&source->base, sync_fd, G_IO_IN); ++ source->owned_sync_fd[0] = g_steal_fd (&sync_fd); ++ ++ return &source->base; ++} ++ + static void + buffer_params_create_common (struct wl_client *client, + struct wl_resource *params_resource, +diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h +index 8f71dac42..5b2cda734 100644 +--- a/src/wayland/meta-wayland-dma-buf.h ++++ b/src/wayland/meta-wayland-dma-buf.h +@@ -63,6 +63,13 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, + MetaWaylandDmaBufSourceDispatch dispatch, + gpointer user_data); + ++GSource * ++meta_wayland_drm_syncobj_create_source (MetaWaylandBuffer *buffer, ++ MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ MetaWaylandDmaBufSourceDispatch dispatch, ++ gpointer user_data); ++ + CoglScanout * + meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, + CoglOnscreen *onscreen, +diff --git a/src/wayland/meta-wayland-linux-drm-syncobj.c b/src/wayland/meta-wayland-linux-drm-syncobj.c +new file mode 100644 +index 000000000..a922415d9 +--- /dev/null ++++ b/src/wayland/meta-wayland-linux-drm-syncobj.c +@@ -0,0 +1,637 @@ ++/* ++ * Copyright (C) 2023 NVIDIA Corporation. ++ * ++ * 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 . ++ * ++ * Written by: ++ * Austin Shafer ++ */ ++ ++#include "config.h" ++ ++#include "backends/native/meta-backend-native-types.h" ++#include "backends/native/meta-device-pool.h" ++#include "backends/native/meta-renderer-native.h" ++#include "meta/util.h" ++#include "wayland/meta-wayland-buffer.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" ++#include "wayland/meta-wayland-private.h" ++#include ++#include ++ ++typedef struct _MetaWaylandDrmSyncobjManager ++{ ++ GObject parent; ++ ++ int drm; ++} MetaWaylandDrmSyncobjManager; ++ ++typedef struct _MetaWaylandSyncobjSurface ++{ ++ GObject parent; ++ ++ struct wl_resource *resource; ++ MetaWaylandSurface *surface; ++ gulong surface_destroy_handler_id; ++} MetaWaylandSyncobjSurface; ++ ++typedef struct _MetaWaylandSyncobjTimeline ++{ ++ GObject parent; ++ ++ MetaDrmTimeline *drm_timeline; ++} MetaWaylandSyncobjTimeline; ++ ++#define META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER (meta_wayland_drm_syncobj_manager_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaWaylandDrmSyncobjManager, meta_wayland_drm_syncobj_manager, ++ META, WAYLAND_DRM_SYNCOBJ_MANAGER, GObject) ++ ++#define META_TYPE_WAYLAND_SYNCOBJ_SURFACE (meta_wayland_syncobj_surface_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaWaylandSyncobjSurface, meta_wayland_syncobj_surface, ++ META, WAYLAND_SYNCOBJ_SURFACE, GObject) ++ ++#define META_TYPE_WAYLAND_SYNCOBJ_TIMELINE (meta_wayland_syncobj_timeline_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaWaylandSyncobjTimeline, meta_wayland_syncobj_timeline, ++ META, WAYLAND_SYNCOBJ_TIMELINE, GObject) ++ ++#define META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER (meta_wayland_drm_syncobj_manager_get_type ()) ++G_DEFINE_FINAL_TYPE (MetaWaylandDrmSyncobjManager, meta_wayland_drm_syncobj_manager, ++ G_TYPE_OBJECT) ++ ++#define META_TYPE_WAYLAND_SYNCOBJ_SURFACE (meta_wayland_syncobj_surface_get_type ()) ++G_DEFINE_FINAL_TYPE (MetaWaylandSyncobjSurface, meta_wayland_syncobj_surface, ++ G_TYPE_OBJECT) ++ ++#define META_TYPE_WAYLAND_SYNCOBJ_TIMELINE (meta_wayland_syncobj_timeline_get_type ()) ++G_DEFINE_FINAL_TYPE (MetaWaylandSyncobjTimeline, meta_wayland_syncobj_timeline, ++ G_TYPE_OBJECT) ++ ++G_DEFINE_FINAL_TYPE (MetaWaylandSyncPoint, meta_wayland_sync_point, G_TYPE_OBJECT); ++ ++static GQuark quark_syncobj_surface; ++ ++static void ++meta_wayland_sync_point_set (MetaWaylandSyncPoint **sync_point_ptr, ++ MetaWaylandSyncobjTimeline *syncobj_timeline, ++ uint32_t point_hi, ++ uint32_t point_lo) ++{ ++ MetaWaylandSyncPoint *sync_point; ++ ++ if (!*sync_point_ptr) ++ *sync_point_ptr = g_object_new (META_TYPE_WAYLAND_SYNC_POINT, NULL); ++ ++ sync_point = *sync_point_ptr; ++ g_set_object (&sync_point->timeline, syncobj_timeline); ++ sync_point->sync_point = (uint64_t)point_hi << 32 | point_lo; ++} ++ ++static void ++meta_wayland_sync_point_finalize (GObject *object) ++{ ++ MetaWaylandSyncPoint *sync = META_WAYLAND_SYNC_POINT (object); ++ ++ g_object_unref (sync->timeline); ++ ++ G_OBJECT_CLASS (meta_wayland_sync_point_parent_class)->finalize (object); ++} ++ ++static void ++meta_wayland_sync_point_init (MetaWaylandSyncPoint *sync) ++{ ++} ++ ++static void ++meta_wayland_sync_point_class_init (MetaWaylandSyncPointClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = meta_wayland_sync_point_finalize; ++} ++ ++static void ++syncobj_timeline_handle_resource_destroy (struct wl_resource *resource) ++{ ++ MetaWaylandSyncobjTimeline *syncobj_timeline = ++ wl_resource_get_user_data (resource); ++ g_object_unref (syncobj_timeline); ++} ++ ++static void ++meta_wayland_syncobj_timeline_finalize (GObject *object) ++{ ++ MetaWaylandSyncobjTimeline *syncobj_timeline = ++ META_WAYLAND_SYNCOBJ_TIMELINE (object); ++ ++ g_clear_object (&syncobj_timeline->drm_timeline); ++ ++ G_OBJECT_CLASS (meta_wayland_syncobj_timeline_parent_class)->finalize (object); ++} ++ ++static void ++meta_wayland_syncobj_timeline_class_init (MetaWaylandSyncobjTimelineClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = meta_wayland_syncobj_timeline_finalize; ++} ++ ++static void ++meta_wayland_syncobj_timeline_init (MetaWaylandSyncobjTimeline *syncobj_timeline) ++{ ++ syncobj_timeline->drm_timeline = NULL; ++} ++ ++static void ++syncobj_timeline_handle_destroy (struct wl_client *client, ++ struct wl_resource *resource) ++{ ++ wl_resource_destroy (resource); ++} ++ ++static const struct wp_linux_drm_syncobj_timeline_v1_interface ++ syncobj_timeline_implementation = ++{ ++ syncobj_timeline_handle_destroy, ++}; ++ ++gboolean ++meta_wayland_sync_timeline_set_sync_point (MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ int sync_fd, ++ GError **error) ++{ ++ return meta_drm_timeline_set_sync_point (timeline->drm_timeline, ++ sync_point, ++ sync_fd, ++ error); ++} ++ ++int ++meta_wayland_sync_timeline_get_eventfd (MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ GError **error) ++{ ++ return meta_drm_timeline_get_eventfd (timeline->drm_timeline, ++ sync_point, ++ error); ++} ++ ++static void ++syncobj_surface_handle_destroy (struct wl_client *client, ++ struct wl_resource *resource) ++{ ++ wl_resource_destroy (resource); ++} ++ ++static void ++syncobj_surface_handle_set_acquire_point (struct wl_client *client, ++ struct wl_resource *resource, ++ struct wl_resource *timeline_resource, ++ uint32_t point_hi, ++ uint32_t point_lo) ++{ ++ MetaWaylandSyncobjSurface *syncobj_surface = wl_resource_get_user_data (resource); ++ MetaWaylandSurface *surface = syncobj_surface->surface; ++ MetaWaylandSyncobjTimeline *syncobj_timeline = ++ wl_resource_get_user_data (timeline_resource); ++ ++ if (!surface) ++ { ++ wl_resource_post_error (resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, ++ "Underlying surface object has been destroyed"); ++ return; ++ } ++ ++ meta_wayland_sync_point_set (&surface->pending_state->drm_syncobj.acquire, ++ syncobj_timeline, ++ point_hi, ++ point_lo); ++} ++ ++static void syncobj_surface_handle_set_release_point (struct wl_client *client, ++ struct wl_resource *resource, ++ struct wl_resource *timeline_resource, ++ uint32_t point_hi, ++ uint32_t point_lo) ++{ ++ MetaWaylandSyncobjSurface *syncobj_surface = wl_resource_get_user_data (resource); ++ MetaWaylandSurface *surface = syncobj_surface->surface; ++ MetaWaylandSyncobjTimeline *syncobj_timeline = ++ wl_resource_get_user_data (timeline_resource); ++ ++ if (!surface) ++ { ++ wl_resource_post_error (resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, ++ "Underlying surface object has been destroyed"); ++ return; ++ } ++ ++ meta_wayland_sync_point_set (&surface->pending_state->drm_syncobj.release, ++ syncobj_timeline, ++ point_hi, ++ point_lo); ++} ++ ++static const struct wp_linux_drm_syncobj_surface_v1_interface ++ syncobj_surface_implementation = ++{ ++ syncobj_surface_handle_destroy, ++ syncobj_surface_handle_set_acquire_point, ++ syncobj_surface_handle_set_release_point, ++}; ++ ++static void ++syncobj_surface_resource_destroyed (MetaWaylandSurface *surface, ++ MetaWaylandSyncobjSurface *syncobj_surface) ++{ ++ g_clear_signal_handler (&syncobj_surface->surface_destroy_handler_id, ++ syncobj_surface->surface); ++ ++ g_object_set_qdata (G_OBJECT (syncobj_surface->surface), ++ quark_syncobj_surface, ++ NULL); ++ ++ syncobj_surface->surface = NULL; ++} ++ ++static void ++syncobj_surface_destructor (struct wl_resource *resource) ++{ ++ MetaWaylandSyncobjSurface *syncobj_surface = ++ wl_resource_get_user_data (resource); ++ ++ if (syncobj_surface->surface) ++ syncobj_surface_resource_destroyed (syncobj_surface->surface, syncobj_surface); ++ ++ g_object_unref (syncobj_surface); ++} ++ ++static void ++meta_wayland_syncobj_surface_class_init (MetaWaylandSyncobjSurfaceClass *klass) ++{ ++} ++ ++static void ++meta_wayland_syncobj_surface_init (MetaWaylandSyncobjSurface *syncobj_surface) ++{ ++} ++ ++static void ++drm_syncobj_manager_handle_destroy (struct wl_client *client, ++ struct wl_resource *resource) ++{ ++ wl_resource_destroy (resource); ++} ++ ++static void ++drm_syncobj_manager_handle_get_surface (struct wl_client *client, ++ struct wl_resource *resource, ++ uint32_t id, ++ struct wl_resource *surface_resource) ++{ ++ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); ++ MetaWaylandSyncobjSurface *syncobj_surface = ++ g_object_get_qdata (G_OBJECT (surface), quark_syncobj_surface); ++ struct wl_resource *sync_resource; ++ ++ if (syncobj_surface) ++ { ++ wl_resource_post_error (surface_resource, ++ WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, ++ "DRM Syncobj surface object already created for surface %d", ++ wl_resource_get_id (surface_resource)); ++ return; ++ } ++ ++ sync_resource = ++ wl_resource_create (client, ++ &wp_linux_drm_syncobj_surface_v1_interface, ++ wl_resource_get_version (resource), ++ id); ++ if (sync_resource == NULL) ++ { ++ wl_resource_post_no_memory (resource); ++ return; ++ } ++ ++ syncobj_surface = g_object_new (META_TYPE_WAYLAND_SYNCOBJ_SURFACE, NULL); ++ syncobj_surface->surface = surface; ++ syncobj_surface->surface_destroy_handler_id = ++ g_signal_connect (surface, ++ "destroy", ++ G_CALLBACK (syncobj_surface_resource_destroyed), ++ syncobj_surface); ++ ++ g_object_set_qdata (G_OBJECT (surface), ++ quark_syncobj_surface, ++ syncobj_surface); ++ ++ wl_resource_set_implementation (sync_resource, ++ &syncobj_surface_implementation, ++ syncobj_surface, ++ syncobj_surface_destructor); ++ syncobj_surface->resource = sync_resource; ++} ++ ++static void ++drm_syncobj_manager_handle_import_timeline (struct wl_client *client, ++ struct wl_resource *resource, ++ uint32_t id, ++ int drm_syncobj_fd) ++{ ++ MetaWaylandDrmSyncobjManager *drm_syncobj = wl_resource_get_user_data (resource); ++ g_autoptr (GError) error = NULL; ++ g_autoptr (MetaDrmTimeline) drm_timeline = NULL; ++ g_autoptr (MetaWaylandSyncobjTimeline) syncobj_timeline = NULL; ++ struct wl_resource *timeline_resource; ++ ++ drm_timeline = meta_drm_timeline_import_syncobj (drm_syncobj->drm, ++ drm_syncobj_fd, ++ &error); ++ close (drm_syncobj_fd); ++ if (!drm_timeline) ++ { ++ wl_resource_post_error (resource, ++ WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, ++ "Failed to import DRM syncobj: %s", ++ error->message); ++ return; ++ } ++ ++ syncobj_timeline = g_object_new (META_TYPE_WAYLAND_SYNCOBJ_TIMELINE, NULL); ++ ++ timeline_resource = wl_resource_create (client, ++ &wp_linux_drm_syncobj_timeline_v1_interface, ++ wl_resource_get_version (resource), ++ id); ++ if (timeline_resource == NULL) ++ { ++ wl_resource_post_no_memory (resource); ++ return; ++ } ++ ++ syncobj_timeline->drm_timeline = g_steal_pointer (&drm_timeline); ++ wl_resource_set_implementation (timeline_resource, ++ &syncobj_timeline_implementation, ++ g_steal_pointer (&syncobj_timeline), ++ syncobj_timeline_handle_resource_destroy); ++} ++ ++static const struct wp_linux_drm_syncobj_manager_v1_interface ++ drm_syncobj_manager_implementation = ++{ ++ drm_syncobj_manager_handle_destroy, ++ drm_syncobj_manager_handle_get_surface, ++ drm_syncobj_manager_handle_import_timeline, ++}; ++ ++static void ++meta_wayland_drm_syncobj_manager_finalize (GObject *object) ++{ ++ MetaWaylandDrmSyncobjManager *drm_syncobj = ++ META_WAYLAND_DRM_SYNCOBJ_MANAGER (object); ++ ++ g_clear_fd (&drm_syncobj->drm, NULL); ++ ++ G_OBJECT_CLASS (meta_wayland_drm_syncobj_manager_parent_class)->finalize (object); ++} ++ ++static void ++meta_wayland_drm_syncobj_manager_class_init (MetaWaylandDrmSyncobjManagerClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = meta_wayland_drm_syncobj_manager_finalize; ++ ++ quark_syncobj_surface = g_quark_from_static_string ("drm-syncobj-quark"); ++} ++ ++static void ++meta_wayland_drm_syncobj_manager_init (MetaWaylandDrmSyncobjManager *drm_syncobj) ++{ ++ drm_syncobj->drm = -1; ++} ++ ++static void ++drm_syncobj_manager_bind (struct wl_client *client, ++ void *user_data, ++ uint32_t version, ++ uint32_t id) ++{ ++ MetaWaylandDrmSyncobjManager *drm_syncobj_manager = user_data; ++ struct wl_resource *resource; ++ ++ resource = wl_resource_create (client, ++ &wp_linux_drm_syncobj_manager_v1_interface, ++ version, ++ id); ++ wl_resource_set_implementation (resource, ++ &drm_syncobj_manager_implementation, ++ drm_syncobj_manager, ++ NULL); ++} ++ ++static MetaWaylandDrmSyncobjManager * ++meta_wayland_drm_syncobj_manager_new (MetaWaylandCompositor *compositor, ++ GError **error) ++{ ++ MetaContext *context = ++ meta_wayland_compositor_get_context (compositor); ++ MetaBackend *backend = meta_context_get_backend (context); ++ MetaEgl *egl = meta_backend_get_egl (backend); ++ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); ++ CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); ++ EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); ++ MetaWaylandDrmSyncobjManager *drm_syncobj_manager; ++ EGLDeviceEXT egl_device; ++ g_autofd int drm_fd = -1; ++ EGLAttrib attrib; ++ uint64_t timeline_supported = false; ++ const char *device_path = NULL; ++ ++ g_assert (backend && egl && clutter_backend && cogl_context && egl_display); ++ ++ if (!meta_egl_query_display_attrib (egl, egl_display, ++ EGL_DEVICE_EXT, &attrib, ++ error)) ++ return NULL; ++ ++ egl_device = (EGLDeviceEXT) attrib; ++ ++ if (meta_egl_egl_device_has_extensions (egl, egl_device, NULL, ++ "EGL_EXT_device_drm_render_node", ++ NULL)) ++ { ++ if (!meta_egl_query_device_string (egl, egl_device, ++ EGL_DRM_RENDER_NODE_FILE_EXT, ++ &device_path, error)) ++ return NULL; ++ } ++ ++ if (!device_path && ++ meta_egl_egl_device_has_extensions (egl, egl_device, NULL, ++ "EGL_EXT_device_drm", ++ NULL)) ++ { ++ if (!meta_egl_query_device_string (egl, egl_device, ++ EGL_DRM_DEVICE_FILE_EXT, ++ &device_path, error)) ++ return NULL; ++ } ++ ++ if (!device_path) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "Failed to find EGL device to initialize linux-drm-syncobj-v1"); ++ return NULL; ++ } ++ ++ drm_fd = open (device_path, O_RDWR | O_CLOEXEC); ++ if (drm_fd < 0) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_FAILED, ++ "Failed to open DRM device %s", ++ device_path); ++ return NULL; ++ } ++ ++ if (drmGetCap (drm_fd, DRM_CAP_SYNCOBJ_TIMELINE, &timeline_supported) != 0 ++ || !timeline_supported) ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "Failed to check DRM syncobj timeline capability"); ++ return NULL; ++ } ++ ++#ifdef HAVE_EVENTFD ++ if (drmSyncobjEventfd (drm_fd, 0, 0, -1, 0) != -1 || errno != ENOENT) ++#endif ++ { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ "drmSyncobjEventfd failed: linux-drm-syncobj requires eventfd support"); ++ return NULL; ++ } ++ ++ drm_syncobj_manager = g_object_new (META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER, NULL); ++ drm_syncobj_manager->drm = g_steal_fd (&drm_fd); ++ ++ if (!wl_global_create (compositor->wayland_display, ++ &wp_linux_drm_syncobj_manager_v1_interface, ++ 1, ++ drm_syncobj_manager, ++ drm_syncobj_manager_bind)) ++ { ++ g_error ("Failed to create wp_linux_drm_syncobj_manager_v1_interface global"); ++ } ++ ++ return drm_syncobj_manager; ++} ++ ++void ++meta_wayland_drm_syncobj_init (MetaWaylandCompositor *compositor) ++{ ++ g_autoptr (GError) error = NULL; ++ MetaWaylandDrmSyncobjManager *manager = ++ meta_wayland_drm_syncobj_manager_new (compositor, &error); ++ ++ if (!manager) ++ { ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) ++ { ++ meta_topic (META_DEBUG_WAYLAND, "Disabling explicit sync: %s", ++ error->message); ++ } ++ else ++ { ++ g_warning ("Failed to create linux-drm-syncobj-manager: %s", ++ error->message); ++ } ++ return; ++ } ++ ++ g_object_set_data_full (G_OBJECT (compositor), "-meta-wayland-drm-syncobj-manager", ++ manager, ++ g_object_unref); ++} ++ ++/* ++ * Validate that the appropriate acquire and release points have been set ++ * for this surface. ++ */ ++bool ++meta_wayland_surface_explicit_sync_validate (MetaWaylandSurface *surface, ++ MetaWaylandSurfaceState *state) ++{ ++ MetaWaylandSyncobjSurface *syncobj_surface = g_object_get_qdata (G_OBJECT (surface), ++ quark_syncobj_surface); ++ ++ if (!syncobj_surface) ++ return TRUE; ++ ++ if (state->buffer) ++ { ++ if (state->buffer->type != META_WAYLAND_BUFFER_TYPE_DMA_BUF) ++ { ++ wl_resource_post_error (syncobj_surface->resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_UNSUPPORTED_BUFFER, ++ "Explicit Sync only supported on dmabuf buffers"); ++ return FALSE; ++ } ++ ++ if (!state->drm_syncobj.acquire) ++ { ++ wl_resource_post_error (syncobj_surface->resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, ++ "No Acquire point provided"); ++ return FALSE; ++ } ++ ++ if (!state->drm_syncobj.release) ++ { ++ wl_resource_post_error (syncobj_surface->resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT, ++ "No Release point provided"); ++ return FALSE; ++ } ++ ++ if (state->drm_syncobj.acquire->timeline == state->drm_syncobj.release->timeline && ++ state->drm_syncobj.acquire->sync_point >= state->drm_syncobj.release->sync_point) ++ { ++ wl_resource_post_error (syncobj_surface->resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, ++ "Invalid Release and Acquire point combination"); ++ return FALSE; ++ } ++ } ++ else if (state->drm_syncobj.acquire || state->drm_syncobj.release) ++ { ++ wl_resource_post_error (syncobj_surface->resource, ++ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, ++ "Release or Acquire point set but no buffer attached"); ++ return FALSE; ++ } ++ ++ return TRUE; ++} +diff --git a/src/wayland/meta-wayland-linux-drm-syncobj.h b/src/wayland/meta-wayland-linux-drm-syncobj.h +new file mode 100644 +index 000000000..cfe361b7c +--- /dev/null ++++ b/src/wayland/meta-wayland-linux-drm-syncobj.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2023 NVIDIA Corporation. ++ * ++ * 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 . ++ * ++ * Written by: ++ * Austin Shafer ++ */ ++ ++#pragma once ++ ++#include ++ ++#include "wayland/meta-wayland-types.h" ++#include "wayland/meta-drm-timeline.h" ++ ++#include "linux-drm-syncobj-v1-server-protocol.h" ++ ++#define META_TYPE_WAYLAND_SYNC_POINT (meta_wayland_sync_point_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaWaylandSyncPoint, ++ meta_wayland_sync_point, ++ META, WAYLAND_SYNC_POINT, ++ GObject) ++ ++typedef struct _MetaWaylandSyncPoint { ++ GObject parent; ++ ++ MetaWaylandSyncobjTimeline *timeline; ++ uint64_t sync_point; ++} MetaWaylandSyncPoint; ++ ++bool ++meta_wayland_surface_explicit_sync_validate (MetaWaylandSurface *surface, ++ MetaWaylandSurfaceState *state); ++ ++void ++meta_wayland_drm_syncobj_init (MetaWaylandCompositor *compositor); ++ ++gboolean ++meta_wayland_sync_timeline_set_sync_point (MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ int sync_fd, ++ GError **error); ++ ++int ++meta_wayland_sync_timeline_get_eventfd (MetaWaylandSyncobjTimeline *timeline, ++ uint64_t sync_point, ++ GError **error); +diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c +index ebbe533c3..ea4d4608c 100644 +--- a/src/wayland/meta-wayland-seat.c ++++ b/src/wayland/meta-wayland-seat.c +@@ -531,6 +531,8 @@ void + meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, + MetaWaylandSurface *surface) + { ++ ClutterSeat *clutter_seat; ++ + if (seat->input_focus == surface) + return; + +@@ -551,16 +553,10 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, + seat); + } + +- if (meta_wayland_seat_has_keyboard (seat)) +- { +- meta_wayland_keyboard_set_focus (seat->keyboard, surface); +- meta_wayland_data_device_set_keyboard_focus (&seat->data_device); +- meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device); +- } +- +- meta_wayland_tablet_seat_set_pad_focus (seat->tablet_seat, surface); +- +- meta_wayland_text_input_set_focus (seat->text_input, surface); ++ clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); ++ meta_wayland_input_invalidate_focus (seat->input_handler, ++ clutter_seat_get_keyboard (clutter_seat), ++ NULL); + } + + MetaWaylandSurface * +diff --git a/src/wayland/meta-wayland-single-pixel-buffer.c b/src/wayland/meta-wayland-single-pixel-buffer.c +index 5b23b917a..be93de802 100644 +--- a/src/wayland/meta-wayland-single-pixel-buffer.c ++++ b/src/wayland/meta-wayland-single-pixel-buffer.c +@@ -122,7 +122,10 @@ meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer, + CoglTexture *tex_2d; + + if (buffer->single_pixel.texture) +- return TRUE; ++ { ++ *texture = g_object_ref (buffer->single_pixel.texture); ++ return TRUE; ++ } + + data[0] = single_pixel_buffer->b / (UINT32_MAX / 0xff); + data[1] = single_pixel_buffer->g / (UINT32_MAX / 0xff); +diff --git a/src/wayland/meta-wayland-surface-private.h b/src/wayland/meta-wayland-surface-private.h +index 2b61a2fc8..e3a88c0a3 100644 +--- a/src/wayland/meta-wayland-surface-private.h ++++ b/src/wayland/meta-wayland-surface-private.h +@@ -29,6 +29,7 @@ + #include "meta/meta-wayland-surface.h" + #include "wayland/meta-wayland-pointer-constraints.h" + #include "wayland/meta-wayland-types.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #define META_TYPE_WAYLAND_SURFACE_ROLE (meta_wayland_surface_role_get_type ()) + G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRole, meta_wayland_surface_role, +@@ -128,6 +129,12 @@ struct _MetaWaylandSurfaceState + /* xdg_popup */ + MetaWaylandXdgPositioner *xdg_positioner; + uint32_t xdg_popup_reposition_token; ++ ++ /* Explicit Synchronization */ ++ struct { ++ MetaWaylandSyncPoint *acquire; ++ MetaWaylandSyncPoint *release; ++ } drm_syncobj; + }; + + struct _MetaWaylandDragDestFuncs +diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c +index 0012798df..81ee47bbd 100644 +--- a/src/wayland/meta-wayland-surface.c ++++ b/src/wayland/meta-wayland-surface.c +@@ -48,6 +48,7 @@ + #include "wayland/meta-wayland-viewporter.h" + #include "wayland/meta-wayland-xdg-shell.h" + #include "wayland/meta-window-wayland.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #ifdef HAVE_XWAYLAND + #include "wayland/meta-xwayland-private.h" +@@ -446,6 +447,9 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) + wl_list_init (&state->presentation_feedback_list); + + state->xdg_popup_reposition_token = 0; ++ ++ state->drm_syncobj.acquire = NULL; ++ state->drm_syncobj.release = NULL; + } + + static void +@@ -466,6 +470,8 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) + MetaWaylandFrameCallback *cb, *next; + + g_clear_object (&state->texture); ++ g_clear_object (&state->drm_syncobj.acquire); ++ g_clear_object (&state->drm_syncobj.release); + + g_clear_pointer (&state->surface_damage, mtk_region_unref); + g_clear_pointer (&state->buffer_damage, mtk_region_unref); +@@ -630,6 +636,11 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, + to->xdg_positioner = g_steal_pointer (&from->xdg_positioner); + to->xdg_popup_reposition_token = from->xdg_popup_reposition_token; + } ++ ++ g_set_object (&to->drm_syncobj.acquire, from->drm_syncobj.acquire); ++ g_clear_object (&from->drm_syncobj.acquire); ++ g_set_object (&to->drm_syncobj.release, from->drm_syncobj.release); ++ g_clear_object (&from->drm_syncobj.release); + } + + static void +@@ -925,6 +936,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) + MetaWaylandBuffer *buffer = pending->buffer; + MetaWaylandTransaction *transaction; + MetaWaylandSurface *subsurface_surface; ++ MetaWaylandSyncPoint *release_point = pending->drm_syncobj.release; + + COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, + "Meta::WaylandSurface::commit()"); +@@ -932,6 +944,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) + if (pending->scale > 0) + surface->committed_state.scale = pending->scale; + ++ if (!meta_wayland_surface_explicit_sync_validate (surface, pending)) ++ return; ++ + if (buffer) + { + g_autoptr (GError) error = NULL; +@@ -957,6 +972,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) + + pending->texture = g_object_ref (surface->committed_state.texture); + ++ if (release_point) ++ g_ptr_array_add (buffer->release_points, g_object_ref (release_point)); ++ + g_object_ref (buffer); + meta_wayland_buffer_inc_use_count (buffer); + } +diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c +index 70f2b4047..694ce6dbe 100644 +--- a/src/wayland/meta-wayland-transaction.c ++++ b/src/wayland/meta-wayland-transaction.c +@@ -26,6 +26,7 @@ + #include "wayland/meta-wayland.h" + #include "wayland/meta-wayland-buffer.h" + #include "wayland/meta-wayland-dma-buf.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE) + +@@ -314,6 +315,17 @@ meta_wayland_transaction_dma_buf_dispatch (MetaWaylandBuffer *buffer, + meta_wayland_transaction_maybe_apply (transaction); + } + ++static void ++ensure_buf_sources (MetaWaylandTransaction *transaction) ++{ ++ if (!transaction->buf_sources) ++ { ++ transaction->buf_sources = ++ g_hash_table_new_full (NULL, NULL, NULL, ++ (GDestroyNotify) g_source_destroy); ++ } ++} ++ + static gboolean + meta_wayland_transaction_add_dma_buf_source (MetaWaylandTransaction *transaction, + MetaWaylandBuffer *buffer) +@@ -330,12 +342,35 @@ meta_wayland_transaction_add_dma_buf_source (MetaWaylandTransaction *transaction + if (!source) + return FALSE; + +- if (!transaction->buf_sources) +- { +- transaction->buf_sources = +- g_hash_table_new_full (NULL, NULL, NULL, +- (GDestroyNotify) g_source_destroy); +- } ++ ensure_buf_sources (transaction); ++ ++ g_hash_table_insert (transaction->buf_sources, buffer, source); ++ g_source_attach (source, NULL); ++ g_source_unref (source); ++ ++ return TRUE; ++} ++ ++static gboolean ++meta_wayland_transaction_add_drm_syncobj_source (MetaWaylandTransaction *transaction, ++ MetaWaylandBuffer *buffer, ++ MetaWaylandSyncPoint *acquire) ++{ ++ GSource *source; ++ ++ if (transaction->buf_sources && ++ g_hash_table_contains (transaction->buf_sources, buffer)) ++ return FALSE; ++ ++ source = meta_wayland_drm_syncobj_create_source (buffer, ++ acquire->timeline, ++ acquire->sync_point, ++ meta_wayland_transaction_dma_buf_dispatch, ++ transaction); ++ if (!source) ++ return FALSE; ++ ++ ensure_buf_sources (transaction); + + g_hash_table_insert (transaction->buf_sources, buffer, source); + g_source_attach (source, NULL); +@@ -382,8 +417,11 @@ meta_wayland_transaction_commit (MetaWaylandTransaction *transaction) + { + MetaWaylandBuffer *buffer = entry->state->buffer; + +- if (buffer && +- meta_wayland_transaction_add_dma_buf_source (transaction, buffer)) ++ if ((entry->state->drm_syncobj.acquire && ++ meta_wayland_transaction_add_drm_syncobj_source (transaction, buffer, ++ entry->state->drm_syncobj.acquire)) ++ || (buffer && ++ meta_wayland_transaction_add_dma_buf_source (transaction, buffer))) + maybe_apply = FALSE; + + if (entry->state->subsurface_placement_ops) +diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h +index 40c3bb733..4f224a900 100644 +--- a/src/wayland/meta-wayland-types.h ++++ b/src/wayland/meta-wayland-types.h +@@ -60,6 +60,8 @@ typedef struct _MetaWaylandActivation MetaWaylandActivation; + + typedef struct _MetaWaylandDmaBufManager MetaWaylandDmaBufManager; + ++typedef struct _MetaWaylandSyncobjTimeline MetaWaylandSyncobjTimeline; ++ + typedef struct _MetaWaylandXdgPositioner MetaWaylandXdgPositioner; + + typedef struct _MetaXWaylandManager MetaXWaylandManager; +diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c +index 4298d1eec..56fa77ad6 100644 +--- a/src/wayland/meta-wayland-window-configuration.c ++++ b/src/wayland/meta-wayland-window-configuration.c +@@ -100,14 +100,15 @@ meta_wayland_window_configuration_new_relative (MetaWindow *window, + + MetaWaylandWindowConfiguration * + meta_wayland_window_configuration_new_empty (int bounds_width, +- int bounds_height) ++ int bounds_height, ++ int scale) + { + MetaWaylandWindowConfiguration *configuration; + + configuration = g_new0 (MetaWaylandWindowConfiguration, 1); + *configuration = (MetaWaylandWindowConfiguration) { + .serial = ++global_serial_counter, +- .scale = 1, ++ .scale = scale, + .bounds_width = bounds_width, + .bounds_height = bounds_height, + }; +diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h +index 064e73ea1..fb26344bb 100644 +--- a/src/wayland/meta-wayland-window-configuration.h ++++ b/src/wayland/meta-wayland-window-configuration.h +@@ -68,6 +68,7 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative + int scale); + + MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (int bounds_width, +- int bounds_height); ++ int bounds_height, ++ int scale); + + void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); +diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c +index 28b39577b..ff1b7a11a 100644 +--- a/src/wayland/meta-wayland-xdg-shell.c ++++ b/src/wayland/meta-wayland-xdg-shell.c +@@ -869,6 +869,9 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandWindowConfiguration *configuration; + int bounds_width; + int bounds_height; ++ int geometry_scale; ++ ++ geometry_scale = meta_window_wayland_get_geometry_scale (window); + + if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) + { +@@ -878,7 +881,8 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + + configuration = + meta_wayland_window_configuration_new_empty (bounds_width, +- bounds_height); ++ bounds_height, ++ geometry_scale); + meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); + meta_wayland_window_configuration_free (configuration); + return; +diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c +index 7a24cf6b4..501b69a91 100644 +--- a/src/wayland/meta-wayland.c ++++ b/src/wayland/meta-wayland.c +@@ -57,6 +57,7 @@ + #include "wayland/meta-wayland-tablet-manager.h" + #include "wayland/meta-wayland-transaction.h" + #include "wayland/meta-wayland-xdg-foreign.h" ++#include "wayland/meta-wayland-linux-drm-syncobj.h" + + #ifdef HAVE_XWAYLAND + #include "wayland/meta-wayland-x11-interop.h" +@@ -868,6 +869,7 @@ meta_wayland_compositor_new (MetaContext *context) + meta_wayland_activation_init (compositor); + meta_wayland_transaction_init (compositor); + meta_wayland_idle_inhibit_init (compositor); ++ meta_wayland_drm_syncobj_init (compositor); + + #ifdef HAVE_WAYLAND_EGLSTREAM + { +diff --git a/src/wayland/protocol/linux-drm-syncobj-v1.xml b/src/wayland/protocol/linux-drm-syncobj-v1.xml +new file mode 100644 +index 000000000..2c491eaf4 +--- /dev/null ++++ b/src/wayland/protocol/linux-drm-syncobj-v1.xml +@@ -0,0 +1,261 @@ ++ ++ ++ ++ Copyright 2016 The Chromium Authors. ++ Copyright 2017 Intel Corporation ++ Copyright 2018 Collabora, Ltd ++ Copyright 2021 Simon Ser ++ ++ Permission is hereby granted, free of charge, to any person obtaining a ++ copy of this software and associated documentation files (the "Software"), ++ to deal in the Software without restriction, including without limitation ++ the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ and/or sell copies of the Software, and to permit persons to whom the ++ Software is furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice (including the next ++ paragraph) shall be included in all copies or substantial portions of the ++ Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. ++ ++ ++ ++ This protocol allows clients to request explicit synchronization for ++ buffers. It is tied to the Linux DRM synchronization object framework. ++ ++ Synchronization refers to co-ordination of pipelined operations performed ++ on buffers. Most GPU clients will schedule an asynchronous operation to ++ render to the buffer, then immediately send the buffer to the compositor ++ to be attached to a surface. ++ ++ With implicit synchronization, ensuring that the rendering operation is ++ complete before the compositor displays the buffer is an implementation ++ detail handled by either the kernel or userspace graphics driver. ++ ++ By contrast, with explicit synchronization, DRM synchronization object ++ timeline points mark when the asynchronous operations are complete. When ++ submitting a buffer, the client provides a timeline point which will be ++ waited on before the compositor accesses the buffer, and another timeline ++ point that the compositor will signal when it no longer needs to access the ++ buffer contents for the purposes of the surface commit. ++ ++ Linux DRM synchronization objects are documented at: ++ https://dri.freedesktop.org/docs/drm/gpu/drm-mm.html#drm-sync-objects ++ ++ Warning! The protocol described in this file is currently in the testing ++ phase. Backward compatible changes may be added together with the ++ corresponding interface version bump. Backward incompatible changes can ++ only be done by creating a new major version of the extension. ++ ++ ++ ++ ++ This global is a factory interface, allowing clients to request ++ explicit synchronization for buffers on a per-surface basis. ++ ++ See wp_linux_drm_syncobj_surface_v1 for more information. ++ ++ ++ ++ ++ Destroy this explicit synchronization factory object. Other objects ++ shall not be affected by this request. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Instantiate an interface extension for the given wl_surface to provide ++ explicit synchronization. ++ ++ If the given wl_surface already has an explicit synchronization object ++ associated, the surface_exists protocol error is raised. ++ ++ Graphics APIs, like EGL or Vulkan, that manage the buffer queue and ++ commits of a wl_surface themselves, are likely to be using this ++ extension internally. If a client is using such an API for a ++ wl_surface, it should not directly use this extension on that surface, ++ to avoid raising a surface_exists protocol error. ++ ++ ++ ++ ++ ++ ++ ++ Import a DRM synchronization object timeline. ++ ++ If the FD cannot be imported, the invalid_timeline error is raised. ++ ++ ++ ++ ++ ++ ++ ++ ++ This object represents an explicit synchronization object timeline ++ imported by the client to the compositor. ++ ++ ++ ++ ++ Destroy the synchronization object timeline. Other objects are not ++ affected by this request, in particular timeline points set by ++ set_acquire_point and set_release_point are not unset. ++ ++ ++ ++ ++ ++ ++ This object is an add-on interface for wl_surface to enable explicit ++ synchronization. ++ ++ Each surface can be associated with only one object of this interface at ++ any time. ++ ++ Explicit synchronization is guaranteed to be supported for buffers ++ created with any version of the linux-dmabuf protocol. Compositors are ++ free to support explicit synchronization for additional buffer types. ++ If at surface commit time the attached buffer does not support explicit ++ synchronization, an unsupported_buffer error is raised. ++ ++ As long as the wp_linux_drm_syncobj_surface_v1 object is alive, the ++ compositor may ignore implicit synchronization for buffers attached and ++ committed to the wl_surface. The delivery of wl_buffer.release events ++ for buffers attached to the surface becomes undefined. ++ ++ Clients must set both acquire and release points if and only if a ++ non-null buffer is attached in the same surface commit. See the ++ no_buffer, no_acquire_point and no_release_point protocol errors. ++ ++ If at surface commit time the acquire and release DRM syncobj timelines ++ are identical, the acquire point value must be strictly less than the ++ release point value, or else the conflicting_points protocol error is ++ raised. ++ ++ ++ ++ ++ Destroy this surface synchronization object. ++ ++ Any timeline point set by this object with set_acquire_point or ++ set_release_point since the last commit may be discarded by the ++ compositor. Any timeline point set by this object before the last ++ commit will not be affected. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Set the timeline point that must be signalled before the compositor may ++ sample from the buffer attached with wl_surface.attach. ++ ++ The 64-bit unsigned value combined from point_hi and point_lo is the ++ point value. ++ ++ The acquire point is double-buffered state, and will be applied on the ++ next wl_surface.commit request for the associated surface. Thus, it ++ applies only to the buffer that is attached to the surface at commit ++ time. ++ ++ If an acquire point has already been attached during the same commit ++ cycle, the new point replaces the old one. ++ ++ If the associated wl_surface was destroyed, a no_surface error is ++ raised. ++ ++ If at surface commit time there is a pending acquire timeline point set ++ but no pending buffer attached, a no_buffer error is raised. If at ++ surface commit time there is a pending buffer attached but no pending ++ acquire timeline point set, the no_acquire_point protocol error is ++ raised. ++ ++ ++ ++ ++ ++ ++ ++ ++ Set the timeline point that must be signalled by the compositor when it ++ has finished its usage of the buffer attached with wl_surface.attach ++ for the relevant commit. ++ ++ Once the timeline point is signaled, and assuming the associated buffer ++ is not pending release from other wl_surface.commit requests, no ++ additional explicit or implicit synchronization with the compositor is ++ required to safely re-use the buffer. ++ ++ Note that clients cannot rely on the release point being always ++ signaled after the acquire point: compositors may release buffers ++ without ever reading from them. In addition, the compositor may use ++ different presentation paths for different commits, which may have ++ different release behavior. As a result, the compositor may signal the ++ release points in a different order than the client committed them. ++ ++ Because signaling a timeline point also signals every previous point, ++ it is generally not safe to use the same timeline object for the ++ release points of multiple buffers. The out-of-order signaling ++ described above may lead to a release point being signaled before the ++ compositor has finished reading. To avoid this, it is strongly ++ recommended that each buffer should use a separate timeline for its ++ release points. ++ ++ The 64-bit unsigned value combined from point_hi and point_lo is the ++ point value. ++ ++ The release point is double-buffered state, and will be applied on the ++ next wl_surface.commit request for the associated surface. Thus, it ++ applies only to the buffer that is attached to the surface at commit ++ time. ++ ++ If a release point has already been attached during the same commit ++ cycle, the new point replaces the old one. ++ ++ If the associated wl_surface was destroyed, a no_surface error is ++ raised. ++ ++ If at surface commit time there is a pending release timeline point set ++ but no pending buffer attached, a no_buffer error is raised. If at ++ surface commit time there is a pending buffer attached but no pending ++ release timeline point set, the no_release_point protocol error is ++ raised. ++ ++ ++ ++ ++ ++ ++ diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 8aa8fc3..ca43edb 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.1 +Version: %{gnome_version}.xscaling.2 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -47,7 +47,15 @@ Patch: 0001-modified-3329.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 # Scaling for Xwayland applications -Patch: 3567.patch +Patch: 0002-3567.patch + +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ +# Nvidia secondary GPU copy acceleration +Patch: 0003-3304.patch + +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ +# Dynamic triple buffering +Patch: 0004-1441.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From 46054fe3f138d45aa7dc3c463321040c499d5020 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 11:28:16 -0700 Subject: [PATCH 08/41] chore: Manually number patches --- staging/mutter/mutter.spec | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index ca43edb..4a93836 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -25,37 +25,37 @@ URL: http://www.gnome.org Source0: https://download.gnome.org/sources/%{name}/%{gnome_major_version}/%{name}-%{tarball_version}.tar.xz # Work-around for OpenJDK's compliance test -Patch: 0001-window-actor-Special-case-shaped-Java-windows.patch +Patch0: 0001-window-actor-Special-case-shaped-Java-windows.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1936991 -Patch: mutter-42.alpha-disable-tegra.patch +Patch1: mutter-42.alpha-disable-tegra.patch # https://pagure.io/fedora-workstation/issue/79 -Patch: 0001-place-Always-center-initial-setup-fedora-welcome.patch +Patch2: 0001-place-Always-center-initial-setup-fedora-welcome.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2239128 # https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 # not upstreamed because for upstream we'd really want to find a way # to fix *both* problems -Patch: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch +Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329 # Modified to add the change from # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329#note_1874837 # which solves the problems reported with #3329 alone -Patch: 0001-modified-3329.patch +Patch4: 0001-modified-3329.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 # Scaling for Xwayland applications -Patch: 0002-3567.patch +Patch5: 0002-3567.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ # Nvidia secondary GPU copy acceleration -Patch: 0003-3304.patch +Patch6: 0003-3304.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ # Dynamic triple buffering -Patch: 0004-1441.patch +Patch7: 0004-1441.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From 01648e5d04098f1a80b70313794c13e3ee8d772f Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 11:53:19 -0700 Subject: [PATCH 09/41] chore: Minor fixes for triple buffering patch --- staging/mutter/0004-1441.patch | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index ce61d92..d5ca289 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -4844,14 +4844,6 @@ index f5ebc23fe..2f870fdc3 100644 .loop = g_main_loop_new (NULL, FALSE), }; -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png -new file mode 100644 -index 000000000..c2b0c2ff5 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png -new file mode 100644 -index 000000000..28fc7b266 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c index cb78489b4..8591e88d6 100644 --- a/src/tests/wayland-test-clients/buffer-transform.c @@ -6931,16 +6923,16 @@ index 59360e30a..3f64758a5 100644 #include "backends/meta-backend-private.h" #include "clutter/clutter.h" -@@ -59,6 +60,8 @@ +@@ -58,6 +59,8 @@ + #include "wayland/meta-wayland-private.h" #include "common/meta-cogl-drm-formats.h" - #include "common/meta-drm-format-helpers.h" #include "compositor/meta-multi-texture-format-private.h" +#include "wayland/meta-drm-timeline.h" +#include "wayland/meta-wayland-linux-drm-syncobj.h" #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -712,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) +@@ -711,12 +714,43 @@ void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) { @@ -6985,7 +6977,7 @@ index 59360e30a..3f64758a5 100644 } gboolean -@@ -981,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -980,6 +1014,7 @@ clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); @@ -6993,7 +6985,7 @@ index 59360e30a..3f64758a5 100644 g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -999,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -998,6 +1033,7 @@ static void meta_wayland_buffer_init (MetaWaylandBuffer *buffer) { @@ -7001,17 +6993,18 @@ index 59360e30a..3f64758a5 100644 } static void -@@ -1091,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) +@@ -1090,8 +1126,10 @@ drm_format = shm_to_drm_format (possible_formats[i]); format_info = meta_format_info_from_drm_format (drm_format); - g_assert (format_info); -+ + + if (!format_info) + continue; - ++ if (!context_supports_format (cogl_context, format_info)) continue; + diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index 23aea7cb2..a0d59f51b 100644 --- a/src/wayland/meta-wayland-buffer.h From b6a438c39bee6165857c25457031893b1ea57f21 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 13:24:23 -0700 Subject: [PATCH 10/41] fix: Remove triple buffering patch for now --- staging/mutter/mutter.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 4a93836..7bfcdd4 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -55,7 +55,7 @@ Patch6: 0003-3304.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ # Dynamic triple buffering -Patch7: 0004-1441.patch +# Patch7: 0004-1441.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From 58c05b9c100cea8211bbb53f20a8862658fc042b Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 13:28:43 -0700 Subject: [PATCH 11/41] chore: Increase version --- staging/mutter/mutter.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 7bfcdd4..f7d5d4d 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.2 +Version: %{gnome_version}.xscaling.3 Release: %autorelease Summary: Window and compositing manager based on Clutter From c24f994b3c671982ab72b2bd010b024d002672ad Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 16:16:59 -0700 Subject: [PATCH 12/41] Revert "fix: Remove triple buffering patch for now" This reverts commit b6a438c39bee6165857c25457031893b1ea57f21. --- staging/mutter/mutter.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index f7d5d4d..c884895 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.3 +Version: %{gnome_version}.xscaling.4 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -55,7 +55,7 @@ Patch6: 0003-3304.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ # Dynamic triple buffering -# Patch7: 0004-1441.patch +Patch7: 0004-1441.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From 458ddc381bb6ac6c4014f7b7f4605780ab7b1542 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 16:30:29 -0700 Subject: [PATCH 13/41] chore: Use upstream common package --- staging/mutter/mutter.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index c884895..4f519ca 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.4 +Version: %{gnome_version}.xscaling.5 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -126,7 +126,7 @@ Requires: startup-notification Requires: dbus # Need common -Requires: %{name}-common = %{version}-%{release} +Requires: %{name}-common = %{gnome_version}-%{release} Recommends: mesa-dri-drivers%{?_isa} From ff4116c991d9a4864ef4b98aabb87c3d76712b6a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 18:20:55 -0700 Subject: [PATCH 14/41] fix: Temporarily remove xwayland scaling patch while issue with Discord is addressed --- staging/mutter/0004-1441.patch | 31 +++++++++++++++---------------- staging/mutter/mutter.spec | 4 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index d5ca289..8dadb51 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -1282,7 +1282,7 @@ index 094d79616..9919bd4d0 100644 +/* Supports eventfd */ +#mesondefine HAVE_EVENTFD diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index 86421b7b0..7294c57a8 100644 +index 2fe8450a8..b05337d74 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml @@ -396,8 +396,8 @@ @@ -4559,7 +4559,7 @@ index 47c29d94a..c6c23708e 100644 /** diff --git a/src/meson.build b/src/meson.build -index f7797ff9c..e658f98ca 100644 +index 653ea0c9a..05df3bfd2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -579,6 +579,8 @@ if have_wayland @@ -4580,7 +4580,7 @@ index f7797ff9c..e658f98ca 100644 'wayland/meta-wayland-outputs.c', 'wayland/meta-wayland-outputs.h', 'wayland/meta-wayland-pointer.c', -@@ -1084,6 +1088,7 @@ if have_wayland +@@ -1079,6 +1083,7 @@ if have_wayland ['xdg-output', 'unstable', 'v1', ], ['xdg-shell', 'stable', ], ['xwayland-keyboard-grab', 'unstable', 'v1', ], @@ -6923,16 +6923,16 @@ index 59360e30a..3f64758a5 100644 #include "backends/meta-backend-private.h" #include "clutter/clutter.h" -@@ -58,6 +59,8 @@ - #include "wayland/meta-wayland-private.h" +@@ -59,6 +60,8 @@ #include "common/meta-cogl-drm-formats.h" + #include "common/meta-drm-format-helpers.h" #include "compositor/meta-multi-texture-format-private.h" +#include "wayland/meta-drm-timeline.h" +#include "wayland/meta-wayland-linux-drm-syncobj.h" #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -711,12 +714,43 @@ +@@ -712,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) { @@ -6977,7 +6977,7 @@ index 59360e30a..3f64758a5 100644 } gboolean -@@ -980,6 +1014,7 @@ +@@ -981,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); @@ -6985,7 +6985,7 @@ index 59360e30a..3f64758a5 100644 g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -998,6 +1033,7 @@ +@@ -999,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) static void meta_wayland_buffer_init (MetaWaylandBuffer *buffer) { @@ -6993,18 +6993,17 @@ index 59360e30a..3f64758a5 100644 } static void -@@ -1090,8 +1126,10 @@ +@@ -1091,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) drm_format = shm_to_drm_format (possible_formats[i]); format_info = meta_format_info_from_drm_format (drm_format); - g_assert (format_info); - ++ + if (!format_info) + continue; -+ + if (!context_supports_format (cogl_context, format_info)) continue; - diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index 23aea7cb2..a0d59f51b 100644 --- a/src/wayland/meta-wayland-buffer.h @@ -7872,7 +7871,7 @@ index 2b61a2fc8..e3a88c0a3 100644 struct _MetaWaylandDragDestFuncs diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index 0012798df..81ee47bbd 100644 +index b132504d3..6dc5006b7 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -48,6 +48,7 @@ @@ -7914,7 +7913,7 @@ index 0012798df..81ee47bbd 100644 } static void -@@ -925,6 +936,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -914,6 +925,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = pending->buffer; MetaWaylandTransaction *transaction; MetaWaylandSurface *subsurface_surface; @@ -7922,7 +7921,7 @@ index 0012798df..81ee47bbd 100644 COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, "Meta::WaylandSurface::commit()"); -@@ -932,6 +944,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -921,6 +933,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) if (pending->scale > 0) surface->committed_state.scale = pending->scale; @@ -7932,7 +7931,7 @@ index 0012798df..81ee47bbd 100644 if (buffer) { g_autoptr (GError) error = NULL; -@@ -957,6 +972,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -946,6 +961,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) pending->texture = g_object_ref (surface->committed_state.texture); diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 4f519ca..b58a1b8 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.5 +Version: %{gnome_version}.xscaling.6 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -47,7 +47,7 @@ Patch4: 0001-modified-3329.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 # Scaling for Xwayland applications -Patch5: 0002-3567.patch +# Patch5: 0002-3567.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ # Nvidia secondary GPU copy acceleration From 9cd01ee6ad7b30fb1586dba19c0454b321296c8f Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 18:21:05 -0700 Subject: [PATCH 15/41] chore: Remove unneeded binary files from patch --- staging/mutter/0004-1441.patch | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index 8dadb51..96edb10 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -4844,6 +4844,14 @@ index f5ebc23fe..2f870fdc3 100644 .loop = g_main_loop_new (NULL, FALSE), }; +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png +new file mode 100644 +index 000000000..c2b0c2ff5 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png +new file mode 100644 +index 000000000..28fc7b266 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c index cb78489b4..8591e88d6 100644 --- a/src/tests/wayland-test-clients/buffer-transform.c From 9d96c6164f165a202393ea8d10efa40ea73829a8 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 19:22:09 -0700 Subject: [PATCH 16/41] fix: Drop input region patch due to conflict with xwayland fractional scaling --- staging/mutter/0004-1441.patch | 39 ++++++++++++++-------------------- staging/mutter/mutter.spec | 6 +++--- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index 96edb10..d5ca289 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -1282,7 +1282,7 @@ index 094d79616..9919bd4d0 100644 +/* Supports eventfd */ +#mesondefine HAVE_EVENTFD diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index 2fe8450a8..b05337d74 100644 +index 86421b7b0..7294c57a8 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml @@ -396,8 +396,8 @@ @@ -4559,7 +4559,7 @@ index 47c29d94a..c6c23708e 100644 /** diff --git a/src/meson.build b/src/meson.build -index 653ea0c9a..05df3bfd2 100644 +index f7797ff9c..e658f98ca 100644 --- a/src/meson.build +++ b/src/meson.build @@ -579,6 +579,8 @@ if have_wayland @@ -4580,7 +4580,7 @@ index 653ea0c9a..05df3bfd2 100644 'wayland/meta-wayland-outputs.c', 'wayland/meta-wayland-outputs.h', 'wayland/meta-wayland-pointer.c', -@@ -1079,6 +1083,7 @@ if have_wayland +@@ -1084,6 +1088,7 @@ if have_wayland ['xdg-output', 'unstable', 'v1', ], ['xdg-shell', 'stable', ], ['xwayland-keyboard-grab', 'unstable', 'v1', ], @@ -4844,14 +4844,6 @@ index f5ebc23fe..2f870fdc3 100644 .loop = g_main_loop_new (NULL, FALSE), }; -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png -new file mode 100644 -index 000000000..c2b0c2ff5 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png -new file mode 100644 -index 000000000..28fc7b266 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c index cb78489b4..8591e88d6 100644 --- a/src/tests/wayland-test-clients/buffer-transform.c @@ -6931,16 +6923,16 @@ index 59360e30a..3f64758a5 100644 #include "backends/meta-backend-private.h" #include "clutter/clutter.h" -@@ -59,6 +60,8 @@ +@@ -58,6 +59,8 @@ + #include "wayland/meta-wayland-private.h" #include "common/meta-cogl-drm-formats.h" - #include "common/meta-drm-format-helpers.h" #include "compositor/meta-multi-texture-format-private.h" +#include "wayland/meta-drm-timeline.h" +#include "wayland/meta-wayland-linux-drm-syncobj.h" #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -712,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) +@@ -711,12 +714,43 @@ void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) { @@ -6985,7 +6977,7 @@ index 59360e30a..3f64758a5 100644 } gboolean -@@ -981,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -980,6 +1014,7 @@ clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); @@ -6993,7 +6985,7 @@ index 59360e30a..3f64758a5 100644 g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -999,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -998,6 +1033,7 @@ static void meta_wayland_buffer_init (MetaWaylandBuffer *buffer) { @@ -7001,17 +6993,18 @@ index 59360e30a..3f64758a5 100644 } static void -@@ -1091,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) +@@ -1090,8 +1126,10 @@ drm_format = shm_to_drm_format (possible_formats[i]); format_info = meta_format_info_from_drm_format (drm_format); - g_assert (format_info); -+ + + if (!format_info) + continue; - ++ if (!context_supports_format (cogl_context, format_info)) continue; + diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index 23aea7cb2..a0d59f51b 100644 --- a/src/wayland/meta-wayland-buffer.h @@ -7879,7 +7872,7 @@ index 2b61a2fc8..e3a88c0a3 100644 struct _MetaWaylandDragDestFuncs diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index b132504d3..6dc5006b7 100644 +index 0012798df..81ee47bbd 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -48,6 +48,7 @@ @@ -7921,7 +7914,7 @@ index b132504d3..6dc5006b7 100644 } static void -@@ -914,6 +925,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -925,6 +936,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = pending->buffer; MetaWaylandTransaction *transaction; MetaWaylandSurface *subsurface_surface; @@ -7929,7 +7922,7 @@ index b132504d3..6dc5006b7 100644 COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, "Meta::WaylandSurface::commit()"); -@@ -921,6 +933,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -932,6 +944,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) if (pending->scale > 0) surface->committed_state.scale = pending->scale; @@ -7939,7 +7932,7 @@ index b132504d3..6dc5006b7 100644 if (buffer) { g_autoptr (GError) error = NULL; -@@ -946,6 +961,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -957,6 +972,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) pending->texture = g_object_ref (surface->committed_state.texture); diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index b58a1b8..2da5324 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.6 +Version: %{gnome_version}.xscaling.7 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -37,7 +37,7 @@ Patch2: 0001-place-Always-center-initial-setup-fedora-welcome.patch # https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 # not upstreamed because for upstream we'd really want to find a way # to fix *both* problems -Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch +# Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329 # Modified to add the change from @@ -47,7 +47,7 @@ Patch4: 0001-modified-3329.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 # Scaling for Xwayland applications -# Patch5: 0002-3567.patch +Patch5: 0002-3567.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ # Nvidia secondary GPU copy acceleration From 9fe690f1467da86da68aaf09ac72ddfad4c5d65a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 19:34:58 -0700 Subject: [PATCH 17/41] chore: Drop one unneeded Fedora patch --- staging/mutter/0002-3567.patch | 56 ++++++++++----------- staging/mutter/0003-3304.patch | 16 +++--- staging/mutter/0004-1441.patch | 92 +++++++++++++++++----------------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/staging/mutter/0002-3567.patch b/staging/mutter/0002-3567.patch index b4eaaef..7e397f5 100644 --- a/staging/mutter/0002-3567.patch +++ b/staging/mutter/0002-3567.patch @@ -163,7 +163,7 @@ index 7d5e46ac7..577ed2760 100644 meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); } diff --git a/src/core/frame.c b/src/core/frame.c -index 1c90ce423..dbd111d76 100644 +index 145f0b7bd..502622598 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -33,6 +33,7 @@ @@ -173,8 +173,8 @@ index 1c90ce423..dbd111d76 100644 +#include "x11/window-x11.h" #include - -@@ -65,6 +66,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, + #include +@@ -66,6 +67,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, XSetWindowAttributes attrs; gulong create_serial = 0; MetaFrame *frame; @@ -182,7 +182,7 @@ index 1c90ce423..dbd111d76 100644 if (window->frame) return; -@@ -123,11 +125,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, +@@ -127,11 +129,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, meta_stack_tracker_record_remove (window->display->stack_tracker, meta_window_x11_get_xwindow (window), XNextRequest (x11_display->xdisplay)); @@ -204,7 +204,7 @@ index 1c90ce423..dbd111d76 100644 window->reparents_pending += 1; /* FIXME handle this error */ mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -197,6 +207,8 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -201,6 +211,8 @@ meta_window_destroy_frame (MetaWindow *window) if (!x11_display->closing) { @@ -213,7 +213,7 @@ index 1c90ce423..dbd111d76 100644 if (!window->unmanaging) { meta_stack_tracker_record_add (window->display->stack_tracker, -@@ -204,6 +216,14 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -208,6 +220,14 @@ meta_window_destroy_frame (MetaWindow *window) XNextRequest (x11_display->xdisplay)); } @@ -228,7 +228,7 @@ index 1c90ce423..dbd111d76 100644 XReparentWindow (x11_display->xdisplay, meta_window_x11_get_xwindow (window), x11_display->xroot, -@@ -211,8 +231,7 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -215,8 +235,7 @@ meta_window_destroy_frame (MetaWindow *window) * coordinates here means we'll need to ensure a configure * notify event is sent; see bug 399552. */ @@ -238,7 +238,7 @@ index 1c90ce423..dbd111d76 100644 window->reparents_pending += 1; } -@@ -263,6 +282,7 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -270,6 +289,7 @@ meta_frame_query_borders (MetaFrame *frame, MetaFrameBorders *borders) { MetaWindow *window = frame->window; @@ -246,7 +246,7 @@ index 1c90ce423..dbd111d76 100644 MetaX11Display *x11_display = window->display->x11_display; int format, res; Atom type; -@@ -288,12 +308,22 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -295,12 +315,22 @@ meta_frame_query_borders (MetaFrame *frame, if (res == Success && nitems == 4) { @@ -275,7 +275,7 @@ index 1c90ce423..dbd111d76 100644 } g_clear_pointer (&data, XFree); -@@ -314,12 +344,21 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -321,12 +351,21 @@ meta_frame_query_borders (MetaFrame *frame, if (res == Success && nitems == 4) { @@ -303,7 +303,7 @@ index 1c90ce423..dbd111d76 100644 } g_clear_pointer (&data, XFree); -@@ -363,7 +402,9 @@ meta_frame_sync_to_window (MetaFrame *frame, +@@ -370,7 +409,9 @@ meta_frame_sync_to_window (MetaFrame *frame, gboolean need_resize) { MetaWindow *window = frame->window; @@ -313,7 +313,7 @@ index 1c90ce423..dbd111d76 100644 meta_topic (META_DEBUG_GEOMETRY, "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", -@@ -374,12 +415,22 @@ meta_frame_sync_to_window (MetaFrame *frame, +@@ -381,12 +422,22 @@ meta_frame_sync_to_window (MetaFrame *frame, mtk_x11_error_trap_push (x11_display->xdisplay); @@ -340,7 +340,7 @@ index 1c90ce423..dbd111d76 100644 mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -416,6 +467,7 @@ static void +@@ -423,6 +474,7 @@ static void send_configure_notify (MetaFrame *frame) { MetaX11Display *x11_display = frame->window->display->x11_display; @@ -348,7 +348,7 @@ index 1c90ce423..dbd111d76 100644 XEvent event = { 0 }; /* We never get told by the frames client, just reassert the -@@ -425,10 +477,16 @@ send_configure_notify (MetaFrame *frame) +@@ -432,10 +484,16 @@ send_configure_notify (MetaFrame *frame) event.xconfigure.display = x11_display->xdisplay; event.xconfigure.event = frame->xwindow; event.xconfigure.window = frame->xwindow; @@ -1299,7 +1299,7 @@ index 5c0760daa..f67e9e427 100644 static Bool diff --git a/src/x11/window-props.c b/src/x11/window-props.c -index c18b3eab5..55c7b8b98 100644 +index c18b3eab5..6adb69bb8 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -305,10 +305,15 @@ reload_icon_geometry (MetaWindow *window, @@ -1436,7 +1436,7 @@ index c18b3eab5..55c7b8b98 100644 window->size_hints.flags = 0; diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index c2ae6bad7..45506120e 100644 +index a60650732..839759bc4 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) @@ -1745,9 +1745,9 @@ index c2ae6bad7..45506120e 100644 + attrs.border_width, 0, 0, 0, + &priv->border_width, NULL, NULL, NULL); - G_OBJECT_CLASS (meta_window_x11_parent_class)->constructed (object); - } -@@ -2188,6 +2340,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) + g_signal_connect (window, "notify::decorated", + G_CALLBACK (meta_window_x11_update_input_region), +@@ -2192,6 +2344,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) klass->thaw_commits = meta_window_x11_impl_thaw_commits; klass->always_update_shape = meta_window_x11_impl_always_update_shape; klass->process_property_notify = meta_window_x11_impl_process_property_notify; @@ -1756,7 +1756,7 @@ index c2ae6bad7..45506120e 100644 obj_props[PROP_ATTRIBUTES] = g_param_spec_pointer ("attributes", NULL, NULL, -@@ -2459,7 +2613,10 @@ meta_window_x11_update_input_region (MetaWindow *window) +@@ -2468,7 +2622,10 @@ meta_window_x11_update_input_region (MetaWindow *window) else { /* Window has a custom shape. */ @@ -1768,7 +1768,7 @@ index c2ae6bad7..45506120e 100644 } meta_XFree (rects); -@@ -2543,7 +2700,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) +@@ -2552,7 +2709,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) if (rects) { @@ -1780,7 +1780,7 @@ index c2ae6bad7..45506120e 100644 XFree (rects); } } -@@ -2821,6 +2981,7 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2830,6 +2990,7 @@ meta_window_x11_configure_request (MetaWindow *window, { MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); @@ -1788,7 +1788,7 @@ index c2ae6bad7..45506120e 100644 /* Note that x, y is the corner of the window border, * and width, height is the size of the window inside -@@ -2829,15 +2990,25 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2838,15 +2999,25 @@ meta_window_x11_configure_request (MetaWindow *window, * requested border here. */ if (event->xconfigurerequest.value_mask & CWBorderWidth) @@ -1822,7 +1822,7 @@ index c2ae6bad7..45506120e 100644 /* Handle stacking. We only handle raises/lowers, mostly because * stack.c really can't deal with anything else. I guess we'll fix -@@ -3332,8 +3503,13 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3341,8 +3512,13 @@ meta_window_x11_client_message (MetaWindow *window, guint32 timestamp; MetaWindowDrag *window_drag; @@ -1838,7 +1838,7 @@ index c2ae6bad7..45506120e 100644 action = event->xclient.data.l[2]; button = event->xclient.data.l[3]; -@@ -3497,6 +3673,7 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3506,6 +3682,7 @@ meta_window_x11_client_message (MetaWindow *window, { MetaGravity gravity; guint value_mask; @@ -1846,7 +1846,7 @@ index c2ae6bad7..45506120e 100644 gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; -@@ -3505,13 +3682,20 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3514,13 +3691,20 @@ meta_window_x11_client_message (MetaWindow *window, if (gravity == 0) gravity = window->size_hints.win_gravity; @@ -1871,7 +1871,7 @@ index c2ae6bad7..45506120e 100644 } else if (event->xclient.message_type == x11_display->atom__NET_ACTIVE_WINDOW && -@@ -3568,11 +3752,15 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3577,11 +3761,15 @@ meta_window_x11_client_message (MetaWindow *window, else if (event->xclient.message_type == x11_display->atom__GTK_SHOW_WINDOW_MENU) { @@ -1890,7 +1890,7 @@ index c2ae6bad7..45506120e 100644 meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); } -@@ -4094,10 +4282,11 @@ meta_window_x11_configure_notify (MetaWindow *window, +@@ -4103,10 +4291,11 @@ meta_window_x11_configure_notify (MetaWindow *window, g_assert (window->override_redirect); g_assert (window->frame == NULL); diff --git a/staging/mutter/0003-3304.patch b/staging/mutter/0003-3304.patch index 745e6b1..b3a7946 100644 --- a/staging/mutter/0003-3304.patch +++ b/staging/mutter/0003-3304.patch @@ -33,10 +33,10 @@ index 09bee954a..8b955c90c 100644 EGLDisplay display, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 405ce80a4..086e217cb 100644 +index e40b03f3e..2710352d1 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c -@@ -841,6 +841,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, +@@ -840,6 +840,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, "copy_shared_framebuffer_gpu()"); @@ -46,7 +46,7 @@ index 405ce80a4..086e217cb 100644 render_device = renderer_gpu_data->render_device; egl_display = meta_render_device_get_egl_display (render_device); -@@ -948,8 +951,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre +@@ -947,8 +950,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, "copy_shared_framebuffer_primary_gpu()"); @@ -56,7 +56,7 @@ index 405ce80a4..086e217cb 100644 return NULL; primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); -@@ -2418,6 +2420,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat +@@ -2417,6 +2419,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat width, height, format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); @@ -471,7 +471,7 @@ index 997fe6f69..2d3fe1971 100644 /* For GPU blit mode */ EGLContext egl_context; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index 5ffbafb58..aa76d018c 100644 +index 7b64ff3f4..893ee4216 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -63,6 +63,7 @@ @@ -482,7 +482,7 @@ index 5ffbafb58..aa76d018c 100644 #include "backends/native/meta-renderer-native-private.h" #include "backends/native/meta-renderer-view-native.h" #include "cogl/cogl.h" -@@ -137,6 +138,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data +@@ -136,6 +137,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); @@ -492,7 +492,7 @@ index 5ffbafb58..aa76d018c 100644 meta_egl_destroy_context (egl, egl_display, renderer_gpu_data->secondary.egl_context, -@@ -1806,6 +1810,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, +@@ -1805,6 +1809,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, CoglContext *cogl_context; CoglDisplay *cogl_display; const char **missing_gl_extensions; @@ -500,7 +500,7 @@ index 5ffbafb58..aa76d018c 100644 egl_display = meta_render_device_get_egl_display (render_device); if (egl_display == EGL_NO_DISPLAY) -@@ -1872,6 +1877,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, +@@ -1871,6 +1876,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, meta_egl_has_extensions (egl, egl_display, NULL, "EGL_EXT_image_dma_buf_import_modifiers", NULL); diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index d5ca289..f22aa64 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -3465,10 +3465,10 @@ index 743401406..f6b19520b 100644 MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 086e217cb..9836663d0 100644 +index 2710352d1..a2469aed7 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c -@@ -76,7 +76,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState +@@ -75,7 +75,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState struct { MetaDrmBufferDumb *current_dumb_fb; @@ -3477,7 +3477,7 @@ index 086e217cb..9836663d0 100644 } cpu; gboolean noted_primary_gpu_copy_ok; -@@ -98,9 +98,13 @@ struct _MetaOnscreenNative +@@ -97,9 +97,13 @@ struct _MetaOnscreenNative struct { struct gbm_surface *surface; MetaDrmBuffer *current_fb; @@ -3491,7 +3491,7 @@ index 086e217cb..9836663d0 100644 } gbm; #ifdef HAVE_EGL_DEVICE -@@ -125,6 +129,16 @@ struct _MetaOnscreenNative +@@ -124,6 +128,16 @@ struct _MetaOnscreenNative gulong privacy_screen_changed_handler_id; gulong color_space_changed_handler_id; gulong hdr_metadata_changed_handler_id; @@ -3508,7 +3508,7 @@ index 086e217cb..9836663d0 100644 }; G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, -@@ -132,44 +146,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, +@@ -131,44 +145,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, static GQuark blit_source_quark = 0; @@ -3569,7 +3569,7 @@ index 086e217cb..9836663d0 100644 } static void -@@ -207,7 +219,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) +@@ -206,7 +218,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) info = cogl_onscreen_pop_head_frame_info (onscreen); @@ -3578,7 +3578,7 @@ index 086e217cb..9836663d0 100644 _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); -@@ -243,6 +255,7 @@ notify_view_crtc_presented (MetaRendererView *view, +@@ -242,6 +254,7 @@ notify_view_crtc_presented (MetaRendererView *view, meta_onscreen_native_notify_frame_complete (onscreen); meta_onscreen_native_swap_drm_fb (onscreen); @@ -3586,7 +3586,7 @@ index 086e217cb..9836663d0 100644 } static void -@@ -292,15 +305,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, +@@ -291,15 +304,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); @@ -3603,7 +3603,7 @@ index 086e217cb..9836663d0 100644 } static void -@@ -350,7 +361,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, +@@ -349,7 +360,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -3613,7 +3613,7 @@ index 086e217cb..9836663d0 100644 } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -411,18 +423,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, +@@ -410,18 +422,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ @@ -3658,7 +3658,7 @@ index 086e217cb..9836663d0 100644 static void apply_transform (MetaCrtcKms *crtc_kms, MetaKmsPlaneAssignment *kms_plane_assignment, -@@ -506,6 +541,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -505,6 +540,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaGpuKms *gpu_kms; MetaDrmBuffer *buffer; MetaKmsPlaneAssignment *plane_assignment; @@ -3667,7 +3667,7 @@ index 086e217cb..9836663d0 100644 COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, "Meta::OnscreenNative::flip_crtc()"); -@@ -519,16 +556,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -518,16 +555,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -3695,7 +3695,7 @@ index 086e217cb..9836663d0 100644 &dst_rect); } else -@@ -919,12 +961,17 @@ static MetaDrmBufferDumb * +@@ -918,12 +960,17 @@ static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -3717,7 +3717,7 @@ index 086e217cb..9836663d0 100644 } static MetaDrmBuffer * -@@ -1256,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1255,10 +1302,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Page flip failed: %s", error->message); frame_info = cogl_onscreen_peek_head_frame_info (onscreen); @@ -3738,7 +3738,7 @@ index 086e217cb..9836663d0 100644 } static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1280,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1279,35 +1333,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -3806,7 +3806,7 @@ index 086e217cb..9836663d0 100644 parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); parent_class->swap_buffers_with_damage (onscreen, rectangles, -@@ -1362,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1361,11 +1438,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -3840,7 +3840,7 @@ index 086e217cb..9836663d0 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: break; -@@ -1376,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1375,6 +1473,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } @@ -3850,7 +3850,7 @@ index 086e217cb..9836663d0 100644 /* * If we changed EGL context, cogl will have the wrong idea about what is * current, making it fail to set it when it needs to. Avoid that by making -@@ -1385,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1384,12 +1485,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); @@ -3931,7 +3931,7 @@ index 086e217cb..9836663d0 100644 kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1405,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1404,15 +1571,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, onscreen_native->crtc, kms_update, META_KMS_ASSIGN_PLANE_FLAG_NONE, @@ -3949,7 +3949,7 @@ index 086e217cb..9836663d0 100644 return; } -@@ -1433,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1432,8 +1597,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -3958,7 +3958,7 @@ index 086e217cb..9836663d0 100644 return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1448,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1447,8 +1610,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -3967,7 +3967,7 @@ index 086e217cb..9836663d0 100644 return; } break; -@@ -1465,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1464,8 +1625,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -3976,7 +3976,7 @@ index 086e217cb..9836663d0 100644 return; } break; -@@ -1481,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1480,7 +1639,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -3984,7 +3984,7 @@ index 086e217cb..9836663d0 100644 } gboolean -@@ -1552,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1551,7 +1709,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Direct scanout page flip failed: %s", error->message); @@ -3993,7 +3993,7 @@ index 086e217cb..9836663d0 100644 onscreen); clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); -@@ -1562,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1561,7 +1719,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -4002,7 +4002,7 @@ index 086e217cb..9836663d0 100644 } static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1614,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1613,6 +1771,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -4021,7 +4021,7 @@ index 086e217cb..9836663d0 100644 renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); -@@ -1729,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, +@@ -1728,11 +1898,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -4033,7 +4033,7 @@ index 086e217cb..9836663d0 100644 maybe_update_frame_sync (onscreen_native, frame); } -@@ -1849,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1848,22 +2014,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -4121,7 +4121,7 @@ index 086e217cb..9836663d0 100644 meta_kms_update_add_result_listener (kms_update, &finish_frame_result_listener_vtable, NULL, -@@ -1887,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1886,7 +2109,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_update_set_flushing (kms_update, kms_crtc); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -4142,7 +4142,7 @@ index 086e217cb..9836663d0 100644 } static gboolean -@@ -2802,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2801,8 +3036,11 @@ meta_onscreen_native_dispose (GObject *object) { case META_RENDERER_NATIVE_MODE_GBM: g_clear_object (&onscreen_native->gbm.next_fb); @@ -4155,7 +4155,7 @@ index 086e217cb..9836663d0 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); -@@ -2837,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2836,6 +3074,10 @@ meta_onscreen_native_dispose (GObject *object) g_clear_object (&onscreen_native->output); g_clear_object (&onscreen_native->crtc); @@ -4180,10 +4180,10 @@ index 0e1193325..e30357d19 100644 MetaRendererView *view); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index aa76d018c..3c22b4e86 100644 +index 893ee4216..884f1ccef 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c -@@ -731,12 +731,18 @@ static gboolean +@@ -730,12 +730,18 @@ static gboolean dummy_power_save_page_flip_cb (gpointer user_data) { MetaRendererNative *renderer_native = user_data; @@ -4204,7 +4204,7 @@ index aa76d018c..3c22b4e86 100644 renderer_native->power_save_page_flip_source_id = 0; return G_SOURCE_REMOVE; -@@ -748,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na +@@ -747,6 +753,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na { const unsigned int timeout_ms = 100; @@ -4214,7 +4214,7 @@ index aa76d018c..3c22b4e86 100644 if (!renderer_native->power_save_page_flip_source_id) { renderer_native->power_save_page_flip_source_id = -@@ -1529,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) +@@ -1528,6 +1537,26 @@ detach_onscreens (MetaRenderer *renderer) } } @@ -4241,7 +4241,7 @@ index aa76d018c..3c22b4e86 100644 static void meta_renderer_native_rebuild_views (MetaRenderer *renderer) { -@@ -1539,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) +@@ -1538,6 +1567,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) MetaRendererClass *parent_renderer_class = META_RENDERER_CLASS (meta_renderer_native_parent_class); @@ -4559,7 +4559,7 @@ index 47c29d94a..c6c23708e 100644 /** diff --git a/src/meson.build b/src/meson.build -index f7797ff9c..e658f98ca 100644 +index ea2dcb2dd..f3e7e22af 100644 --- a/src/meson.build +++ b/src/meson.build @@ -579,6 +579,8 @@ if have_wayland @@ -4580,7 +4580,7 @@ index f7797ff9c..e658f98ca 100644 'wayland/meta-wayland-outputs.c', 'wayland/meta-wayland-outputs.h', 'wayland/meta-wayland-pointer.c', -@@ -1084,6 +1088,7 @@ if have_wayland +@@ -1082,6 +1086,7 @@ if have_wayland ['xdg-output', 'unstable', 'v1', ], ['xdg-shell', 'stable', ], ['xwayland-keyboard-grab', 'unstable', 'v1', ], @@ -6912,7 +6912,7 @@ index 000000000..8206e3066 + int sync_fd, + GError **error); diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c -index 59360e30a..3f64758a5 100644 +index a2ddcf567..1d245327e 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -49,6 +49,7 @@ @@ -6932,7 +6932,7 @@ index 59360e30a..3f64758a5 100644 #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -711,12 +714,43 @@ +@@ -711,12 +714,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) { @@ -6977,7 +6977,7 @@ index 59360e30a..3f64758a5 100644 } gboolean -@@ -980,6 +1014,7 @@ +@@ -980,6 +1014,7 @@ meta_wayland_buffer_finalize (GObject *object) clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); @@ -6985,7 +6985,7 @@ index 59360e30a..3f64758a5 100644 g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -998,6 +1033,7 @@ +@@ -998,6 +1033,7 @@ meta_wayland_buffer_finalize (GObject *object) static void meta_wayland_buffer_init (MetaWaylandBuffer *buffer) { @@ -6993,7 +6993,7 @@ index 59360e30a..3f64758a5 100644 } static void -@@ -1090,8 +1126,10 @@ +@@ -1090,8 +1126,10 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) drm_format = shm_to_drm_format (possible_formats[i]); format_info = meta_format_info_from_drm_format (drm_format); @@ -7019,10 +7019,10 @@ index 23aea7cb2..a0d59f51b 100644 #define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ()) diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c -index 8b326ecfa..5e4ee671c 100644 +index 221df3dc0..d23597b7f 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c -@@ -57,6 +57,7 @@ +@@ -56,6 +56,7 @@ #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-versions.h" @@ -7030,7 +7030,7 @@ index 8b326ecfa..5e4ee671c 100644 #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -1046,6 +1047,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, +@@ -1045,6 +1046,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, return &source->base; } From 01dbbe060c779531d6c0357df057696750127946 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 19:58:00 -0700 Subject: [PATCH 18/41] chore: Drop scaling patch, breaks Discord. --- staging/mutter/0004-1441.patch | 1170 ++++++++++++++++++++++++++++++-- staging/mutter/mutter.spec | 6 +- 2 files changed, 1118 insertions(+), 58 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index f22aa64..67c525a 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -1282,7 +1282,7 @@ index 094d79616..9919bd4d0 100644 +/* Supports eventfd */ +#mesondefine HAVE_EVENTFD diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index 86421b7b0..7294c57a8 100644 +index 2fe8450a8..b05337d74 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml @@ -396,8 +396,8 @@ @@ -3340,6 +3340,40 @@ index 3032d34c2..0d6cf40db 100644 } static void +diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c +index 9a57c52de..2f8247b3a 100644 +--- a/src/backends/meta-egl.c ++++ b/src/backends/meta-egl.c +@@ -260,6 +260,14 @@ meta_egl_has_extensions (MetaEgl *egl, + return has_extensions; + } + ++const char * ++meta_egl_query_string (MetaEgl *egl, ++ EGLDisplay display, ++ EGLint name) ++{ ++ return eglQueryString (display, name); ++} ++ + gboolean + meta_egl_initialize (MetaEgl *egl, + EGLDisplay display, +diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h +index 09bee954a..8b955c90c 100644 +--- a/src/backends/meta-egl.h ++++ b/src/backends/meta-egl.h +@@ -47,6 +47,10 @@ gboolean meta_egl_has_extensions (MetaEgl *egl, + const char *first_extension, + ...); + ++const char * meta_egl_query_string (MetaEgl *egl, ++ EGLDisplay display, ++ EGLint name); ++ + gboolean meta_egl_initialize (MetaEgl *egl, + EGLDisplay display, + GError **error); diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index 7aa24439d..727e1a5f3 100644 --- a/src/backends/meta-stage-impl.c @@ -3400,6 +3434,19 @@ index 161d43957..4ca8fb0f4 100644 } MetaDrmBufferGbm * +diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c +index a109b4ea2..30bbfb59a 100644 +--- a/src/backends/native/meta-drm-buffer.c ++++ b/src/backends/native/meta-drm-buffer.c +@@ -28,7 +28,7 @@ + + #include "backends/native/meta-device-pool.h" + #include "backends/native/meta-kms-utils.h" +-#include "common/meta-cogl-drm-formats.h" ++#include "common/meta-drm-format-helpers.h" + + #include "meta-private-enum-types.h" + diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index b15eee14d..05bc89e83 100644 --- a/src/backends/native/meta-kms-impl-device.c @@ -3465,10 +3512,18 @@ index 743401406..f6b19520b 100644 MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 2710352d1..a2469aed7 100644 +index e40b03f3e..9836663d0 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c -@@ -75,7 +75,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState +@@ -51,6 +51,7 @@ + #include "backends/native/meta-renderer-native-private.h" + #include "cogl/cogl.h" + #include "common/meta-cogl-drm-formats.h" ++#include "common/meta-drm-format-helpers.h" + + typedef enum _MetaSharedFramebufferImportStatus + { +@@ -75,7 +76,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState struct { MetaDrmBufferDumb *current_dumb_fb; @@ -3477,7 +3532,7 @@ index 2710352d1..a2469aed7 100644 } cpu; gboolean noted_primary_gpu_copy_ok; -@@ -97,9 +97,13 @@ struct _MetaOnscreenNative +@@ -97,9 +98,13 @@ struct _MetaOnscreenNative struct { struct gbm_surface *surface; MetaDrmBuffer *current_fb; @@ -3491,7 +3546,7 @@ index 2710352d1..a2469aed7 100644 } gbm; #ifdef HAVE_EGL_DEVICE -@@ -124,6 +128,16 @@ struct _MetaOnscreenNative +@@ -124,6 +129,16 @@ struct _MetaOnscreenNative gulong privacy_screen_changed_handler_id; gulong color_space_changed_handler_id; gulong hdr_metadata_changed_handler_id; @@ -3508,7 +3563,7 @@ index 2710352d1..a2469aed7 100644 }; G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, -@@ -131,44 +145,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, +@@ -131,44 +146,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, static GQuark blit_source_quark = 0; @@ -3569,7 +3624,7 @@ index 2710352d1..a2469aed7 100644 } static void -@@ -206,7 +218,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) +@@ -206,7 +219,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) info = cogl_onscreen_pop_head_frame_info (onscreen); @@ -3578,7 +3633,7 @@ index 2710352d1..a2469aed7 100644 _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); -@@ -242,6 +254,7 @@ notify_view_crtc_presented (MetaRendererView *view, +@@ -242,6 +255,7 @@ notify_view_crtc_presented (MetaRendererView *view, meta_onscreen_native_notify_frame_complete (onscreen); meta_onscreen_native_swap_drm_fb (onscreen); @@ -3586,7 +3641,7 @@ index 2710352d1..a2469aed7 100644 } static void -@@ -291,15 +304,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, +@@ -291,15 +305,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); @@ -3603,7 +3658,7 @@ index 2710352d1..a2469aed7 100644 } static void -@@ -349,7 +360,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, +@@ -349,7 +361,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -3613,7 +3668,7 @@ index 2710352d1..a2469aed7 100644 } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -410,18 +422,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, +@@ -410,18 +423,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ @@ -3658,7 +3713,7 @@ index 2710352d1..a2469aed7 100644 static void apply_transform (MetaCrtcKms *crtc_kms, MetaKmsPlaneAssignment *kms_plane_assignment, -@@ -505,6 +540,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -505,6 +541,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaGpuKms *gpu_kms; MetaDrmBuffer *buffer; MetaKmsPlaneAssignment *plane_assignment; @@ -3667,7 +3722,7 @@ index 2710352d1..a2469aed7 100644 COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, "Meta::OnscreenNative::flip_crtc()"); -@@ -518,16 +555,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -518,16 +556,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -3695,7 +3750,17 @@ index 2710352d1..a2469aed7 100644 &dst_rect); } else -@@ -918,12 +960,17 @@ static MetaDrmBufferDumb * +@@ -840,6 +883,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, + "copy_shared_framebuffer_gpu()"); + ++ if (renderer_gpu_data->secondary.needs_explicit_sync) ++ cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); ++ + render_device = renderer_gpu_data->render_device; + egl_display = meta_render_device_get_egl_display (render_device); + +@@ -915,12 +961,17 @@ static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -3717,7 +3782,17 @@ index 2710352d1..a2469aed7 100644 } static MetaDrmBuffer * -@@ -1255,10 +1302,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -947,8 +998,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre + COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, + "copy_shared_framebuffer_primary_gpu()"); + +- if (!secondary_gpu_state || +- secondary_gpu_state->egl_surface == EGL_NO_SURFACE) ++ if (!secondary_gpu_state) + return NULL; + + primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); +@@ -1253,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Page flip failed: %s", error->message); frame_info = cogl_onscreen_peek_head_frame_info (onscreen); @@ -3738,7 +3813,7 @@ index 2710352d1..a2469aed7 100644 } static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1279,35 +1333,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1277,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -3806,7 +3881,7 @@ index 2710352d1..a2469aed7 100644 parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); parent_class->swap_buffers_with_damage (onscreen, rectangles, -@@ -1361,11 +1438,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1359,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -3840,7 +3915,7 @@ index 2710352d1..a2469aed7 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: break; -@@ -1375,6 +1473,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1373,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } @@ -3850,7 +3925,7 @@ index 2710352d1..a2469aed7 100644 /* * If we changed EGL context, cogl will have the wrong idea about what is * current, making it fail to set it when it needs to. Avoid that by making -@@ -1384,12 +1485,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1382,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); @@ -3931,7 +4006,7 @@ index 2710352d1..a2469aed7 100644 kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1404,15 +1571,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1402,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, onscreen_native->crtc, kms_update, META_KMS_ASSIGN_PLANE_FLAG_NONE, @@ -3949,7 +4024,7 @@ index 2710352d1..a2469aed7 100644 return; } -@@ -1432,8 +1597,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1430,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -3958,7 +4033,7 @@ index 2710352d1..a2469aed7 100644 return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1447,8 +1610,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1445,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -3967,7 +4042,7 @@ index 2710352d1..a2469aed7 100644 return; } break; -@@ -1464,8 +1625,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1462,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -3976,7 +4051,7 @@ index 2710352d1..a2469aed7 100644 return; } break; -@@ -1480,7 +1639,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1478,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -3984,7 +4059,7 @@ index 2710352d1..a2469aed7 100644 } gboolean -@@ -1551,7 +1709,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1549,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Direct scanout page flip failed: %s", error->message); @@ -3993,7 +4068,7 @@ index 2710352d1..a2469aed7 100644 onscreen); clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); -@@ -1561,7 +1719,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1559,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -4002,7 +4077,7 @@ index 2710352d1..a2469aed7 100644 } static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1613,6 +1771,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1611,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -4021,7 +4096,7 @@ index 2710352d1..a2469aed7 100644 renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); -@@ -1728,11 +1898,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, +@@ -1726,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -4033,7 +4108,7 @@ index 2710352d1..a2469aed7 100644 maybe_update_frame_sync (onscreen_native, frame); } -@@ -1848,22 +2014,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1846,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -4121,7 +4196,7 @@ index 2710352d1..a2469aed7 100644 meta_kms_update_add_result_listener (kms_update, &finish_frame_result_listener_vtable, NULL, -@@ -1886,7 +2109,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1884,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_update_set_flushing (kms_update, kms_crtc); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -4142,7 +4217,23 @@ index 2710352d1..a2469aed7 100644 } static gboolean -@@ -2801,8 +3036,11 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2417,6 +2655,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat + width, height, + format, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); ++ ++ if (!gbm_surface) ++ { ++ gbm_surface = gbm_surface_create (gbm_device, ++ width, height, ++ format, ++ 0); ++ } ++ + if (!gbm_surface) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, +@@ -2790,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) { case META_RENDERER_NATIVE_MODE_GBM: g_clear_object (&onscreen_native->gbm.next_fb); @@ -4155,7 +4246,7 @@ index 2710352d1..a2469aed7 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); -@@ -2836,6 +3074,10 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2825,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) g_clear_object (&onscreen_native->output); g_clear_object (&onscreen_native->crtc); @@ -4179,11 +4270,432 @@ index 0e1193325..e30357d19 100644 void meta_onscreen_native_set_view (CoglOnscreen *onscreen, MetaRendererView *view); +diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c +index cf27ba8d4..0d50de177 100644 +--- a/src/backends/native/meta-renderer-native-gles3.c ++++ b/src/backends/native/meta-renderer-native-gles3.c +@@ -3,6 +3,7 @@ + /* + * Copyright (C) 2017 Red Hat + * Copyright (c) 2018 DisplayLink (UK) Ltd. ++ * Copyright (c) 2023 Canonical Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as +@@ -34,6 +35,7 @@ + #include "backends/meta-egl-ext.h" + #include "backends/meta-gles3.h" + #include "backends/meta-gles3-table.h" ++#include "meta/meta-debug.h" + + /* + * GL/gl.h being included may conflict with gl3.h on some architectures. +@@ -43,17 +45,240 @@ + #error "Somehow included OpenGL headers when we shouldn't have" + #endif + ++typedef struct _ContextData ++{ ++ GArray *buffer_support; ++ GLuint shader_program; ++} ContextData; ++ ++typedef struct ++{ ++ uint32_t drm_format; ++ uint64_t drm_modifier; ++ gboolean can_blit; ++} BufferTypeSupport; ++ + static void +-paint_egl_image (MetaGles3 *gles3, +- EGLImageKHR egl_image, +- int width, +- int height) ++context_data_free (ContextData *context_data) ++{ ++ g_array_free (context_data->buffer_support, TRUE); ++ g_free (context_data); ++} ++ ++static GQuark ++get_quark_for_egl_context (EGLContext egl_context) ++{ ++ char key[128]; ++ ++ g_snprintf (key, sizeof key, "EGLContext %p", egl_context); ++ ++ return g_quark_from_string (key); ++} ++ ++static gboolean ++can_blit_buffer (ContextData *context_data, ++ MetaEgl *egl, ++ EGLDisplay egl_display, ++ uint32_t drm_format, ++ uint64_t drm_modifier) ++{ ++ EGLint num_modifiers; ++ EGLuint64KHR *modifiers; ++ EGLBoolean *external_only; ++ g_autoptr (GError) error = NULL; ++ int i; ++ gboolean can_blit; ++ BufferTypeSupport support; ++ ++ can_blit = drm_modifier == DRM_FORMAT_MOD_LINEAR; ++ ++ for (i = 0; i < context_data->buffer_support->len; i++) ++ { ++ BufferTypeSupport *support = ++ &g_array_index (context_data->buffer_support, BufferTypeSupport, i); ++ ++ if (support->drm_format == drm_format && ++ support->drm_modifier == drm_modifier) ++ return support->can_blit; ++ } ++ ++ if (!meta_egl_has_extensions (egl, egl_display, NULL, ++ "EGL_EXT_image_dma_buf_import_modifiers", ++ NULL)) ++ { ++ meta_topic (META_DEBUG_RENDER, ++ "No support for EGL_EXT_image_dma_buf_import_modifiers, " ++ "assuming blitting linearly will still work."); ++ goto out; ++ } ++ ++ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, ++ drm_format, 0, NULL, NULL, ++ &num_modifiers, &error)) ++ { ++ meta_topic (META_DEBUG_RENDER, ++ "Failed to query supported DMA buffer modifiers (%s), " ++ "assuming blitting linearly will still work.", ++ error->message); ++ goto out; ++ } ++ ++ if (num_modifiers == 0) ++ goto out; ++ ++ modifiers = g_alloca0 (sizeof (EGLuint64KHR) * num_modifiers); ++ external_only = g_alloca0 (sizeof (EGLBoolean) * num_modifiers); ++ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, ++ drm_format, num_modifiers, ++ modifiers, external_only, ++ &num_modifiers, &error)) ++ { ++ g_warning ("Failed to requery supported DMA buffer modifiers: %s", ++ error->message); ++ can_blit = FALSE; ++ goto out; ++ } ++ ++ can_blit = FALSE; ++ for (i = 0; i < num_modifiers; i++) ++ { ++ if (drm_modifier == modifiers[i]) ++ { ++ can_blit = !external_only[i]; ++ goto out; ++ } ++ } ++ ++out: ++ support = (BufferTypeSupport) { ++ .drm_format = drm_format, ++ .drm_modifier = drm_modifier, ++ .can_blit = can_blit, ++ }; ++ g_array_append_val (context_data->buffer_support, support); ++ return can_blit; ++} ++ ++static GLuint ++load_shader (const char *src, ++ GLenum type) ++{ ++ GLuint shader = glCreateShader (type); ++ ++ if (shader) ++ { ++ GLint compiled; ++ ++ glShaderSource (shader, 1, &src, NULL); ++ glCompileShader (shader); ++ glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); ++ if (!compiled) ++ { ++ GLchar log[1024]; ++ ++ glGetShaderInfoLog (shader, sizeof (log) - 1, NULL, log); ++ log[sizeof (log) - 1] = '\0'; ++ g_warning ("load_shader compile failed: %s", log); ++ glDeleteShader (shader); ++ shader = 0; ++ } ++ } ++ ++ return shader; ++} ++ ++static void ++ensure_shader_program (ContextData *context_data, ++ MetaGles3 *gles3) ++{ ++ static const char vertex_shader_source[] = ++ "#version 100\n" ++ "attribute vec2 position;\n" ++ "attribute vec2 texcoord;\n" ++ "varying vec2 v_texcoord;\n" ++ "\n" ++ "void main()\n" ++ "{\n" ++ " gl_Position = vec4(position, 0.0, 1.0);\n" ++ " v_texcoord = texcoord;\n" ++ "}\n"; ++ ++ static const char fragment_shader_source[] = ++ "#version 100\n" ++ "#extension GL_OES_EGL_image_external : require\n" ++ "precision mediump float;\n" ++ "uniform samplerExternalOES s_texture;\n" ++ "varying vec2 v_texcoord;\n" ++ "\n" ++ " void main()\n" ++ "{\n" ++ " gl_FragColor = texture2D(s_texture, v_texcoord);\n" ++ "}\n"; ++ ++ static const GLfloat box[] = ++ { /* position texcoord */ ++ -1.0f, +1.0f, 0.0f, 0.0f, ++ +1.0f, +1.0f, 1.0f, 0.0f, ++ +1.0f, -1.0f, 1.0f, 1.0f, ++ -1.0f, -1.0f, 0.0f, 1.0f, ++ }; ++ GLint linked; ++ GLuint vertex_shader, fragment_shader; ++ GLint position_attrib, texcoord_attrib; ++ GLuint shader_program; ++ ++ if (context_data->shader_program) ++ return; ++ ++ shader_program = glCreateProgram (); ++ g_return_if_fail (shader_program); ++ context_data->shader_program = shader_program; ++ ++ vertex_shader = load_shader (vertex_shader_source, GL_VERTEX_SHADER); ++ g_return_if_fail (vertex_shader); ++ fragment_shader = load_shader (fragment_shader_source, GL_FRAGMENT_SHADER); ++ g_return_if_fail (fragment_shader); ++ ++ GLBAS (gles3, glAttachShader, (shader_program, vertex_shader)); ++ GLBAS (gles3, glAttachShader, (shader_program, fragment_shader)); ++ GLBAS (gles3, glLinkProgram, (shader_program)); ++ GLBAS (gles3, glGetProgramiv, (shader_program, GL_LINK_STATUS, &linked)); ++ if (!linked) ++ { ++ GLchar log[1024]; ++ ++ glGetProgramInfoLog (shader_program, sizeof (log) - 1, NULL, log); ++ log[sizeof (log) - 1] = '\0'; ++ g_warning ("Link failed: %s", log); ++ return; ++ } ++ ++ GLBAS (gles3, glUseProgram, (shader_program)); ++ ++ position_attrib = glGetAttribLocation (shader_program, "position"); ++ GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (position_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box)); ++ ++ texcoord_attrib = glGetAttribLocation (shader_program, "texcoord"); ++ GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box + 2)); ++} ++ ++static void ++blit_egl_image (MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height) + { + GLuint texture; + GLuint framebuffer; + + meta_gles3_clear_error (gles3); + ++ GLBAS (gles3, glViewport, (0, 0, width, height)); ++ + GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); + GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); + +@@ -85,6 +310,43 @@ paint_egl_image (MetaGles3 *gles3, + GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); + } + ++static void ++paint_egl_image (ContextData *context_data, ++ MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height) ++{ ++ GLuint texture; ++ ++ meta_gles3_clear_error (gles3); ++ ensure_shader_program (context_data, gles3); ++ ++ GLBAS (gles3, glViewport, (0, 0, width, height)); ++ ++ GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); ++ GLBAS (gles3, glGenTextures, (1, &texture)); ++ GLBAS (gles3, glBindTexture, (GL_TEXTURE_EXTERNAL_OES, texture)); ++ GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_EXTERNAL_OES, ++ egl_image)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_MAG_FILTER, ++ GL_NEAREST)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_MIN_FILTER, ++ GL_NEAREST)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_WRAP_S, ++ GL_CLAMP_TO_EDGE)); ++ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, ++ GL_TEXTURE_WRAP_T, ++ GL_CLAMP_TO_EDGE)); ++ ++ GLBAS (gles3, glDrawArrays, (GL_TRIANGLE_FAN, 0, 4)); ++ ++ GLBAS (gles3, glDeleteTextures, (1, &texture)); ++} ++ + gboolean + meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + MetaGles3 *gles3, +@@ -105,6 +367,28 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + uint32_t format; + EGLImageKHR egl_image; + gboolean use_modifiers; ++ GQuark context_data_quark; ++ ContextData *context_data; ++ gboolean can_blit; ++ ++ context_data_quark = get_quark_for_egl_context (egl_context); ++ context_data = g_object_get_qdata (G_OBJECT (gles3), context_data_quark); ++ if (!context_data) ++ { ++ context_data = g_new0 (ContextData, 1); ++ context_data->buffer_support = g_array_new (FALSE, FALSE, ++ sizeof (BufferTypeSupport)); ++ ++ g_object_set_qdata_full (G_OBJECT (gles3), ++ context_data_quark, ++ context_data, ++ (GDestroyNotify) context_data_free); ++ } ++ ++ can_blit = can_blit_buffer (context_data, ++ egl, egl_display, ++ gbm_bo_get_format (shared_bo), ++ gbm_bo_get_modifier (shared_bo)); + + shared_bo_fd = gbm_bo_get_fd (shared_bo); + if (shared_bo_fd < 0) +@@ -150,9 +434,21 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, + if (!egl_image) + return FALSE; + +- paint_egl_image (gles3, egl_image, width, height); ++ if (can_blit) ++ blit_egl_image (gles3, egl_image, width, height); ++ else ++ paint_egl_image (context_data, gles3, egl_image, width, height); + + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + + return TRUE; + } ++ ++void ++meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, ++ EGLContext egl_context) ++{ ++ GQuark context_data_quark = get_quark_for_egl_context (egl_context); ++ ++ g_object_set_qdata (G_OBJECT (gles3), context_data_quark, NULL); ++} +diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h +index 591ff82e1..f5791a171 100644 +--- a/src/backends/native/meta-renderer-native-gles3.h ++++ b/src/backends/native/meta-renderer-native-gles3.h +@@ -26,10 +26,13 @@ + #include "backends/meta-egl.h" + #include "backends/meta-gles3.h" + +-gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, +- MetaGles3 *gles3, +- EGLDisplay egl_display, +- EGLContext egl_context, +- EGLSurface egl_surface, +- struct gbm_bo *shared_bo, +- GError **error); ++gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, ++ MetaGles3 *gles3, ++ EGLDisplay egl_display, ++ EGLContext egl_context, ++ EGLSurface egl_surface, ++ struct gbm_bo *shared_bo, ++ GError **error); ++ ++void meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, ++ EGLContext egl_context); +diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h +index 997fe6f69..2d3fe1971 100644 +--- a/src/backends/native/meta-renderer-native-private.h ++++ b/src/backends/native/meta-renderer-native-private.h +@@ -60,6 +60,7 @@ typedef struct _MetaRendererNativeGpuData + struct { + MetaSharedFramebufferCopyMode copy_mode; + gboolean has_EGL_EXT_image_dma_buf_import_modifiers; ++ gboolean needs_explicit_sync; + + /* For GPU blit mode */ + EGLContext egl_context; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index 893ee4216..884f1ccef 100644 +index 7b64ff3f4..3c22b4e86 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c -@@ -730,12 +730,18 @@ static gboolean +@@ -63,10 +63,12 @@ + #include "backends/native/meta-output-kms.h" + #include "backends/native/meta-render-device-gbm.h" + #include "backends/native/meta-render-device-surfaceless.h" ++#include "backends/native/meta-renderer-native-gles3.h" + #include "backends/native/meta-renderer-native-private.h" + #include "backends/native/meta-renderer-view-native.h" + #include "cogl/cogl.h" + #include "common/meta-cogl-drm-formats.h" ++#include "common/meta-drm-format-helpers.h" + #include "core/boxes-private.h" + + #ifdef HAVE_EGL_DEVICE +@@ -136,6 +138,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data + MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; + MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); + ++ meta_renderer_native_gles3_forget_context (renderer_native->gles3, ++ renderer_gpu_data->secondary.egl_context); ++ + meta_egl_destroy_context (egl, + egl_display, + renderer_gpu_data->secondary.egl_context, +@@ -726,12 +731,18 @@ static gboolean dummy_power_save_page_flip_cb (gpointer user_data) { MetaRendererNative *renderer_native = user_data; @@ -4204,7 +4716,7 @@ index 893ee4216..884f1ccef 100644 renderer_native->power_save_page_flip_source_id = 0; return G_SOURCE_REMOVE; -@@ -747,6 +753,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na +@@ -743,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na { const unsigned int timeout_ms = 100; @@ -4214,7 +4726,7 @@ index 893ee4216..884f1ccef 100644 if (!renderer_native->power_save_page_flip_source_id) { renderer_native->power_save_page_flip_source_id = -@@ -1528,6 +1537,26 @@ detach_onscreens (MetaRenderer *renderer) +@@ -1524,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) } } @@ -4241,7 +4753,7 @@ index 893ee4216..884f1ccef 100644 static void meta_renderer_native_rebuild_views (MetaRenderer *renderer) { -@@ -1538,6 +1567,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) +@@ -1534,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) MetaRendererClass *parent_renderer_class = META_RENDERER_CLASS (meta_renderer_native_parent_class); @@ -4249,6 +4761,26 @@ index 893ee4216..884f1ccef 100644 meta_kms_discard_pending_page_flips (kms); g_hash_table_remove_all (renderer_native->mode_set_updates); +@@ -1805,6 +1840,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, + CoglContext *cogl_context; + CoglDisplay *cogl_display; + const char **missing_gl_extensions; ++ const char *egl_vendor; + + egl_display = meta_render_device_get_egl_display (render_device); + if (egl_display == EGL_NO_DISPLAY) +@@ -1871,6 +1907,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, + meta_egl_has_extensions (egl, egl_display, NULL, + "EGL_EXT_image_dma_buf_import_modifiers", + NULL); ++ ++ egl_vendor = meta_egl_query_string (egl, egl_display, EGL_VENDOR); ++ if (!g_strcmp0 (egl_vendor, "NVIDIA")) ++ renderer_gpu_data->secondary.needs_explicit_sync = TRUE; ++ + ret = TRUE; + out: + maybe_restore_cogl_egl_api (renderer_native); diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c index 41b78ec18..02eccc77d 100644 --- a/src/backends/x11/nested/meta-stage-x11-nested.c @@ -4262,6 +4794,170 @@ index 41b78ec18..02eccc77d 100644 cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info, frame); if (!clutter_frame_has_result (frame)) +diff --git a/src/common/meta-cogl-drm-formats.c b/src/common/meta-cogl-drm-formats.c +index 225d6b537..dee5c5134 100644 +--- a/src/common/meta-cogl-drm-formats.c ++++ b/src/common/meta-cogl-drm-formats.c +@@ -24,40 +24,6 @@ + + #include "common/meta-cogl-drm-formats.h" + +- +-/** +- * meta_drm_format_to_string: +- * @tmp: temporary buffer +- * @drm_format: DRM fourcc pixel format +- * +- * Returns a pointer to a string naming the given pixel format, +- * usually a pointer to the temporary buffer but not always. +- * Invalid formats may return nonsense names. +- * +- * When calling this, allocate one MetaDrmFormatBuf on the stack to +- * be used as the temporary buffer. +- */ +-const char * +-meta_drm_format_to_string (MetaDrmFormatBuf *tmp, +- uint32_t drm_format) +-{ +- int i; +- +- if (drm_format == DRM_FORMAT_INVALID) +- return "INVALID"; +- +- G_STATIC_ASSERT (sizeof (tmp->s) == 5); +- for (i = 0; i < 4; i++) +- { +- char c = (drm_format >> (i * 8)) & 0xff; +- tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; +- } +- +- tmp->s[i] = 0; +- +- return tmp->s; +-} +- + const MetaFormatInfo * + meta_format_info_from_drm_format (uint32_t drm_format) + { +diff --git a/src/common/meta-cogl-drm-formats.h b/src/common/meta-cogl-drm-formats.h +index dbbc88294..d64bbc241 100644 +--- a/src/common/meta-cogl-drm-formats.h ++++ b/src/common/meta-cogl-drm-formats.h +@@ -29,14 +29,6 @@ + + G_BEGIN_DECLS + +-typedef struct _MetaDrmFormatBuf +-{ +- char s[5]; +-} MetaDrmFormatBuf; +- +-const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, +- uint32_t drm_format); +- + typedef struct _MetaFormatInfo + { + uint32_t drm_format; +diff --git a/src/common/meta-drm-format-helpers.c b/src/common/meta-drm-format-helpers.c +new file mode 100644 +index 000000000..0fc28dc7a +--- /dev/null ++++ b/src/common/meta-drm-format-helpers.c +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2020 Georges Basile Stavracas Neto ++ * Copyright (C) 2023 Collabora Ltd. ++ * ++ * 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 "config.h" ++ ++#include "common/meta-drm-format-helpers.h" ++ ++#include ++#include ++ ++/** ++ * meta_drm_format_to_string: ++ * @tmp: temporary buffer ++ * @drm_format: DRM fourcc pixel format ++ * ++ * Returns a pointer to a string naming the given pixel format, ++ * usually a pointer to the temporary buffer but not always. ++ * Invalid formats may return nonsense names. ++ * ++ * When calling this, allocate one MetaDrmFormatBuf on the stack to ++ * be used as the temporary buffer. ++ */ ++const char * ++meta_drm_format_to_string (MetaDrmFormatBuf *tmp, ++ uint32_t drm_format) ++{ ++ int i; ++ ++ if (drm_format == DRM_FORMAT_INVALID) ++ return "INVALID"; ++ ++ G_STATIC_ASSERT (sizeof (tmp->s) == 5); ++ for (i = 0; i < 4; i++) ++ { ++ char c = (drm_format >> (i * 8)) & 0xff; ++ tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; ++ } ++ ++ tmp->s[i] = 0; ++ ++ return tmp->s; ++} +diff --git a/src/common/meta-drm-format-helpers.h b/src/common/meta-drm-format-helpers.h +new file mode 100644 +index 000000000..53834350f +--- /dev/null ++++ b/src/common/meta-drm-format-helpers.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2020 Georges Basile Stavracas Neto ++ * Copyright (C) 2023 Collabora Ltd. ++ * ++ * 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 ++ ++typedef struct _MetaDrmFormatBuf ++{ ++ char s[5]; ++} MetaDrmFormatBuf; ++ ++const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, ++ uint32_t drm_format); diff --git a/src/compositor/edge-resistance.c b/src/compositor/edge-resistance.c index f3005714b..338886255 100644 --- a/src/compositor/edge-resistance.c @@ -4559,7 +5255,7 @@ index 47c29d94a..c6c23708e 100644 /** diff --git a/src/meson.build b/src/meson.build -index ea2dcb2dd..f3e7e22af 100644 +index a8cf7e197..05df3bfd2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -579,6 +579,8 @@ if have_wayland @@ -4580,7 +5276,16 @@ index ea2dcb2dd..f3e7e22af 100644 'wayland/meta-wayland-outputs.c', 'wayland/meta-wayland-outputs.h', 'wayland/meta-wayland-pointer.c', -@@ -1082,6 +1086,7 @@ if have_wayland +@@ -869,6 +873,8 @@ if have_wayland or have_native_backend + mutter_sources += [ + 'common/meta-cogl-drm-formats.c', + 'common/meta-cogl-drm-formats.h', ++ 'common/meta-drm-format-helpers.c', ++ 'common/meta-drm-format-helpers.h', + ] + endif + +@@ -1077,6 +1083,7 @@ if have_wayland ['xdg-output', 'unstable', 'v1', ], ['xdg-shell', 'stable', ], ['xwayland-keyboard-grab', 'unstable', 'v1', ], @@ -4588,6 +5293,346 @@ index ea2dcb2dd..f3e7e22af 100644 ] if have_wayland_eglstream wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable('pkgdatadir') +diff --git a/src/meta/common.h b/src/meta/common.h +index ee978ac6a..ed3aa81ef 100644 +--- a/src/meta/common.h ++++ b/src/meta/common.h +@@ -27,6 +27,7 @@ + #include + + #include "clutter/clutter.h" ++#include "meta/meta-base.h" + #include "meta/meta-enums.h" + + /** +@@ -42,8 +43,6 @@ + /* Replacement for X11 CurrentTime */ + #define META_CURRENT_TIME 0L + +-#define META_EXPORT __attribute__((visibility("default"))) extern +- + #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST + + /* Keep array size in sync with MAX_BUTTONS_PER_CORNER */ +diff --git a/src/meta/meson.build b/src/meta/meson.build +index 655dedeaf..bc3910408 100644 +--- a/src/meta/meson.build ++++ b/src/meta/meson.build +@@ -9,6 +9,7 @@ mutter_public_headers = [ + 'keybindings.h', + 'main.h', + 'meta-backend.h', ++ 'meta-base.h', + 'meta-background.h', + 'meta-background-actor.h', + 'meta-background-content.h', +@@ -17,6 +18,7 @@ mutter_public_headers = [ + 'meta-close-dialog.h', + 'meta-cursor-tracker.h', + 'meta-context.h', ++ 'meta-debug.h', + 'meta-dnd.h', + 'meta-enums.h', + 'meta-idle-monitor.h', +diff --git a/src/meta/meta-base.h b/src/meta/meta-base.h +new file mode 100644 +index 000000000..e344b2221 +--- /dev/null ++++ b/src/meta/meta-base.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2001 Havoc Pennington ++ * Copyright (C) 2005 Elijah Newren ++ * ++ * 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 ++ ++#define META_EXPORT __attribute__((visibility("default"))) extern +diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h +new file mode 100644 +index 000000000..b4c70144b +--- /dev/null ++++ b/src/meta/meta-debug.h +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (C) 2001 Havoc Pennington ++ * Copyright (C) 2005 Elijah Newren ++ * ++ * 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 "meta/meta-base.h" ++ ++/** ++ * MetaDebugTopic: ++ * @META_DEBUG_VERBOSE: verbose logging ++ * @META_DEBUG_FOCUS: focus ++ * @META_DEBUG_WORKAREA: workarea ++ * @META_DEBUG_STACK: stack ++ * @META_DEBUG_SM: session management ++ * @META_DEBUG_EVENTS: events ++ * @META_DEBUG_WINDOW_STATE: window state ++ * @META_DEBUG_WINDOW_OPS: window operations ++ * @META_DEBUG_GEOMETRY: geometry ++ * @META_DEBUG_PLACEMENT: window placement ++ * @META_DEBUG_PING: ping ++ * @META_DEBUG_KEYBINDINGS: keybindings ++ * @META_DEBUG_SYNC: sync ++ * @META_DEBUG_STARTUP: startup ++ * @META_DEBUG_PREFS: preferences ++ * @META_DEBUG_GROUPS: groups ++ * @META_DEBUG_RESIZING: resizing ++ * @META_DEBUG_SHAPES: shapes ++ * @META_DEBUG_EDGE_RESISTANCE: edge resistance ++ * @META_DEBUG_WAYLAND: Wayland ++ * @META_DEBUG_KMS: kernel mode setting ++ * @META_DEBUG_SCREEN_CAST: screencasting ++ * @META_DEBUG_REMOTE_DESKTOP: remote desktop ++ * @META_DEBUG_BACKEND: backend ++ * @META_DEBUG_RENDER: native backend rendering ++ * @META_DEBUG_COLOR: color management ++ * @META_DEBUG_INPUT_EVENTS: input events ++ * @META_DEBUG_EIS: eis state ++ */ ++typedef enum ++{ ++ META_DEBUG_VERBOSE = -1, ++ META_DEBUG_FOCUS = 1 << 0, ++ META_DEBUG_WORKAREA = 1 << 1, ++ META_DEBUG_STACK = 1 << 2, ++ META_DEBUG_SM = 1 << 3, ++ META_DEBUG_EVENTS = 1 << 4, ++ META_DEBUG_WINDOW_STATE = 1 << 5, ++ META_DEBUG_WINDOW_OPS = 1 << 6, ++ META_DEBUG_GEOMETRY = 1 << 7, ++ META_DEBUG_PLACEMENT = 1 << 8, ++ META_DEBUG_PING = 1 << 9, ++ META_DEBUG_KEYBINDINGS = 1 << 10, ++ META_DEBUG_SYNC = 1 << 11, ++ META_DEBUG_STARTUP = 1 << 12, ++ META_DEBUG_PREFS = 1 << 13, ++ META_DEBUG_GROUPS = 1 << 14, ++ META_DEBUG_RESIZING = 1 << 15, ++ META_DEBUG_SHAPES = 1 << 16, ++ META_DEBUG_EDGE_RESISTANCE = 1 << 17, ++ META_DEBUG_DBUS = 1 << 18, ++ META_DEBUG_INPUT = 1 << 19, ++ META_DEBUG_WAYLAND = 1 << 20, ++ META_DEBUG_KMS = 1 << 21, ++ META_DEBUG_SCREEN_CAST = 1 << 22, ++ META_DEBUG_REMOTE_DESKTOP = 1 << 23, ++ META_DEBUG_BACKEND = 1 << 24, ++ META_DEBUG_RENDER = 1 << 25, ++ META_DEBUG_COLOR = 1 << 26, ++ META_DEBUG_INPUT_EVENTS = 1 << 27, ++ META_DEBUG_EIS = 1 << 28, ++} MetaDebugTopic; ++ ++META_EXPORT ++gboolean meta_is_topic_enabled (MetaDebugTopic topic); ++ ++/* To disable verbose mode, we make these functions into no-ops */ ++#ifdef WITH_VERBOSE_MODE ++ ++const char * meta_topic_to_string (MetaDebugTopic topic); ++ ++META_EXPORT ++void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); ++ ++#define meta_topic(debug_topic, ...) \ ++ G_STMT_START \ ++ { \ ++ if (meta_is_topic_enabled (debug_topic)) \ ++ { \ ++ g_autofree char *_topic_message = NULL; \ ++\ ++ _topic_message = g_strdup_printf (__VA_ARGS__); \ ++ meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ ++ _topic_message); \ ++ } \ ++ } \ ++ G_STMT_END ++ ++#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) ++ ++#else ++ ++# ifdef G_HAVE_ISO_VARARGS ++# define meta_verbose(...) ++# define meta_topic(...) ++# elif defined(G_HAVE_GNUC_VARARGS) ++# define meta_verbose(format...) ++# define meta_topic(format...) ++# else ++# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" ++# endif ++ ++#endif /* !WITH_VERBOSE_MODE */ +diff --git a/src/meta/util.h b/src/meta/util.h +index 0019c8078..ca8ca2ade 100644 +--- a/src/meta/util.h ++++ b/src/meta/util.h +@@ -26,6 +26,7 @@ + #include + + #include "meta/common.h" ++#include "meta/meta-debug.h" + #include "meta/meta-later.h" + + META_EXPORT +@@ -46,71 +47,6 @@ META_EXPORT + void meta_fatal (const char *format, + ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN G_ANALYZER_NORETURN; + +-/** +- * MetaDebugTopic: +- * @META_DEBUG_VERBOSE: verbose logging +- * @META_DEBUG_FOCUS: focus +- * @META_DEBUG_WORKAREA: workarea +- * @META_DEBUG_STACK: stack +- * @META_DEBUG_SM: session management +- * @META_DEBUG_EVENTS: events +- * @META_DEBUG_WINDOW_STATE: window state +- * @META_DEBUG_WINDOW_OPS: window operations +- * @META_DEBUG_GEOMETRY: geometry +- * @META_DEBUG_PLACEMENT: window placement +- * @META_DEBUG_PING: ping +- * @META_DEBUG_KEYBINDINGS: keybindings +- * @META_DEBUG_SYNC: sync +- * @META_DEBUG_STARTUP: startup +- * @META_DEBUG_PREFS: preferences +- * @META_DEBUG_GROUPS: groups +- * @META_DEBUG_RESIZING: resizing +- * @META_DEBUG_SHAPES: shapes +- * @META_DEBUG_EDGE_RESISTANCE: edge resistance +- * @META_DEBUG_WAYLAND: Wayland +- * @META_DEBUG_KMS: kernel mode setting +- * @META_DEBUG_SCREEN_CAST: screencasting +- * @META_DEBUG_REMOTE_DESKTOP: remote desktop +- * @META_DEBUG_BACKEND: backend +- * @META_DEBUG_RENDER: native backend rendering +- * @META_DEBUG_COLOR: color management +- * @META_DEBUG_INPUT_EVENTS: input events +- * @META_DEBUG_EIS: eis state +- */ +-typedef enum +-{ +- META_DEBUG_VERBOSE = -1, +- META_DEBUG_FOCUS = 1 << 0, +- META_DEBUG_WORKAREA = 1 << 1, +- META_DEBUG_STACK = 1 << 2, +- META_DEBUG_SM = 1 << 3, +- META_DEBUG_EVENTS = 1 << 4, +- META_DEBUG_WINDOW_STATE = 1 << 5, +- META_DEBUG_WINDOW_OPS = 1 << 6, +- META_DEBUG_GEOMETRY = 1 << 7, +- META_DEBUG_PLACEMENT = 1 << 8, +- META_DEBUG_PING = 1 << 9, +- META_DEBUG_KEYBINDINGS = 1 << 10, +- META_DEBUG_SYNC = 1 << 11, +- META_DEBUG_STARTUP = 1 << 12, +- META_DEBUG_PREFS = 1 << 13, +- META_DEBUG_GROUPS = 1 << 14, +- META_DEBUG_RESIZING = 1 << 15, +- META_DEBUG_SHAPES = 1 << 16, +- META_DEBUG_EDGE_RESISTANCE = 1 << 17, +- META_DEBUG_DBUS = 1 << 18, +- META_DEBUG_INPUT = 1 << 19, +- META_DEBUG_WAYLAND = 1 << 20, +- META_DEBUG_KMS = 1 << 21, +- META_DEBUG_SCREEN_CAST = 1 << 22, +- META_DEBUG_REMOTE_DESKTOP = 1 << 23, +- META_DEBUG_BACKEND = 1 << 24, +- META_DEBUG_RENDER = 1 << 25, +- META_DEBUG_COLOR = 1 << 26, +- META_DEBUG_INPUT_EVENTS = 1 << 27, +- META_DEBUG_EIS = 1 << 28, +-} MetaDebugTopic; +- + /** + * MetaDebugPaintFlag: + * @META_DEBUG_PAINT_NONE: default +@@ -122,9 +58,6 @@ typedef enum + META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, + } MetaDebugPaintFlag; + +-META_EXPORT +-gboolean meta_is_topic_enabled (MetaDebugTopic topic); +- + META_EXPORT + void meta_add_verbose_topic (MetaDebugTopic topic); + +@@ -155,44 +88,6 @@ char* meta_external_binding_name_for_action (guint keybinding_action); + META_EXPORT + char* meta_g_utf8_strndup (const gchar *src, gsize n); + +-/* To disable verbose mode, we make these functions into no-ops */ +-#ifdef WITH_VERBOSE_MODE +- +-const char * meta_topic_to_string (MetaDebugTopic topic); +- +-META_EXPORT +-void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); +- +-#define meta_topic(debug_topic, ...) \ +- G_STMT_START \ +- { \ +- if (meta_is_topic_enabled (debug_topic)) \ +- { \ +- g_autofree char *_topic_message = NULL; \ +-\ +- _topic_message = g_strdup_printf (__VA_ARGS__); \ +- meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ +- _topic_message); \ +- } \ +- } \ +- G_STMT_END +- +-#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) +- +-#else +- +-# ifdef G_HAVE_ISO_VARARGS +-# define meta_verbose(...) +-# define meta_topic(...) +-# elif defined(G_HAVE_GNUC_VARARGS) +-# define meta_verbose(format...) +-# define meta_topic(format...) +-# else +-# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" +-# endif +- +-#endif /* !WITH_VERBOSE_MODE */ +- + typedef enum + { + META_LOCALE_DIRECTION_LTR, diff --git a/src/tests/mtk/region-tests.c b/src/tests/mtk/region-tests.c index 7e41a53f0..c9ebc2adb 100644 --- a/src/tests/mtk/region-tests.c @@ -4844,6 +5889,14 @@ index f5ebc23fe..2f870fdc3 100644 .loop = g_main_loop_new (NULL, FALSE), }; +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png +new file mode 100644 +index 000000000..c2b0c2ff5 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ +diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png +new file mode 100644 +index 000000000..28fc7b266 +Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c index cb78489b4..8591e88d6 100644 --- a/src/tests/wayland-test-clients/buffer-transform.c @@ -6912,7 +7965,7 @@ index 000000000..8206e3066 + int sync_fd, + GError **error); diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c -index a2ddcf567..1d245327e 100644 +index a2ddcf567..3f64758a5 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -49,6 +49,7 @@ @@ -6923,16 +7976,18 @@ index a2ddcf567..1d245327e 100644 #include "backends/meta-backend-private.h" #include "clutter/clutter.h" -@@ -58,6 +59,8 @@ +@@ -57,7 +58,10 @@ + #include "wayland/meta-wayland-dma-buf.h" #include "wayland/meta-wayland-private.h" #include "common/meta-cogl-drm-formats.h" ++#include "common/meta-drm-format-helpers.h" #include "compositor/meta-multi-texture-format-private.h" +#include "wayland/meta-drm-timeline.h" +#include "wayland/meta-wayland-linux-drm-syncobj.h" #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -711,12 +714,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) +@@ -711,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) { @@ -6977,7 +8032,7 @@ index a2ddcf567..1d245327e 100644 } gboolean -@@ -980,6 +1014,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -980,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); @@ -6985,7 +8040,7 @@ index a2ddcf567..1d245327e 100644 g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -998,6 +1033,7 @@ meta_wayland_buffer_finalize (GObject *object) +@@ -998,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) static void meta_wayland_buffer_init (MetaWaylandBuffer *buffer) { @@ -6993,18 +8048,17 @@ index a2ddcf567..1d245327e 100644 } static void -@@ -1090,8 +1126,10 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) +@@ -1090,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) drm_format = shm_to_drm_format (possible_formats[i]); format_info = meta_format_info_from_drm_format (drm_format); - g_assert (format_info); - ++ + if (!format_info) + continue; -+ + if (!context_supports_format (cogl_context, format_info)) continue; - diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index 23aea7cb2..a0d59f51b 100644 --- a/src/wayland/meta-wayland-buffer.h @@ -7019,10 +8073,16 @@ index 23aea7cb2..a0d59f51b 100644 #define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ()) diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c -index 221df3dc0..d23597b7f 100644 +index 221df3dc0..5e4ee671c 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c -@@ -56,6 +56,7 @@ +@@ -51,11 +51,13 @@ + #include "cogl/cogl-egl.h" + #include "cogl/cogl.h" + #include "common/meta-cogl-drm-formats.h" ++#include "common/meta-drm-format-helpers.h" + #include "compositor/meta-multi-texture-format-private.h" + #include "meta/meta-backend.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-versions.h" @@ -7030,7 +8090,7 @@ index 221df3dc0..d23597b7f 100644 #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-drm-buffer-gbm.h" -@@ -1045,6 +1046,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, +@@ -1045,6 +1047,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, return &source->base; } @@ -7872,7 +8932,7 @@ index 2b61a2fc8..e3a88c0a3 100644 struct _MetaWaylandDragDestFuncs diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index 0012798df..81ee47bbd 100644 +index b132504d3..6dc5006b7 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -48,6 +48,7 @@ @@ -7914,7 +8974,7 @@ index 0012798df..81ee47bbd 100644 } static void -@@ -925,6 +936,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -914,6 +925,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = pending->buffer; MetaWaylandTransaction *transaction; MetaWaylandSurface *subsurface_surface; @@ -7922,7 +8982,7 @@ index 0012798df..81ee47bbd 100644 COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, "Meta::WaylandSurface::commit()"); -@@ -932,6 +944,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -921,6 +933,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) if (pending->scale > 0) surface->committed_state.scale = pending->scale; @@ -7932,7 +8992,7 @@ index 0012798df..81ee47bbd 100644 if (buffer) { g_autoptr (GError) error = NULL; -@@ -957,6 +972,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -946,6 +961,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) pending->texture = g_object_ref (surface->committed_state.texture); diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 2da5324..624bbab 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.7 +Version: %{gnome_version}.xscaling.8 Release: %autorelease Summary: Window and compositing manager based on Clutter @@ -37,7 +37,7 @@ Patch2: 0001-place-Always-center-initial-setup-fedora-welcome.patch # https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 # not upstreamed because for upstream we'd really want to find a way # to fix *both* problems -# Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch +Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329 # Modified to add the change from @@ -47,7 +47,7 @@ Patch4: 0001-modified-3329.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 # Scaling for Xwayland applications -Patch5: 0002-3567.patch +# Patch5: 0002-3567.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ # Nvidia secondary GPU copy acceleration From 9f129f5334ede9b0350ad0540c3cf6d6551b64af Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 20:14:57 -0700 Subject: [PATCH 19/41] chore: Update patch files for new order --- staging/mutter/0004-1441.patch | 895 +-------------------------------- staging/mutter/mutter.spec | 8 +- 2 files changed, 28 insertions(+), 875 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index 67c525a..380efbf 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -3340,40 +3340,6 @@ index 3032d34c2..0d6cf40db 100644 } static void -diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c -index 9a57c52de..2f8247b3a 100644 ---- a/src/backends/meta-egl.c -+++ b/src/backends/meta-egl.c -@@ -260,6 +260,14 @@ meta_egl_has_extensions (MetaEgl *egl, - return has_extensions; - } - -+const char * -+meta_egl_query_string (MetaEgl *egl, -+ EGLDisplay display, -+ EGLint name) -+{ -+ return eglQueryString (display, name); -+} -+ - gboolean - meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, -diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h -index 09bee954a..8b955c90c 100644 ---- a/src/backends/meta-egl.h -+++ b/src/backends/meta-egl.h -@@ -47,6 +47,10 @@ gboolean meta_egl_has_extensions (MetaEgl *egl, - const char *first_extension, - ...); - -+const char * meta_egl_query_string (MetaEgl *egl, -+ EGLDisplay display, -+ EGLint name); -+ - gboolean meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, - GError **error); diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index 7aa24439d..727e1a5f3 100644 --- a/src/backends/meta-stage-impl.c @@ -3512,7 +3478,7 @@ index 743401406..f6b19520b 100644 MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index e40b03f3e..9836663d0 100644 +index 2710352d1..9836663d0 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -51,6 +51,7 @@ @@ -3750,17 +3716,7 @@ index e40b03f3e..9836663d0 100644 &dst_rect); } else -@@ -840,6 +883,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, - "copy_shared_framebuffer_gpu()"); - -+ if (renderer_gpu_data->secondary.needs_explicit_sync) -+ cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); -+ - render_device = renderer_gpu_data->render_device; - egl_display = meta_render_device_get_egl_display (render_device); - -@@ -915,12 +961,17 @@ static MetaDrmBufferDumb * +@@ -918,12 +961,17 @@ static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -3782,17 +3738,7 @@ index e40b03f3e..9836663d0 100644 } static MetaDrmBuffer * -@@ -947,8 +998,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, - "copy_shared_framebuffer_primary_gpu()"); - -- if (!secondary_gpu_state || -- secondary_gpu_state->egl_surface == EGL_NO_SURFACE) -+ if (!secondary_gpu_state) - return NULL; - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); -@@ -1253,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1255,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Page flip failed: %s", error->message); frame_info = cogl_onscreen_peek_head_frame_info (onscreen); @@ -3813,7 +3759,7 @@ index e40b03f3e..9836663d0 100644 } static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1277,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1279,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -3881,7 +3827,7 @@ index e40b03f3e..9836663d0 100644 parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); parent_class->swap_buffers_with_damage (onscreen, rectangles, -@@ -1359,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1361,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -3915,7 +3861,7 @@ index e40b03f3e..9836663d0 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: break; -@@ -1373,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1375,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } @@ -3925,7 +3871,7 @@ index e40b03f3e..9836663d0 100644 /* * If we changed EGL context, cogl will have the wrong idea about what is * current, making it fail to set it when it needs to. Avoid that by making -@@ -1382,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1384,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); @@ -4006,7 +3952,7 @@ index e40b03f3e..9836663d0 100644 kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1402,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1404,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, onscreen_native->crtc, kms_update, META_KMS_ASSIGN_PLANE_FLAG_NONE, @@ -4024,7 +3970,7 @@ index e40b03f3e..9836663d0 100644 return; } -@@ -1430,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1432,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -4033,7 +3979,7 @@ index e40b03f3e..9836663d0 100644 return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1445,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1447,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -4042,7 +3988,7 @@ index e40b03f3e..9836663d0 100644 return; } break; -@@ -1462,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1464,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -4051,7 +3997,7 @@ index e40b03f3e..9836663d0 100644 return; } break; -@@ -1478,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1480,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -4059,7 +4005,7 @@ index e40b03f3e..9836663d0 100644 } gboolean -@@ -1549,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1551,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Direct scanout page flip failed: %s", error->message); @@ -4068,7 +4014,7 @@ index e40b03f3e..9836663d0 100644 onscreen); clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); -@@ -1559,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1561,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -4077,7 +4023,7 @@ index e40b03f3e..9836663d0 100644 } static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1611,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1613,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -4096,7 +4042,7 @@ index e40b03f3e..9836663d0 100644 renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); -@@ -1726,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, +@@ -1728,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -4108,7 +4054,7 @@ index e40b03f3e..9836663d0 100644 maybe_update_frame_sync (onscreen_native, frame); } -@@ -1846,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1848,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -4196,7 +4142,7 @@ index e40b03f3e..9836663d0 100644 meta_kms_update_add_result_listener (kms_update, &finish_frame_result_listener_vtable, NULL, -@@ -1884,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1886,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_update_set_flushing (kms_update, kms_crtc); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -4217,23 +4163,7 @@ index e40b03f3e..9836663d0 100644 } static gboolean -@@ -2417,6 +2655,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat - width, height, - format, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); -+ -+ if (!gbm_surface) -+ { -+ gbm_surface = gbm_surface_create (gbm_device, -+ width, height, -+ format, -+ 0); -+ } -+ - if (!gbm_surface) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, -@@ -2790,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2801,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) { case META_RENDERER_NATIVE_MODE_GBM: g_clear_object (&onscreen_native->gbm.next_fb); @@ -4246,7 +4176,7 @@ index e40b03f3e..9836663d0 100644 break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); -@@ -2825,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2836,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) g_clear_object (&onscreen_native->output); g_clear_object (&onscreen_native->crtc); @@ -4270,414 +4200,11 @@ index 0e1193325..e30357d19 100644 void meta_onscreen_native_set_view (CoglOnscreen *onscreen, MetaRendererView *view); -diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c -index cf27ba8d4..0d50de177 100644 ---- a/src/backends/native/meta-renderer-native-gles3.c -+++ b/src/backends/native/meta-renderer-native-gles3.c -@@ -3,6 +3,7 @@ - /* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. -+ * Copyright (c) 2023 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -34,6 +35,7 @@ - #include "backends/meta-egl-ext.h" - #include "backends/meta-gles3.h" - #include "backends/meta-gles3-table.h" -+#include "meta/meta-debug.h" - - /* - * GL/gl.h being included may conflict with gl3.h on some architectures. -@@ -43,17 +45,240 @@ - #error "Somehow included OpenGL headers when we shouldn't have" - #endif - -+typedef struct _ContextData -+{ -+ GArray *buffer_support; -+ GLuint shader_program; -+} ContextData; -+ -+typedef struct -+{ -+ uint32_t drm_format; -+ uint64_t drm_modifier; -+ gboolean can_blit; -+} BufferTypeSupport; -+ - static void --paint_egl_image (MetaGles3 *gles3, -- EGLImageKHR egl_image, -- int width, -- int height) -+context_data_free (ContextData *context_data) -+{ -+ g_array_free (context_data->buffer_support, TRUE); -+ g_free (context_data); -+} -+ -+static GQuark -+get_quark_for_egl_context (EGLContext egl_context) -+{ -+ char key[128]; -+ -+ g_snprintf (key, sizeof key, "EGLContext %p", egl_context); -+ -+ return g_quark_from_string (key); -+} -+ -+static gboolean -+can_blit_buffer (ContextData *context_data, -+ MetaEgl *egl, -+ EGLDisplay egl_display, -+ uint32_t drm_format, -+ uint64_t drm_modifier) -+{ -+ EGLint num_modifiers; -+ EGLuint64KHR *modifiers; -+ EGLBoolean *external_only; -+ g_autoptr (GError) error = NULL; -+ int i; -+ gboolean can_blit; -+ BufferTypeSupport support; -+ -+ can_blit = drm_modifier == DRM_FORMAT_MOD_LINEAR; -+ -+ for (i = 0; i < context_data->buffer_support->len; i++) -+ { -+ BufferTypeSupport *support = -+ &g_array_index (context_data->buffer_support, BufferTypeSupport, i); -+ -+ if (support->drm_format == drm_format && -+ support->drm_modifier == drm_modifier) -+ return support->can_blit; -+ } -+ -+ if (!meta_egl_has_extensions (egl, egl_display, NULL, -+ "EGL_EXT_image_dma_buf_import_modifiers", -+ NULL)) -+ { -+ meta_topic (META_DEBUG_RENDER, -+ "No support for EGL_EXT_image_dma_buf_import_modifiers, " -+ "assuming blitting linearly will still work."); -+ goto out; -+ } -+ -+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, -+ drm_format, 0, NULL, NULL, -+ &num_modifiers, &error)) -+ { -+ meta_topic (META_DEBUG_RENDER, -+ "Failed to query supported DMA buffer modifiers (%s), " -+ "assuming blitting linearly will still work.", -+ error->message); -+ goto out; -+ } -+ -+ if (num_modifiers == 0) -+ goto out; -+ -+ modifiers = g_alloca0 (sizeof (EGLuint64KHR) * num_modifiers); -+ external_only = g_alloca0 (sizeof (EGLBoolean) * num_modifiers); -+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, -+ drm_format, num_modifiers, -+ modifiers, external_only, -+ &num_modifiers, &error)) -+ { -+ g_warning ("Failed to requery supported DMA buffer modifiers: %s", -+ error->message); -+ can_blit = FALSE; -+ goto out; -+ } -+ -+ can_blit = FALSE; -+ for (i = 0; i < num_modifiers; i++) -+ { -+ if (drm_modifier == modifiers[i]) -+ { -+ can_blit = !external_only[i]; -+ goto out; -+ } -+ } -+ -+out: -+ support = (BufferTypeSupport) { -+ .drm_format = drm_format, -+ .drm_modifier = drm_modifier, -+ .can_blit = can_blit, -+ }; -+ g_array_append_val (context_data->buffer_support, support); -+ return can_blit; -+} -+ -+static GLuint -+load_shader (const char *src, -+ GLenum type) -+{ -+ GLuint shader = glCreateShader (type); -+ -+ if (shader) -+ { -+ GLint compiled; -+ -+ glShaderSource (shader, 1, &src, NULL); -+ glCompileShader (shader); -+ glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); -+ if (!compiled) -+ { -+ GLchar log[1024]; -+ -+ glGetShaderInfoLog (shader, sizeof (log) - 1, NULL, log); -+ log[sizeof (log) - 1] = '\0'; -+ g_warning ("load_shader compile failed: %s", log); -+ glDeleteShader (shader); -+ shader = 0; -+ } -+ } -+ -+ return shader; -+} -+ -+static void -+ensure_shader_program (ContextData *context_data, -+ MetaGles3 *gles3) -+{ -+ static const char vertex_shader_source[] = -+ "#version 100\n" -+ "attribute vec2 position;\n" -+ "attribute vec2 texcoord;\n" -+ "varying vec2 v_texcoord;\n" -+ "\n" -+ "void main()\n" -+ "{\n" -+ " gl_Position = vec4(position, 0.0, 1.0);\n" -+ " v_texcoord = texcoord;\n" -+ "}\n"; -+ -+ static const char fragment_shader_source[] = -+ "#version 100\n" -+ "#extension GL_OES_EGL_image_external : require\n" -+ "precision mediump float;\n" -+ "uniform samplerExternalOES s_texture;\n" -+ "varying vec2 v_texcoord;\n" -+ "\n" -+ " void main()\n" -+ "{\n" -+ " gl_FragColor = texture2D(s_texture, v_texcoord);\n" -+ "}\n"; -+ -+ static const GLfloat box[] = -+ { /* position texcoord */ -+ -1.0f, +1.0f, 0.0f, 0.0f, -+ +1.0f, +1.0f, 1.0f, 0.0f, -+ +1.0f, -1.0f, 1.0f, 1.0f, -+ -1.0f, -1.0f, 0.0f, 1.0f, -+ }; -+ GLint linked; -+ GLuint vertex_shader, fragment_shader; -+ GLint position_attrib, texcoord_attrib; -+ GLuint shader_program; -+ -+ if (context_data->shader_program) -+ return; -+ -+ shader_program = glCreateProgram (); -+ g_return_if_fail (shader_program); -+ context_data->shader_program = shader_program; -+ -+ vertex_shader = load_shader (vertex_shader_source, GL_VERTEX_SHADER); -+ g_return_if_fail (vertex_shader); -+ fragment_shader = load_shader (fragment_shader_source, GL_FRAGMENT_SHADER); -+ g_return_if_fail (fragment_shader); -+ -+ GLBAS (gles3, glAttachShader, (shader_program, vertex_shader)); -+ GLBAS (gles3, glAttachShader, (shader_program, fragment_shader)); -+ GLBAS (gles3, glLinkProgram, (shader_program)); -+ GLBAS (gles3, glGetProgramiv, (shader_program, GL_LINK_STATUS, &linked)); -+ if (!linked) -+ { -+ GLchar log[1024]; -+ -+ glGetProgramInfoLog (shader_program, sizeof (log) - 1, NULL, log); -+ log[sizeof (log) - 1] = '\0'; -+ g_warning ("Link failed: %s", log); -+ return; -+ } -+ -+ GLBAS (gles3, glUseProgram, (shader_program)); -+ -+ position_attrib = glGetAttribLocation (shader_program, "position"); -+ GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); -+ GLBAS (gles3, glVertexAttribPointer, -+ (position_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box)); -+ -+ texcoord_attrib = glGetAttribLocation (shader_program, "texcoord"); -+ GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); -+ GLBAS (gles3, glVertexAttribPointer, -+ (texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box + 2)); -+} -+ -+static void -+blit_egl_image (MetaGles3 *gles3, -+ EGLImageKHR egl_image, -+ int width, -+ int height) - { - GLuint texture; - GLuint framebuffer; - - meta_gles3_clear_error (gles3); - -+ GLBAS (gles3, glViewport, (0, 0, width, height)); -+ - GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - -@@ -85,6 +310,43 @@ paint_egl_image (MetaGles3 *gles3, - GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); - } - -+static void -+paint_egl_image (ContextData *context_data, -+ MetaGles3 *gles3, -+ EGLImageKHR egl_image, -+ int width, -+ int height) -+{ -+ GLuint texture; -+ -+ meta_gles3_clear_error (gles3); -+ ensure_shader_program (context_data, gles3); -+ -+ GLBAS (gles3, glViewport, (0, 0, width, height)); -+ -+ GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); -+ GLBAS (gles3, glGenTextures, (1, &texture)); -+ GLBAS (gles3, glBindTexture, (GL_TEXTURE_EXTERNAL_OES, texture)); -+ GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_EXTERNAL_OES, -+ egl_image)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_MAG_FILTER, -+ GL_NEAREST)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_MIN_FILTER, -+ GL_NEAREST)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_WRAP_S, -+ GL_CLAMP_TO_EDGE)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_WRAP_T, -+ GL_CLAMP_TO_EDGE)); -+ -+ GLBAS (gles3, glDrawArrays, (GL_TRIANGLE_FAN, 0, 4)); -+ -+ GLBAS (gles3, glDeleteTextures, (1, &texture)); -+} -+ - gboolean - meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, -@@ -105,6 +367,28 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - uint32_t format; - EGLImageKHR egl_image; - gboolean use_modifiers; -+ GQuark context_data_quark; -+ ContextData *context_data; -+ gboolean can_blit; -+ -+ context_data_quark = get_quark_for_egl_context (egl_context); -+ context_data = g_object_get_qdata (G_OBJECT (gles3), context_data_quark); -+ if (!context_data) -+ { -+ context_data = g_new0 (ContextData, 1); -+ context_data->buffer_support = g_array_new (FALSE, FALSE, -+ sizeof (BufferTypeSupport)); -+ -+ g_object_set_qdata_full (G_OBJECT (gles3), -+ context_data_quark, -+ context_data, -+ (GDestroyNotify) context_data_free); -+ } -+ -+ can_blit = can_blit_buffer (context_data, -+ egl, egl_display, -+ gbm_bo_get_format (shared_bo), -+ gbm_bo_get_modifier (shared_bo)); - - shared_bo_fd = gbm_bo_get_fd (shared_bo); - if (shared_bo_fd < 0) -@@ -150,9 +434,21 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - if (!egl_image) - return FALSE; - -- paint_egl_image (gles3, egl_image, width, height); -+ if (can_blit) -+ blit_egl_image (gles3, egl_image, width, height); -+ else -+ paint_egl_image (context_data, gles3, egl_image, width, height); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - return TRUE; - } -+ -+void -+meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, -+ EGLContext egl_context) -+{ -+ GQuark context_data_quark = get_quark_for_egl_context (egl_context); -+ -+ g_object_set_qdata (G_OBJECT (gles3), context_data_quark, NULL); -+} -diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h -index 591ff82e1..f5791a171 100644 ---- a/src/backends/native/meta-renderer-native-gles3.h -+++ b/src/backends/native/meta-renderer-native-gles3.h -@@ -26,10 +26,13 @@ - #include "backends/meta-egl.h" - #include "backends/meta-gles3.h" - --gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, -- MetaGles3 *gles3, -- EGLDisplay egl_display, -- EGLContext egl_context, -- EGLSurface egl_surface, -- struct gbm_bo *shared_bo, -- GError **error); -+gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, -+ MetaGles3 *gles3, -+ EGLDisplay egl_display, -+ EGLContext egl_context, -+ EGLSurface egl_surface, -+ struct gbm_bo *shared_bo, -+ GError **error); -+ -+void meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, -+ EGLContext egl_context); -diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h -index 997fe6f69..2d3fe1971 100644 ---- a/src/backends/native/meta-renderer-native-private.h -+++ b/src/backends/native/meta-renderer-native-private.h -@@ -60,6 +60,7 @@ typedef struct _MetaRendererNativeGpuData - struct { - MetaSharedFramebufferCopyMode copy_mode; - gboolean has_EGL_EXT_image_dma_buf_import_modifiers; -+ gboolean needs_explicit_sync; - - /* For GPU blit mode */ - EGLContext egl_context; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index 7b64ff3f4..3c22b4e86 100644 +index 893ee4216..3c22b4e86 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c -@@ -63,10 +63,12 @@ - #include "backends/native/meta-output-kms.h" - #include "backends/native/meta-render-device-gbm.h" - #include "backends/native/meta-render-device-surfaceless.h" -+#include "backends/native/meta-renderer-native-gles3.h" - #include "backends/native/meta-renderer-native-private.h" +@@ -68,6 +68,7 @@ #include "backends/native/meta-renderer-view-native.h" #include "cogl/cogl.h" #include "common/meta-cogl-drm-formats.h" @@ -4685,17 +4212,7 @@ index 7b64ff3f4..3c22b4e86 100644 #include "core/boxes-private.h" #ifdef HAVE_EGL_DEVICE -@@ -136,6 +138,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - -+ meta_renderer_native_gles3_forget_context (renderer_native->gles3, -+ renderer_gpu_data->secondary.egl_context); -+ - meta_egl_destroy_context (egl, - egl_display, - renderer_gpu_data->secondary.egl_context, -@@ -726,12 +731,18 @@ static gboolean +@@ -730,12 +731,18 @@ static gboolean dummy_power_save_page_flip_cb (gpointer user_data) { MetaRendererNative *renderer_native = user_data; @@ -4716,7 +4233,7 @@ index 7b64ff3f4..3c22b4e86 100644 renderer_native->power_save_page_flip_source_id = 0; return G_SOURCE_REMOVE; -@@ -743,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na +@@ -747,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na { const unsigned int timeout_ms = 100; @@ -4726,7 +4243,7 @@ index 7b64ff3f4..3c22b4e86 100644 if (!renderer_native->power_save_page_flip_source_id) { renderer_native->power_save_page_flip_source_id = -@@ -1524,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) +@@ -1528,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) } } @@ -4753,7 +4270,7 @@ index 7b64ff3f4..3c22b4e86 100644 static void meta_renderer_native_rebuild_views (MetaRenderer *renderer) { -@@ -1534,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) +@@ -1538,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) MetaRendererClass *parent_renderer_class = META_RENDERER_CLASS (meta_renderer_native_parent_class); @@ -4761,26 +4278,6 @@ index 7b64ff3f4..3c22b4e86 100644 meta_kms_discard_pending_page_flips (kms); g_hash_table_remove_all (renderer_native->mode_set_updates); -@@ -1805,6 +1840,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - CoglContext *cogl_context; - CoglDisplay *cogl_display; - const char **missing_gl_extensions; -+ const char *egl_vendor; - - egl_display = meta_render_device_get_egl_display (render_device); - if (egl_display == EGL_NO_DISPLAY) -@@ -1871,6 +1907,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL); -+ -+ egl_vendor = meta_egl_query_string (egl, egl_display, EGL_VENDOR); -+ if (!g_strcmp0 (egl_vendor, "NVIDIA")) -+ renderer_gpu_data->secondary.needs_explicit_sync = TRUE; -+ - ret = TRUE; - out: - maybe_restore_cogl_egl_api (renderer_native); diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c index 41b78ec18..02eccc77d 100644 --- a/src/backends/x11/nested/meta-stage-x11-nested.c @@ -5293,346 +4790,6 @@ index a8cf7e197..05df3bfd2 100644 ] if have_wayland_eglstream wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable('pkgdatadir') -diff --git a/src/meta/common.h b/src/meta/common.h -index ee978ac6a..ed3aa81ef 100644 ---- a/src/meta/common.h -+++ b/src/meta/common.h -@@ -27,6 +27,7 @@ - #include - - #include "clutter/clutter.h" -+#include "meta/meta-base.h" - #include "meta/meta-enums.h" - - /** -@@ -42,8 +43,6 @@ - /* Replacement for X11 CurrentTime */ - #define META_CURRENT_TIME 0L - --#define META_EXPORT __attribute__((visibility("default"))) extern -- - #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST - - /* Keep array size in sync with MAX_BUTTONS_PER_CORNER */ -diff --git a/src/meta/meson.build b/src/meta/meson.build -index 655dedeaf..bc3910408 100644 ---- a/src/meta/meson.build -+++ b/src/meta/meson.build -@@ -9,6 +9,7 @@ mutter_public_headers = [ - 'keybindings.h', - 'main.h', - 'meta-backend.h', -+ 'meta-base.h', - 'meta-background.h', - 'meta-background-actor.h', - 'meta-background-content.h', -@@ -17,6 +18,7 @@ mutter_public_headers = [ - 'meta-close-dialog.h', - 'meta-cursor-tracker.h', - 'meta-context.h', -+ 'meta-debug.h', - 'meta-dnd.h', - 'meta-enums.h', - 'meta-idle-monitor.h', -diff --git a/src/meta/meta-base.h b/src/meta/meta-base.h -new file mode 100644 -index 000000000..e344b2221 ---- /dev/null -+++ b/src/meta/meta-base.h -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2001 Havoc Pennington -+ * Copyright (C) 2005 Elijah Newren -+ * -+ * 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 -+ -+#define META_EXPORT __attribute__((visibility("default"))) extern -diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h -new file mode 100644 -index 000000000..b4c70144b ---- /dev/null -+++ b/src/meta/meta-debug.h -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2001 Havoc Pennington -+ * Copyright (C) 2005 Elijah Newren -+ * -+ * 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 "meta/meta-base.h" -+ -+/** -+ * MetaDebugTopic: -+ * @META_DEBUG_VERBOSE: verbose logging -+ * @META_DEBUG_FOCUS: focus -+ * @META_DEBUG_WORKAREA: workarea -+ * @META_DEBUG_STACK: stack -+ * @META_DEBUG_SM: session management -+ * @META_DEBUG_EVENTS: events -+ * @META_DEBUG_WINDOW_STATE: window state -+ * @META_DEBUG_WINDOW_OPS: window operations -+ * @META_DEBUG_GEOMETRY: geometry -+ * @META_DEBUG_PLACEMENT: window placement -+ * @META_DEBUG_PING: ping -+ * @META_DEBUG_KEYBINDINGS: keybindings -+ * @META_DEBUG_SYNC: sync -+ * @META_DEBUG_STARTUP: startup -+ * @META_DEBUG_PREFS: preferences -+ * @META_DEBUG_GROUPS: groups -+ * @META_DEBUG_RESIZING: resizing -+ * @META_DEBUG_SHAPES: shapes -+ * @META_DEBUG_EDGE_RESISTANCE: edge resistance -+ * @META_DEBUG_WAYLAND: Wayland -+ * @META_DEBUG_KMS: kernel mode setting -+ * @META_DEBUG_SCREEN_CAST: screencasting -+ * @META_DEBUG_REMOTE_DESKTOP: remote desktop -+ * @META_DEBUG_BACKEND: backend -+ * @META_DEBUG_RENDER: native backend rendering -+ * @META_DEBUG_COLOR: color management -+ * @META_DEBUG_INPUT_EVENTS: input events -+ * @META_DEBUG_EIS: eis state -+ */ -+typedef enum -+{ -+ META_DEBUG_VERBOSE = -1, -+ META_DEBUG_FOCUS = 1 << 0, -+ META_DEBUG_WORKAREA = 1 << 1, -+ META_DEBUG_STACK = 1 << 2, -+ META_DEBUG_SM = 1 << 3, -+ META_DEBUG_EVENTS = 1 << 4, -+ META_DEBUG_WINDOW_STATE = 1 << 5, -+ META_DEBUG_WINDOW_OPS = 1 << 6, -+ META_DEBUG_GEOMETRY = 1 << 7, -+ META_DEBUG_PLACEMENT = 1 << 8, -+ META_DEBUG_PING = 1 << 9, -+ META_DEBUG_KEYBINDINGS = 1 << 10, -+ META_DEBUG_SYNC = 1 << 11, -+ META_DEBUG_STARTUP = 1 << 12, -+ META_DEBUG_PREFS = 1 << 13, -+ META_DEBUG_GROUPS = 1 << 14, -+ META_DEBUG_RESIZING = 1 << 15, -+ META_DEBUG_SHAPES = 1 << 16, -+ META_DEBUG_EDGE_RESISTANCE = 1 << 17, -+ META_DEBUG_DBUS = 1 << 18, -+ META_DEBUG_INPUT = 1 << 19, -+ META_DEBUG_WAYLAND = 1 << 20, -+ META_DEBUG_KMS = 1 << 21, -+ META_DEBUG_SCREEN_CAST = 1 << 22, -+ META_DEBUG_REMOTE_DESKTOP = 1 << 23, -+ META_DEBUG_BACKEND = 1 << 24, -+ META_DEBUG_RENDER = 1 << 25, -+ META_DEBUG_COLOR = 1 << 26, -+ META_DEBUG_INPUT_EVENTS = 1 << 27, -+ META_DEBUG_EIS = 1 << 28, -+} MetaDebugTopic; -+ -+META_EXPORT -+gboolean meta_is_topic_enabled (MetaDebugTopic topic); -+ -+/* To disable verbose mode, we make these functions into no-ops */ -+#ifdef WITH_VERBOSE_MODE -+ -+const char * meta_topic_to_string (MetaDebugTopic topic); -+ -+META_EXPORT -+void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); -+ -+#define meta_topic(debug_topic, ...) \ -+ G_STMT_START \ -+ { \ -+ if (meta_is_topic_enabled (debug_topic)) \ -+ { \ -+ g_autofree char *_topic_message = NULL; \ -+\ -+ _topic_message = g_strdup_printf (__VA_ARGS__); \ -+ meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ -+ _topic_message); \ -+ } \ -+ } \ -+ G_STMT_END -+ -+#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) -+ -+#else -+ -+# ifdef G_HAVE_ISO_VARARGS -+# define meta_verbose(...) -+# define meta_topic(...) -+# elif defined(G_HAVE_GNUC_VARARGS) -+# define meta_verbose(format...) -+# define meta_topic(format...) -+# else -+# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" -+# endif -+ -+#endif /* !WITH_VERBOSE_MODE */ -diff --git a/src/meta/util.h b/src/meta/util.h -index 0019c8078..ca8ca2ade 100644 ---- a/src/meta/util.h -+++ b/src/meta/util.h -@@ -26,6 +26,7 @@ - #include - - #include "meta/common.h" -+#include "meta/meta-debug.h" - #include "meta/meta-later.h" - - META_EXPORT -@@ -46,71 +47,6 @@ META_EXPORT - void meta_fatal (const char *format, - ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN G_ANALYZER_NORETURN; - --/** -- * MetaDebugTopic: -- * @META_DEBUG_VERBOSE: verbose logging -- * @META_DEBUG_FOCUS: focus -- * @META_DEBUG_WORKAREA: workarea -- * @META_DEBUG_STACK: stack -- * @META_DEBUG_SM: session management -- * @META_DEBUG_EVENTS: events -- * @META_DEBUG_WINDOW_STATE: window state -- * @META_DEBUG_WINDOW_OPS: window operations -- * @META_DEBUG_GEOMETRY: geometry -- * @META_DEBUG_PLACEMENT: window placement -- * @META_DEBUG_PING: ping -- * @META_DEBUG_KEYBINDINGS: keybindings -- * @META_DEBUG_SYNC: sync -- * @META_DEBUG_STARTUP: startup -- * @META_DEBUG_PREFS: preferences -- * @META_DEBUG_GROUPS: groups -- * @META_DEBUG_RESIZING: resizing -- * @META_DEBUG_SHAPES: shapes -- * @META_DEBUG_EDGE_RESISTANCE: edge resistance -- * @META_DEBUG_WAYLAND: Wayland -- * @META_DEBUG_KMS: kernel mode setting -- * @META_DEBUG_SCREEN_CAST: screencasting -- * @META_DEBUG_REMOTE_DESKTOP: remote desktop -- * @META_DEBUG_BACKEND: backend -- * @META_DEBUG_RENDER: native backend rendering -- * @META_DEBUG_COLOR: color management -- * @META_DEBUG_INPUT_EVENTS: input events -- * @META_DEBUG_EIS: eis state -- */ --typedef enum --{ -- META_DEBUG_VERBOSE = -1, -- META_DEBUG_FOCUS = 1 << 0, -- META_DEBUG_WORKAREA = 1 << 1, -- META_DEBUG_STACK = 1 << 2, -- META_DEBUG_SM = 1 << 3, -- META_DEBUG_EVENTS = 1 << 4, -- META_DEBUG_WINDOW_STATE = 1 << 5, -- META_DEBUG_WINDOW_OPS = 1 << 6, -- META_DEBUG_GEOMETRY = 1 << 7, -- META_DEBUG_PLACEMENT = 1 << 8, -- META_DEBUG_PING = 1 << 9, -- META_DEBUG_KEYBINDINGS = 1 << 10, -- META_DEBUG_SYNC = 1 << 11, -- META_DEBUG_STARTUP = 1 << 12, -- META_DEBUG_PREFS = 1 << 13, -- META_DEBUG_GROUPS = 1 << 14, -- META_DEBUG_RESIZING = 1 << 15, -- META_DEBUG_SHAPES = 1 << 16, -- META_DEBUG_EDGE_RESISTANCE = 1 << 17, -- META_DEBUG_DBUS = 1 << 18, -- META_DEBUG_INPUT = 1 << 19, -- META_DEBUG_WAYLAND = 1 << 20, -- META_DEBUG_KMS = 1 << 21, -- META_DEBUG_SCREEN_CAST = 1 << 22, -- META_DEBUG_REMOTE_DESKTOP = 1 << 23, -- META_DEBUG_BACKEND = 1 << 24, -- META_DEBUG_RENDER = 1 << 25, -- META_DEBUG_COLOR = 1 << 26, -- META_DEBUG_INPUT_EVENTS = 1 << 27, -- META_DEBUG_EIS = 1 << 28, --} MetaDebugTopic; -- - /** - * MetaDebugPaintFlag: - * @META_DEBUG_PAINT_NONE: default -@@ -122,9 +58,6 @@ typedef enum - META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, - } MetaDebugPaintFlag; - --META_EXPORT --gboolean meta_is_topic_enabled (MetaDebugTopic topic); -- - META_EXPORT - void meta_add_verbose_topic (MetaDebugTopic topic); - -@@ -155,44 +88,6 @@ char* meta_external_binding_name_for_action (guint keybinding_action); - META_EXPORT - char* meta_g_utf8_strndup (const gchar *src, gsize n); - --/* To disable verbose mode, we make these functions into no-ops */ --#ifdef WITH_VERBOSE_MODE -- --const char * meta_topic_to_string (MetaDebugTopic topic); -- --META_EXPORT --void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); -- --#define meta_topic(debug_topic, ...) \ -- G_STMT_START \ -- { \ -- if (meta_is_topic_enabled (debug_topic)) \ -- { \ -- g_autofree char *_topic_message = NULL; \ --\ -- _topic_message = g_strdup_printf (__VA_ARGS__); \ -- meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ -- _topic_message); \ -- } \ -- } \ -- G_STMT_END -- --#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) -- --#else -- --# ifdef G_HAVE_ISO_VARARGS --# define meta_verbose(...) --# define meta_topic(...) --# elif defined(G_HAVE_GNUC_VARARGS) --# define meta_verbose(format...) --# define meta_topic(format...) --# else --# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" --# endif -- --#endif /* !WITH_VERBOSE_MODE */ -- - typedef enum - { - META_LOCALE_DIRECTION_LTR, diff --git a/src/tests/mtk/region-tests.c b/src/tests/mtk/region-tests.c index 7e41a53f0..c9ebc2adb 100644 --- a/src/tests/mtk/region-tests.c diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 624bbab..a8cfcb3 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -45,17 +45,13 @@ Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # which solves the problems reported with #3329 alone Patch4: 0001-modified-3329.patch -# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 -# Scaling for Xwayland applications -# Patch5: 0002-3567.patch - # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ # Nvidia secondary GPU copy acceleration -Patch6: 0003-3304.patch +Patch5: 0003-3304.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ # Dynamic triple buffering -Patch7: 0004-1441.patch +Patch6: 0004-1441.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From 33ab06293809cd850cb230ef3b5782a776ba03ea Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 19 Apr 2024 20:20:04 -0700 Subject: [PATCH 20/41] chore: Remove binary patch --- staging/mutter/0004-1441.patch | 8 -------- 1 file changed, 8 deletions(-) diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch index 380efbf..2590422 100644 --- a/staging/mutter/0004-1441.patch +++ b/staging/mutter/0004-1441.patch @@ -5046,14 +5046,6 @@ index f5ebc23fe..2f870fdc3 100644 .loop = g_main_loop_new (NULL, FALSE), }; -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png -new file mode 100644 -index 000000000..c2b0c2ff5 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_7.ref.png differ -diff --git a/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png -new file mode 100644 -index 000000000..28fc7b266 -Binary files /dev/null and b/src/tests/ref-tests/wayland_buffer_single-pixel-buffer_8.ref.png differ diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c index cb78489b4..8591e88d6 100644 --- a/src/tests/wayland-test-clients/buffer-transform.c From 1ed1d575e353abfb4b659454f7526adc44a7bcfd Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 21 Apr 2024 21:26:03 -0600 Subject: [PATCH 21/41] feat: Add initial support for building Wolfi packages (#20) * feat(ci): Support building Wolfi packages * feat(wolfi): Add Ublue metapackage * fix(wolfi): Only pass packages to melangs * fix(wolfi): Copy package resources to workdir Signed-off-by: RJ Trujillo * feat(wolfi): Add Bluefin metapackage Signed-off-by: RJ Trujillo * chore(wolfi): Build 10 minutes before toolboxes This can be more relaxed as packages are added Signed-off-by: RJ Trujillo --------- Signed-off-by: RJ Trujillo --- .github/workflows/wolfi.yml | 58 +++++++++++ wolfi/bluefin-base.yaml | 52 ++++++++++ wolfi/bluefin-base/etc/bashrc | 66 +++++++++++++ .../profile.d/00-bluefin-cli-brew-firstrun.sh | 47 +++++++++ .../etc/profile.d/bash_completion.sh | 42 ++++++++ .../profile.d/command-not-found-host-exec.sh | 14 +++ .../etc/profile.d/homebrew-env.sh | 10 ++ .../bluefin-base/etc/profile.d/modern-unix.sh | 20 ++++ .../etc/profile.d/zz-profile_sourced.sh | 4 + wolfi/bluefin-base/etc/starship.toml | 49 ++++++++++ wolfi/bluefin-base/root/.bash_profile | 3 + wolfi/bluefin-base/root/.bashrc | 3 + .../00-bluefin-cli-brew-firstrun.fish | 45 +++++++++ .../usr/share/fish/vendor_conf.d/bling.fish | 27 ++++++ .../usr/share/fish/vendor_conf.d/brew.fish | 15 +++ .../fish_command_not_found.fish | 8 ++ .../fish/vendor_functions.d/fish_title.fish | 4 + wolfi/ublue-base.yaml | 96 +++++++++++++++++++ wolfi/ublue-base/pinentry | 2 + wolfi/ublue-base/sudo | 2 + 20 files changed, 567 insertions(+) create mode 100644 .github/workflows/wolfi.yml create mode 100644 wolfi/bluefin-base.yaml create mode 100644 wolfi/bluefin-base/etc/bashrc create mode 100644 wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh create mode 100644 wolfi/bluefin-base/etc/profile.d/bash_completion.sh create mode 100644 wolfi/bluefin-base/etc/profile.d/command-not-found-host-exec.sh create mode 100644 wolfi/bluefin-base/etc/profile.d/homebrew-env.sh create mode 100644 wolfi/bluefin-base/etc/profile.d/modern-unix.sh create mode 100644 wolfi/bluefin-base/etc/profile.d/zz-profile_sourced.sh create mode 100644 wolfi/bluefin-base/etc/starship.toml create mode 100644 wolfi/bluefin-base/root/.bash_profile create mode 100644 wolfi/bluefin-base/root/.bashrc create mode 100644 wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish create mode 100644 wolfi/bluefin-base/usr/share/fish/vendor_conf.d/bling.fish create mode 100644 wolfi/bluefin-base/usr/share/fish/vendor_conf.d/brew.fish create mode 100644 wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_command_not_found.fish create mode 100644 wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_title.fish create mode 100644 wolfi/ublue-base.yaml create mode 100755 wolfi/ublue-base/pinentry create mode 100755 wolfi/ublue-base/sudo diff --git a/.github/workflows/wolfi.yml b/.github/workflows/wolfi.yml new file mode 100644 index 0000000..d76eb4f --- /dev/null +++ b/.github/workflows/wolfi.yml @@ -0,0 +1,58 @@ +name: Build and Upload Wolfi Packages +on: + schedule: + - cron: '50 5,17 * * *' # 5:50 AM and 5:50 PM UTC every day + pull_request: + merge_group: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + upload-wolfi-packages: + name: Build and upload Wolfi packages + runs-on: ubuntu-22.04 + permissions: + contents: read + packages: write + id-token: write + strategy: + fail-fast: false + steps: + # Checkout push-to-registry action GitHub repository + - name: Checkout Push to Registry action + uses: actions/checkout@v4 + + - name: Generate package list + run: | + cd wolfi + # Copy package resources to workdir + RESOURCES=$(ls -d */) + for resource in $RESOURCES; do + cp -r $resource/* . + done + # Create package list + APK_LIST=$(find *.yaml -type 'f' | tr '\n' ',') + echo "APK_LIST=$APK_LIST" >> $GITHUB_ENV + + # Build APKs with melange + - name: Build APKs + id: melange + uses: chainguard-dev/actions/melange-build@main + with: + archs: aarch64,x86_64 + empty-workspace: false + multi-config: ${{ env.APK_LIST }} + sign-with-temporary-key: true + workdir: ./wolfi + + # Upload packages + - name: 'Upload built packages archive to Github Artifacts' + uses: actions/upload-artifact@v4 + with: + name: wolfi-packages + path: ./packages + retention-days: 1 # Low ttl since this is just an intermediary used once + if-no-files-found: error diff --git a/wolfi/bluefin-base.yaml b/wolfi/bluefin-base.yaml new file mode 100644 index 0000000..8f7494b --- /dev/null +++ b/wolfi/bluefin-base.yaml @@ -0,0 +1,52 @@ +package: + name: bluefin-base + version: 0.0.0 + epoch: 0 + description: "Bluefin metapackage" + copyright: + - license: Apache-2.0 + dependencies: + runtime: + - atuin + - brew + - gawk + - eza + - fd + - fish + - fzf + - rclone + - ripgrep + - sed + - starship + - ublue-base + - uutils + - zoxide + - zsh + +environment: + contents: + keyring: + - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub + repositories: + - https://packages.wolfi.dev/os + packages: + - busybox + - curl + +pipeline: + - runs: | + # Symlink linuxbrew to homebrew + mkdir -p "${{targets.destdir}}"/home + ln -sf /home/linuxbrew "${{targets.destdir}}"/home/homebrew + + # Install bash-prexec + mkdir -p "${{targets.destdir}}"/usr/share + curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o "${{targets.destdir}}"/usr/share/bash-prexec + + # Copy system files + cp -r etc "${{targets.destdir}}" + cp -r usr "${{targets.destdir}}" + cp -r root "${{targets.destdir}}" + +update: + manual: true diff --git a/wolfi/bluefin-base/etc/bashrc b/wolfi/bluefin-base/etc/bashrc new file mode 100644 index 0000000..31e1248 --- /dev/null +++ b/wolfi/bluefin-base/etc/bashrc @@ -0,0 +1,66 @@ +# shellcheck shell=bash disable=SC1091 +# /etc/bashrc + +# System wide functions and aliases +# Environment stuff goes in /etc/profile + +# It's NOT a good idea to change this file unless you know what you +# are doing. It's much better to create a custom.sh shell script in +# /etc/profile.d/ to make custom changes to your environment, as this +# will prevent the need for merging in future updates. + +# Prevent doublesourcing +if [ -z "$PROFILESOURCED" ] && [ "$PS1" ]; then + PROFILESOURCED="Y" + . /etc/profile +fi + +if [ -z "$BASHRCSOURCED" ]; then + BASHRCSOURCED="Y" + + # are we an interactive shell? + if [ "$PS1" ]; then + if [ -z "$PROMPT_COMMAND" ]; then + case $TERM in + xterm*) + PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"' + ;; + screen*) + PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"' + ;; + *) + [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default + ;; + esac + fi + # Turn on parallel history + shopt -s histappend + # Turn on checkwinsize + shopt -s checkwinsize + [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ " + # You might want to have e.g. tty in prompt (e.g. more virtual machines) + # and console windows + # If you want to do so, just add e.g. + # if [ "$PS1" ]; then + # PS1="[\u@\h:\l \W]\\$ " + # fi + # to your custom modification shell script in /etc/profile.d/ directory + fi + STARSHIP_CONFIG=/etc/starship.toml + export STARSHIP_CONFIG + eval "$(starship init bash)" + + # Enable fzf keybindings + [ -r /run/host/usr/share/fzf/shell/key-bindings.bash ] && \ + . /run/host/usr/share/fzf/shell/key-bindings.bash + + # Enable atuin and bash-prexec + source /usr/share/bash-prexec + eval "$(atuin init bash)" + + # Enable zoxide + eval "$(zoxide init bash --cmd cd)" +fi + +# vim:ts=4:sw=4 + diff --git a/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh new file mode 100644 index 0000000..29f450f --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh @@ -0,0 +1,47 @@ +# shellcheck shell=sh disable=SC1091 +if test "$(id -u)" -gt "0"; then + blue=$(printf '\033[38;5;32m') + bold=$(printf '\033[1m') + normal=$(printf '\033[0m') + if test ! -f /etc/linuxbrew.firstrun; then + printf "\nBluefin-CLI First Run Setup\n\n" + printf "Setting up sudo for %s%s%s%s...\t\t\t " "$bold" "$blue" "$USER" "$normal" + echo "#$(id -u) ALL = (root) NOPASSWD:ALL" | su-exec root tee -a /etc/sudoers > /dev/null + printf "%s[ OK ]%s\n" "${blue}" "${normal}" + fi + + if test ! -d /home/linuxbrew/.linuxbrew; then + name="$(hostname -s)" + linuxbrew_home="${XDG_DATA_HOME:-$HOME/.local/share}"/bluefin-cli/"${name}" + printf "Setting up Linuxbrew...\t\t\t\t " + if test ! -d "${linuxbrew_home}"; then + mkdir -p "${linuxbrew_home}" + if test -d "${XDG_DATA_HOME:-$HOME/.local/share}"/bluefin-cli/.linuxbrew; then + mv "${XDG_DATA_HOME:-$HOME/.local/share}"/bluefin-cli/.linuxbrew "${linuxbrew_home}"/.linuxbrew + fi + fi + if test ! -d /home/linuxbrew; then + su-exec root mkdir -p /home/linuxbrew + fi + su-exec root mount --bind "${linuxbrew_home}" /home/linuxbrew + su-exec root cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ + su-exec root chown -R "$(id -u)" /home/linuxbrew + unset linuxbrew_home + printf "%s[ OK ]%s\n" "${blue}" "${normal}" + fi + + if test ! -d /usr/local/share/bash-completion/completions; then + printf "Setting up Tab-Completions...\t\t\t " + su-exec root mkdir -p /usr/local/share/bash-completion + su-exec root mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion + if test -x /run/host/usr/bin/ujust; then + su-exec root ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust + fi + printf "%s[ OK ]%s\n" "${blue}" "${normal}" + fi + + if test ! -f /etc/linuxbrew.firstrun; then + su-exec root touch /etc/linuxbrew.firstrun + printf "\nBluefin-CLI first run complete!\n\n" + fi +fi diff --git a/wolfi/bluefin-base/etc/profile.d/bash_completion.sh b/wolfi/bluefin-base/etc/profile.d/bash_completion.sh new file mode 100644 index 0000000..910b484 --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/bash_completion.sh @@ -0,0 +1,42 @@ +# shellcheck shell=sh disable=SC1090,SC1091,SC2039,SC2166,SC2268 +# Check for interactive bash and that we haven't already been sourced. +if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then + + # Check for recent enough version of bash. + if [ "${BASH_VERSINFO[0]}" -gt 4 ] || + [ "${BASH_VERSINFO[0]}" -eq 4 -a "${BASH_VERSINFO[1]}" -ge 2 ]; then + [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" ] && + . "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" + if shopt -q progcomp && [ -d /usr/share/bash-completion/completions ]; then + for rc in /usr/share/bash-completion/completions/*; do + if test -r "$rc"; then + . "$rc" + fi + done + unset rc + fi + if shopt -q progcomp && [ -r /usr/local/share/bash-completion/bash_completion ]; then + # Source completion code. + . /usr/local/share/bash-completion/bash_completion + fi + if ! test -L /home/linuxbrew/.linuxbrew/etc/bash_completion.d/brew && test "$(id -u)" -gt 0; then + /home/linuxbrew/.linuxbrew/bin/brew completions link > /dev/null + fi + if test -d /home/linuxbrew/.linuxbrew/etc/bash_completion.d; then + for rc in /home/linuxbrew/.linuxbrew/etc/bash_completion.d/*; do + if test -r "$rc"; then + . "$rc" + fi + done + unset rc + fi + if test -d /run/host/etc/bash_completion.d; then + for rc in /run/host/etc/bash_completion.d/*; do + if test -r "$rc"; then + . "$rc" + fi + done + unset rc + fi + fi +fi diff --git a/wolfi/bluefin-base/etc/profile.d/command-not-found-host-exec.sh b/wolfi/bluefin-base/etc/profile.d/command-not-found-host-exec.sh new file mode 100644 index 0000000..0961c55 --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/command-not-found-host-exec.sh @@ -0,0 +1,14 @@ +# shellcheck shell=sh +command_not_found_handle() { +# don't run if not in a container + if [ ! -e /run/.containerenv ] && [ ! -e /.dockerenv ]; then + exit 127 + fi + + distrobox-host-exec "${@}" +} +if [ -n "${ZSH_VERSION-}" ]; then + command_not_found_handler() { + command_not_found_handle "$@" + } +fi diff --git a/wolfi/bluefin-base/etc/profile.d/homebrew-env.sh b/wolfi/bluefin-base/etc/profile.d/homebrew-env.sh new file mode 100644 index 0000000..8fe8879 --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/homebrew-env.sh @@ -0,0 +1,10 @@ +# shellcheck shell=sh + +PATH="$PATH:/home/linuxbrew/.linuxbrew/sbin" +export PATH +HOMEBREW_REPOSITORY="/home/linuxbrew/.linuxbrew" +export HOMEBREW_REPOSITORY +HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" +export HOMEBREW_PREFIX +HOMEBREW_CELLAR="/home/linuxbrew/.linuxbrew/Cellar" +export HOMEBREW_CELLAR \ No newline at end of file diff --git a/wolfi/bluefin-base/etc/profile.d/modern-unix.sh b/wolfi/bluefin-base/etc/profile.d/modern-unix.sh new file mode 100644 index 0000000..1b38fd0 --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/modern-unix.sh @@ -0,0 +1,20 @@ +# shellcheck shell=sh +# Eza for ls +alias ll='eza -l --icons=auto --group-directories-first' 2>/dev/null +alias l.='eza -d .*' 2>/dev/null +alias ls='eza' 2>/dev/null +alias l1='eza -1' + +# Ripgrep for grep +alias grep='rg' 2>/dev/null +alias egrep='rg' 2>/dev/null +alias fgrep='rg -F' 2>/dev/null +alias xzgrep='rg -z' 2>/dev/null +alias xzegrep='rg -z' 2>/dev/null +alias xzfgrep='rg -z -F' 2>/dev/null + +# Zoxide is handling cd +alias cd='cd' 2>/dev/null + +# Fd for find +alias find='fd' 2>/dev/null \ No newline at end of file diff --git a/wolfi/bluefin-base/etc/profile.d/zz-profile_sourced.sh b/wolfi/bluefin-base/etc/profile.d/zz-profile_sourced.sh new file mode 100644 index 0000000..5140d0e --- /dev/null +++ b/wolfi/bluefin-base/etc/profile.d/zz-profile_sourced.sh @@ -0,0 +1,4 @@ +# shellcheck shell=sh +if [ -z "$PROFILESOURCED" ] && [ "$PS1" ]; then + PROFILESOURCED="Y" +fi diff --git a/wolfi/bluefin-base/etc/starship.toml b/wolfi/bluefin-base/etc/starship.toml new file mode 100644 index 0000000..6817c9c --- /dev/null +++ b/wolfi/bluefin-base/etc/starship.toml @@ -0,0 +1,49 @@ +[character] +success_symbol = '[\$](bold blue dimmed)' +error_symbol = '[\$](bold red)' + +[container] +symbol='📦' +format='[$symbol](bold blue dimmed) ' + +[directory] +style = 'bold cyan dimmed' + +[hostname] +ssh_only = false +style = 'blue bold dimmed' +format = '[$ssh_symbol$hostname]($style) ' + +[username] +style_user = 'blue bold dimmed' +style_root = 'red bold' +format = '[$user]($style)@' +show_always = true + +[palettes.catppuccin_mocha] +rosewater = "#f5e0dc" +flamingo = "#f2cdcd" +pink = "#f5c2e7" +mauve = "#cba6f7" +red = "#f38ba8" +maroon = "#eba0ac" +peach = "#fab387" +yellow = "#f9e2af" +green = "#a6e3a1" +teal = "#94e2d5" +sky = "#89dceb" +sapphire = "#74c7ec" +blue = "#89b4fa" +lavender = "#b4befe" +text = "#cdd6f4" +subtext1 = "#bac2de" +subtext0 = "#a6adc8" +overlay2 = "#9399b2" +overlay1 = "#7f849c" +overlay0 = "#6c7086" +surface2 = "#585b70" +surface1 = "#45475a" +surface0 = "#313244" +base = "#1e1e2e" +mantle = "#181825" +crust = "#11111b" diff --git a/wolfi/bluefin-base/root/.bash_profile b/wolfi/bluefin-base/root/.bash_profile new file mode 100644 index 0000000..a459ace --- /dev/null +++ b/wolfi/bluefin-base/root/.bash_profile @@ -0,0 +1,3 @@ +if [ -f ~/.bashrc ]; then + . ~/.bashrc +fi \ No newline at end of file diff --git a/wolfi/bluefin-base/root/.bashrc b/wolfi/bluefin-base/root/.bashrc new file mode 100644 index 0000000..2782dcd --- /dev/null +++ b/wolfi/bluefin-base/root/.bashrc @@ -0,0 +1,3 @@ +if [ -f /etc/bashrc ]; then + . /etc/bashrc +fi \ No newline at end of file diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish new file mode 100644 index 0000000..3dc3bb0 --- /dev/null +++ b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish @@ -0,0 +1,45 @@ +if test "$(id -u)" -gt "0" + set blue (set_color blue) + set bold (set_color -o blue) + set normal (set_color normal) + if test ! -f /etc/linuxbrew.firstrun + printf "\nBluefin-CLI First Run Setup\n\n" + printf "Setting up sudo for %s%s%s...\t\t\t " "$bold" "$USER" "$normal" + echo "#$UID ALL = (root) NOPASSWD:ALL" | su-exec root tee -a /etc/sudoers > /dev/null + printf "%s[ OK ]%s\n" "$blue" "$normal" + end + + if test ! -d /home/linuxbrew/.linuxbrew + set name $(hostname -s) + set xdg_data_home "$XDG_DATA_HOME" + test -z "$xdg_data_home"; and set xdg_data_home "$HOME/.local/share/" + set linuxbrew_home "$xdg_data_home/bluefin-cli/$name" + printf "Setting up Linuxbrew...\t\t\t\t " + if test ! -d "$linuxbrew_home" + mkdir -p "$linuxbrew_home" + end + if test ! -d /home/linuxbrew + su-exec root mkdir -p /home/linuxbrew + end + su-exec root mount --bind "$linuxbrew_home" /home/linuxbrew + su-exec root cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ + su-exec root chown -R "$UID" /home/linuxbrew + set -e linuxbrew_home + printf "%s[ OK ]%s\n" "$blue" "$normal" + end + + if test ! -d /usr/local/share/bash-completion/completions + printf "Setting up Tab-Completions...\t\t\t " + su-exec root mkdir -p /usr/local/share/bash-completion + su-exec root mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion + if test -x /run/host/usr/bin/ujust + su-exec root ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust + end + printf "%s[ OK ]%s\n" "$blue" "$normal" + end + + if test ! -f /etc/linuxbrew.firstrun + su-exec root touch /etc/linuxbrew.firstrun + printf "\nBluefin-CLI first run complete!\n\n" + end +end diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/bling.fish b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/bling.fish new file mode 100644 index 0000000..34b6438 --- /dev/null +++ b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/bling.fish @@ -0,0 +1,27 @@ +if status is-interactive + set -gx STARSHIP_CONFIG /etc/starship.toml + eval "$(starship init fish)" + eval "$(atuin init fish)" + eval "$(zoxide init fish --cmd cd)" + set -gx HOST (hostname -s) +end + +# Eza for ls +alias ll='eza -l --icons=auto --group-directories-first' 2>/dev/null +alias l.='eza -d .*' 2>/dev/null +alias ls='eza' 2>/dev/null +alias l1='eza -1' + +# Ripgrep for grep +alias grep='rg' 2>/dev/null +alias egrep='rg' 2>/dev/null +alias fgrep='rg -F' 2>/dev/null +alias xzgrep='rg -z' 2>/dev/null +alias xzegrep='rg -z' 2>/dev/null +alias xzfgrep='rg -z -F' 2>/dev/null + +# Zoxide is handling cd +alias cd='cd' 2>/dev/null + +# Fd for find +alias find='fd' 2>/dev/null \ No newline at end of file diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/brew.fish b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/brew.fish new file mode 100644 index 0000000..e702181 --- /dev/null +++ b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/brew.fish @@ -0,0 +1,15 @@ +if test "$(id -u)" -gt "0" + set -gx PATH $PATH /home/linuxbrew/.linuxbrew/bin + set -gx HOMEBREW_PREFIX /home/linuxbrew/.linuxbrew + set -gx HOMEBREW_CELLAR /home/linuxbrew/.linuxbrew/Cellar + set -gx HOMEBREW_REPOSITORY /home/linuxbrew/.linuxbrew + if ! test -L (brew --prefix)"/share/fish/completions" + brew completions link + end + if test -d (brew --prefix)"/share/fish/completions" + set -p fish_complete_path (brew --prefix)/share/fish/completions + end + if test -d (brew --prefix)"/share/fish/vendor_completions.d" + set -p fish_complete_path (brew --prefix)/share/fish/vendor_completions.d + end +end \ No newline at end of file diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_command_not_found.fish b/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_command_not_found.fish new file mode 100644 index 0000000..d7243f0 --- /dev/null +++ b/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_command_not_found.fish @@ -0,0 +1,8 @@ +function fish_command_not_found + # "In a container" check + if test -e /run/.containerenv -o -e /.dockerenv + distrobox-host-exec $argv + else + __fish_default_command_not_found_handler $argv + end +end \ No newline at end of file diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_title.fish b/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_title.fish new file mode 100644 index 0000000..f1e820a --- /dev/null +++ b/wolfi/bluefin-base/usr/share/fish/vendor_functions.d/fish_title.fish @@ -0,0 +1,4 @@ +function fish_title + set -q argv[1]; or set argv fish + echo "$USER@$HOST" (fish_prompt_pwd_dir_length=1 prompt_pwd): $argv +end \ No newline at end of file diff --git a/wolfi/ublue-base.yaml b/wolfi/ublue-base.yaml new file mode 100644 index 0000000..85c7c02 --- /dev/null +++ b/wolfi/ublue-base.yaml @@ -0,0 +1,96 @@ +package: + name: ublue-base + version: 0.0.0 + epoch: 0 + description: "Universal Blue metapackage" + copyright: + - license: Apache-2.0 + dependencies: + runtime: + - bash + - busybox + - bzip2 + - coreutils + - curl + - diffutils + - findmnt + - findutils + - git + - gnupg + - gpg + - iproute2 + - iputils + - keyutils + - libcap + - libsm + - libx11 + - libxau + - libxcb + - libxdmcp + - libxext + - libice + - libxmu + - libxt + - linux-pam + - man-db + - mount + - ncurses + - ncurses-terminfo + - net-tools + - openssh-client + - pigz + - posix-libc-utils + - procps + - rsync + - shadow + - su-exec + - tcpdump + - tree + - tzdata + - umount + - unzip + - util-linux + - util-linux-misc + - vulkan-loader + - wget + - xauth + - xz + - zip + +environment: + contents: + keyring: + - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub + repositories: + - https://packages.wolfi.dev/os + packages: + - busybox + - git + - wget + +pipeline: + - runs: | + mkdir -p "${{targets.contextdir}}"/usr/bin + mkdir -p "${{targets.contextdir}}"/usr/local/bin + + # Setup fake sudo and pinentry + install -Dm755 sudo "${{targets.contextdir}}"/usr/bin/sudo + install -Dm755 pinentry "${{targets.contextdir}}"/usr/bin/pinentry + + # Get Distrobox-host-exec and host-spawn + git clone https://github.com/89luca89/distrobox.git --single-branch distrobox + install -Dm755 distrobox/distrobox-host-exec "${{targets.contextdir}}"/usr/bin/distrobox-host-exec + install -Dm755 distrobox/distrobox-export "${{targets.contextdir}}"/usr/bin/distrobox-export + install -Dm755 distrobox/distrobox-init "${{targets.contextdir}}"/usr/bin/entrypoint + wget https://github.com/1player/host-spawn/releases/download/$(cat distrobox/distrobox-host-exec | grep host_spawn_version= | cut -d "\"" -f 2)/host-spawn-$(uname -m) -O "${{ targets.contextdir }}"/usr/bin/host-spawn + chmod +x "${{ targets.contextdir }}"/usr/bin/host-spawn + + # Make some symlinks + ln -sf /bin/sh "${{targets.contextdir}}"/usr/bin/sh + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/docker + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/flatpak + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/podman + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/rpm-ostree + +update: + manual: true diff --git a/wolfi/ublue-base/pinentry b/wolfi/ublue-base/pinentry new file mode 100755 index 0000000..039e4d0 --- /dev/null +++ b/wolfi/ublue-base/pinentry @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/wolfi/ublue-base/sudo b/wolfi/ublue-base/sudo new file mode 100755 index 0000000..f458bb7 --- /dev/null +++ b/wolfi/ublue-base/sudo @@ -0,0 +1,2 @@ +#!/bin/sh +/sbin/su-exec root "$@" From ea9447b85e6d715d60d0c944b697f1b8a27c00d0 Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 21 Apr 2024 22:46:51 -0600 Subject: [PATCH 22/41] fix(bluefin-base): Temporarily withdraw uutils --- wolfi/bluefin-base.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/wolfi/bluefin-base.yaml b/wolfi/bluefin-base.yaml index 8f7494b..a6d755f 100644 --- a/wolfi/bluefin-base.yaml +++ b/wolfi/bluefin-base.yaml @@ -19,7 +19,6 @@ package: - sed - starship - ublue-base - - uutils - zoxide - zsh From 6b8110118ca1025a666e9a6dde2442b7e36dd071 Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 21 Apr 2024 22:49:51 -0600 Subject: [PATCH 23/41] fix(ublue-base): Add apk-tools --- wolfi/ublue-base.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/wolfi/ublue-base.yaml b/wolfi/ublue-base.yaml index 85c7c02..d3ab43d 100644 --- a/wolfi/ublue-base.yaml +++ b/wolfi/ublue-base.yaml @@ -7,6 +7,7 @@ package: - license: Apache-2.0 dependencies: runtime: + - apk-tools - bash - busybox - bzip2 From 74f61128c1fdf6313f37d694f2014d48ed2cf28d Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Tue, 23 Apr 2024 12:17:00 -0700 Subject: [PATCH 24/41] feat: Add kmod for framework laptops --- .../framework-laptop-kmod-common.spec | 27 ++++++++++ .../framework-laptop-kmod.spec | 53 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 akmods/framework-laptop/framework-laptop-kmod-common.spec create mode 100644 akmods/framework-laptop/framework-laptop-kmod.spec diff --git a/akmods/framework-laptop/framework-laptop-kmod-common.spec b/akmods/framework-laptop/framework-laptop-kmod-common.spec new file mode 100644 index 0000000..0083f57 --- /dev/null +++ b/akmods/framework-laptop/framework-laptop-kmod-common.spec @@ -0,0 +1,27 @@ +%global real_name framework-laptop + +Name: %{real_name}-kmod-common +Version: {{{ git_dir_version }}} +Release: 1%{?dist} +Summary: Kernel module to expose more Framework Laptop stuff +License: GPLv2 +URL: https://github.com/KyleGospo/framework-laptop-kmod +BuildArch: noarch + +Source: %{url}/archive/refs/heads/main.tar.gz + +Requires: %{real_name}-kmod = %{?epoch:%{epoch}:}%{version} +Provides: %{real_name}-kmod-common = %{?epoch:%{epoch}:}%{version} + +%description +A kernel module that exposes the Framework Laptop (13, 16)'s battery charge limit and LEDs to userspace. + +%prep +%autosetup -p1 -n %{real_name}-kmod-main + +%files +%license LICENSE +%doc README.md + +%changelog +{{{ git_dir_changelog }}} diff --git a/akmods/framework-laptop/framework-laptop-kmod.spec b/akmods/framework-laptop/framework-laptop-kmod.spec new file mode 100644 index 0000000..dc230d6 --- /dev/null +++ b/akmods/framework-laptop/framework-laptop-kmod.spec @@ -0,0 +1,53 @@ +# Build only the akmod package and no kernel module packages: +%define buildforkernels akmod +%global real_name framework-laptop +%global modname framework_laptop + +%global debug_package %{nil} + +Name: %{real_name}-kmod +Version: {{{ git_dir_version }}} +Release: 1%{?dist} +Summary: Kernel module to expose more Framework Laptop stuff +License: GPLv2 +URL: https://github.com/KyleGospo/framework-laptop-kmod + +Source: %{url}/archive/refs/heads/main.tar.gz + +# Get the needed BuildRequires (in parts depending on what we build for): +BuildRequires: kmodtool + +# kmodtool does its magic here +%{expand:%(kmodtool --target %{_target_cpu} --kmodname %{name} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null) } + +%description +A kernel module that exposes the Framework Laptop (13, 16)'s battery charge limit and LEDs to userspace. + +%prep +# Error out if there was something wrong with kmodtool: +%{?kmodtool_check} +# Print kmodtool output for debugging purposes: +kmodtool --target %{_target_cpu} --kmodname %{name} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null + +%autosetup -p1 -n %{real_name}-kmod-master + +for kernel_version in %{?kernel_versions} ; do + mkdir -p _kmod_build_${kernel_version%%___*} + cp -a %{modname}.c %{modname}.h Makefile _kmod_build_${kernel_version%%___*}/ +done + +%build +for kernel_version in %{?kernel_versions} ; do + make V=1 %{?_smp_mflags} -C ${kernel_version##*___} M=${PWD}/_kmod_build_${kernel_version%%___*} VERSION=v%{version} modules +done + +%install +for kernel_version in %{?kernel_versions}; do + mkdir -p %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + install -D -m 755 _kmod_build_${kernel_version%%___*}/%{modname}.ko %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + chmod a+x %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/%{modname}.ko +done +%{?akmod_install} + +%changelog +{{{ git_dir_changelog }}} From 344c44234b1afdb44d16bb3ca6265aae72826920 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Tue, 23 Apr 2024 12:24:18 -0700 Subject: [PATCH 25/41] chore: Correct folder name for framework-laptop --- akmods/framework-laptop/framework-laptop-kmod.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akmods/framework-laptop/framework-laptop-kmod.spec b/akmods/framework-laptop/framework-laptop-kmod.spec index dc230d6..c4aadde 100644 --- a/akmods/framework-laptop/framework-laptop-kmod.spec +++ b/akmods/framework-laptop/framework-laptop-kmod.spec @@ -29,7 +29,7 @@ A kernel module that exposes the Framework Laptop (13, 16)'s battery charge limi # Print kmodtool output for debugging purposes: kmodtool --target %{_target_cpu} --kmodname %{name} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null -%autosetup -p1 -n %{real_name}-kmod-master +%autosetup -p1 -n %{real_name}-kmod-main for kernel_version in %{?kernel_versions} ; do mkdir -p _kmod_build_${kernel_version%%___*} From 7229df2106043c76f0210aa2b41de3af17b453fa Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Tue, 23 Apr 2024 12:40:54 -0700 Subject: [PATCH 26/41] chore: Remove unneeded .h file inclusion --- akmods/framework-laptop/framework-laptop-kmod.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akmods/framework-laptop/framework-laptop-kmod.spec b/akmods/framework-laptop/framework-laptop-kmod.spec index c4aadde..aa656d6 100644 --- a/akmods/framework-laptop/framework-laptop-kmod.spec +++ b/akmods/framework-laptop/framework-laptop-kmod.spec @@ -33,7 +33,7 @@ kmodtool --target %{_target_cpu} --kmodname %{name} %{?buildforkernels:--%{buil for kernel_version in %{?kernel_versions} ; do mkdir -p _kmod_build_${kernel_version%%___*} - cp -a %{modname}.c %{modname}.h Makefile _kmod_build_${kernel_version%%___*}/ + cp -a %{modname}.c Makefile _kmod_build_${kernel_version%%___*}/ done %build From b663159ffbcb0248261bbf3e6625e2a66aaa9576 Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sat, 27 Apr 2024 18:12:28 -0600 Subject: [PATCH 27/41] feat(wolfi): Add support for additional host package managers Signed-off-by: RJ Trujillo --- wolfi/ublue-base.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wolfi/ublue-base.yaml b/wolfi/ublue-base.yaml index d3ab43d..54b0fd5 100644 --- a/wolfi/ublue-base.yaml +++ b/wolfi/ublue-base.yaml @@ -88,10 +88,20 @@ pipeline: # Make some symlinks ln -sf /bin/sh "${{targets.contextdir}}"/usr/bin/sh + + # Symlink host tools ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/docker - ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/flatpak ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/podman + + # Symlink host package managers + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/apt + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/apt-get + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/dnf + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/flatpak + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/pacman ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/rpm-ostree + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/snap + ln -sf /usr/bin/distrobox-host-exec "${{targets.contextdir}}"/usr/local/bin/zypper update: manual: true From f83578c07ed96f2faa40aa96967d87e769774dbd Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sat, 27 Apr 2024 23:36:31 -0700 Subject: [PATCH 28/41] chore: Update Mutter xwayland fractional scaling patch --- ...nput-region-from-frame-window-for-de.patch | 60 +- staging/mutter/0003-3304.patch | 854 -- staging/mutter/0004-1441.patch | 8598 ----------------- .../mutter/{0002-3567.patch => 3567.patch} | 701 +- staging/mutter/mutter.spec | 11 +- 5 files changed, 486 insertions(+), 9738 deletions(-) delete mode 100644 staging/mutter/0003-3304.patch delete mode 100644 staging/mutter/0004-1441.patch rename staging/mutter/{0002-3567.patch => 3567.patch} (88%) diff --git a/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch b/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch index c2baf41..4124b53 100644 --- a/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch +++ b/staging/mutter/0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch @@ -1,8 +1,56 @@ -From 1d5c47f8970c2027de5f6fa49b84de73d55b419b Mon Sep 17 00:00:00 2001 +From 21680b2f4edb064ff524cb91e9e20ace91deda6d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 21 Apr 2024 16:54:52 +0200 +Subject: [PATCH 1/2] Revert "x11/window: Update comment and variable name to + reflect current behavior" + +This reverts commit e4763d00e8512aeb408ae118597d753f12217487. +--- + src/x11/window-x11.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index 6d2016e3ec..f6f7d87dfe 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -2476,20 +2476,21 @@ meta_window_x11_update_input_region (MetaWindow *window) + + if (region != NULL) + { +- MtkRectangle bounding_rect; ++ MtkRectangle client_area; + +- bounding_rect.x = 0; +- bounding_rect.y = 0; +- bounding_rect.width = window->buffer_rect.width; +- bounding_rect.height = window->buffer_rect.height; ++ client_area.x = 0; ++ client_area.y = 0; ++ client_area.width = window->buffer_rect.width; ++ client_area.height = window->buffer_rect.height; + + /* The shape we get back from the client may have coordinates + * outside of the frame. The X SHAPE Extension requires that + * the overall shape the client provides never exceeds the + * "bounding rectangle" of the window -- the shape that the +- * window would have gotten if it was unshaped. ++ * window would have gotten if it was unshaped. In our case, ++ * this is simply the client area. + */ +- mtk_region_intersect_rectangle (region, &bounding_rect); ++ mtk_region_intersect_rectangle (region, &client_area); + } + + meta_window_set_input_region (window, region); +-- +2.44.0 + + +From f1996e67ad8a5a0009e90c38767c8906e015ba70 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Thu, 5 Oct 2023 13:09:46 -0700 -Subject: [PATCH] Revert "x11: Use input region from frame window for decorated - windows" +Subject: [PATCH 2/2] Revert "x11: Use input region from frame window for + decorated windows" This reverts commit d991961ae2a5c8cf2e58ff1072239f4902b0f767. It seems to cause the broken mouse interaction bug reported in @@ -15,7 +63,7 @@ Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3068 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/core/frame.c b/src/core/frame.c -index 145f0b7bd7..1c90ce4231 100644 +index c74a2e04ec..5feb854805 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -35,7 +35,6 @@ @@ -47,7 +95,7 @@ index 145f0b7bd7..1c90ce4231 100644 meta_window_x11_get_xwindow (window), x11_display->atom__MUTTER_NEEDS_FRAME); diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index 745c45db18..8edff883c9 100644 +index f6f7d87dfe..1bc5c57a1a 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -2082,10 +2082,6 @@ meta_window_x11_constructed (GObject *object) @@ -111,5 +159,5 @@ index 745c45db18..8edff883c9 100644 /* The shape we get back from the client may have coordinates * outside of the frame. The X SHAPE Extension requires that -- -2.43.2 +2.44.0 diff --git a/staging/mutter/0003-3304.patch b/staging/mutter/0003-3304.patch deleted file mode 100644 index b3a7946..0000000 --- a/staging/mutter/0003-3304.patch +++ /dev/null @@ -1,854 +0,0 @@ -diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c -index 9a57c52de..2f8247b3a 100644 ---- a/src/backends/meta-egl.c -+++ b/src/backends/meta-egl.c -@@ -260,6 +260,14 @@ meta_egl_has_extensions (MetaEgl *egl, - return has_extensions; - } - -+const char * -+meta_egl_query_string (MetaEgl *egl, -+ EGLDisplay display, -+ EGLint name) -+{ -+ return eglQueryString (display, name); -+} -+ - gboolean - meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, -diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h -index 09bee954a..8b955c90c 100644 ---- a/src/backends/meta-egl.h -+++ b/src/backends/meta-egl.h -@@ -47,6 +47,10 @@ gboolean meta_egl_has_extensions (MetaEgl *egl, - const char *first_extension, - ...); - -+const char * meta_egl_query_string (MetaEgl *egl, -+ EGLDisplay display, -+ EGLint name); -+ - gboolean meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, - GError **error); -diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index e40b03f3e..2710352d1 100644 ---- a/src/backends/native/meta-onscreen-native.c -+++ b/src/backends/native/meta-onscreen-native.c -@@ -840,6 +840,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, - "copy_shared_framebuffer_gpu()"); - -+ if (renderer_gpu_data->secondary.needs_explicit_sync) -+ cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); -+ - render_device = renderer_gpu_data->render_device; - egl_display = meta_render_device_get_egl_display (render_device); - -@@ -947,8 +950,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, - "copy_shared_framebuffer_primary_gpu()"); - -- if (!secondary_gpu_state || -- secondary_gpu_state->egl_surface == EGL_NO_SURFACE) -+ if (!secondary_gpu_state) - return NULL; - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); -@@ -2417,6 +2419,15 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat - width, height, - format, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); -+ -+ if (!gbm_surface) -+ { -+ gbm_surface = gbm_surface_create (gbm_device, -+ width, height, -+ format, -+ 0); -+ } -+ - if (!gbm_surface) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, -diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c -index cf27ba8d4..0d50de177 100644 ---- a/src/backends/native/meta-renderer-native-gles3.c -+++ b/src/backends/native/meta-renderer-native-gles3.c -@@ -3,6 +3,7 @@ - /* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. -+ * Copyright (c) 2023 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -34,6 +35,7 @@ - #include "backends/meta-egl-ext.h" - #include "backends/meta-gles3.h" - #include "backends/meta-gles3-table.h" -+#include "meta/meta-debug.h" - - /* - * GL/gl.h being included may conflict with gl3.h on some architectures. -@@ -43,17 +45,240 @@ - #error "Somehow included OpenGL headers when we shouldn't have" - #endif - -+typedef struct _ContextData -+{ -+ GArray *buffer_support; -+ GLuint shader_program; -+} ContextData; -+ -+typedef struct -+{ -+ uint32_t drm_format; -+ uint64_t drm_modifier; -+ gboolean can_blit; -+} BufferTypeSupport; -+ - static void --paint_egl_image (MetaGles3 *gles3, -- EGLImageKHR egl_image, -- int width, -- int height) -+context_data_free (ContextData *context_data) -+{ -+ g_array_free (context_data->buffer_support, TRUE); -+ g_free (context_data); -+} -+ -+static GQuark -+get_quark_for_egl_context (EGLContext egl_context) -+{ -+ char key[128]; -+ -+ g_snprintf (key, sizeof key, "EGLContext %p", egl_context); -+ -+ return g_quark_from_string (key); -+} -+ -+static gboolean -+can_blit_buffer (ContextData *context_data, -+ MetaEgl *egl, -+ EGLDisplay egl_display, -+ uint32_t drm_format, -+ uint64_t drm_modifier) -+{ -+ EGLint num_modifiers; -+ EGLuint64KHR *modifiers; -+ EGLBoolean *external_only; -+ g_autoptr (GError) error = NULL; -+ int i; -+ gboolean can_blit; -+ BufferTypeSupport support; -+ -+ can_blit = drm_modifier == DRM_FORMAT_MOD_LINEAR; -+ -+ for (i = 0; i < context_data->buffer_support->len; i++) -+ { -+ BufferTypeSupport *support = -+ &g_array_index (context_data->buffer_support, BufferTypeSupport, i); -+ -+ if (support->drm_format == drm_format && -+ support->drm_modifier == drm_modifier) -+ return support->can_blit; -+ } -+ -+ if (!meta_egl_has_extensions (egl, egl_display, NULL, -+ "EGL_EXT_image_dma_buf_import_modifiers", -+ NULL)) -+ { -+ meta_topic (META_DEBUG_RENDER, -+ "No support for EGL_EXT_image_dma_buf_import_modifiers, " -+ "assuming blitting linearly will still work."); -+ goto out; -+ } -+ -+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, -+ drm_format, 0, NULL, NULL, -+ &num_modifiers, &error)) -+ { -+ meta_topic (META_DEBUG_RENDER, -+ "Failed to query supported DMA buffer modifiers (%s), " -+ "assuming blitting linearly will still work.", -+ error->message); -+ goto out; -+ } -+ -+ if (num_modifiers == 0) -+ goto out; -+ -+ modifiers = g_alloca0 (sizeof (EGLuint64KHR) * num_modifiers); -+ external_only = g_alloca0 (sizeof (EGLBoolean) * num_modifiers); -+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, -+ drm_format, num_modifiers, -+ modifiers, external_only, -+ &num_modifiers, &error)) -+ { -+ g_warning ("Failed to requery supported DMA buffer modifiers: %s", -+ error->message); -+ can_blit = FALSE; -+ goto out; -+ } -+ -+ can_blit = FALSE; -+ for (i = 0; i < num_modifiers; i++) -+ { -+ if (drm_modifier == modifiers[i]) -+ { -+ can_blit = !external_only[i]; -+ goto out; -+ } -+ } -+ -+out: -+ support = (BufferTypeSupport) { -+ .drm_format = drm_format, -+ .drm_modifier = drm_modifier, -+ .can_blit = can_blit, -+ }; -+ g_array_append_val (context_data->buffer_support, support); -+ return can_blit; -+} -+ -+static GLuint -+load_shader (const char *src, -+ GLenum type) -+{ -+ GLuint shader = glCreateShader (type); -+ -+ if (shader) -+ { -+ GLint compiled; -+ -+ glShaderSource (shader, 1, &src, NULL); -+ glCompileShader (shader); -+ glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); -+ if (!compiled) -+ { -+ GLchar log[1024]; -+ -+ glGetShaderInfoLog (shader, sizeof (log) - 1, NULL, log); -+ log[sizeof (log) - 1] = '\0'; -+ g_warning ("load_shader compile failed: %s", log); -+ glDeleteShader (shader); -+ shader = 0; -+ } -+ } -+ -+ return shader; -+} -+ -+static void -+ensure_shader_program (ContextData *context_data, -+ MetaGles3 *gles3) -+{ -+ static const char vertex_shader_source[] = -+ "#version 100\n" -+ "attribute vec2 position;\n" -+ "attribute vec2 texcoord;\n" -+ "varying vec2 v_texcoord;\n" -+ "\n" -+ "void main()\n" -+ "{\n" -+ " gl_Position = vec4(position, 0.0, 1.0);\n" -+ " v_texcoord = texcoord;\n" -+ "}\n"; -+ -+ static const char fragment_shader_source[] = -+ "#version 100\n" -+ "#extension GL_OES_EGL_image_external : require\n" -+ "precision mediump float;\n" -+ "uniform samplerExternalOES s_texture;\n" -+ "varying vec2 v_texcoord;\n" -+ "\n" -+ " void main()\n" -+ "{\n" -+ " gl_FragColor = texture2D(s_texture, v_texcoord);\n" -+ "}\n"; -+ -+ static const GLfloat box[] = -+ { /* position texcoord */ -+ -1.0f, +1.0f, 0.0f, 0.0f, -+ +1.0f, +1.0f, 1.0f, 0.0f, -+ +1.0f, -1.0f, 1.0f, 1.0f, -+ -1.0f, -1.0f, 0.0f, 1.0f, -+ }; -+ GLint linked; -+ GLuint vertex_shader, fragment_shader; -+ GLint position_attrib, texcoord_attrib; -+ GLuint shader_program; -+ -+ if (context_data->shader_program) -+ return; -+ -+ shader_program = glCreateProgram (); -+ g_return_if_fail (shader_program); -+ context_data->shader_program = shader_program; -+ -+ vertex_shader = load_shader (vertex_shader_source, GL_VERTEX_SHADER); -+ g_return_if_fail (vertex_shader); -+ fragment_shader = load_shader (fragment_shader_source, GL_FRAGMENT_SHADER); -+ g_return_if_fail (fragment_shader); -+ -+ GLBAS (gles3, glAttachShader, (shader_program, vertex_shader)); -+ GLBAS (gles3, glAttachShader, (shader_program, fragment_shader)); -+ GLBAS (gles3, glLinkProgram, (shader_program)); -+ GLBAS (gles3, glGetProgramiv, (shader_program, GL_LINK_STATUS, &linked)); -+ if (!linked) -+ { -+ GLchar log[1024]; -+ -+ glGetProgramInfoLog (shader_program, sizeof (log) - 1, NULL, log); -+ log[sizeof (log) - 1] = '\0'; -+ g_warning ("Link failed: %s", log); -+ return; -+ } -+ -+ GLBAS (gles3, glUseProgram, (shader_program)); -+ -+ position_attrib = glGetAttribLocation (shader_program, "position"); -+ GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); -+ GLBAS (gles3, glVertexAttribPointer, -+ (position_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box)); -+ -+ texcoord_attrib = glGetAttribLocation (shader_program, "texcoord"); -+ GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); -+ GLBAS (gles3, glVertexAttribPointer, -+ (texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box + 2)); -+} -+ -+static void -+blit_egl_image (MetaGles3 *gles3, -+ EGLImageKHR egl_image, -+ int width, -+ int height) - { - GLuint texture; - GLuint framebuffer; - - meta_gles3_clear_error (gles3); - -+ GLBAS (gles3, glViewport, (0, 0, width, height)); -+ - GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - -@@ -85,6 +310,43 @@ paint_egl_image (MetaGles3 *gles3, - GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); - } - -+static void -+paint_egl_image (ContextData *context_data, -+ MetaGles3 *gles3, -+ EGLImageKHR egl_image, -+ int width, -+ int height) -+{ -+ GLuint texture; -+ -+ meta_gles3_clear_error (gles3); -+ ensure_shader_program (context_data, gles3); -+ -+ GLBAS (gles3, glViewport, (0, 0, width, height)); -+ -+ GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); -+ GLBAS (gles3, glGenTextures, (1, &texture)); -+ GLBAS (gles3, glBindTexture, (GL_TEXTURE_EXTERNAL_OES, texture)); -+ GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_EXTERNAL_OES, -+ egl_image)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_MAG_FILTER, -+ GL_NEAREST)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_MIN_FILTER, -+ GL_NEAREST)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_WRAP_S, -+ GL_CLAMP_TO_EDGE)); -+ GLBAS (gles3, glTexParameteri, (GL_TEXTURE_EXTERNAL_OES, -+ GL_TEXTURE_WRAP_T, -+ GL_CLAMP_TO_EDGE)); -+ -+ GLBAS (gles3, glDrawArrays, (GL_TRIANGLE_FAN, 0, 4)); -+ -+ GLBAS (gles3, glDeleteTextures, (1, &texture)); -+} -+ - gboolean - meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, -@@ -105,6 +367,28 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - uint32_t format; - EGLImageKHR egl_image; - gboolean use_modifiers; -+ GQuark context_data_quark; -+ ContextData *context_data; -+ gboolean can_blit; -+ -+ context_data_quark = get_quark_for_egl_context (egl_context); -+ context_data = g_object_get_qdata (G_OBJECT (gles3), context_data_quark); -+ if (!context_data) -+ { -+ context_data = g_new0 (ContextData, 1); -+ context_data->buffer_support = g_array_new (FALSE, FALSE, -+ sizeof (BufferTypeSupport)); -+ -+ g_object_set_qdata_full (G_OBJECT (gles3), -+ context_data_quark, -+ context_data, -+ (GDestroyNotify) context_data_free); -+ } -+ -+ can_blit = can_blit_buffer (context_data, -+ egl, egl_display, -+ gbm_bo_get_format (shared_bo), -+ gbm_bo_get_modifier (shared_bo)); - - shared_bo_fd = gbm_bo_get_fd (shared_bo); - if (shared_bo_fd < 0) -@@ -150,9 +434,21 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - if (!egl_image) - return FALSE; - -- paint_egl_image (gles3, egl_image, width, height); -+ if (can_blit) -+ blit_egl_image (gles3, egl_image, width, height); -+ else -+ paint_egl_image (context_data, gles3, egl_image, width, height); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - return TRUE; - } -+ -+void -+meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, -+ EGLContext egl_context) -+{ -+ GQuark context_data_quark = get_quark_for_egl_context (egl_context); -+ -+ g_object_set_qdata (G_OBJECT (gles3), context_data_quark, NULL); -+} -diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h -index 591ff82e1..f5791a171 100644 ---- a/src/backends/native/meta-renderer-native-gles3.h -+++ b/src/backends/native/meta-renderer-native-gles3.h -@@ -26,10 +26,13 @@ - #include "backends/meta-egl.h" - #include "backends/meta-gles3.h" - --gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, -- MetaGles3 *gles3, -- EGLDisplay egl_display, -- EGLContext egl_context, -- EGLSurface egl_surface, -- struct gbm_bo *shared_bo, -- GError **error); -+gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, -+ MetaGles3 *gles3, -+ EGLDisplay egl_display, -+ EGLContext egl_context, -+ EGLSurface egl_surface, -+ struct gbm_bo *shared_bo, -+ GError **error); -+ -+void meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, -+ EGLContext egl_context); -diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h -index 997fe6f69..2d3fe1971 100644 ---- a/src/backends/native/meta-renderer-native-private.h -+++ b/src/backends/native/meta-renderer-native-private.h -@@ -60,6 +60,7 @@ typedef struct _MetaRendererNativeGpuData - struct { - MetaSharedFramebufferCopyMode copy_mode; - gboolean has_EGL_EXT_image_dma_buf_import_modifiers; -+ gboolean needs_explicit_sync; - - /* For GPU blit mode */ - EGLContext egl_context; -diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index 7b64ff3f4..893ee4216 100644 ---- a/src/backends/native/meta-renderer-native.c -+++ b/src/backends/native/meta-renderer-native.c -@@ -63,6 +63,7 @@ - #include "backends/native/meta-output-kms.h" - #include "backends/native/meta-render-device-gbm.h" - #include "backends/native/meta-render-device-surfaceless.h" -+#include "backends/native/meta-renderer-native-gles3.h" - #include "backends/native/meta-renderer-native-private.h" - #include "backends/native/meta-renderer-view-native.h" - #include "cogl/cogl.h" -@@ -136,6 +137,9 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - -+ meta_renderer_native_gles3_forget_context (renderer_native->gles3, -+ renderer_gpu_data->secondary.egl_context); -+ - meta_egl_destroy_context (egl, - egl_display, - renderer_gpu_data->secondary.egl_context, -@@ -1805,6 +1809,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - CoglContext *cogl_context; - CoglDisplay *cogl_display; - const char **missing_gl_extensions; -+ const char *egl_vendor; - - egl_display = meta_render_device_get_egl_display (render_device); - if (egl_display == EGL_NO_DISPLAY) -@@ -1871,6 +1876,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL); -+ -+ egl_vendor = meta_egl_query_string (egl, egl_display, EGL_VENDOR); -+ if (!g_strcmp0 (egl_vendor, "NVIDIA")) -+ renderer_gpu_data->secondary.needs_explicit_sync = TRUE; -+ - ret = TRUE; - out: - maybe_restore_cogl_egl_api (renderer_native); -diff --git a/src/meta/common.h b/src/meta/common.h -index ee978ac6a..ed3aa81ef 100644 ---- a/src/meta/common.h -+++ b/src/meta/common.h -@@ -27,6 +27,7 @@ - #include - - #include "clutter/clutter.h" -+#include "meta/meta-base.h" - #include "meta/meta-enums.h" - - /** -@@ -42,8 +43,6 @@ - /* Replacement for X11 CurrentTime */ - #define META_CURRENT_TIME 0L - --#define META_EXPORT __attribute__((visibility("default"))) extern -- - #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST - - /* Keep array size in sync with MAX_BUTTONS_PER_CORNER */ -diff --git a/src/meta/meson.build b/src/meta/meson.build -index 655dedeaf..bc3910408 100644 ---- a/src/meta/meson.build -+++ b/src/meta/meson.build -@@ -9,6 +9,7 @@ mutter_public_headers = [ - 'keybindings.h', - 'main.h', - 'meta-backend.h', -+ 'meta-base.h', - 'meta-background.h', - 'meta-background-actor.h', - 'meta-background-content.h', -@@ -17,6 +18,7 @@ mutter_public_headers = [ - 'meta-close-dialog.h', - 'meta-cursor-tracker.h', - 'meta-context.h', -+ 'meta-debug.h', - 'meta-dnd.h', - 'meta-enums.h', - 'meta-idle-monitor.h', -diff --git a/src/meta/meta-base.h b/src/meta/meta-base.h -new file mode 100644 -index 000000000..e344b2221 ---- /dev/null -+++ b/src/meta/meta-base.h -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2001 Havoc Pennington -+ * Copyright (C) 2005 Elijah Newren -+ * -+ * 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 -+ -+#define META_EXPORT __attribute__((visibility("default"))) extern -diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h -new file mode 100644 -index 000000000..b4c70144b ---- /dev/null -+++ b/src/meta/meta-debug.h -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2001 Havoc Pennington -+ * Copyright (C) 2005 Elijah Newren -+ * -+ * 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 "meta/meta-base.h" -+ -+/** -+ * MetaDebugTopic: -+ * @META_DEBUG_VERBOSE: verbose logging -+ * @META_DEBUG_FOCUS: focus -+ * @META_DEBUG_WORKAREA: workarea -+ * @META_DEBUG_STACK: stack -+ * @META_DEBUG_SM: session management -+ * @META_DEBUG_EVENTS: events -+ * @META_DEBUG_WINDOW_STATE: window state -+ * @META_DEBUG_WINDOW_OPS: window operations -+ * @META_DEBUG_GEOMETRY: geometry -+ * @META_DEBUG_PLACEMENT: window placement -+ * @META_DEBUG_PING: ping -+ * @META_DEBUG_KEYBINDINGS: keybindings -+ * @META_DEBUG_SYNC: sync -+ * @META_DEBUG_STARTUP: startup -+ * @META_DEBUG_PREFS: preferences -+ * @META_DEBUG_GROUPS: groups -+ * @META_DEBUG_RESIZING: resizing -+ * @META_DEBUG_SHAPES: shapes -+ * @META_DEBUG_EDGE_RESISTANCE: edge resistance -+ * @META_DEBUG_WAYLAND: Wayland -+ * @META_DEBUG_KMS: kernel mode setting -+ * @META_DEBUG_SCREEN_CAST: screencasting -+ * @META_DEBUG_REMOTE_DESKTOP: remote desktop -+ * @META_DEBUG_BACKEND: backend -+ * @META_DEBUG_RENDER: native backend rendering -+ * @META_DEBUG_COLOR: color management -+ * @META_DEBUG_INPUT_EVENTS: input events -+ * @META_DEBUG_EIS: eis state -+ */ -+typedef enum -+{ -+ META_DEBUG_VERBOSE = -1, -+ META_DEBUG_FOCUS = 1 << 0, -+ META_DEBUG_WORKAREA = 1 << 1, -+ META_DEBUG_STACK = 1 << 2, -+ META_DEBUG_SM = 1 << 3, -+ META_DEBUG_EVENTS = 1 << 4, -+ META_DEBUG_WINDOW_STATE = 1 << 5, -+ META_DEBUG_WINDOW_OPS = 1 << 6, -+ META_DEBUG_GEOMETRY = 1 << 7, -+ META_DEBUG_PLACEMENT = 1 << 8, -+ META_DEBUG_PING = 1 << 9, -+ META_DEBUG_KEYBINDINGS = 1 << 10, -+ META_DEBUG_SYNC = 1 << 11, -+ META_DEBUG_STARTUP = 1 << 12, -+ META_DEBUG_PREFS = 1 << 13, -+ META_DEBUG_GROUPS = 1 << 14, -+ META_DEBUG_RESIZING = 1 << 15, -+ META_DEBUG_SHAPES = 1 << 16, -+ META_DEBUG_EDGE_RESISTANCE = 1 << 17, -+ META_DEBUG_DBUS = 1 << 18, -+ META_DEBUG_INPUT = 1 << 19, -+ META_DEBUG_WAYLAND = 1 << 20, -+ META_DEBUG_KMS = 1 << 21, -+ META_DEBUG_SCREEN_CAST = 1 << 22, -+ META_DEBUG_REMOTE_DESKTOP = 1 << 23, -+ META_DEBUG_BACKEND = 1 << 24, -+ META_DEBUG_RENDER = 1 << 25, -+ META_DEBUG_COLOR = 1 << 26, -+ META_DEBUG_INPUT_EVENTS = 1 << 27, -+ META_DEBUG_EIS = 1 << 28, -+} MetaDebugTopic; -+ -+META_EXPORT -+gboolean meta_is_topic_enabled (MetaDebugTopic topic); -+ -+/* To disable verbose mode, we make these functions into no-ops */ -+#ifdef WITH_VERBOSE_MODE -+ -+const char * meta_topic_to_string (MetaDebugTopic topic); -+ -+META_EXPORT -+void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); -+ -+#define meta_topic(debug_topic, ...) \ -+ G_STMT_START \ -+ { \ -+ if (meta_is_topic_enabled (debug_topic)) \ -+ { \ -+ g_autofree char *_topic_message = NULL; \ -+\ -+ _topic_message = g_strdup_printf (__VA_ARGS__); \ -+ meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ -+ _topic_message); \ -+ } \ -+ } \ -+ G_STMT_END -+ -+#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) -+ -+#else -+ -+# ifdef G_HAVE_ISO_VARARGS -+# define meta_verbose(...) -+# define meta_topic(...) -+# elif defined(G_HAVE_GNUC_VARARGS) -+# define meta_verbose(format...) -+# define meta_topic(format...) -+# else -+# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" -+# endif -+ -+#endif /* !WITH_VERBOSE_MODE */ -diff --git a/src/meta/util.h b/src/meta/util.h -index 0019c8078..ca8ca2ade 100644 ---- a/src/meta/util.h -+++ b/src/meta/util.h -@@ -26,6 +26,7 @@ - #include - - #include "meta/common.h" -+#include "meta/meta-debug.h" - #include "meta/meta-later.h" - - META_EXPORT -@@ -46,71 +47,6 @@ META_EXPORT - void meta_fatal (const char *format, - ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN G_ANALYZER_NORETURN; - --/** -- * MetaDebugTopic: -- * @META_DEBUG_VERBOSE: verbose logging -- * @META_DEBUG_FOCUS: focus -- * @META_DEBUG_WORKAREA: workarea -- * @META_DEBUG_STACK: stack -- * @META_DEBUG_SM: session management -- * @META_DEBUG_EVENTS: events -- * @META_DEBUG_WINDOW_STATE: window state -- * @META_DEBUG_WINDOW_OPS: window operations -- * @META_DEBUG_GEOMETRY: geometry -- * @META_DEBUG_PLACEMENT: window placement -- * @META_DEBUG_PING: ping -- * @META_DEBUG_KEYBINDINGS: keybindings -- * @META_DEBUG_SYNC: sync -- * @META_DEBUG_STARTUP: startup -- * @META_DEBUG_PREFS: preferences -- * @META_DEBUG_GROUPS: groups -- * @META_DEBUG_RESIZING: resizing -- * @META_DEBUG_SHAPES: shapes -- * @META_DEBUG_EDGE_RESISTANCE: edge resistance -- * @META_DEBUG_WAYLAND: Wayland -- * @META_DEBUG_KMS: kernel mode setting -- * @META_DEBUG_SCREEN_CAST: screencasting -- * @META_DEBUG_REMOTE_DESKTOP: remote desktop -- * @META_DEBUG_BACKEND: backend -- * @META_DEBUG_RENDER: native backend rendering -- * @META_DEBUG_COLOR: color management -- * @META_DEBUG_INPUT_EVENTS: input events -- * @META_DEBUG_EIS: eis state -- */ --typedef enum --{ -- META_DEBUG_VERBOSE = -1, -- META_DEBUG_FOCUS = 1 << 0, -- META_DEBUG_WORKAREA = 1 << 1, -- META_DEBUG_STACK = 1 << 2, -- META_DEBUG_SM = 1 << 3, -- META_DEBUG_EVENTS = 1 << 4, -- META_DEBUG_WINDOW_STATE = 1 << 5, -- META_DEBUG_WINDOW_OPS = 1 << 6, -- META_DEBUG_GEOMETRY = 1 << 7, -- META_DEBUG_PLACEMENT = 1 << 8, -- META_DEBUG_PING = 1 << 9, -- META_DEBUG_KEYBINDINGS = 1 << 10, -- META_DEBUG_SYNC = 1 << 11, -- META_DEBUG_STARTUP = 1 << 12, -- META_DEBUG_PREFS = 1 << 13, -- META_DEBUG_GROUPS = 1 << 14, -- META_DEBUG_RESIZING = 1 << 15, -- META_DEBUG_SHAPES = 1 << 16, -- META_DEBUG_EDGE_RESISTANCE = 1 << 17, -- META_DEBUG_DBUS = 1 << 18, -- META_DEBUG_INPUT = 1 << 19, -- META_DEBUG_WAYLAND = 1 << 20, -- META_DEBUG_KMS = 1 << 21, -- META_DEBUG_SCREEN_CAST = 1 << 22, -- META_DEBUG_REMOTE_DESKTOP = 1 << 23, -- META_DEBUG_BACKEND = 1 << 24, -- META_DEBUG_RENDER = 1 << 25, -- META_DEBUG_COLOR = 1 << 26, -- META_DEBUG_INPUT_EVENTS = 1 << 27, -- META_DEBUG_EIS = 1 << 28, --} MetaDebugTopic; -- - /** - * MetaDebugPaintFlag: - * @META_DEBUG_PAINT_NONE: default -@@ -122,9 +58,6 @@ typedef enum - META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, - } MetaDebugPaintFlag; - --META_EXPORT --gboolean meta_is_topic_enabled (MetaDebugTopic topic); -- - META_EXPORT - void meta_add_verbose_topic (MetaDebugTopic topic); - -@@ -155,44 +88,6 @@ char* meta_external_binding_name_for_action (guint keybinding_action); - META_EXPORT - char* meta_g_utf8_strndup (const gchar *src, gsize n); - --/* To disable verbose mode, we make these functions into no-ops */ --#ifdef WITH_VERBOSE_MODE -- --const char * meta_topic_to_string (MetaDebugTopic topic); -- --META_EXPORT --void meta_log (const char *format, ...) G_GNUC_PRINTF (1, 2); -- --#define meta_topic(debug_topic, ...) \ -- G_STMT_START \ -- { \ -- if (meta_is_topic_enabled (debug_topic)) \ -- { \ -- g_autofree char *_topic_message = NULL; \ --\ -- _topic_message = g_strdup_printf (__VA_ARGS__); \ -- meta_log ("%s: %s", meta_topic_to_string (debug_topic), \ -- _topic_message); \ -- } \ -- } \ -- G_STMT_END -- --#define meta_verbose(...) meta_topic (META_DEBUG_VERBOSE, __VA_ARGS__) -- --#else -- --# ifdef G_HAVE_ISO_VARARGS --# define meta_verbose(...) --# define meta_topic(...) --# elif defined(G_HAVE_GNUC_VARARGS) --# define meta_verbose(format...) --# define meta_topic(format...) --# else --# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" --# endif -- --#endif /* !WITH_VERBOSE_MODE */ -- - typedef enum - { - META_LOCALE_DIRECTION_LTR, diff --git a/staging/mutter/0004-1441.patch b/staging/mutter/0004-1441.patch deleted file mode 100644 index 2590422..0000000 --- a/staging/mutter/0004-1441.patch +++ /dev/null @@ -1,8598 +0,0 @@ -diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml -index 7aadfceb2..5020c9bed 100644 ---- a/.gitlab-ci.yml -+++ b/.gitlab-ci.yml -@@ -237,6 +237,29 @@ workflow: - - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME - when: on_success - -+repo-sanity: -+ extends: -+ - .fdo.ci-fairy -+ stage: review -+ variables: -+ GIT_DEPTH: "1" -+ script: -+ - > -+ if [[ -z "$CI_REGISTRY_IMAGE" ]] ; -+ then -+ .gitlab-ci/simple-junit-report.sh check-junit-report.xml \ -+ repo-sanity "The container registry should be enabled in the project general settings panel at $CI_PROJECT_URL/edit" ; -+ exit 1 ; -+ fi -+ artifacts: -+ expire_in: 1 week -+ paths: -+ - check-junit-report.xml -+ reports: -+ junit: check-junit-report.xml -+ rules: -+ - !reference [.only-merge-requests, rules] -+ - check-commit-log: - extends: - - .fdo.ci-fairy -diff --git a/.gitlab-ci/simple-junit-report.sh b/.gitlab-ci/simple-junit-report.sh -new file mode 100755 -index 000000000..3a60324d3 ---- /dev/null -+++ b/.gitlab-ci/simple-junit-report.sh -@@ -0,0 +1,18 @@ -+#!/bin/bash -+OUTFILE=$1 -+NAME=$2 -+MESSAGE=$3 -+ -+cat >$OUTFILE < -+ -+ -+ -+ -+ -+ -+ -+EOF -+ -+# Also echo the message in stdout for good measure -+echo $MESSAGE -diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c -index 93e4c9329..a6c7ecea2 100644 ---- a/clutter/clutter/clutter-frame-clock.c -+++ b/clutter/clutter/clutter-frame-clock.c -@@ -42,6 +42,15 @@ enum - - static guint signals[N_SIGNALS]; - -+typedef enum -+{ -+ TRIPLE_BUFFERING_MODE_NEVER, -+ TRIPLE_BUFFERING_MODE_AUTO, -+ TRIPLE_BUFFERING_MODE_ALWAYS, -+} TripleBufferingMode; -+ -+static TripleBufferingMode triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO; -+ - #define SYNC_DELAY_FALLBACK_FRACTION 0.875 - - #define MINIMUM_REFRESH_RATE 30.f -@@ -70,8 +79,10 @@ typedef enum _ClutterFrameClockState - CLUTTER_FRAME_CLOCK_STATE_IDLE, - CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, - CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW, -- CLUTTER_FRAME_CLOCK_STATE_DISPATCHING, -- CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED, -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE, -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED, -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW, -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO, - } ClutterFrameClockState; - - struct _ClutterFrameClock -@@ -92,6 +103,7 @@ struct _ClutterFrameClock - ClutterFrameClockMode mode; - - int64_t last_dispatch_time_us; -+ int64_t prev_last_dispatch_time_us; - int64_t last_dispatch_lateness_us; - int64_t last_presentation_time_us; - int64_t next_update_time_us; -@@ -111,6 +123,9 @@ struct _ClutterFrameClock - int64_t vblank_duration_us; - /* Last KMS buffer submission time. */ - int64_t last_flip_time_us; -+ int64_t prev_last_flip_time_us; -+ -+ ClutterFrameHint last_flip_hints; - - /* Last time we promoted short-term maximum to long-term one */ - int64_t longterm_promotion_us; -@@ -245,10 +260,6 @@ static void - maybe_update_longterm_max_duration_us (ClutterFrameClock *frame_clock, - ClutterFrameInfo *frame_info) - { -- /* Do not update long-term max if there has been no measurement */ -- if (!frame_clock->shortterm_max_update_duration_us) -- return; -- - if ((frame_info->presentation_time - frame_clock->longterm_promotion_us) < - G_USEC_PER_SEC) - return; -@@ -275,6 +286,12 @@ void - clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - ClutterFrameInfo *frame_info) - { -+#ifdef CLUTTER_ENABLE_DEBUG -+ const char *debug_state = -+ frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO ? -+ "Triple buffering" : "Double buffering"; -+#endif -+ - COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented, - "Clutter::FrameClock::presented()"); - COGL_TRACE_DESCRIBE (ClutterFrameClockNotifyPresented, -@@ -361,22 +378,52 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - - frame_clock->got_measurements_last_frame = FALSE; - -- if (frame_info->cpu_time_before_buffer_swap_us != 0 && -- frame_info->has_valid_gpu_rendering_duration) -+ if ((frame_info->cpu_time_before_buffer_swap_us != 0 && -+ frame_info->has_valid_gpu_rendering_duration) || -+ frame_clock->ever_got_measurements) - { - int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us; -+ int64_t dispatch_time_us = 0, flip_time_us = 0; - -- dispatch_to_swap_us = -- frame_info->cpu_time_before_buffer_swap_us - -- frame_clock->last_dispatch_time_us; -+ switch (frame_clock->state) -+ { -+ case CLUTTER_FRAME_CLOCK_STATE_INIT: -+ case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ g_warn_if_reached (); -+ G_GNUC_FALLTHROUGH; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ dispatch_time_us = frame_clock->last_dispatch_time_us; -+ flip_time_us = frame_clock->last_flip_time_us; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ dispatch_time_us = frame_clock->prev_last_dispatch_time_us; -+ flip_time_us = frame_clock->prev_last_flip_time_us; -+ break; -+ } -+ -+ if (frame_info->cpu_time_before_buffer_swap_us == 0) -+ { -+ /* Cursor-only updates with no "swap" or "flip" */ -+ dispatch_to_swap_us = 0; -+ swap_to_flip_us = 0; -+ } -+ else -+ { -+ dispatch_to_swap_us = frame_info->cpu_time_before_buffer_swap_us - -+ dispatch_time_us; -+ swap_to_flip_us = flip_time_us - -+ frame_info->cpu_time_before_buffer_swap_us; -+ } - swap_to_rendering_done_us = - frame_info->gpu_rendering_duration_ns / 1000; -- swap_to_flip_us = -- frame_clock->last_flip_time_us - -- frame_info->cpu_time_before_buffer_swap_us; - - CLUTTER_NOTE (FRAME_TIMINGS, -- "update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", -+ "%s: update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", -+ debug_state, - frame_clock->last_dispatch_lateness_us, - dispatch_to_swap_us, - swap_to_rendering_done_us, -@@ -386,7 +433,7 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us + - MAX (swap_to_rendering_done_us, swap_to_flip_us), - frame_clock->shortterm_max_update_duration_us, -- frame_clock->refresh_interval_us); -+ 2 * frame_clock->refresh_interval_us); - - maybe_update_longterm_max_duration_us (frame_clock, frame_info); - -@@ -395,7 +442,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - } - else - { -- CLUTTER_NOTE (FRAME_TIMINGS, "update2dispatch %ld µs", -+ CLUTTER_NOTE (FRAME_TIMINGS, "%s: update2dispatch %ld µs", -+ debug_state, - frame_clock->last_dispatch_lateness_us); - } - -@@ -413,11 +461,22 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: - g_warn_if_reached (); - break; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; - maybe_reschedule_update (frame_clock); - break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ maybe_reschedule_update (frame_clock); -+ break; - } - } - -@@ -435,26 +494,37 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: - g_warn_if_reached (); - break; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; - maybe_reschedule_update (frame_clock); - break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ maybe_reschedule_update (frame_clock); -+ break; - } - } - --static int64_t --clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) -+static gboolean -+clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock, -+ int64_t *max_render_time_us) - { - int64_t refresh_interval_us; -- int64_t max_render_time_us; - - refresh_interval_us = frame_clock->refresh_interval_us; - - if (!frame_clock->ever_got_measurements || - G_UNLIKELY (clutter_paint_debug_flags & - CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME)) -- return refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; -+ return FALSE; - - /* Max render time shows how early the frame clock needs to be dispatched - * to make it to the predicted next presentation time. It is an estimate of -@@ -468,15 +538,15 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) - * - The duration of vertical blank. - * - A constant to account for variations in the above estimates. - */ -- max_render_time_us = -+ *max_render_time_us = - MAX (frame_clock->longterm_max_update_duration_us, - frame_clock->shortterm_max_update_duration_us) + - frame_clock->vblank_duration_us + - clutter_max_render_time_constant_us; - -- max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us); -+ *max_render_time_us = CLAMP (*max_render_time_us, 0, 2 * refresh_interval_us); - -- return max_render_time_us; -+ return TRUE; - } - - static void -@@ -491,7 +561,9 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, - int64_t min_render_time_allowed_us; - int64_t max_render_time_allowed_us; - int64_t next_presentation_time_us; -+ int64_t next_smooth_presentation_time_us = 0; - int64_t next_update_time_us; -+ gboolean max_render_time_is_known; - - now_us = g_get_monotonic_time (); - -@@ -511,10 +583,13 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, - } - - min_render_time_allowed_us = refresh_interval_us / 2; -- max_render_time_allowed_us = -- clutter_frame_clock_compute_max_render_time_us (frame_clock); - -- if (min_render_time_allowed_us > max_render_time_allowed_us) -+ max_render_time_is_known = -+ clutter_frame_clock_compute_max_render_time_us (frame_clock, -+ &max_render_time_allowed_us); -+ -+ if (max_render_time_is_known && -+ min_render_time_allowed_us > max_render_time_allowed_us) - min_render_time_allowed_us = max_render_time_allowed_us; - - /* -@@ -535,7 +610,28 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, - * - */ - last_presentation_time_us = frame_clock->last_presentation_time_us; -- next_presentation_time_us = last_presentation_time_us + refresh_interval_us; -+ switch (frame_clock->state) -+ { -+ case CLUTTER_FRAME_CLOCK_STATE_INIT: -+ case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ next_smooth_presentation_time_us = last_presentation_time_us + -+ refresh_interval_us; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ next_smooth_presentation_time_us = last_presentation_time_us + -+ 2 * refresh_interval_us; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ next_smooth_presentation_time_us = last_presentation_time_us + -+ 3 * refresh_interval_us; -+ break; -+ } -+ -+ next_presentation_time_us = next_smooth_presentation_time_us; - - /* - * However, the last presentation could have happened more than a frame ago. -@@ -601,7 +697,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, - } - } - -- if (next_presentation_time_us != last_presentation_time_us + refresh_interval_us) -+ if (next_presentation_time_us != next_smooth_presentation_time_us) - { - /* There was an idle period since the last presentation, so there seems - * be no constantly updating actor. In this case it's best to start -@@ -613,6 +709,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, - } - else - { -+ /* If the max render time isn't known then using the current value of -+ * next_presentation_time_us is suboptimal. Targeting always one frame -+ * prior to that we'd lose the ability to scale up to triple buffering -+ * on late presentation. But targeting two frames prior we would be -+ * always triple buffering even when not required. -+ * So the algorithm for deciding when to scale up to triple buffering -+ * in the absence of render time measurements is to simply target full -+ * frame rate. If we're keeping up then we'll stay double buffering. If -+ * we're not keeping up then this will switch us to triple buffering. -+ */ -+ if (!max_render_time_is_known) -+ { -+ max_render_time_allowed_us = -+ refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; -+ next_presentation_time_us = -+ last_presentation_time_us + refresh_interval_us; -+ } -+ - while (next_presentation_time_us - min_render_time_allowed_us < now_us) - next_presentation_time_us += refresh_interval_us; - -@@ -644,7 +758,9 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock, - - refresh_interval_us = frame_clock->refresh_interval_us; - -- if (frame_clock->last_presentation_time_us == 0) -+ if (frame_clock->last_presentation_time_us == 0 || -+ !clutter_frame_clock_compute_max_render_time_us (frame_clock, -+ &max_render_time_allowed_us)) - { - *out_next_update_time_us = - frame_clock->last_dispatch_time_us ? -@@ -657,9 +773,6 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock, - return; - } - -- max_render_time_allowed_us = -- clutter_frame_clock_compute_max_render_time_us (frame_clock); -- - last_presentation_time_us = frame_clock->last_presentation_time_us; - next_presentation_time_us = last_presentation_time_us + refresh_interval_us; - -@@ -733,8 +846,17 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) - frame_clock->pending_reschedule_now = TRUE; - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; - break; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ frame_clock->pending_reschedule = TRUE; -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->pending_reschedule = TRUE; -+ frame_clock->pending_reschedule_now = TRUE; -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: - break; - } - -@@ -770,11 +892,18 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) - case CLUTTER_FRAME_CLOCK_STATE_INIT: - case CLUTTER_FRAME_CLOCK_STATE_IDLE: - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; - break; - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: - return; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ next_update_time_us = g_get_monotonic_time (); -+ frame_clock->state = -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: - frame_clock->pending_reschedule = TRUE; - frame_clock->pending_reschedule_now = TRUE; - return; -@@ -803,13 +932,18 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) - - frame_clock->next_update_time_us = next_update_time_us; - g_source_set_ready_time (frame_clock->source, next_update_time_us); -- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; - } - - void - clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) - { - int64_t next_update_time_us = -1; -+ TripleBufferingMode current_mode = triple_buffering_mode; -+ -+ if (current_mode == TRIPLE_BUFFERING_MODE_AUTO && -+ (frame_clock->last_flip_hints & -+ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)) -+ current_mode = TRIPLE_BUFFERING_MODE_NEVER; - - if (frame_clock->inhibit_count > 0) - { -@@ -825,12 +959,41 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; - return; - case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; - break; - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: - return; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ switch (current_mode) -+ { -+ case TRIPLE_BUFFERING_MODE_NEVER: -+ frame_clock->pending_reschedule = TRUE; -+ return; -+ case TRIPLE_BUFFERING_MODE_AUTO: -+ calculate_next_update_time_us (frame_clock, -+ &next_update_time_us, -+ &frame_clock->next_presentation_time_us, -+ &frame_clock->next_frame_deadline_us); -+ frame_clock->is_next_presentation_time_valid = -+ (frame_clock->next_presentation_time_us != 0); -+ frame_clock->has_next_frame_deadline = -+ (frame_clock->next_frame_deadline_us != 0); -+ frame_clock->state = -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; -+ break; -+ case TRIPLE_BUFFERING_MODE_ALWAYS: -+ next_update_time_us = g_get_monotonic_time (); -+ frame_clock->next_presentation_time_us = 0; -+ frame_clock->is_next_presentation_time_valid = FALSE; -+ frame_clock->state = -+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; -+ break; -+ } -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: - frame_clock->pending_reschedule = TRUE; - return; - } -@@ -859,7 +1022,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) - - frame_clock->next_update_time_us = next_update_time_us; - g_source_set_ready_time (frame_clock->source, next_update_time_us); -- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; - } - - void -@@ -875,6 +1037,8 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, - { - case CLUTTER_FRAME_CLOCK_STATE_INIT: - case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: - break; - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: - frame_clock->pending_reschedule = TRUE; -@@ -885,8 +1049,14 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, - frame_clock->pending_reschedule_now = TRUE; - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; - break; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ frame_clock->pending_reschedule = TRUE; -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->pending_reschedule = TRUE; -+ frame_clock->pending_reschedule_now = TRUE; -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; - break; - } - -@@ -922,7 +1092,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, - frame_clock->refresh_interval_us; - - lateness_us = time_us - ideal_dispatch_time_us; -- if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us) -+ if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us / 4) - frame_clock->last_dispatch_lateness_us = 0; - else - frame_clock->last_dispatch_lateness_us = lateness_us; -@@ -943,10 +1113,27 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, - } - #endif - -+ frame_clock->prev_last_dispatch_time_us = frame_clock->last_dispatch_time_us; - frame_clock->last_dispatch_time_us = time_us; - g_source_set_ready_time (frame_clock->source, -1); - -- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING; -+ switch (frame_clock->state) -+ { -+ case CLUTTER_FRAME_CLOCK_STATE_INIT: -+ case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ g_warn_if_reached (); -+ return; -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO; -+ break; -+ } - - frame_count = frame_clock->frame_count++; - -@@ -977,26 +1164,36 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, - result = iface->frame (frame_clock, frame, frame_clock->listener.user_data); - COGL_TRACE_END (ClutterFrameClockFrame); - -- switch (frame_clock->state) -+ switch (result) - { -- case CLUTTER_FRAME_CLOCK_STATE_INIT: -- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: -- g_warn_if_reached (); -+ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: - break; -- case CLUTTER_FRAME_CLOCK_STATE_IDLE: -- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -- break; -- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: -- switch (result) -+ case CLUTTER_FRAME_RESULT_IDLE: -+ /* The frame was aborted; nothing to paint/present */ -+ switch (frame_clock->state) - { -- case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: -- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED; -+ case CLUTTER_FRAME_CLOCK_STATE_INIT: -+ case CLUTTER_FRAME_CLOCK_STATE_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: -+ g_warn_if_reached (); - break; -- case CLUTTER_FRAME_RESULT_IDLE: -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; - maybe_reschedule_update (frame_clock); - break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW; -+ maybe_reschedule_update (frame_clock); -+ break; -+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: -+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; -+ maybe_reschedule_update (frame_clock); -+ break; - } - break; - } -@@ -1029,21 +1226,31 @@ frame_clock_source_dispatch (GSource *source, - } - - void --clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, -- int64_t flip_time_us) -+clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, -+ int64_t flip_time_us, -+ ClutterFrameHint hints) - { -+ frame_clock->prev_last_flip_time_us = frame_clock->last_flip_time_us; - frame_clock->last_flip_time_us = flip_time_us; -+ frame_clock->last_flip_hints = hints; - } - - GString * - clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock) - { -+ int64_t max_render_time_us; - int64_t max_update_duration_us; - GString *string; - -- string = g_string_new (NULL); -- g_string_append_printf (string, "Max render time: %ld µs", -- clutter_frame_clock_compute_max_render_time_us (frame_clock)); -+ string = g_string_new ("Max render time: "); -+ if (!clutter_frame_clock_compute_max_render_time_us (frame_clock, -+ &max_render_time_us)) -+ { -+ g_string_append (string, "unknown"); -+ return string; -+ } -+ -+ g_string_append_printf (string, "%ld µs", max_render_time_us); - - if (frame_clock->got_measurements_last_frame) - g_string_append_printf (string, " ="); -@@ -1210,8 +1417,6 @@ clutter_frame_clock_dispose (GObject *object) - { - ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object); - -- g_warn_if_fail (frame_clock->state != CLUTTER_FRAME_CLOCK_STATE_DISPATCHING); -- - if (frame_clock->source) - { - g_signal_emit (frame_clock, signals[DESTROY], 0); -@@ -1235,6 +1440,15 @@ static void - clutter_frame_clock_class_init (ClutterFrameClockClass *klass) - { - GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ const char *mode_str; -+ -+ mode_str = g_getenv ("MUTTER_DEBUG_TRIPLE_BUFFERING"); -+ if (!g_strcmp0 (mode_str, "never")) -+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_NEVER; -+ else if (!g_strcmp0 (mode_str, "auto")) -+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO; -+ else if (!g_strcmp0 (mode_str, "always")) -+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_ALWAYS; - - object_class->dispose = clutter_frame_clock_dispose; - -diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h -index a7be5ef31..bfc89bde0 100644 ---- a/clutter/clutter/clutter-frame-clock.h -+++ b/clutter/clutter/clutter-frame-clock.h -@@ -33,6 +33,12 @@ typedef enum _ClutterFrameResult - CLUTTER_FRAME_RESULT_IDLE, - } ClutterFrameResult; - -+typedef enum _ClutterFrameHint -+{ -+ CLUTTER_FRAME_HINT_NONE = 0, -+ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED = 1 << 0, -+} ClutterFrameHint; -+ - #define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ()) - CLUTTER_EXPORT - G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock, -@@ -102,7 +108,8 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock, - CLUTTER_EXPORT - float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock); - --void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, -- int64_t flip_time_us); -+void clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, -+ int64_t flip_time_us, -+ ClutterFrameHint hints); - - GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); -diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h -index ef66b874e..ce140560a 100644 ---- a/clutter/clutter/clutter-frame-private.h -+++ b/clutter/clutter/clutter-frame-private.h -@@ -36,6 +36,7 @@ struct _ClutterFrame - - gboolean has_result; - ClutterFrameResult result; -+ ClutterFrameHint hints; - }; - - CLUTTER_EXPORT -diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c -index 7436f9f18..53c289b2c 100644 ---- a/clutter/clutter/clutter-frame.c -+++ b/clutter/clutter/clutter-frame.c -@@ -115,3 +115,16 @@ clutter_frame_set_result (ClutterFrame *frame, - frame->result = result; - frame->has_result = TRUE; - } -+ -+void -+clutter_frame_set_hint (ClutterFrame *frame, -+ ClutterFrameHint hint) -+{ -+ frame->hints |= hint; -+} -+ -+ClutterFrameHint -+clutter_frame_get_hints (ClutterFrame *frame) -+{ -+ return frame->hints; -+} -diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h -index 34f0770bd..c7b3d02ac 100644 ---- a/clutter/clutter/clutter-frame.h -+++ b/clutter/clutter/clutter-frame.h -@@ -54,4 +54,11 @@ void clutter_frame_set_result (ClutterFrame *frame, - CLUTTER_EXPORT - gboolean clutter_frame_has_result (ClutterFrame *frame); - -+CLUTTER_EXPORT -+void clutter_frame_set_hint (ClutterFrame *frame, -+ ClutterFrameHint hint); -+ -+CLUTTER_EXPORT -+ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame); -+ - G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFrame, clutter_frame_unref) -diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c -index b503ef839..1fbe3ae7a 100644 ---- a/clutter/clutter/clutter-stage-view.c -+++ b/clutter/clutter/clutter-stage-view.c -@@ -902,14 +902,21 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, - - _clutter_stage_window_redraw_view (stage_window, view, frame); - -- clutter_frame_clock_record_flip_time (frame_clock, -- g_get_monotonic_time ()); -+ clutter_frame_clock_record_flip (frame_clock, -+ g_get_monotonic_time (), -+ clutter_frame_get_hints (frame)); - - clutter_stage_emit_after_paint (stage, view, frame); - - if (_clutter_context_get_show_fps ()) - end_frame_timing_measurement (view); - } -+ else -+ { -+ clutter_frame_clock_record_flip (frame_clock, -+ g_get_monotonic_time (), -+ clutter_frame_get_hints (frame)); -+ } - - _clutter_stage_window_finish_frame (stage_window, view, frame); - -diff --git a/cogl/cogl/cogl-attribute-buffer.c b/cogl/cogl/cogl-attribute-buffer.c -index 55e296dd3..ee89e500a 100644 ---- a/cogl/cogl/cogl-attribute-buffer.c -+++ b/cogl/cogl/cogl-attribute-buffer.c -@@ -51,13 +51,13 @@ cogl_attribute_buffer_init (CoglAttributeBuffer *buffer) - - CoglAttributeBuffer * - cogl_attribute_buffer_new_with_size (CoglContext *context, -- size_t bytes) -+ size_t bytes) - { - CoglAttributeBuffer *buffer; - - buffer = g_object_new (COGL_TYPE_ATTRIBUTE_BUFFER, - "context", context, -- "size", bytes, -+ "size", (uint64_t) bytes, - "default-target", COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER, - "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, - NULL); -@@ -67,8 +67,8 @@ cogl_attribute_buffer_new_with_size (CoglContext *context, - - CoglAttributeBuffer * - cogl_attribute_buffer_new (CoglContext *context, -- size_t bytes, -- const void *data) -+ size_t bytes, -+ const void *data) - { - CoglAttributeBuffer *buffer; - -diff --git a/cogl/cogl/cogl-attribute-buffer.h b/cogl/cogl/cogl-attribute-buffer.h -index 45040f7d9..59876a112 100644 ---- a/cogl/cogl/cogl-attribute-buffer.h -+++ b/cogl/cogl/cogl-attribute-buffer.h -@@ -92,7 +92,7 @@ GType cogl_attribute_buffer_get_type (void) G_GNUC_CONST; - */ - COGL_EXPORT CoglAttributeBuffer * - cogl_attribute_buffer_new_with_size (CoglContext *context, -- size_t bytes); -+ size_t bytes); - - /** - * cogl_attribute_buffer_new: -@@ -122,7 +122,7 @@ cogl_attribute_buffer_new_with_size (CoglContext *context, - */ - COGL_EXPORT CoglAttributeBuffer * - cogl_attribute_buffer_new (CoglContext *context, -- size_t bytes, -- const void *data); -+ size_t bytes, -+ const void *data); - - G_END_DECLS -diff --git a/cogl/cogl/cogl-context-private.h b/cogl/cogl/cogl-context-private.h -index 4c0bc4bea..cd5db0ee3 100644 ---- a/cogl/cogl/cogl-context-private.h -+++ b/cogl/cogl/cogl-context-private.h -@@ -311,3 +311,6 @@ _cogl_context_set_current_projection_entry (CoglContext *context, - void - _cogl_context_set_current_modelview_entry (CoglContext *context, - CoglMatrixEntry *entry); -+ -+void -+_cogl_context_update_sync (CoglContext *context); -diff --git a/cogl/cogl/cogl-context.c b/cogl/cogl/cogl-context.c -index be13933ec..492d49542 100644 ---- a/cogl/cogl/cogl-context.c -+++ b/cogl/cogl/cogl-context.c -@@ -463,6 +463,28 @@ _cogl_context_set_current_modelview_entry (CoglContext *context, - context->current_modelview_entry = entry; - } - -+void -+_cogl_context_update_sync (CoglContext *context) -+{ -+ const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); -+ -+ if (!winsys->update_sync) -+ return; -+ -+ winsys->update_sync (context); -+} -+ -+int -+cogl_context_get_latest_sync_fd (CoglContext *context) -+{ -+ const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); -+ -+ if (!winsys->get_sync_fd) -+ return -1; -+ -+ return winsys->get_sync_fd (context); -+} -+ - CoglGraphicsResetStatus - cogl_get_graphics_reset_status (CoglContext *context) - { -diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h -index 614a351fe..fba7bedf2 100644 ---- a/cogl/cogl/cogl-context.h -+++ b/cogl/cogl/cogl-context.h -@@ -367,4 +367,18 @@ cogl_context_timestamp_query_get_time_ns (CoglContext *context, - COGL_EXPORT int64_t - cogl_context_get_gpu_time_ns (CoglContext *context); - -+/** -+ * cogl_context_get_latest_sync_fd -+ * @context: a #CoglContext pointer -+ * -+ * This function is used to get support for waiting on previous -+ * GPU work through sync fds. It will return a sync fd which will -+ * signal when the previous work has completed. -+ * -+ * Return value: sync fd for latest GPU submission if available, -+ * returns -1 if not. -+ */ -+COGL_EXPORT int -+cogl_context_get_latest_sync_fd (CoglContext *context); -+ - G_END_DECLS -diff --git a/cogl/cogl/cogl-index-buffer.c b/cogl/cogl/cogl-index-buffer.c -index 4de5205d3..1e4309436 100644 ---- a/cogl/cogl/cogl-index-buffer.c -+++ b/cogl/cogl/cogl-index-buffer.c -@@ -53,13 +53,14 @@ cogl_index_buffer_init (CoglIndexBuffer *buffer) - * indices buffer should be able to contain multiple ranges of indices - * which the wiki design doesn't currently consider. */ - CoglIndexBuffer * --cogl_index_buffer_new (CoglContext *context, size_t bytes) -+cogl_index_buffer_new (CoglContext *context, -+ size_t bytes) - { - CoglIndexBuffer *indices; - - indices = g_object_new (COGL_TYPE_INDEX_BUFFER, - "context", context, -- "size", bytes, -+ "size", (uint64_t) bytes, - "default-target", COGL_BUFFER_BIND_TARGET_INDEX_BUFFER, - "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, - NULL); -diff --git a/cogl/cogl/cogl-index-buffer.h b/cogl/cogl/cogl-index-buffer.h -index 23b75d837..ec7418318 100644 ---- a/cogl/cogl/cogl-index-buffer.h -+++ b/cogl/cogl/cogl-index-buffer.h -@@ -78,6 +78,6 @@ GType cogl_index_buffer_get_type (void) G_GNUC_CONST; - */ - COGL_EXPORT CoglIndexBuffer * - cogl_index_buffer_new (CoglContext *context, -- size_t bytes); -+ size_t bytes); - - G_END_DECLS -diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h -index 959a60533..86d8ea2d5 100644 ---- a/cogl/cogl/cogl-onscreen-private.h -+++ b/cogl/cogl/cogl-onscreen-private.h -@@ -78,4 +78,7 @@ COGL_EXPORT CoglFrameInfo * - cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen); - - COGL_EXPORT CoglFrameInfo * --cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen); -+cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen); -+ -+COGL_EXPORT unsigned int -+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen); -diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c -index f4b460a83..086be7ed7 100644 ---- a/cogl/cogl/cogl-onscreen.c -+++ b/cogl/cogl/cogl-onscreen.c -@@ -325,6 +325,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, - { - CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen); - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); -+ CoglContext *context = cogl_framebuffer_get_context (framebuffer); - CoglOnscreenClass *klass = COGL_ONSCREEN_GET_CLASS (onscreen); - - g_return_if_fail (COGL_IS_ONSCREEN (framebuffer)); -@@ -334,6 +335,9 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, - - _cogl_framebuffer_flush_journal (framebuffer); - -+ /* Update our "latest" sync fd to contain all previous work */ -+ _cogl_context_update_sync (context); -+ - if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME))) - cogl_framebuffer_finish (framebuffer); - -@@ -511,6 +515,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen) - return g_queue_pop_head (&priv->pending_frame_infos); - } - -+unsigned int -+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen) -+{ -+ CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen); -+ -+ return g_queue_get_length (&priv->pending_frame_infos); -+} -+ - CoglFrameClosure * - cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, - CoglFrameCallback callback, -diff --git a/cogl/cogl/cogl-pixel-buffer.c b/cogl/cogl/cogl-pixel-buffer.c -index fc238580a..392460933 100644 ---- a/cogl/cogl/cogl-pixel-buffer.c -+++ b/cogl/cogl/cogl-pixel-buffer.c -@@ -63,15 +63,15 @@ cogl_pixel_buffer_init (CoglPixelBuffer *buffer) - - static CoglPixelBuffer * - _cogl_pixel_buffer_new (CoglContext *context, -- size_t size, -- const void *data, -- GError **error) -+ size_t size, -+ const void *data, -+ GError **error) - { - CoglPixelBuffer *pixel_buffer; - - pixel_buffer = g_object_new (COGL_TYPE_PIXEL_BUFFER, - "context", context, -- "size", size, -+ "size", (uint64_t) size, - "default-target", COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, - "update-hint", COGL_BUFFER_UPDATE_HINT_STATIC, - NULL); -@@ -94,8 +94,8 @@ _cogl_pixel_buffer_new (CoglContext *context, - - CoglPixelBuffer * - cogl_pixel_buffer_new (CoglContext *context, -- size_t size, -- const void *data) -+ size_t size, -+ const void *data) - { - GError *ignore_error = NULL; - CoglPixelBuffer *buffer = -diff --git a/cogl/cogl/cogl-pixel-buffer.h b/cogl/cogl/cogl-pixel-buffer.h -index e7abe0888..cf26a61b2 100644 ---- a/cogl/cogl/cogl-pixel-buffer.h -+++ b/cogl/cogl/cogl-pixel-buffer.h -@@ -87,7 +87,7 @@ GType cogl_pixel_buffer_get_type (void) G_GNUC_CONST; - */ - COGL_EXPORT CoglPixelBuffer * - cogl_pixel_buffer_new (CoglContext *context, -- size_t size, -- const void *data); -+ size_t size, -+ const void *data); - - G_END_DECLS -diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build -index d1aa6ef1d..261edbd86 100644 ---- a/cogl/cogl/meson.build -+++ b/cogl/cogl/meson.build -@@ -407,6 +407,7 @@ libmutter_cogl = shared_library(libmutter_cogl_name, - install: true, - ) - libmutter_cogl_dep = declare_dependency( -+ sources: [cogl_enums[1]], - dependencies: [cogl_deps], - link_with: libmutter_cogl, - ) -diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.c b/cogl/cogl/winsys/cogl-onscreen-egl.c -index 6c5bf2654..44010969c 100644 ---- a/cogl/cogl/winsys/cogl-onscreen-egl.c -+++ b/cogl/cogl/winsys/cogl-onscreen-egl.c -@@ -281,6 +281,27 @@ cogl_onscreen_egl_queue_damage_region (CoglOnscreen *onscreen, - g_warning ("Error reported by eglSetDamageRegion"); - } - -+void -+cogl_onscreen_egl_maybe_create_timestamp_query (CoglOnscreen *onscreen, -+ CoglFrameInfo *info) -+{ -+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); -+ CoglContext *context = cogl_framebuffer_get_context (framebuffer); -+ -+ if (!cogl_has_feature (context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) -+ return; -+ -+ info->gpu_time_before_buffer_swap_ns = -+ cogl_context_get_gpu_time_ns (context); -+ info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); -+ -+ /* Set up a timestamp query for when all rendering will be finished. */ -+ info->timestamp_query = -+ cogl_framebuffer_create_timestamp_query (framebuffer); -+ -+ info->has_valid_gpu_rendering_duration = TRUE; -+} -+ - static void - cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, - const int *rectangles, -@@ -309,19 +330,6 @@ cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, - COGL_FRAMEBUFFER (onscreen), - COGL_FRAMEBUFFER_STATE_BIND); - -- if (cogl_has_feature (context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) -- { -- info->gpu_time_before_buffer_swap_ns = -- cogl_context_get_gpu_time_ns (context); -- info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); -- -- /* Set up a timestamp query for when all rendering will be finished. */ -- info->timestamp_query = -- cogl_framebuffer_create_timestamp_query (COGL_FRAMEBUFFER (onscreen)); -- -- info->has_valid_gpu_rendering_duration = TRUE; -- } -- - if (n_rectangles && priv->pf_eglSwapBuffersWithDamage) - { - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); -diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.h b/cogl/cogl/winsys/cogl-onscreen-egl.h -index 13662be60..d4dda6636 100644 ---- a/cogl/cogl/winsys/cogl-onscreen-egl.h -+++ b/cogl/cogl/winsys/cogl-onscreen-egl.h -@@ -40,6 +40,10 @@ struct _CoglOnscreenEglClass - CoglOnscreenClass parent_class; - }; - -+COGL_EXPORT void -+cogl_onscreen_egl_maybe_create_timestamp_query (CoglOnscreen *onscreen, -+ CoglFrameInfo *info); -+ - COGL_EXPORT void - cogl_onscreen_egl_set_egl_surface (CoglOnscreenEgl *onscreen_egl, - EGLSurface egl_surface); -diff --git a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h -index 4b74e2088..a0d03a3c4 100644 ---- a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h -+++ b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h -@@ -162,6 +162,15 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroySync, - (EGLDisplay dpy, - EGLSyncKHR sync)) - COGL_WINSYS_FEATURE_END () -+ -+COGL_WINSYS_FEATURE_BEGIN (native_fence_sync, -+ "ANDROID\0", -+ "native_fence_sync\0", -+ COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC) -+COGL_WINSYS_FEATURE_FUNCTION (EGLint, eglDupNativeFenceFD, -+ (EGLDisplay dpy, -+ EGLSyncKHR sync)) -+COGL_WINSYS_FEATURE_END () - #endif - - COGL_WINSYS_FEATURE_BEGIN (surfaceless_context, -diff --git a/cogl/cogl/winsys/cogl-winsys-egl-private.h b/cogl/cogl/winsys/cogl-winsys-egl-private.h -index 9b0b168b4..6a31d1ab2 100644 ---- a/cogl/cogl/winsys/cogl-winsys-egl-private.h -+++ b/cogl/cogl/winsys/cogl-winsys-egl-private.h -@@ -101,6 +101,7 @@ typedef enum _CoglEGLWinsysFeature - COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT = 1L << 6, - COGL_EGL_WINSYS_FEATURE_CONTEXT_PRIORITY = 1L << 7, - COGL_EGL_WINSYS_FEATURE_NO_CONFIG_CONTEXT = 1L << 8, -+ COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC = 1L << 9, - } CoglEGLWinsysFeature; - - typedef struct _CoglRendererEGL -@@ -119,6 +120,9 @@ typedef struct _CoglRendererEGL - /* vtable for platform specific parts */ - const CoglWinsysEGLVtable *platform_vtable; - -+ /* Sync for latest submitted work */ -+ EGLSyncKHR sync; -+ - /* Function pointers for EGL specific extensions */ - #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d) - -diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c -index 5472ba9d9..7a52129c2 100644 ---- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c -+++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c -@@ -243,6 +243,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, - xlib_renderer = _cogl_xlib_renderer_get_data (renderer); - - egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; -+ egl_renderer->sync = EGL_NO_SYNC_KHR; - - if (!_cogl_xlib_renderer_connect (renderer, error)) - goto error; -diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c -index ee7c1df54..66b9940c0 100644 ---- a/cogl/cogl/winsys/cogl-winsys-egl.c -+++ b/cogl/cogl/winsys/cogl-winsys-egl.c -@@ -441,6 +441,9 @@ _cogl_winsys_display_destroy (CoglDisplay *display) - - g_return_if_fail (egl_display != NULL); - -+ if (egl_renderer->sync != EGL_NO_SYNC_KHR) -+ egl_renderer->pf_eglDestroySync (egl_renderer->edpy, egl_renderer->sync); -+ - cleanup_context (display); - - if (egl_renderer->platform_vtable->display_destroy) -@@ -573,6 +576,37 @@ _cogl_winsys_fence_destroy (CoglContext *context, void *fence) - - renderer->pf_eglDestroySync (renderer->edpy, fence); - } -+ -+static int -+_cogl_winsys_get_sync_fd (CoglContext *context) -+{ -+ CoglRendererEGL *renderer = context->display->renderer->winsys; -+ int fd; -+ -+ if (!renderer->pf_eglDupNativeFenceFD) -+ return -1; -+ -+ fd = renderer->pf_eglDupNativeFenceFD (renderer->edpy, renderer->sync); -+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) -+ return -1; -+ -+ return fd; -+} -+ -+static void -+_cogl_winsys_update_sync (CoglContext *context) -+{ -+ CoglRendererEGL *renderer = context->display->renderer->winsys; -+ -+ if (!renderer->pf_eglDestroySync || !renderer->pf_eglCreateSync) -+ return; -+ -+ if (renderer->sync != EGL_NO_SYNC_KHR) -+ renderer->pf_eglDestroySync (renderer->edpy, renderer->sync); -+ -+ renderer->sync = renderer->pf_eglCreateSync (renderer->edpy, -+ EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); -+} - #endif - - static CoglWinsysVtable _cogl_winsys_vtable = -@@ -595,6 +629,8 @@ static CoglWinsysVtable _cogl_winsys_vtable = - .fence_add = _cogl_winsys_fence_add, - .fence_is_complete = _cogl_winsys_fence_is_complete, - .fence_destroy = _cogl_winsys_fence_destroy, -+ .get_sync_fd = _cogl_winsys_get_sync_fd, -+ .update_sync = _cogl_winsys_update_sync, - #endif - }; - -diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h -index 7dfbd13ed..d627617d6 100644 ---- a/cogl/cogl/winsys/cogl-winsys-private.h -+++ b/cogl/cogl/winsys/cogl-winsys-private.h -@@ -141,6 +141,12 @@ typedef struct _CoglWinsysVtable - (*fence_destroy) (CoglContext *ctx, - void *fence); - -+ void -+ (*update_sync) (CoglContext *ctx); -+ -+ int -+ (*get_sync_fd) (CoglContext *ctx); -+ - } CoglWinsysVtable; - - typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void); -diff --git a/config.h.meson b/config.h.meson -index 094d79616..9919bd4d0 100644 ---- a/config.h.meson -+++ b/config.h.meson -@@ -135,3 +135,6 @@ - - /* Supports malloc_trim */ - #mesondefine HAVE_MALLOC_TRIM -+ -+/* Supports eventfd */ -+#mesondefine HAVE_EVENTFD -diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index 2fe8450a8..b05337d74 100644 ---- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -+++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -@@ -396,8 +396,8 @@ - @layout_mode current layout mode represents the way logical monitors - are laid out on the screen. Possible modes include: - -- 1 : physical -- 2 : logical -+ 1 : logical -+ 2 : physical - - With physical layout mode, each logical monitor has the same dimensions - as the monitor modes of the associated monitors assigned to it, no -diff --git a/meson.build b/meson.build -index c5ec57395..9732d8460 100644 ---- a/meson.build -+++ b/meson.build -@@ -541,6 +541,8 @@ endif - - cc.compiles('void main (void) { __builtin_ffsl (0); __builtin_popcountl (0); }') - -+have_eventfd = cc.has_header('sys/eventfd.h') -+ - cdata = configuration_data() - cdata.set_quoted('GETTEXT_PACKAGE', gettext_package) - cdata.set_quoted('VERSION', meson.project_version()) -@@ -573,6 +575,7 @@ cdata.set('HAVE_LIBDISPLAY_INFO', have_libdisplay_info) - cdata.set('HAVE_PANGO_FT2', have_pango_ft2) - cdata.set('HAVE_TIMERFD', have_timerfd) - cdata.set('HAVE_MALLOC_TRIM', have_malloc_trim) -+cdata.set('HAVE_EVENTFD', have_eventfd) - - if have_x11_client - xkb_base = xkeyboard_config_dep.get_variable('xkb_base') -diff --git a/mtk/mtk/mtk-rectangle.c b/mtk/mtk/mtk-rectangle.c -index 55626d8e2..4f5927ccc 100644 ---- a/mtk/mtk/mtk-rectangle.c -+++ b/mtk/mtk/mtk-rectangle.c -@@ -65,6 +65,12 @@ mtk_rectangle_new (int x, - return rect; - } - -+MtkRectangle * -+mtk_rectangle_new_empty (void) -+{ -+ return g_new0 (MtkRectangle, 1); -+} -+ - /** - * mtk_rectangle_area: - * @rect: A rectangle -diff --git a/mtk/mtk/mtk-rectangle.h b/mtk/mtk/mtk-rectangle.h -index 2463d3b08..1cb598fce 100644 ---- a/mtk/mtk/mtk-rectangle.h -+++ b/mtk/mtk/mtk-rectangle.h -@@ -86,6 +86,9 @@ MtkRectangle * mtk_rectangle_new (int x, - int width, - int height); - -+MTK_EXPORT -+MtkRectangle * mtk_rectangle_new_empty (void); -+ - /* Basic comparison functions */ - MTK_EXPORT - int mtk_rectangle_area (const MtkRectangle *rect); -@@ -149,3 +152,5 @@ void mtk_rectangle_scale_double (const MtkRectangle *rect, - MTK_EXPORT - gboolean mtk_rectangle_is_adjacent_to (const MtkRectangle *rect, - const MtkRectangle *other); -+ -+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MtkRectangle, mtk_rectangle_free) -diff --git a/po/LINGUAS b/po/LINGUAS -index 02ae4c496..b89761cb3 100644 ---- a/po/LINGUAS -+++ b/po/LINGUAS -@@ -47,6 +47,7 @@ is - it - ja - ka -+kab - kk - kn - ko -diff --git a/po/kab.po b/po/kab.po -new file mode 100644 -index 000000000..5cc29556c ---- /dev/null -+++ b/po/kab.po -@@ -0,0 +1,793 @@ -+# Kabyle translation for mutter. -+# Copyright (C) 2024 mutter's COPYRIGHT HOLDER -+# This file is distributed under the same license as the mutter package. -+# FIRST AUTHOR , YEAR. -+# ButterflyOfFire , 2024. -+# -+msgid "" -+msgstr "" -+"Project-Id-Version: mutter main\n" -+"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" -+"POT-Creation-Date: 2024-04-04 12:25+0000\n" -+"PO-Revision-Date: 2024-04-08 06:56+0200\n" -+"Last-Translator: sa\n" -+"Language-Team: Kabyle <>\n" -+"Language: kab\n" -+"MIME-Version: 1.0\n" -+"Content-Type: text/plain; charset=UTF-8\n" -+"Content-Transfer-Encoding: 8bit\n" -+"Plural-Forms: nplurals=2; plural=n>1;\n" -+"X-DL-Team: kab\n" -+"X-DL-Module: mutter\n" -+"X-DL-Branch: main\n" -+"X-DL-Domain: po\n" -+"X-DL-State: Translating\n" -+"X-Generator: Poedit 3.4.2\n" -+ -+#: data/50-mutter-navigation.xml:6 -+msgid "Navigation" -+msgstr "Tunigin" -+ -+#: data/50-mutter-navigation.xml:9 -+msgid "Move window to workspace 1" -+msgstr "Smutti asfaylu ɣer tallunt umahil tis 1" -+ -+#: data/50-mutter-navigation.xml:12 -+msgid "Move window to workspace 2" -+msgstr "Smutti asfaylu ɣer tallunt umahil tis 2" -+ -+#: data/50-mutter-navigation.xml:15 -+msgid "Move window to workspace 3" -+msgstr "Smutti asfaylu ɣer tallunt umahil tis 3" -+ -+#: data/50-mutter-navigation.xml:18 -+msgid "Move window to workspace 4" -+msgstr "Smutti asfaylu ɣer tallunt umahil tis 3" -+ -+#: data/50-mutter-navigation.xml:21 -+msgid "Move window to last workspace" -+msgstr "Smutti asfaylu ɣer tallunt umahil" -+ -+#: data/50-mutter-navigation.xml:24 -+msgid "Move window one workspace to the left" -+msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan ɣer tama tazelmaḍt" -+ -+#: data/50-mutter-navigation.xml:27 -+msgid "Move window one workspace to the right" -+msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan ɣer tama tayeffust" -+ -+#: data/50-mutter-navigation.xml:31 -+msgid "Move window one workspace up" -+msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan d asawen" -+ -+#: data/50-mutter-navigation.xml:35 -+msgid "Move window one workspace down" -+msgstr "Ssiweḍ asfaylu yiwet n tallunt n umahil yellan d akessar" -+ -+#: data/50-mutter-navigation.xml:38 -+msgid "Move window one monitor to the left" -+msgstr "Senkez asfaylu s yiwen usefrak ɣer uzelmaḍ" -+ -+#: data/50-mutter-navigation.xml:41 -+msgid "Move window one monitor to the right" -+msgstr "Senkez asfaylu s yiwen usefrak ɣer uyeffus" -+ -+#: data/50-mutter-navigation.xml:44 -+msgid "Move window one monitor up" -+msgstr "Senkez asfaylu s yiwen usefrak d asawen" -+ -+#: data/50-mutter-navigation.xml:47 -+msgid "Move window one monitor down" -+msgstr "Senkez asfaylu s yiwen usefrak d akessar" -+ -+#: data/50-mutter-navigation.xml:51 -+msgid "Switch applications" -+msgstr "Senfel isnasen" -+ -+#: data/50-mutter-navigation.xml:56 -+msgid "Switch to previous application" -+msgstr "Uɣal ɣer usnas yezrin" -+ -+#: data/50-mutter-navigation.xml:60 -+msgid "Switch windows" -+msgstr "Senfel isfuyla" -+ -+#: data/50-mutter-navigation.xml:65 -+msgid "Switch to previous window" -+msgstr "Uɣal ɣer usfaylu yezrin" -+ -+#: data/50-mutter-navigation.xml:69 -+msgid "Switch windows of an application" -+msgstr "Senfel isfuyla n usnas" -+ -+#: data/50-mutter-navigation.xml:74 -+msgid "Switch to previous window of an application" -+msgstr "Uɣal ɣer usfaylu yezrin n usnas" -+ -+#: data/50-mutter-navigation.xml:78 -+msgid "Switch system controls" -+msgstr "Senfel isenqaden n unagraw" -+ -+#: data/50-mutter-navigation.xml:83 -+msgid "Switch to previous system control" -+msgstr "Uɣal ɣer usenqad n unagraw yezrin" -+ -+#: data/50-mutter-navigation.xml:87 -+msgid "Switch windows directly" -+msgstr "Senfel srid isfuyla" -+ -+#: data/50-mutter-navigation.xml:92 -+msgid "Switch directly to previous window" -+msgstr "Uɣam srid ɣer usfaylu yezrin" -+ -+#: data/50-mutter-navigation.xml:96 -+msgid "Switch windows of an app directly" -+msgstr "Senfel srid isfuyla n usnas" -+ -+#: data/50-mutter-navigation.xml:101 -+msgid "Switch directly to previous window of an app" -+msgstr "Uɣal srid usfaylu yezrin n usnas" -+ -+#: data/50-mutter-navigation.xml:105 -+msgid "Switch system controls directly" -+msgstr "Senfel srid isenqaden n ungraw" -+ -+#: data/50-mutter-navigation.xml:110 -+msgid "Switch directly to previous system control" -+msgstr "Uɣal srid ɣer usenqad n ungraw yezrin" -+ -+#: data/50-mutter-navigation.xml:113 -+msgid "Hide all normal windows" -+msgstr "Ffer akk isfuyla imugna" -+ -+#: data/50-mutter-navigation.xml:116 -+msgid "Switch to workspace 1" -+msgstr "Ddu ɣer tallunt n umahil tis 1" -+ -+#: data/50-mutter-navigation.xml:119 -+msgid "Switch to workspace 2" -+msgstr "Ddu ɣer tallunt n umahil tis 2" -+ -+#: data/50-mutter-navigation.xml:122 -+msgid "Switch to workspace 3" -+msgstr "Ddu ɣer tallunt n umahil tis 3" -+ -+#: data/50-mutter-navigation.xml:125 -+msgid "Switch to workspace 4" -+msgstr "Ddu ɣer tallunt n umahil tis 4" -+ -+#: data/50-mutter-navigation.xml:128 -+msgid "Switch to last workspace" -+msgstr "Ddu ɣer tallunt n umahil taneggarut" -+ -+#: data/50-mutter-navigation.xml:131 -+msgid "Switch to workspace on the left" -+msgstr "Ddu ɣer tallunt n umahil deg tama taẓelmaḍt" -+ -+#: data/50-mutter-navigation.xml:134 -+msgid "Switch to workspace on the right" -+msgstr "Ddu ɣer tallunt n umahil deg tama tayeffust" -+ -+#: data/50-mutter-navigation.xml:138 -+msgid "Switch to workspace above" -+msgstr "Ddu ɣer tallunt n umahil ufella" -+ -+#: data/50-mutter-navigation.xml:142 -+msgid "Switch to workspace below" -+msgstr "Ddu ɣer tallunt n umahil wadda" -+ -+#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6 -+msgid "System" -+msgstr "Anagraw" -+ -+#: data/50-mutter-system.xml:8 -+msgid "Show the run command prompt" -+msgstr "Sken aneftay n tladna n uselkem" -+ -+#: data/50-mutter-wayland.xml:8 -+msgid "Restore the keyboard shortcuts" -+msgstr "Err-d inegzumen n unasiw" -+ -+#: data/50-mutter-windows.xml:6 -+msgid "Windows" -+msgstr "Isfuyla" -+ -+#: data/50-mutter-windows.xml:8 -+msgid "Activate the window menu" -+msgstr "Rmed umuɣ n usfaylu" -+ -+#: data/50-mutter-windows.xml:10 -+msgid "Toggle fullscreen mode" -+msgstr "Ldi/Mdel askar n ugdil aččuran" -+ -+#: data/50-mutter-windows.xml:12 -+msgid "Toggle maximization state" -+msgstr "Ldi/Mdel addad n usumɣer" -+ -+#: data/50-mutter-windows.xml:14 -+msgid "Maximize window" -+msgstr "Semɣer asfaylu" -+ -+#: data/50-mutter-windows.xml:16 -+msgid "Restore window" -+msgstr "Err-d asfaylu" -+ -+#: data/50-mutter-windows.xml:18 -+msgid "Close window" -+msgstr "Mdel asfaylu" -+ -+#: data/50-mutter-windows.xml:20 -+msgid "Hide window" -+msgstr "Ffer asfaylu" -+ -+#: data/50-mutter-windows.xml:22 -+msgid "Move window" -+msgstr "Senkez asfaylu" -+ -+#: data/50-mutter-windows.xml:24 -+msgid "Resize window" -+msgstr "Semsawi teɣzi n usfaylu" -+ -+#: data/50-mutter-windows.xml:27 -+msgid "Toggle window on all workspaces or one" -+msgstr "Ldi/Mdel asfaylu deg meṛṛa tallunin n umahil neɣ deg yiwet kan" -+ -+#: data/50-mutter-windows.xml:29 -+msgid "Raise window if covered, otherwise lower it" -+msgstr "Sali asfaylu ma yella iɣumm, neɣ ṣbb-it" -+ -+#: data/50-mutter-windows.xml:31 -+msgid "Raise window above other windows" -+msgstr "Sezmer asfaylu yellan nnig yisfuyla niḍen" -+ -+#: data/50-mutter-windows.xml:33 -+msgid "Lower window below other windows" -+msgstr "Asfaylu n wadda ddaw n yisfuyla niḍen" -+ -+#: data/50-mutter-windows.xml:35 -+msgid "Maximize window vertically" -+msgstr "Semɣer asfaylu s wudem ubdid" -+ -+#: data/50-mutter-windows.xml:37 -+msgid "Maximize window horizontally" -+msgstr "Semɣer asfaylu s wudem aglawan" -+ -+#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 -+msgid "View split on left" -+msgstr "Sken beṭṭu ɣer uzelmaḍ" -+ -+#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 -+msgid "View split on right" -+msgstr "Sken beṭṭu ɣer uyeffus" -+ -+#: data/org.gnome.mutter.gschema.xml.in:15 -+msgid "Modifier to use for extended window management operations" -+msgstr "Aneglam ara yettwasqedcen i temhilin ɣezzifen n usefrek n yisfuyla" -+ -+#: data/org.gnome.mutter.gschema.xml.in:16 -+msgid "" -+"This key will initiate the “overlay”, which is a combination window overview " -+"and application launching system. The default is intended to be the “Windows " -+"key” on PC hardware. It’s expected that this binding either the default or " -+"set to the empty string." -+msgstr "" -+"Tasarut-a ad twennez \"asembibbi\", d anagraw n usuddes n teskant n yisfuyla " -+"akked uskar n usnas. Azal amezwer d \"tasarut n Windows\" ɣef warrum PC. " -+"Yetturaǧu tasarut-a ad tettusbadu s wudem amezwer neɣ ad tettusbadu ɣer " -+"uzrir ilem." -+ -+#: data/org.gnome.mutter.gschema.xml.in:28 -+msgid "Attach modal dialogs" -+msgstr "Seddu idiwenniyen iskaranen" -+ -+#: data/org.gnome.mutter.gschema.xml.in:29 -+msgid "" -+"When true, instead of having independent titlebars, modal dialogs appear " -+"attached to the titlebar of the parent window and are moved together with " -+"the parent window." -+msgstr "" -+"Mi ara yili d tidet, deg wadeg n yifeggagen n yizwal ilelliyen, idiwenniyen " -+"iskaranen ad d-banen ddan deg ufeggag n uzwel n usfaylu maraw, ad " -+"ttwasnekzen akken akkedd usfaylu amaraw." -+ -+#: data/org.gnome.mutter.gschema.xml.in:38 -+msgid "Enable edge tiling when dropping windows on screen edges" -+msgstr "Rmed aburset n tamiwin mi ara tserseḍ isfuyla ɣef tamiwin n ugdil" -+ -+#: data/org.gnome.mutter.gschema.xml.in:39 -+msgid "" -+"If enabled, dropping windows on vertical screen edges maximizes them " -+"vertically and resizes them horizontally to cover half of the available " -+"area. Dropping windows on the top screen edge maximizes them completely." -+msgstr "" -+"Ma yella tettwarmed textiṛt-a, tarusi yisfuyla ɣef tamiwin tiratakin n ugdil " -+"ad ttwasmeɣren s wudem aglawan, akken ara ččaren azgen n temnaḍt i yellan. " -+"Azuɣer n yisfuyla ɣef tama tafellayt n ugdil ad ten-issemɣer s wudem ummid." -+ -+#: data/org.gnome.mutter.gschema.xml.in:48 -+msgid "Workspaces are managed dynamically" -+msgstr "Tallunin n umahil ttwasefrakent s wudem asmussan" -+ -+#: data/org.gnome.mutter.gschema.xml.in:49 -+msgid "" -+"Determines whether workspaces are managed dynamically or whether there’s a " -+"static number of workspaces (determined by the num-workspaces key in org." -+"gnome.desktop.wm.preferences)." -+msgstr "" -+"Yettguccul ma yella tallunin n umahil ttwasefrakent s wudem asmussan neɣ ma " -+"yella amḍan udmis n tallunin n umahil (yettwaguccel s tsarut num-workspaces " -+"deg org.gnome.desktop.wm.preferences)." -+ -+#: data/org.gnome.mutter.gschema.xml.in:58 -+msgid "Workspaces only on primary" -+msgstr "Tallunin n umahil ɣef umezwaru kan" -+ -+#: data/org.gnome.mutter.gschema.xml.in:59 -+msgid "" -+"Determines whether workspace switching should happen for windows on all " -+"monitors or only for windows on the primary monitor." -+msgstr "" -+"Yesguccul ma yella tallunin n umahil ttwasefrakent s wudem asmussan neɣ ma " -+"yella amḍan udmis n tallunin n umahil (yettwaguccel s tsarut num-workspaces " -+"deg org.gnome.desktop.wm.preferences)." -+ -+#: data/org.gnome.mutter.gschema.xml.in:67 -+msgid "Delay focus changes until the pointer stops moving" -+msgstr "Saẓey isenfal n usaḍes alamma asewwar ad iḥbes asenkez" -+ -+#: data/org.gnome.mutter.gschema.xml.in:68 -+msgid "" -+"If set to true, and the focus mode is either “sloppy” or “mouse” then the " -+"focus will not be changed immediately when entering a window, but only after " -+"the pointer stops moving." -+msgstr "" -+"Ma yella yettusbadu s tidet, askar asaḍes \"sloppy\" neɣ \"d taɣerdayt\", " -+"asiḍes ur yettwasenfal ara mi ara d-yekcem usfaylu, maca ma yeḥbes kan " -+"usewwar asenkez." -+ -+#: data/org.gnome.mutter.gschema.xml.in:78 -+msgid "Draggable border width" -+msgstr "Tehri n tama yettwazuɣaren" -+ -+#: data/org.gnome.mutter.gschema.xml.in:79 -+msgid "" -+"The amount of total draggable borders. If the theme’s visible borders are " -+"not enough, invisible borders will be added to meet this value." -+msgstr "" -+"Tasmekta tasemdayt n tamiwin i izmeren ad tettwaszuɣarent. Ma yella tamiwin " -+"ibanen n usentel d timagdazin, tamiwin ur nban ara ad ttwarnunt i wakken ad " -+"yaweḍ wazal-nni." -+ -+#: data/org.gnome.mutter.gschema.xml.in:88 -+msgid "Auto maximize nearly monitor sized windows" -+msgstr "Asemɣer awurman i yisfuyla n teɣzi i iqerben ɣer teɣzi n ugdil" -+ -+#: data/org.gnome.mutter.gschema.xml.in:89 -+msgid "" -+"If enabled, new windows that are initially the size of the monitor " -+"automatically get maximized." -+msgstr "" -+"Ma yella yettwarmed, isfuyla imaynuten i yesεan teɣzi am tin n ugdil " -+"yettnernin s wudem awurman." -+ -+#: data/org.gnome.mutter.gschema.xml.in:97 -+msgid "Place new windows in the center" -+msgstr "Sers isfuyla imaynuten deg tlemmast" -+ -+#: data/org.gnome.mutter.gschema.xml.in:98 -+msgid "" -+"When true, the new windows will always be put in the center of the active " -+"screen of the monitor." -+msgstr "" -+"Ma yella d tidet, isfuyla imaynuten zgan ttuɣalen deg tlemmast n ugdil urmid " -+"n usefrak." -+ -+#: data/org.gnome.mutter.gschema.xml.in:107 -+msgid "Enable experimental features" -+msgstr "Rmed timahilin tirmitanin" -+ -+#: data/org.gnome.mutter.gschema.xml.in:108 -+msgid "" -+"To enable experimental features, add the feature keyword to the list. " -+"Whether the feature requires restarting the compositor depends on the given " -+"feature. Any experimental feature is not required to still be available, or " -+"configurable. Don’t expect adding anything in this setting to be future " -+"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " -+"mutter default to layout logical monitors in a logical pixel coordinate " -+"space, while scaling monitor framebuffers instead of window content, to " -+"manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " -+"mutter always allocate scanout buffers with explicit modifiers, if supported " -+"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " -+"terminates Xwayland if all relevant X11 clients are gone. Requires a " -+"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " -+"refresh rate of the monitor when applicable if supported by the monitor, GPU " -+"and DRM driver. Configurable in Settings. Requires a restart." -+msgstr "" -+"I urmad n tmahilin tirmitanin, rnu awal n tsarut n tmahilt ɣer tebdart. " -+"Allus n usenker n usuddas yettwasra almend n tmahilt i d-yettwamudden. Ur " -+"tettwasra ara kra n tmahilt tarmitant ad teqqim tella kan neɣ tezmer ad " -+"tettuswal. Mačči yal timerna n kra deg uɣewwar-a yeskanay-d imal. Awalen n " -+"tsura yettwaqbalen akka tura: • “scale-monitor-framebuffer” — yettarra " -+"mutter ad yesεu s wudem amezwer isefraken imeẓẓulen deg wadeg ameẓẓul n " -+"yimsidag n yipiksilen, lawan n usemɣer n yikataren n usefrak deg wadeg n " -+"ugbur n usfaylu, i usefrek n HiDPI. Ur yesra allus n usenker. • “kms-" -+"modifiers” — yettarra mutter yezga yettḥerri aḥrazen n uḍummu s yisenfalayen " -+"iflayanen, ma yella yettwasefrak sɣur unuḍaf. Yesra allus n usenkar. • " -+"“autoclose-xwayland” — yettfakk s wudem awurman Xwayland ma yella akk " -+"imsaɣen X11 yesεan azal ruḥen. Yesra allus n usenker. • “variable-refresh-" -+"rate” — yettarra mutter yezmer ad isemsawi s wudem asmussan aktum n usismeḍ " -+"n usefrak, ma yella tettunefk tegnit, ma yella yettwasefrak sɣur usefrak, " -+"GPU akked unuḍaf DRM. Yettwaswal deg yiɣewwaren. Yesra alluas n usenker." -+ -+#: data/org.gnome.mutter.gschema.xml.in:144 -+msgid "Modifier to use to locate the pointer" -+msgstr "Senfel ara yettwasqedcen i usideg n usewwaṛ" -+ -+#: data/org.gnome.mutter.gschema.xml.in:145 -+msgid "This key will initiate the “locate pointer” action." -+msgstr "Tasarut-a ad twennez tigawt n \"usideg n usewwaṛ\"." -+ -+#: data/org.gnome.mutter.gschema.xml.in:152 -+msgid "Timeout for check-alive ping" -+msgstr "Tanzagt n keffu n ping n usenqed" -+ -+#: data/org.gnome.mutter.gschema.xml.in:153 -+msgid "" -+"Number of milliseconds a client has to respond to a ping request in order to " -+"not be detected as frozen. Using 0 will disable the alive check completely." -+msgstr "" -+"Amḍan n yiliten tsinin i yesεa umsaɣ i wakken ad yerr ɣef ussuter ping akken " -+"ur yettuneḥsab ara yegres. Aseqdec n 0 yesnusuy s wudem ummid asenqed n " -+"tiltin n umsaɣ." -+ -+#: data/org.gnome.mutter.gschema.xml.in:177 -+msgid "Switch monitor configurations" -+msgstr "Senfel tiwila n usefrak" -+ -+#: data/org.gnome.mutter.gschema.xml.in:182 -+msgid "Rotates the built-in monitor configuration" -+msgstr "Sezzi tawila n usefrak usliɣ" -+ -+#: data/org.gnome.mutter.gschema.xml.in:187 -+msgid "Cancel any active input capture session" -+msgstr "Sefsex akk n tɣimiyin n tuṭṭfa n unekcum yettwaremden" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:12 -+msgid "Switch to VT 1" -+msgstr "Ddu ɣer VT 1" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:16 -+msgid "Switch to VT 2" -+msgstr "Ddu ɣer VT 2" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:20 -+msgid "Switch to VT 3" -+msgstr "Ddu ɣer VT 3" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:24 -+msgid "Switch to VT 4" -+msgstr "Ddu ɣer VT 4" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:28 -+msgid "Switch to VT 5" -+msgstr "Ddu ɣer VT 5" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:32 -+msgid "Switch to VT 6" -+msgstr "Ddu ɣer VT 6" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:36 -+msgid "Switch to VT 7" -+msgstr "Ddu ɣer VT 7" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:40 -+msgid "Switch to VT 8" -+msgstr "Ddu ɣer VT 8" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:44 -+msgid "Switch to VT 9" -+msgstr "Ddu ɣer VT 9" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:48 -+msgid "Switch to VT 10" -+msgstr "Ddu ɣer VT 10" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:52 -+msgid "Switch to VT 11" -+msgstr "Ddu ɣer VT 11" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:56 -+msgid "Switch to VT 12" -+msgstr "Ddu ɣer VT 12" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:60 -+msgid "Re-enable shortcuts" -+msgstr "Ales armad n yinegzumen n unasiw" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:70 -+msgid "Allow X11 grabs to lock keyboard focus with Xwayland" -+msgstr "Sireg tuṭṭfiwin X11 ad sekkṛent afukus n unasiw s Xwayland" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:71 -+msgid "" -+"Allow all keyboard events to be routed to X11 “override redirect” windows " -+"with a grab when running in Xwayland. This option is to support X11 clients " -+"which map an “override redirect” window (which do not receive keyboard " -+"focus) and issue a keyboard grab to force all keyboard events to that " -+"window. This option is seldom used and has no effect on regular X11 windows " -+"which can receive keyboard focus under normal circumstances. For a X11 grab " -+"to be taken into account under Wayland, the client must also either send a " -+"specific X11 ClientMessage to the root window or be among the applications " -+"allowed in key “xwayland-grab-access-rules”." -+msgstr "" -+"Asireg n usezzi n meṛṛa tidyanin n unasiw ɣer yisfuyla X11 \"override " -+"redirect\" s uzuɣer lawan n uselkem deg Xwayland. Taxtiṛt-a tettaǧǧa imsaɣen " -+"X11 azuɣer n usfaylu \"override redirect\" (ur nremmes ara asiḍes n unasiw) " -+"akked useqdec n uzuɣer i uḥettem n meṛṛa tidyanin n unasiw ɣer usfaylu-a. " -+"Taxtiṛt-a ur tettwaseqdac ara s waṭas, ur txeddem kra i yisfuyla X11 i " -+"izemren ad remsen asiḍes n unasiw deg tegnatin timugna. I uzuɣer n X11 ad " -+"tettwaṭṭef deg Wayland, amsaɣ ilaq ad yazen daɣen X11 ClientMessage ɣer " -+"usfaylu aẓar neɣ ad yili seg yisnasen yettwasirgen deg tsarut “xwayland-grab-" -+"access-rules”." -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:90 -+msgid "Xwayland applications allowed to issue keyboard grabs" -+msgstr "Isnasen Xwayland ttusirgent ad gent tuṭṭfiwin n unasiw" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:91 -+msgid "" -+"List the resource names or resource class of X11 windows either allowed or " -+"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " -+"resource class of a given X11 window can be obtained using the command " -+"“xprop WM_CLASS”. Wildcards “*” and jokers “?” in the values are supported. " -+"Values starting with “!” are denied, which has precedence over the list of " -+"values allowed, to revoke applications from the default system list. The " -+"default system list includes the following applications: " -+"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Users can break an existing grab by " -+"using the specific keyboard shortcut defined by the keybinding key “restore-" -+"shortcuts”." -+msgstr "" -+"Bder ismawen n yiɣbula neɣ ismilen n yiɣbula n yisfuyla X11 yettwasirgen neɣ " -+"uhu, ad gen tuṭṭfiwin n unasiw X11 deg Wayland. Isem neɣ asmel n uɣbalu n " -+"usfaylu X11 i yettwamudden zemren ad d-ttwawin s useqdec n tladna “xprop " -+"WM_CLASS”. Isekkilen imcettlen “*” akked ijukiṛen “?” deg wazalen " -+"yettwasferken. Azalen i ibeddun s \"!\" ttwagin, i yellan deg tebdart " -+"yettwasirgen yakan, i usefsex n yisnasen seg tebdart n unagraw amezwer. " -+"Tabdart n unagraw amezwer deg-s isnasen-a: " -+"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Iseqdacen zemren ad sḥebsen tira " -+"yellan yakan s useqdec n unegzum n unasiw uzzig yettusbadun s tsarut n " -+"tuqqna \"restore-shortcuts\"." -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:116 -+msgid "Disable selected X extensions in Xwayland" -+msgstr "Sens isiɣzaf X i yettwafernen deg Xwayland" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:117 -+msgid "" -+"This option disables the selected X extensions in Xwayland if Xwayland was " -+"built with support for those X extensions. This option has no effect if " -+"Xwayland was built without support for the selected extensions. Xwayland " -+"needs to be restarted for this setting to take effect." -+msgstr "" -+"Taxtiṛt-a tesnusuy isiɣzaf X i yettwafernen deg Xwayland ma yella Xwayland " -+"yebna s usefrek i yisiɣzaf-a X. Taxtiṛt-a ur d-tgellu s wecemma ma yella " -+"Xwayland yebna war asefrek n yisiɣzaf i yettwafernen. Xwayland yesra ad " -+"yales asenker i uɣewwar-a i wakken ad yeddu." -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:130 -+msgid "Allow X11 clients with a different endianness to connect to Xwayland" -+msgstr "Sireg imsaɣen X11 s at taggara yemgaraden i tuqqna ɣer Xwayland" -+ -+#: data/org.gnome.mutter.wayland.gschema.xml.in:131 -+msgid "" -+"Allow connections from clients with an endianness different to that of " -+"Xwayland. The X server byte-swapping code is a huge attack surface, much of " -+"that code in Xwayland is prone to security issues. The use-case of byte-" -+"swapped clients is very niche, and disabled by default in Xwayland. Enable " -+"this option to instruct Xwayland to accept connections from X11 clients with " -+"a different endianness. This option has no effect if Xwayland does not " -+"support the command line option +byteswappedclients/-byteswappedclients to " -+"control that setting. Xwayland needs to be restarted for this setting to " -+"take effect." -+msgstr "" -+"Asireg n tuqqniwin seg yimsaɣen ideg endianness yemgarad ɣef win n Xwayland. " -+"Tangalt n umyibedel n yibiten n uqeddac X d tajumma meqqren n uzḍam, amur " -+"ameqqran seg tengalt-a deg Xwayland yezmer ad yesεu uguren n tɣellist. " -+"Addaden n useqdec n yimsaɣen yettmyibeddalen ibiten drus maḍi, yettwasens s " -+"wudem amezwer deg Xwayland. Armad n textiṛt-a i ussuter deg Xwayland aqbal n " -+"tuqqniwin n yimsaɣen X11 s endianness yemgaraden. Taxtiṛt-a ur txeddem " -+"acemma ma yella Xwayland ur yessefrak ara taxtiṛt n yizirig n tiludna " -+"+byteswappedclients/-byteswappedclients i usenqed n uɣewwar-a. Xwayland " -+"yesra ad yales asenker i uɣewwar-a i wakken ad yeṭṭef." -+ -+#: src/backends/meta-monitor.c:251 -+msgid "Built-in display" -+msgstr "Agdil usliɣ" -+ -+#: src/backends/meta-monitor.c:278 -+msgid "Unknown" -+msgstr "Arussin" -+ -+#: src/backends/meta-monitor.c:280 -+msgid "Unknown Display" -+msgstr "Agdil arussin" -+ -+#: src/backends/meta-monitor.c:288 -+#, c-format -+msgctxt "" -+"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" -+msgid "%s %s" -+msgstr "%s %s" -+ -+#: src/backends/meta-monitor.c:296 -+#, c-format -+msgctxt "" -+"This is a monitor vendor name followed by product/model name where size in " -+"inches could not be calculated, e.g. Dell U2414H" -+msgid "%s %s" -+msgstr "%s %s" -+ -+#: src/core/bell.c:193 -+msgid "Bell event" -+msgstr "Tadyant n unayna" -+ -+#: src/core/display.c:734 -+msgid "Privacy Screen Enabled" -+msgstr "Agdil n tbaḍnit yermed" -+ -+#: src/core/display.c:735 -+msgid "Privacy Screen Disabled" -+msgstr "Agdil n tbaḍnit yensa" -+ -+#: src/core/meta-context-main.c:601 -+msgid "Replace the running window manager" -+msgstr "Semselsi amsefrak n usfaylu yettwaselkamen" -+ -+#: src/core/meta-context-main.c:607 -+msgid "X Display to use" -+msgstr "Taskant X ara yettusqedcen" -+ -+#: src/core/meta-context-main.c:613 -+msgid "Disable connection to session manager" -+msgstr "Sens tuqqna i umsefrak n tɣimit" -+ -+#: src/core/meta-context-main.c:619 -+msgid "Specify session management ID" -+msgstr "Asulay n usefrek n tɣimit tuzzigt" -+ -+#: src/core/meta-context-main.c:625 -+msgid "Initialize session from savefile" -+msgstr "Wennez tiɣimit seg ufaylu i yettwaskelsen" -+ -+#: src/core/meta-context-main.c:631 -+msgid "Make X calls synchronous" -+msgstr "Err isawalen X mtawan" -+ -+#: src/core/meta-context-main.c:639 -+msgid "Run as a wayland compositor" -+msgstr "Selkem am umsuddas Wayland" -+ -+#: src/core/meta-context-main.c:645 -+msgid "Run as a nested compositor" -+msgstr "Selkem am umsuddas yemyekcamen" -+ -+#: src/core/meta-context-main.c:651 -+msgid "Run wayland compositor without starting Xwayland" -+msgstr "Selkem amsuddas wayland war asenker n Xwayland" -+ -+#: src/core/meta-context-main.c:657 -+msgid "Specify Wayland display name to use" -+msgstr "Sded agdil Wayland i useqdec" -+ -+#: src/core/meta-context-main.c:665 -+msgid "Run as a full display server, rather than nested" -+msgstr "Selkem am uqeddac n uskan aččuran, deg wadeg n umyikcam" -+ -+#: src/core/meta-context-main.c:670 -+msgid "Run as a headless display server" -+msgstr "Selkem am uqeddac n uskan war aqerru" -+ -+#: src/core/meta-context-main.c:675 -+msgid "Add persistent virtual monitor (WxH or WxH@R)" -+msgstr "Rnu asefrak uhlis amaɣlal (WxH neɣ WxH@R)" -+ -+#: src/core/meta-context-main.c:687 -+msgid "Run with X11 backend" -+msgstr "Selkem s ugdil n deffir X11" -+ -+#: src/core/meta-context-main.c:693 -+msgid "Profile performance using trace instrumentation" -+msgstr "Timellit n umaɣnu s useqdec n ifecka n uḍfar" -+ -+#: src/core/meta-context-main.c:699 -+msgid "Enable debug control D-Bus interface" -+msgstr "Rmed agrudem D-Bus n usenqed n tseɣtayt" -+ -+#. TRANSLATORS: This string refers to a button that switches between -+#. * different modes. -+#. -+#: src/core/meta-pad-action-mapper.c:826 -+#, c-format -+msgid "Mode Switch (Group %d)" -+msgstr "Asenfel n uskar (Agraw %d)" -+ -+#. TRANSLATORS: This string refers to an action, cycles drawing tablets' -+#. * mapping through the available outputs. -+#. -+#: src/core/meta-pad-action-mapper.c:848 -+msgid "Switch monitor" -+msgstr "Senfel asefrak" -+ -+#: src/core/meta-pad-action-mapper.c:850 -+msgid "Show on-screen help" -+msgstr "Sken tallalt ɣef ugdil" -+ -+#. Translators: this string will appear in Sysprof -+#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 -+msgid "Compositor" -+msgstr "Amsuddas" -+ -+#: src/core/mutter.c:74 -+msgid "Print version" -+msgstr "Sken lqem" -+ -+#: src/core/mutter.c:80 -+msgid "Mutter plugin to use" -+msgstr "Azegrir Mutter ara yettwasqedcen" -+ -+#: src/core/prefs.c:1842 -+#, c-format -+msgid "Workspace %d" -+msgstr "Tallunt n umahil %d" -+ -+#: src/core/util.c:139 -+msgid "Mutter was compiled without support for verbose mode" -+msgstr "Mutter yettwasefsu war asefrek n uskar ɣezzifen" -+ -+#: src/core/workspace.c:510 -+msgid "Workspace switched" -+msgstr "Tallunt n umahil tettwasenfel" -+ -+#: src/wayland/meta-wayland-tablet-pad.c:532 -+#, c-format -+msgid "Mode Switch: Mode %d" -+msgstr "Asenfel n uskar: Askar %d" -+ -+#: src/x11/meta-x11-display.c:723 -+#, c-format -+msgid "" -+"Display “%s” already has a window manager; try using the --replace option to " -+"replace the current window manager." -+msgstr "" -+"Sken \"%s\" yesεa yakan asefrak n usfaylu; εreḍ seqdec taxtiṛt --replace i " -+"usemselsi n usefrak n yisfuyla amiran." -+ -+#: src/x11/meta-x11-display.c:1088 -+#, c-format -+msgid "Failed to open X Window System display “%s”" -+msgstr "Yecceḍ ulday n uskan n n yifuyla X Window \"%s\"" -+ -+#: src/x11/meta-x11-display.c:1268 -+#, c-format -+msgid "Screen %d on display “%s” is invalid" -+msgstr "Agdil %d ɣef uskan \"%s\" d arameɣtu" -+ -+#. This probably means that a non-WM compositor like xcompmgr is running; -+#. * we have no way to get it to exit -+#: src/x11/meta-x11-display.c:2547 -+#, c-format -+msgid "" -+"Another compositing manager is already running on screen %i on display “%s”." -+msgstr "" -+"Asefrak niḍen n usuddes yella yakan yettwaselkam ɣef ugdil %i ɣef uskan " -+"\"%s\"." -+ -+#: src/x11/meta-x11-selection-input-stream.c:475 -+#, c-format -+msgid "Format %s not supported" -+msgstr "Amasal %s ur yettwasefrak ara" -+ -+#: src/x11/window-props.c:528 -+#, c-format -+msgid "%s (on %s)" -+msgstr "%s (ɣef %s)" -diff --git a/po/ko.po b/po/ko.po -index 558c6c5ca..3ac430f08 100644 ---- a/po/ko.po -+++ b/po/ko.po -@@ -7,7 +7,7 @@ - # - # Updated in mutter: - # Changwoo Ryu , 2011-2017. --# Gwan-gyeong Mun , 2018-2023. -+# Gwan-gyeong Mun , 2018-2024. - # - # - # 주의: -@@ -17,8 +17,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: mutter\n" --"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" --"POT-Creation-Date: 2023-08-23 16:49+0000\n" -+"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" -+"POT-Creation-Date: 2024-03-11 11:31+0000\n" - "PO-Revision-Date: 2023-03-15 18:43+0200\n" - "Last-Translator: Gwan-gyeong Mun \n" - "Language-Team: GNOME Korea \n" -@@ -257,11 +257,11 @@ msgstr "창을 세로 방향으로 최대화" - msgid "Maximize window horizontally" - msgstr "창을 가로 방향으로 최대화" - --#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 -+#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 - msgid "View split on left" - msgstr "왼쪽 나눔창 보기" - --#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 -+#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 - msgid "View split on right" - msgstr "오른쪽 나눔창 보기" - -@@ -394,10 +394,11 @@ msgid "" - "space, while scaling monitor framebuffers instead of window content, to " - "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " - "mutter always allocate scanout buffers with explicit modifiers, if supported " --"by the driver. Requires a restart. • “rt-scheduler” — makes mutter request a " --"low priority real-time scheduling. Requires a restart. • “autoclose-" --"xwayland” — automatically terminates Xwayland if all relevant X11 clients " --"are gone. Requires a restart." -+"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " -+"terminates Xwayland if all relevant X11 clients are gone. Requires a " -+"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " -+"refresh rate of the monitor when applicable if supported by the monitor, GPU " -+"and DRM driver. Configurable in Settings. Requires a restart." - msgstr "" - "실험적인 기능을 사용하려면, 해당 기능 키워드를 목록에 추가하십시오. 기능에 따" - "라 컴포지터를 다시 시작해야 할 수도 있습니다. 실험적인 기능은 사용할 수 없을 " -@@ -407,24 +408,25 @@ msgstr "" - "를 배치하고, HiDPI 모니터를 관리하기 위해 창 내용 대신 모니터 프레임 버퍼를 " - "스케일링합니다. 재시작은 필요하지 않습니다. • “kms-modifiers” — 드라이버에서 " - "지원하는 경우 머터가 항상 명시적 한정자를 사용하여 스캔아웃 버퍼를 할당 합니" --"다. 재시작이 필요합니다. • “rt-scheduler” — 머터 요청을 우선순위가 낮은 실시" --"간 스케줄링으로 만듭니다. 재시작이 필요합니다. • “autoclose-xwayland” — 모든 " --"X11 관련 클라이언트가 종료되면 X웨일랜드를 자동으로 종료합니다. 재시작이 필요" --"하지 않습니다." -+"다. 재시작이 필요합니다. • “autoclose-xwayland” — 모든 X11 관련 클라이언트가 " -+"종료되면 X웨일랜드를 자동으로 종료합니다. 재시작이 필요하지 않습니다. • " -+"“variable-refresh-rate” — 모니터, GPU 및 DRM 드라이버에서 지원하는 경우 모니" -+"터의 새로 고침 빈도를 동적으로 조정합니다. 설정에서 구성 가능하며, 재시작이 " -+"필요합니다." - --#: data/org.gnome.mutter.gschema.xml.in:141 -+#: data/org.gnome.mutter.gschema.xml.in:144 - msgid "Modifier to use to locate the pointer" - msgstr "포인터 위치 찾기에 사용할 키" - --#: data/org.gnome.mutter.gschema.xml.in:142 -+#: data/org.gnome.mutter.gschema.xml.in:145 - msgid "This key will initiate the “locate pointer” action." - msgstr "이 키는 “포인터 위치 찾기” 동작을 합니다." - --#: data/org.gnome.mutter.gschema.xml.in:149 -+#: data/org.gnome.mutter.gschema.xml.in:152 - msgid "Timeout for check-alive ping" - msgstr "활성 확인 핑 시간 초과" - --#: data/org.gnome.mutter.gschema.xml.in:150 -+#: data/org.gnome.mutter.gschema.xml.in:153 - msgid "" - "Number of milliseconds a client has to respond to a ping request in order to " - "not be detected as frozen. Using 0 will disable the alive check completely." -@@ -432,15 +434,15 @@ msgstr "" - "중지된 것으로 감지되지 않도록 클라이언트가 핑 요청에 응답해야 하는 시간 (밀리" - "초). 0을 사용하면 활성 확인이 완전히 비활성화됩니다." - --#: data/org.gnome.mutter.gschema.xml.in:174 -+#: data/org.gnome.mutter.gschema.xml.in:177 - msgid "Switch monitor configurations" - msgstr "모니터 설정 전환" - --#: data/org.gnome.mutter.gschema.xml.in:179 -+#: data/org.gnome.mutter.gschema.xml.in:182 - msgid "Rotates the built-in monitor configuration" - msgstr "내장된 모니터 설정을 돌아가면서 전환합니다" - --#: data/org.gnome.mutter.gschema.xml.in:184 -+#: data/org.gnome.mutter.gschema.xml.in:187 - msgid "Cancel any active input capture session" - msgstr "활성화된 입력 캡처 세션 취소" - -@@ -587,26 +589,26 @@ msgstr "" - "byteswappedclients을 지원하지 않는 경우 효과가 없습니다. 이 설정을 적용하려" - "면 X웨일랜드를 다시 시작해야 합니다." - --#: src/backends/meta-monitor.c:253 -+#: src/backends/meta-monitor.c:251 - msgid "Built-in display" - msgstr "내장 디스플레이" - --#: src/backends/meta-monitor.c:280 -+#: src/backends/meta-monitor.c:278 - msgid "Unknown" - msgstr "알 수 없음" - --#: src/backends/meta-monitor.c:282 -+#: src/backends/meta-monitor.c:280 - msgid "Unknown Display" - msgstr "알 수 없는 디스플레이" - --#: src/backends/meta-monitor.c:290 -+#: src/backends/meta-monitor.c:288 - #, c-format - msgctxt "" - "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" - msgid "%s %s" - msgstr "%s %s" - --#: src/backends/meta-monitor.c:298 -+#: src/backends/meta-monitor.c:296 - #, c-format - msgctxt "" - "This is a monitor vendor name followed by product/model name where size in " -@@ -618,78 +620,82 @@ msgstr "%s %s" - msgid "Bell event" - msgstr "삑소리 이벤트" - --#: src/core/display.c:723 -+#: src/core/display.c:734 - msgid "Privacy Screen Enabled" - msgstr "사생활 보호 화면 사용" - --#: src/core/display.c:724 -+#: src/core/display.c:735 - msgid "Privacy Screen Disabled" - msgstr "사생활 보호 화면 해제" - --#: src/core/meta-context-main.c:581 -+#: src/core/meta-context-main.c:601 - msgid "Replace the running window manager" - msgstr "실행 중인 창 관리자를 바꿉니다" - --#: src/core/meta-context-main.c:587 -+#: src/core/meta-context-main.c:607 - msgid "X Display to use" - msgstr "사용할 X 디스플레이" - --#: src/core/meta-context-main.c:593 -+#: src/core/meta-context-main.c:613 - msgid "Disable connection to session manager" - msgstr "세션 관리자와 연결 하지 않습니다" - --#: src/core/meta-context-main.c:599 -+#: src/core/meta-context-main.c:619 - msgid "Specify session management ID" - msgstr "세션 관리 ID를 지정합니다" - --#: src/core/meta-context-main.c:605 -+#: src/core/meta-context-main.c:625 - msgid "Initialize session from savefile" - msgstr "저장 파일에서 세션을 초기화 합니다" - --#: src/core/meta-context-main.c:611 -+#: src/core/meta-context-main.c:631 - msgid "Make X calls synchronous" - msgstr "동기 X 호출을 합니다" - --#: src/core/meta-context-main.c:619 -+#: src/core/meta-context-main.c:639 - msgid "Run as a wayland compositor" - msgstr "웨일랜드 컴포지터로 실행합니다" - --#: src/core/meta-context-main.c:625 -+#: src/core/meta-context-main.c:645 - msgid "Run as a nested compositor" - msgstr "중첩 컴포지터로 실행합니다" - --#: src/core/meta-context-main.c:631 -+#: src/core/meta-context-main.c:651 - msgid "Run wayland compositor without starting Xwayland" - msgstr "웨일랜드 컴포지터를 X웨일랜드 시작없이 실행합니다" - --#: src/core/meta-context-main.c:637 -+#: src/core/meta-context-main.c:657 - msgid "Specify Wayland display name to use" - msgstr "사용할 웨일랜드 디스플레이 이름 지정" - --#: src/core/meta-context-main.c:645 -+#: src/core/meta-context-main.c:665 - msgid "Run as a full display server, rather than nested" - msgstr "전체 디스플레이 서버로 실행, 중첩 컴포지터가 아님" - --#: src/core/meta-context-main.c:650 -+#: src/core/meta-context-main.c:670 - msgid "Run as a headless display server" - msgstr "헤드리스 디스플레이 서버로 실행" - --#: src/core/meta-context-main.c:655 -+#: src/core/meta-context-main.c:675 - msgid "Add persistent virtual monitor (WxH or WxH@R)" - msgstr "영구적인 가상 모니터 추가 (WxH or WxH@R)" - --#: src/core/meta-context-main.c:667 -+#: src/core/meta-context-main.c:687 - msgid "Run with X11 backend" - msgstr "X11 백 엔드로 실행 합니다" - --#: src/core/meta-context-main.c:673 -+#: src/core/meta-context-main.c:693 - msgid "Profile performance using trace instrumentation" - msgstr "추적 계측을 사용한 성능 프로파일" - -+#: src/core/meta-context-main.c:699 -+msgid "Enable debug control D-Bus interface" -+msgstr "디버깅 제어 D-Bus 인터페이스 사용" -+ - #. TRANSLATORS: This string refers to a button that switches between - #. * different modes. - #. --#: src/core/meta-pad-action-mapper.c:807 -+#: src/core/meta-pad-action-mapper.c:826 - #, c-format - msgid "Mode Switch (Group %d)" - msgstr "모드 전환 (그룹 %d)" -@@ -697,16 +703,16 @@ msgstr "모드 전환 (그룹 %d)" - #. TRANSLATORS: This string refers to an action, cycles drawing tablets' - #. * mapping through the available outputs. - #. --#: src/core/meta-pad-action-mapper.c:829 -+#: src/core/meta-pad-action-mapper.c:848 - msgid "Switch monitor" - msgstr "모니터 전환" - --#: src/core/meta-pad-action-mapper.c:831 -+#: src/core/meta-pad-action-mapper.c:850 - msgid "Show on-screen help" - msgstr "화면 도움말 표시" - - #. Translators: this string will appear in Sysprof --#: src/core/meta-profiler.c:111 src/core/meta-profiler.c:301 -+#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 - msgid "Compositor" - msgstr "컴포지터" - -@@ -718,7 +724,7 @@ msgstr "버전을 출력합니다" - msgid "Mutter plugin to use" - msgstr "사용할 머터 플러그인" - --#: src/core/prefs.c:1843 -+#: src/core/prefs.c:1842 - #, c-format - msgid "Workspace %d" - msgstr "작업 공간 %d" -@@ -727,16 +733,16 @@ msgstr "작업 공간 %d" - msgid "Mutter was compiled without support for verbose mode" - msgstr "머터가 자세한 정보 표시 모드를 지원하지 않게 컴파일되었습니다" - --#: src/core/workspace.c:535 -+#: src/core/workspace.c:510 - msgid "Workspace switched" - msgstr "작업 공간 전환" - --#: src/wayland/meta-wayland-tablet-pad.c:534 -+#: src/wayland/meta-wayland-tablet-pad.c:532 - #, c-format - msgid "Mode Switch: Mode %d" - msgstr "모드 전환: 모드 %d" - --#: src/x11/meta-x11-display.c:708 -+#: src/x11/meta-x11-display.c:723 - #, c-format - msgid "" - "Display “%s” already has a window manager; try using the --replace option to " -@@ -745,19 +751,19 @@ msgstr "" - "디스플레이 “%s”에 이미 창 관리자가 있습니다. 현재 창 관리자를 바꾸려면 --" - "replace 옵션을 써보십시오." - --#: src/x11/meta-x11-display.c:1073 -+#: src/x11/meta-x11-display.c:1088 - #, c-format - msgid "Failed to open X Window System display “%s”" - msgstr "X 윈도 시스템 디스플레이 “%s”을(를) 여는데 실패하였습니다" - --#: src/x11/meta-x11-display.c:1219 -+#: src/x11/meta-x11-display.c:1268 - #, c-format - msgid "Screen %d on display “%s” is invalid" - msgstr "디스플레이 “%2$s”의 화면 %1$d은(는) 잘못되었습니다" - - #. This probably means that a non-WM compositor like xcompmgr is running; - #. * we have no way to get it to exit --#: src/x11/meta-x11-display.c:2540 -+#: src/x11/meta-x11-display.c:2547 - #, c-format - msgid "" - "Another compositing manager is already running on screen %i on display “%s”." -@@ -771,7 +777,7 @@ msgid "Format %s not supported" - msgstr "%s 형식은 지원하지 않습니다" - - # <창제목> (on <기계>) --#: src/x11/window-props.c:548 -+#: src/x11/window-props.c:528 - #, c-format - msgid "%s (on %s)" - msgstr "%s (%s에서)" -diff --git a/po/nl.po b/po/nl.po -index 1aae5aca9..9f4d33e05 100644 ---- a/po/nl.po -+++ b/po/nl.po -@@ -10,8 +10,8 @@ msgid "" - msgstr "" - "Project-Id-Version: mutter\n" - "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" --"POT-Creation-Date: 2024-02-12 13:12+0000\n" --"PO-Revision-Date: 2024-02-18 17:09+0100\n" -+"POT-Creation-Date: 2024-03-16 16:36+0000\n" -+"PO-Revision-Date: 2024-03-31 12:12+0200\n" - "Last-Translator: Nathan Follens \n" - "Language-Team: GNOME-NL https://matrix.to/#/#nl:gnome.org\n" - "Language: nl\n" -@@ -250,19 +250,19 @@ msgstr "Venster verticaal maximaliseren" - msgid "Maximize window horizontally" - msgstr "Venster horizontaal maximaliseren" - --#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:160 -+#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 - msgid "View split on left" - msgstr "Weergave gesplitst op links" - --#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:165 -+#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 - msgid "View split on right" - msgstr "Weergave gesplitst op rechts" - --#: data/org.gnome.mutter.gschema.xml.in:14 -+#: data/org.gnome.mutter.gschema.xml.in:15 - msgid "Modifier to use for extended window management operations" - msgstr "Controletoets voor uitgebreide vensterbeheerfunctionaliteit" - --#: data/org.gnome.mutter.gschema.xml.in:15 -+#: data/org.gnome.mutter.gschema.xml.in:16 - msgid "" - "This key will initiate the “overlay”, which is a combination window overview " - "and application launching system. The default is intended to be the “Windows " -@@ -274,11 +274,11 @@ msgstr "" - "toets’ en de bedoeling is dat deze sneltoets ofwel de standaardwaarde bevat " - "ofwel leeggemaakt is." - --#: data/org.gnome.mutter.gschema.xml.in:27 -+#: data/org.gnome.mutter.gschema.xml.in:28 - msgid "Attach modal dialogs" - msgstr "Blokkerende dialoogvensters vastmaken" - --#: data/org.gnome.mutter.gschema.xml.in:28 -+#: data/org.gnome.mutter.gschema.xml.in:29 - msgid "" - "When true, instead of having independent titlebars, modal dialogs appear " - "attached to the titlebar of the parent window and are moved together with " -@@ -288,11 +288,11 @@ msgstr "" - "maar vastgekoppeld aan het achterliggende venster en bewegen daardoor ook " - "mee met het achterliggende venster." - --#: data/org.gnome.mutter.gschema.xml.in:37 -+#: data/org.gnome.mutter.gschema.xml.in:38 - msgid "Enable edge tiling when dropping windows on screen edges" - msgstr "Randtegels inschakelen bij het slepen van vensters naar schermranden" - --#: data/org.gnome.mutter.gschema.xml.in:38 -+#: data/org.gnome.mutter.gschema.xml.in:39 - msgid "" - "If enabled, dropping windows on vertical screen edges maximizes them " - "vertically and resizes them horizontally to cover half of the available " -@@ -303,11 +303,11 @@ msgstr "" - "schermgrootte brengen. Het laten vallen van vensters op de bovenrand van het " - "scherm maximaliseert ze helemaal." - --#: data/org.gnome.mutter.gschema.xml.in:47 -+#: data/org.gnome.mutter.gschema.xml.in:48 - msgid "Workspaces are managed dynamically" - msgstr "Werkbladen worden dynamisch beheerd" - --#: data/org.gnome.mutter.gschema.xml.in:48 -+#: data/org.gnome.mutter.gschema.xml.in:49 - msgid "" - "Determines whether workspaces are managed dynamically or whether there’s a " - "static number of workspaces (determined by the num-workspaces key in org." -@@ -317,11 +317,11 @@ msgstr "" - "werkbladen is (gegeven door de sleutel num-workspaces in org.gnome.desktop." - "wm.preferences)." - --#: data/org.gnome.mutter.gschema.xml.in:57 -+#: data/org.gnome.mutter.gschema.xml.in:58 - msgid "Workspaces only on primary" - msgstr "Werkbladen alleen voor primaire venster" - --#: data/org.gnome.mutter.gschema.xml.in:58 -+#: data/org.gnome.mutter.gschema.xml.in:59 - msgid "" - "Determines whether workspace switching should happen for windows on all " - "monitors or only for windows on the primary monitor." -@@ -329,11 +329,11 @@ msgstr "" - "Geeft aan of wisselen van werkblad voor vensters op alle schermen of alleen " - "voor vensters op het hoofdscherm moet gebeuren." - --#: data/org.gnome.mutter.gschema.xml.in:66 -+#: data/org.gnome.mutter.gschema.xml.in:67 - msgid "Delay focus changes until the pointer stops moving" - msgstr "Aandacht vertragen totdat de muispijl stopt met bewegen" - --#: data/org.gnome.mutter.gschema.xml.in:67 -+#: data/org.gnome.mutter.gschema.xml.in:68 - msgid "" - "If set to true, and the focus mode is either “sloppy” or “mouse” then the " - "focus will not be changed immediately when entering a window, but only after " -@@ -343,11 +343,11 @@ msgstr "" - "‘mouse’, dan zal de aandacht niet direct veranderd worden bij het binnengaan " - "van een venster, maar slechts wanneer de muispijl stopt met bewegen." - --#: data/org.gnome.mutter.gschema.xml.in:77 -+#: data/org.gnome.mutter.gschema.xml.in:78 - msgid "Draggable border width" - msgstr "Sleepbare randbreedte" - --#: data/org.gnome.mutter.gschema.xml.in:78 -+#: data/org.gnome.mutter.gschema.xml.in:79 - msgid "" - "The amount of total draggable borders. If the theme’s visible borders are " - "not enough, invisible borders will be added to meet this value." -@@ -356,11 +356,11 @@ msgstr "" - "onvoldoende zijn, worden onzichtbare randen toegevoegd om deze waarde te " - "bereiken." - --#: data/org.gnome.mutter.gschema.xml.in:87 -+#: data/org.gnome.mutter.gschema.xml.in:88 - msgid "Auto maximize nearly monitor sized windows" - msgstr "Vensters van bijna-monitorformaat auto-maximaliseren" - --#: data/org.gnome.mutter.gschema.xml.in:88 -+#: data/org.gnome.mutter.gschema.xml.in:89 - msgid "" - "If enabled, new windows that are initially the size of the monitor " - "automatically get maximized." -@@ -368,11 +368,11 @@ msgstr "" - "Indien ingeschakeld, worden vensters die initieel ongeveer even groot zijn " - "als de monitor automatisch gemaximaliseerd." - --#: data/org.gnome.mutter.gschema.xml.in:96 -+#: data/org.gnome.mutter.gschema.xml.in:97 - msgid "Place new windows in the center" - msgstr "Plaats nieuwe vensters in het midden" - --#: data/org.gnome.mutter.gschema.xml.in:97 -+#: data/org.gnome.mutter.gschema.xml.in:98 - msgid "" - "When true, the new windows will always be put in the center of the active " - "screen of the monitor." -@@ -380,11 +380,11 @@ msgstr "" - "Indien waar zullen nieuwe vensters steeds in het midden van het actieve " - "scherm van de monitor geplaatst worden." - --#: data/org.gnome.mutter.gschema.xml.in:106 -+#: data/org.gnome.mutter.gschema.xml.in:107 - msgid "Enable experimental features" - msgstr "Experimentele functies inschakelen" - --#: data/org.gnome.mutter.gschema.xml.in:107 -+#: data/org.gnome.mutter.gschema.xml.in:108 - msgid "" - "To enable experimental features, add the feature keyword to the list. " - "Whether the feature requires restarting the compositor depends on the given " -@@ -396,7 +396,10 @@ msgid "" - "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " - "mutter always allocate scanout buffers with explicit modifiers, if supported " - "by the driver. Requires a restart. • “autoclose-xwayland” — automatically " --"terminates Xwayland if all relevant X11 clients are gone. Requires a restart." -+"terminates Xwayland if all relevant X11 clients are gone. Requires a " -+"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " -+"refresh rate of the monitor when applicable if supported by the monitor, GPU " -+"and DRM driver. Configurable in Settings. Requires a restart." - msgstr "" - "Voeg het sleutelwoord van een experimentele functie toe aan de lijst om deze " - "in te schakelen. Of de compositor herstart moet worden vooraleer de functie " -@@ -411,21 +414,25 @@ msgstr "" - "scanoutbuffers steeds toewijst met uitdrukkelijke modifiers, indien dit " - "ondersteund wordt door het stuurprogramma. Hiervoor is opnieuw opstarten " - "vereist. • “autoclose-xwayland” — beëindigt Xwayland automatisch wanneer er " --"geen relevante X11-cliënten meer zijn. Hiervoor is opnieuw opstarten vereist." -+"geen relevante X11-cliënten meer zijn. Hiervoor is opnieuw opstarten " -+"vereist. • “variable-refresh-rate” — laat mutter de verversingsfrequentie " -+"van het beeldscherm dynamisch aanpassen wanneer van toepassing en wanneer " -+"het beeldscherm, de GPU en het DRM-stuurprogramma dit ondersteunt. " -+"Instelbaar via Instellingen. Hiervoor is opnieuw opstarten vereist." - --#: data/org.gnome.mutter.gschema.xml.in:137 -+#: data/org.gnome.mutter.gschema.xml.in:144 - msgid "Modifier to use to locate the pointer" - msgstr "Controletoets om de muispijl te lokaliseren" - --#: data/org.gnome.mutter.gschema.xml.in:138 -+#: data/org.gnome.mutter.gschema.xml.in:145 - msgid "This key will initiate the “locate pointer” action." - msgstr "Deze sleutel activeert de actie ‘muispijl lokaliseren’." - --#: data/org.gnome.mutter.gschema.xml.in:145 -+#: data/org.gnome.mutter.gschema.xml.in:152 - msgid "Timeout for check-alive ping" - msgstr "Time-out voor levenscontroleping" - --#: data/org.gnome.mutter.gschema.xml.in:146 -+#: data/org.gnome.mutter.gschema.xml.in:153 - msgid "" - "Number of milliseconds a client has to respond to a ping request in order to " - "not be detected as frozen. Using 0 will disable the alive check completely." -@@ -434,15 +441,15 @@ msgstr "" - "verzoek om niet als bevroren beschouwd te worden. Stel dit in op 0 om de " - "levenscontrole volledig uit te schakelen." - --#: data/org.gnome.mutter.gschema.xml.in:170 -+#: data/org.gnome.mutter.gschema.xml.in:177 - msgid "Switch monitor configurations" - msgstr "Tussen beeldschermconfiguraties schakelen" - --#: data/org.gnome.mutter.gschema.xml.in:175 -+#: data/org.gnome.mutter.gschema.xml.in:182 - msgid "Rotates the built-in monitor configuration" - msgstr "Roteert de ingebouwde beeldschermconfiguratie" - --#: data/org.gnome.mutter.gschema.xml.in:180 -+#: data/org.gnome.mutter.gschema.xml.in:187 - msgid "Cancel any active input capture session" - msgstr "Alle actieve sessies voor opvang van invoer annuleren" - -@@ -632,76 +639,76 @@ msgstr "%s %s" - msgid "Bell event" - msgstr "Bel-gebeurtenis" - --#: src/core/display.c:733 -+#: src/core/display.c:734 - msgid "Privacy Screen Enabled" - msgstr "Privacyscherm ingeschakeld" - --#: src/core/display.c:734 -+#: src/core/display.c:735 - msgid "Privacy Screen Disabled" - msgstr "Privacyscherm uitgeschakeld" - --#: src/core/meta-context-main.c:594 -+#: src/core/meta-context-main.c:601 - msgid "Replace the running window manager" - msgstr "De huidige toepassing voor vensterbeheer vervangen" - --#: src/core/meta-context-main.c:600 -+#: src/core/meta-context-main.c:607 - msgid "X Display to use" - msgstr "De te gebruiken X-weergave" - --#: src/core/meta-context-main.c:606 -+#: src/core/meta-context-main.c:613 - msgid "Disable connection to session manager" - msgstr "Schakel de verbinding met het sessiebeheer uit" - --#: src/core/meta-context-main.c:612 -+#: src/core/meta-context-main.c:619 - msgid "Specify session management ID" - msgstr "Bepaal de ID van het sessiebeheer" - --#: src/core/meta-context-main.c:618 -+#: src/core/meta-context-main.c:625 - msgid "Initialize session from savefile" - msgstr "Initialiseer de sessie middels een opslagbestand" - --#: src/core/meta-context-main.c:624 -+#: src/core/meta-context-main.c:631 - msgid "Make X calls synchronous" - msgstr "X-aanroepen synchroon maken" - --#: src/core/meta-context-main.c:632 -+#: src/core/meta-context-main.c:639 - msgid "Run as a wayland compositor" - msgstr "Uitvoeren als een wayland compositor" - --#: src/core/meta-context-main.c:638 -+#: src/core/meta-context-main.c:645 - msgid "Run as a nested compositor" - msgstr "Uitvoeren als een geneste compositor" - --#: src/core/meta-context-main.c:644 -+#: src/core/meta-context-main.c:651 - msgid "Run wayland compositor without starting Xwayland" - msgstr "Wayland-compositor uitvoeren zonder Xwayland te starten" - --#: src/core/meta-context-main.c:650 -+#: src/core/meta-context-main.c:657 - msgid "Specify Wayland display name to use" - msgstr "Bepaal de te gebruiken Wayland-weergavenaam" - --#: src/core/meta-context-main.c:658 -+#: src/core/meta-context-main.c:665 - msgid "Run as a full display server, rather than nested" - msgstr "Uitvoeren als een volledige displayserver, in plaats van genest" - --#: src/core/meta-context-main.c:663 -+#: src/core/meta-context-main.c:670 - msgid "Run as a headless display server" - msgstr "Uitvoeren als een ‘headless’ displayserver" - --#: src/core/meta-context-main.c:668 -+#: src/core/meta-context-main.c:675 - msgid "Add persistent virtual monitor (WxH or WxH@R)" - msgstr "Blijvend virtueel beeldscherm toevoegen (BxH of BxH@V)" - --#: src/core/meta-context-main.c:680 -+#: src/core/meta-context-main.c:687 - msgid "Run with X11 backend" - msgstr "Uitvoeren met X11-backend" - - # Onduidelijk of 'profile' hier een naamwoord of werkwoord is - Nathan --#: src/core/meta-context-main.c:686 -+#: src/core/meta-context-main.c:693 - msgid "Profile performance using trace instrumentation" - msgstr "Prestaties profileren met trace-hulpmiddelen" - --#: src/core/meta-context-main.c:692 -+#: src/core/meta-context-main.c:699 - msgid "Enable debug control D-Bus interface" - msgstr "Debugbesturing van D-Bus-interface inschakelen" - -@@ -737,7 +744,7 @@ msgstr "Versie-informatie tonen" - msgid "Mutter plugin to use" - msgstr "Te gebruiken Mutter-plug-in" - --#: src/core/prefs.c:1843 -+#: src/core/prefs.c:1842 - #, c-format - msgid "Workspace %d" - msgstr "Werkblad %d" -@@ -746,7 +753,7 @@ msgstr "Werkblad %d" - msgid "Mutter was compiled without support for verbose mode" - msgstr "Mutter is gecompileerd zonder ondersteuning voor verbose-mode" - --#: src/core/workspace.c:511 -+#: src/core/workspace.c:510 - msgid "Workspace switched" - msgstr "Werkblad gewisseld" - -@@ -776,7 +783,7 @@ msgstr "Scherm %d op beeldscherm ‘%s’ is ongeldig" - - #. This probably means that a non-WM compositor like xcompmgr is running; - #. * we have no way to get it to exit --#: src/x11/meta-x11-display.c:2539 -+#: src/x11/meta-x11-display.c:2547 - #, c-format - msgid "" - "Another compositing manager is already running on screen %i on display “%s”." -@@ -789,7 +796,7 @@ msgstr "" - msgid "Format %s not supported" - msgstr "Formaat %s wordt niet ondersteund" - --#: src/x11/window-props.c:524 -+#: src/x11/window-props.c:528 - #, c-format - msgid "%s (on %s)" - msgstr "%s (op %s)" -diff --git a/po/pa.po b/po/pa.po -index 29df49a3f..aeaed0f6d 100644 ---- a/po/pa.po -+++ b/po/pa.po -@@ -5,23 +5,23 @@ - # - # Amanpreet_Singh , 2004. - # Amanpreet Singh Alam , 2004. --# A S Alam , 2006. -+# SPDX-FileCopyrightText: 2006, 2024 A S Alam - # A S Alam , 2007, 2009, 2010, 2011, 2021, 2023. - # ASB , 2007. - # Amanpreet Singh Alam , 2009, 2012, 2013, 2014, 2015, 2017, 2020. - msgid "" - msgstr "" - "Project-Id-Version: metacity.gnome-2-26\n" --"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" --"POT-Creation-Date: 2023-07-15 01:02+0000\n" --"PO-Revision-Date: 2023-09-02 08:25-0700\n" --"Last-Translator: A S Alam \n" -+"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues/\n" -+"POT-Creation-Date: 2024-03-02 12:22+0000\n" -+"PO-Revision-Date: 2024-03-18 08:12-0500\n" -+"Last-Translator: A S Alam \n" - "Language-Team: Punjabi \n" - "Language: pa\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"X-Generator: Lokalize 23.04.3\n" -+"X-Generator: Lokalize 23.08.5\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - "\n" - -@@ -162,22 +162,18 @@ msgid "Switch to last workspace" - msgstr "ਪਿਛਲੇ ਵਰਕਸਪੇਸ ਵਿੱਚ ਜਾਓ" - - #: data/50-mutter-navigation.xml:131 --#| msgid "Move to workspace on the left" - msgid "Switch to workspace on the left" - msgstr "ਖੱਬੇ ਪਾਸੇ ਆਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" - - #: data/50-mutter-navigation.xml:134 --#| msgid "Move to workspace on the right" - msgid "Switch to workspace on the right" - msgstr "ਸੱਜੇ ਪਾਸੇ ਆਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" - - #: data/50-mutter-navigation.xml:138 --#| msgid "Switch to workspace 1" - msgid "Switch to workspace above" - msgstr "ਉੱਤਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" - - #: data/50-mutter-navigation.xml:142 --#| msgid "Switch to workspace 1" - msgid "Switch to workspace below" - msgstr "ਹੇਠਲੇ ਵਰਕਸਪੇਸ ਉੱਤੇ ਜਾਓ" - -@@ -257,11 +253,11 @@ msgstr "ਵਿੰਡੋ ਖੜਵੇਂ ਰੂਪ ਵਿੱਚ ਵੱਧੋ-ਵ - msgid "Maximize window horizontally" - msgstr "ਵਿੰਡੋ ਲੇਟਵੇਂ ਰੂਪ ਵਿੱਚ ਵੱਧੋ-ਵੱਧ" - --#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 -+#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:167 - msgid "View split on left" - msgstr "ਖੱਬੇ ਪਾਸੇ ਵੰਡ ਵੇਖੋ" - --#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 -+#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:172 - msgid "View split on right" - msgstr "ਸੱਜੇ ਪਾਸੇ ਵੰਡ ਵੇਖੋ" - -@@ -404,13 +400,12 @@ msgstr "ਤਜਰਬੇ ਅਧੀਨ ਫ਼ੀਚਰਾਂ ਨੂੰ ਸਮਰ - #| "framebuffer” — makes mutter default to layout logical monitors in a " - #| "logical pixel coordinate space, while scaling monitor framebuffers " - #| "instead of window content, to manage HiDPI monitors. Does not require a " --#| "restart. • “rt-scheduler” — makes mutter request a low priority real-time " --#| "scheduling. The executable or user must have CAP_SYS_NICE. Requires a " --#| "restart. • “dma-buf-screen-sharing\" — enables DMA buffered screen " --#| "sharing. This is already enabled by default when using the i915 driver, " --#| "but disabled for everything else. Requires a restart. • “autoclose-" --#| "xwayland” — automatically terminates Xwayland if all relevant X11 clients " --#| "are gone. Does not require a restart." -+#| "restart. • “kms-modifiers” — makes mutter always allocate scanout buffers " -+#| "with explicit modifiers, if supported by the driver. Requires a restart. " -+#| "• “rt-scheduler” — makes mutter request a low priority real-time " -+#| "scheduling. Requires a restart. • “autoclose-xwayland” — automatically " -+#| "terminates Xwayland if all relevant X11 clients are gone. Requires a " -+#| "restart." - msgid "" - "To enable experimental features, add the feature keyword to the list. " - "Whether the feature requires restarting the compositor depends on the given " -@@ -421,10 +416,11 @@ msgid "" - "space, while scaling monitor framebuffers instead of window content, to " - "manage HiDPI monitors. Does not require a restart. • “kms-modifiers” — makes " - "mutter always allocate scanout buffers with explicit modifiers, if supported " --"by the driver. Requires a restart. • “rt-scheduler” — makes mutter request a " --"low priority real-time scheduling. Requires a restart. • “autoclose-" --"xwayland” — automatically terminates Xwayland if all relevant X11 clients " --"are gone. Requires a restart." -+"by the driver. Requires a restart. • “autoclose-xwayland” — automatically " -+"terminates Xwayland if all relevant X11 clients are gone. Requires a " -+"restart. • “variable-refresh-rate” — makes mutter dynamically adjust the " -+"refresh rate of the monitor when applicable if supported by the monitor, GPU " -+"and DRM driver. Configurable in Settings. Requires a restart." - msgstr "" - "ਤਜਰਬੇ ਅਧੀਨ ਫ਼ੀਚਰ ਸਮਰੱਥ ਕਰਨ ਲਈ, ਫੀਚਰ ਕੀਵਰਡ ਸੂਚੀ ਵਿੱਚ ਜੋੜੋ। ਕੀ ਫ਼ੀਚਰ ਲਈ" - " ਕੰਪੋਜ਼ੀਟਰ ਮੁੜ-ਚਾਲੂ " -@@ -437,24 +433,29 @@ msgstr "" - "ਲਾਜ਼ੀਕਲ ਮਾਨੀਟਰਾਂ ਦੇ ਖਾਕੇ ਲਈ ਮਟਰ ਨੂੰ ਮੂਲ ਬਣਾਉਣਾ, ਜਦੋਂ ਕਿ HiDPI ਮਾਨੀਟਰਾਂ ਦੇ" - " ਇੰਤਜ਼ਾਮ ਲਈ ਵਿੰਡੋ " - "ਸਮੱਗਰੀ ਦੀ ਬਜਾਏ ਸਕੇਲਿੰਗ ਮਾਨੀਟਰ ਫਰੇਮਬਰਫ਼ ਹੋਣ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ। •" --" “kms-modifiers” — ਜੇ ਡਰਾਇਵਰ ਰਾਹੀਂ ਸਹਾਇਕ ਹੋਵੇ ਤਾਂ ਮਟਰ ਖਾਸ ਸੋਧਕਾਂ ਲਈ ਸਕੈਨ-ਆਉਟ" --" ਬਫ਼ਰ ਹਮੇਸ਼ਾਂ ਜਾਰੀ ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। • “autoclose-xwayland” — ਜੇ" --" ਸਾਰੇ ਵਾਜਬ X11 ਕਲਾਈਂਟ ਖਤਮ ਹੋ ਜਾਣ ਤਾਂ ਆਪਣੇ-ਆਪ Xwayland ਨੂੰ ਖਤਮ ਕਰਦਾ ਹੈ।" --" ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।" -- --#: data/org.gnome.mutter.gschema.xml.in:141 -+" “kms-" -+"modifiers” — ਜੇ ਡਰਾਇਵਰ ਰਾਹੀਂ ਸਹਾਇਕ ਹੋਵੇ ਤਾਂ ਮਟਰ ਖਾਸ ਸੋਧਕਾਂ ਲਈ ਸਕੈਨ-ਆਉਟ ਬਫ਼ਰ" -+" ਹਮੇਸ਼ਾਂ ਜਾਰੀ " -+"ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। • “autoclose-xwayland” — ਜੇ ਸਾਰੇ ਵਾਜਬ X11" -+" ਕਲਾਈਂਟ " -+"ਖਤਮ ਹੋ ਜਾਣ ਤਾਂ ਆਪਣੇ-ਆਪ Xwayland ਨੂੰ ਖਤਮ ਕਰਦਾ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। •" -+" “variable-refresh-rate” — ਜੇ ਮਾਨੀਟਰ, GPU ਅਤੇ DRM ਡਰਾਇਵਰ ਸਹਾਇਕ ਹੋਣ ਤਾਂ ਮਟਰ" -+" ਮਾਨੀਟਰ ਦੇ ਡਾਇਨੈਮਿਕ ਰੂਪ ਵਿੱਚ ਰੀ-ਫਰੈਸ਼ ਰੇਟ ਨੂੰ ਅਡਜੱਸਟ ਕਰ ਸਕਦਾ ਹੈ। ਸੈਟਿੰਗਾਂ ਵਿੱਚ" -+" ਸੰਰਚਨਾ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ। ਮੁੜ-ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।" -+ -+#: data/org.gnome.mutter.gschema.xml.in:144 - msgid "Modifier to use to locate the pointer" - msgstr "ਪੁਆਇੰਟਰ ਲੱਭਣ ਲਈ ਵਰਤਣ ਵਾਸਤੇ ਸੋਧਣ" - --#: data/org.gnome.mutter.gschema.xml.in:142 -+#: data/org.gnome.mutter.gschema.xml.in:145 - msgid "This key will initiate the “locate pointer” action." - msgstr "ਇਹ ਕੁੰਜੀ “ਪੁਆਇੰਟਰ ਲੱਭੋ“ ਕਾਰਵਾਈ ਸ਼ੁਰੂ ਕਰਦੀ ਹੈ।" - --#: data/org.gnome.mutter.gschema.xml.in:149 -+#: data/org.gnome.mutter.gschema.xml.in:152 - msgid "Timeout for check-alive ping" - msgstr "ਚੈਕ-ਸਰਗਰਮ ਪਿੰਗ ਲਈ ਸਮਾਂ-ਅੰਤਰਾਲ" - --#: data/org.gnome.mutter.gschema.xml.in:150 -+#: data/org.gnome.mutter.gschema.xml.in:153 - msgid "" - "Number of milliseconds a client has to respond to a ping request in order to " - "not be detected as frozen. Using 0 will disable the alive check completely." -@@ -464,15 +465,15 @@ msgstr "" - "ਜਕੜਿਆ ਨਾ ਖੋਜਿਆ ਜਾਵੇ। 0 ਵਰਤਣ ਨਾਲ ਸਰਗਰਮੀ ਦੀ ਜਾਂਚ ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਅਸਮਰੱਥ ਕੀਤਾ" - " ਜਾਵੇਗਾ।" - --#: data/org.gnome.mutter.gschema.xml.in:174 -+#: data/org.gnome.mutter.gschema.xml.in:177 - msgid "Switch monitor configurations" - msgstr "ਮਾਨੀਟਰ ਸੰਰਚਨਾ ਨੂੰ ਬਦਲੋ" - --#: data/org.gnome.mutter.gschema.xml.in:179 -+#: data/org.gnome.mutter.gschema.xml.in:182 - msgid "Rotates the built-in monitor configuration" - msgstr "ਬਿਲਟ-ਇਨ ਮਾਨੀਟਰ ਸੰਰਚਨਾ ਨੂੰ ਘੁੰਮਾਓ" - --#: data/org.gnome.mutter.gschema.xml.in:184 -+#: data/org.gnome.mutter.gschema.xml.in:187 - msgid "Cancel any active input capture session" - msgstr "ਕਿਸੇ ਵੀ ਸਰਗਰਮ ਇਨਪੁਟ ਸਕਰੀਨ ਕੈਪਚਰ ਕਰਨ ਵਾਲੇ ਸ਼ੈਸ਼ਨ ਨੂੰ ਰੱਦ ਕਰੋ" - -@@ -614,7 +615,8 @@ msgstr "" - msgid "Allow X11 clients with a different endianness to connect to Xwayland" - msgstr "" - "ਵੱਖਰੀ ਏਂਡੀਨੈਸਸ (endianess) ਵਾਲੇ X11 ਵਾਲੇ ਕਲਾਈਂਟਾਂ ਨੂੰ Xwayland ਨਾਲ ਕਨੈਕਟ ਹੋਣ" --" ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ" -+" ਦੀ ਇਜਾਜ਼ਤ " -+"ਦਿਓ" - - #: data/org.gnome.mutter.wayland.gschema.xml.in:131 - msgid "" -@@ -629,26 +631,26 @@ msgid "" - "take effect." - msgstr "" - --#: src/backends/meta-monitor.c:253 -+#: src/backends/meta-monitor.c:251 - msgid "Built-in display" - msgstr "ਬਿਲਟ-ਇਨ ਡਿਸਪਲੇਅ" - --#: src/backends/meta-monitor.c:280 -+#: src/backends/meta-monitor.c:278 - msgid "Unknown" - msgstr "ਅਣਜਾਣ" - --#: src/backends/meta-monitor.c:282 -+#: src/backends/meta-monitor.c:280 - msgid "Unknown Display" - msgstr "ਅਣਜਾਣ ਡਿਸਪਲੇਅ" - --#: src/backends/meta-monitor.c:290 -+#: src/backends/meta-monitor.c:288 - #, c-format - msgctxt "" - "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" - msgid "%s %s" - msgstr "%s %s" - --#: src/backends/meta-monitor.c:298 -+#: src/backends/meta-monitor.c:296 - #, c-format - msgctxt "" - "This is a monitor vendor name followed by product/model name where size in " -@@ -660,78 +662,82 @@ msgstr "%s %s" - msgid "Bell event" - msgstr "ਘੰਟੀ ਈਵੈਂਟ" - --#: src/core/display.c:718 -+#: src/core/display.c:734 - msgid "Privacy Screen Enabled" - msgstr "ਪਰਦੇਦਾਰੀ ਸਕਰੀਨ ਸਮਰੱਥ ਹੈ" - --#: src/core/display.c:719 -+#: src/core/display.c:735 - msgid "Privacy Screen Disabled" - msgstr "ਪਰਦੇਦਾਰੀ ਸਕਰੀਨ ਅਸਮਰੱਥ ਹੈ" - --#: src/core/meta-context-main.c:581 -+#: src/core/meta-context-main.c:601 - msgid "Replace the running window manager" - msgstr "ਚੱਲ ਰਹੇ ਵਿੰਡੋ ਮੈਨੇਜਰ ਨੂੰ ਬਦਲੋ" - --#: src/core/meta-context-main.c:587 -+#: src/core/meta-context-main.c:607 - msgid "X Display to use" - msgstr "ਵਰਤਣ ਲਈ X ਡਿਸਪਲੇਅ" - --#: src/core/meta-context-main.c:593 -+#: src/core/meta-context-main.c:613 - msgid "Disable connection to session manager" - msgstr "ਸ਼ੈਸ਼ਨ ਮੈਨੇਜਰ ਨਾਲ ਕੁਨੈਕਸ਼ਨ ਅਯੋਗ" - --#: src/core/meta-context-main.c:599 -+#: src/core/meta-context-main.c:619 - msgid "Specify session management ID" - msgstr "ਸ਼ੈਸ਼ਨ ਪਰਬੰਧਨ ID ਦਿਓ" - --#: src/core/meta-context-main.c:605 -+#: src/core/meta-context-main.c:625 - msgid "Initialize session from savefile" - msgstr "ਸੰਭਾਲੀ ਫਾਇਲ ਤੋਂ ਸ਼ੈਸ਼ਨ ਸ਼ੁਰੂ" - --#: src/core/meta-context-main.c:611 -+#: src/core/meta-context-main.c:631 - msgid "Make X calls synchronous" - msgstr "X ਕਾਲ ਸੈਕਰੋਨਸ ਬਣਾਓ" - --#: src/core/meta-context-main.c:619 -+#: src/core/meta-context-main.c:639 - msgid "Run as a wayland compositor" - msgstr "ਵੇਲੈਂਡ ਕੰਪੋਜ਼ਰ ਵਜੋਂ ਚਲਾਓ" - --#: src/core/meta-context-main.c:625 -+#: src/core/meta-context-main.c:645 - msgid "Run as a nested compositor" - msgstr "ਨੈਸਟਡ ਕੰਪੋਜ਼ਰ ਵਜੋਂ ਚਲਾਓ" - --#: src/core/meta-context-main.c:631 -+#: src/core/meta-context-main.c:651 - msgid "Run wayland compositor without starting Xwayland" - msgstr "Xwayland ਸ਼ੁਰੂ ਕੀਤੇ ਬਿਨਾਂ ਵੇਲੈਂਡ ਕੰਪੋਜ਼ੀਟਰ ਚਲਾਓ" - --#: src/core/meta-context-main.c:637 -+#: src/core/meta-context-main.c:657 - msgid "Specify Wayland display name to use" - msgstr "ਵਰਤਣ ਲਈ ਵੇਅਲੈਂਡ ਡਿਸਪਲੇਅ ਨਾਂ ਦਿਓ" - --#: src/core/meta-context-main.c:645 -+#: src/core/meta-context-main.c:665 - msgid "Run as a full display server, rather than nested" - msgstr "ਅੰਦਰੂਨੀ ਰੂਪ ਵਿੱਚ ਚਲਾਉਣ ਦੀ ਬਜਾਏ ਪੂਰੇ ਡਿਸਪਲੇਅ ਸਰਵਰ ਵਜੋਂ ਚਲਾਓ" - --#: src/core/meta-context-main.c:650 -+#: src/core/meta-context-main.c:670 - msgid "Run as a headless display server" - msgstr "ਹੈੱਡਲੈੱਸ ਡਿਸਪਲੇਅ ਸਰਵਰ ਵਜੋਂ ਚਲਾਓ" - --#: src/core/meta-context-main.c:655 -+#: src/core/meta-context-main.c:675 - msgid "Add persistent virtual monitor (WxH or WxH@R)" - msgstr "ਸਥਿਰ ਵਰਚੁਅਲ ਮਾਨੀਟਰ ਜੋੜੋ (WxH or WxH@R)" - --#: src/core/meta-context-main.c:667 -+#: src/core/meta-context-main.c:687 - msgid "Run with X11 backend" - msgstr "X11 ਬੈਕਐਡ ਨਾਲ ਚਲਾਓ" - --#: src/core/meta-context-main.c:673 -+#: src/core/meta-context-main.c:693 - msgid "Profile performance using trace instrumentation" - msgstr "ਟਰੇਸ ਸਾਧਨ ਵਰਤ ਕੇ ਕਾਰਗੁਜ਼ਾਰੀ ਦਾ ਪਰੋਫ਼ਾਇਲ ਬਣਾਓ" - -+#: src/core/meta-context-main.c:699 -+msgid "Enable debug control D-Bus interface" -+msgstr "ਡੀਬੱਗ ਕੰਟਰੋਲ ਡੀ-ਬੱਸ ਇੰਟਰਫੇਸ ਸਮਰੱਥ ਕਰੋ" -+ - #. TRANSLATORS: This string refers to a button that switches between - #. * different modes. - #. --#: src/core/meta-pad-action-mapper.c:861 -+#: src/core/meta-pad-action-mapper.c:826 - #, c-format - msgid "Mode Switch (Group %d)" - msgstr "ਮੋਡ ਬਦਲੋ (ਗਰੁੱਪ %d)" -@@ -739,16 +745,16 @@ msgstr "ਮੋਡ ਬਦਲੋ (ਗਰੁੱਪ %d)" - #. TRANSLATORS: This string refers to an action, cycles drawing tablets' - #. * mapping through the available outputs. - #. --#: src/core/meta-pad-action-mapper.c:884 -+#: src/core/meta-pad-action-mapper.c:848 - msgid "Switch monitor" - msgstr "ਮਾਨੀਟਰ ਨੂੰ ਬਦਲੋ" - --#: src/core/meta-pad-action-mapper.c:886 -+#: src/core/meta-pad-action-mapper.c:850 - msgid "Show on-screen help" - msgstr "ਆਨ-ਸਕਰੀਨ ਮਦਦ ਵੇਖੋ" - - #. Translators: this string will appear in Sysprof --#: src/core/meta-profiler.c:111 src/core/meta-profiler.c:301 -+#: src/core/meta-profiler.c:109 src/core/meta-profiler.c:299 - msgid "Compositor" - msgstr "ਕੰਪੋਜੀਟਰ" - -@@ -760,7 +766,7 @@ msgstr "ਵਰਜਨ ਛਾਪੋ" - msgid "Mutter plugin to use" - msgstr "ਵਰਤਣ ਲਈ ਮੁੱਟਰ ਪਲੱਗਇਨ" - --#: src/core/prefs.c:1843 -+#: src/core/prefs.c:1842 - #, c-format - msgid "Workspace %d" - msgstr "ਵਰਕਸਪੇਸ %d" -@@ -769,17 +775,16 @@ msgstr "ਵਰਕਸਪੇਸ %d" - msgid "Mutter was compiled without support for verbose mode" - msgstr "ਮੱਟਰ, ਵਰਬੋਜ਼ ਮੋਡ ਲਈ ਸਹਾਰੇ ਤੋਂ ਬਿਨਾਂ ਕੰਪਾਇਲ ਹੋਇਆ" - --#: src/core/workspace.c:541 --#| msgid "Workspace %s%d" -+#: src/core/workspace.c:510 - msgid "Workspace switched" - msgstr "ਵਰਕਸਪੇਸ ਬਦਲਿਆ" - --#: src/wayland/meta-wayland-tablet-pad.c:530 -+#: src/wayland/meta-wayland-tablet-pad.c:532 - #, c-format - msgid "Mode Switch: Mode %d" - msgstr "ਮੋਡ ਬਦਲੋ: ਮੋਡ %d" - --#: src/x11/meta-x11-display.c:708 -+#: src/x11/meta-x11-display.c:723 - #, c-format - msgid "" - "Display “%s” already has a window manager; try using the --replace option to " -@@ -789,19 +794,19 @@ msgstr "" - " ਬਦਲਣ ਲਈ --replace ਚੋਣ " - "ਵਰਤ ਕੇ ਦੇਖੋ।" - --#: src/x11/meta-x11-display.c:1073 -+#: src/x11/meta-x11-display.c:1088 - #, c-format - msgid "Failed to open X Window System display “%s”" - msgstr "X ਵਿੰਡੋ ਸਿਸਟਮ ਡਿਸਪਲੇਅ ”%s” ਨੂੰ ਖੋਲਣ ਵਿੱਚ ਅਸਮਰਥ" - --#: src/x11/meta-x11-display.c:1219 -+#: src/x11/meta-x11-display.c:1268 - #, c-format - msgid "Screen %d on display “%s” is invalid" - msgstr "ਡਿਸਪਲੇਅ ”%2$s” ਉੱਤੇ ਸਕਰੀਨ %1$d ਗਲਤ ਹੈ" - - #. This probably means that a non-WM compositor like xcompmgr is running; - #. * we have no way to get it to exit --#: src/x11/meta-x11-display.c:2550 -+#: src/x11/meta-x11-display.c:2538 - #, c-format - msgid "" - "Another compositing manager is already running on screen %i on display “%s”." -@@ -814,7 +819,7 @@ msgstr "" - msgid "Format %s not supported" - msgstr "ਫਾਰਮੈਟ %s ਸਹਾਇਕ ਨਹੀਂ ਹੈ" - --#: src/x11/window-props.c:548 -+#: src/x11/window-props.c:528 - #, c-format - msgid "%s (on %s)" - msgstr "%s (%s ਉੱਤੇ)" -@@ -2463,3 +2468,4 @@ msgstr "%s (%s ਉੱਤੇ)" - - #~ msgid "Theme file %s did not contain a root element" - #~ msgstr "ਥੀਮ ਫਾਇਲ %s root ਐਲੀਮੈਂਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਨਹੀਂ ਸੀ" -+ -diff --git a/src/backends/meta-color-device.c b/src/backends/meta-color-device.c -index 3032d34c2..0d6cf40db 100644 ---- a/src/backends/meta-color-device.c -+++ b/src/backends/meta-color-device.c -@@ -963,56 +963,62 @@ static void - create_device_profile_from_edid (MetaColorDevice *color_device, - GTask *task) - { -- const MetaEdidInfo *edid_info; -+ const MetaEdidInfo *edid_info = -+ meta_monitor_get_edid_info (color_device->monitor); -+ GenerateProfileData *data = g_task_get_task_data (task); -+ g_autoptr (CdIcc) cd_icc = NULL; -+ g_autoptr (GBytes) bytes = NULL; -+ g_autofree char *file_md5_checksum = NULL; -+ g_autoptr (GError) error = NULL; - -- edid_info = meta_monitor_get_edid_info (color_device->monitor); - if (edid_info) - { -- g_autoptr (CdIcc) cd_icc = NULL; -- GBytes *bytes; -- g_autoptr (GError) error = NULL; -- GenerateProfileData *data = g_task_get_task_data (task); -- const char *file_path = data->file_path; -- g_autofree char *file_md5_checksum = NULL; -- - meta_topic (META_DEBUG_COLOR, - "Generating ICC profile for '%s' from EDID", - meta_color_device_get_id (color_device)); - - cd_icc = create_icc_profile_from_edid (color_device, -- edid_info, file_path, -+ edid_info, data->file_path, - &error); -- if (!cd_icc) -- { -- g_task_return_error (task, g_steal_pointer (&error)); -- g_object_unref (task); -- return; -- } -+ } -+ else -+ { -+ meta_topic (META_DEBUG_COLOR, -+ "Generating sRGB ICC profile for '%s' because EDID is missing", -+ meta_color_device_get_id (color_device)); - -- bytes = cd_icc_save_data (cd_icc, CD_ICC_SAVE_FLAGS_NONE, &error); -- if (!bytes) -- { -- g_task_return_error (task, g_steal_pointer (&error)); -- g_object_unref (task); -- return; -- } -+ cd_icc = cd_icc_new (); - -- file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes); -- cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, -- file_md5_checksum); -+ if (!cd_icc_create_default_full (cd_icc, -+ CD_ICC_LOAD_FLAGS_PRIMARIES, -+ &error)) -+ g_clear_object (&cd_icc); -+ } - -- data->color_calibration = -- meta_color_calibration_new (cd_icc, NULL); -- data->cd_icc = g_steal_pointer (&cd_icc); -- data->bytes = bytes; -- save_icc_profile (file_path, task); -+ if (!cd_icc) -+ { -+ g_task_return_error (task, g_steal_pointer (&error)); -+ g_object_unref (task); -+ return; - } -- else -+ -+ bytes = cd_icc_save_data (cd_icc, CD_ICC_SAVE_FLAGS_NONE, &error); -+ if (!bytes) - { -- g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, -- "No EDID available"); -+ g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); -+ return; - } -+ -+ file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes); -+ cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, -+ file_md5_checksum); -+ -+ data->color_calibration = -+ meta_color_calibration_new (cd_icc, NULL); -+ data->cd_icc = g_steal_pointer (&cd_icc); -+ data->bytes = g_steal_pointer (&bytes); -+ save_icc_profile (data->file_path, task); - } - - static void -diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c -index 7aa24439d..727e1a5f3 100644 ---- a/src/backends/meta-stage-impl.c -+++ b/src/backends/meta-stage-impl.c -@@ -774,6 +774,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, - { - g_autoptr (GError) error = NULL; - -+ clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED); -+ - if (meta_stage_impl_scanout_view (stage_impl, - stage_view, - scanout, -diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c -index 588caab28..83458cfe6 100644 ---- a/src/backends/native/meta-cursor-renderer-native.c -+++ b/src/backends/native/meta-cursor-renderer-native.c -@@ -454,7 +454,8 @@ create_cursor_drm_buffer_gbm (MetaGpuKms *gpu_kms, - GError **error) - { - struct gbm_bo *bo; -- uint8_t buf[4 * cursor_width * cursor_height]; -+ uint32_t bo_stride; -+ uint8_t *buf; - int i; - MetaDrmBufferFlags flags; - MetaDrmBufferGbm *buffer_gbm; -@@ -476,10 +477,16 @@ create_cursor_drm_buffer_gbm (MetaGpuKms *gpu_kms, - return NULL; - } - -- memset (buf, 0, sizeof (buf)); -+ bo_stride = gbm_bo_get_stride (bo); -+ buf = g_alloca0 (bo_stride * cursor_height); -+ - for (i = 0; i < height; i++) -- memcpy (buf + i * 4 * cursor_width, pixels + i * stride, width * 4); -- if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0) -+ { -+ memcpy (buf + i * bo_stride, -+ pixels + i * stride, -+ MIN (bo_stride, stride)); -+ } -+ if (gbm_bo_write (bo, buf, bo_stride * cursor_height) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Failed write to gbm_bo: %s", g_strerror (errno)); -diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c -index 161d43957..4ca8fb0f4 100644 ---- a/src/backends/native/meta-drm-buffer-gbm.c -+++ b/src/backends/native/meta-drm-buffer-gbm.c -@@ -186,7 +186,7 @@ lock_front_buffer (MetaDrmBufferGbm *buffer_gbm, - return FALSE; - } - -- return meta_drm_buffer_gbm_ensure_fb_id (META_DRM_BUFFER (buffer_gbm), error); -+ return TRUE; - } - - MetaDrmBufferGbm * -diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c -index a109b4ea2..30bbfb59a 100644 ---- a/src/backends/native/meta-drm-buffer.c -+++ b/src/backends/native/meta-drm-buffer.c -@@ -28,7 +28,7 @@ - - #include "backends/native/meta-device-pool.h" - #include "backends/native/meta-kms-utils.h" --#include "common/meta-cogl-drm-formats.h" -+#include "common/meta-drm-format-helpers.h" - - #include "meta-private-enum-types.h" - -diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c -index b15eee14d..05bc89e83 100644 ---- a/src/backends/native/meta-kms-impl-device.c -+++ b/src/backends/native/meta-kms-impl-device.c -@@ -1559,9 +1559,11 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, - meta_kms_update_merge_from (crtc_frame->pending_update, update); - meta_kms_update_free (update); - update = g_steal_pointer (&crtc_frame->pending_update); -- disarm_crtc_frame_deadline_timer (crtc_frame); - } - -+ if (crtc_frame->deadline.armed) -+ disarm_crtc_frame_deadline_timer (crtc_frame); -+ - meta_kms_device_handle_flush (priv->device, latch_crtc); - - feedback = do_process (impl_device, latch_crtc, update, flags); -diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c -index 795008b21..70d1e792c 100644 ---- a/src/backends/native/meta-kms.c -+++ b/src/backends/native/meta-kms.c -@@ -63,6 +63,8 @@ struct _MetaKms - int kernel_thread_inhibit_count; - - MetaKmsCursorManager *cursor_manager; -+ -+ gboolean shutting_down; - }; - - G_DEFINE_TYPE (MetaKms, meta_kms, META_TYPE_THREAD) -@@ -354,6 +356,7 @@ static void - on_prepare_shutdown (MetaBackend *backend, - MetaKms *kms) - { -+ kms->shutting_down = TRUE; - meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); - meta_thread_flush_callbacks (META_THREAD (kms)); - -@@ -408,6 +411,12 @@ meta_kms_new (MetaBackend *backend, - return kms; - } - -+gboolean -+meta_kms_is_shutting_down (MetaKms *kms) -+{ -+ return kms->shutting_down; -+} -+ - static void - meta_kms_finalize (GObject *object) - { -diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h -index 743401406..f6b19520b 100644 ---- a/src/backends/native/meta-kms.h -+++ b/src/backends/native/meta-kms.h -@@ -60,6 +60,8 @@ MetaKmsDevice * meta_kms_create_device (MetaKms *kms, - MetaKmsDeviceFlag flags, - GError **error); - -+gboolean meta_kms_is_shutting_down (MetaKms *kms); -+ - MetaKms * meta_kms_new (MetaBackend *backend, - MetaKmsFlags flags, - GError **error); -diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 2710352d1..9836663d0 100644 ---- a/src/backends/native/meta-onscreen-native.c -+++ b/src/backends/native/meta-onscreen-native.c -@@ -51,6 +51,7 @@ - #include "backends/native/meta-renderer-native-private.h" - #include "cogl/cogl.h" - #include "common/meta-cogl-drm-formats.h" -+#include "common/meta-drm-format-helpers.h" - - typedef enum _MetaSharedFramebufferImportStatus - { -@@ -75,7 +76,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState - - struct { - MetaDrmBufferDumb *current_dumb_fb; -- MetaDrmBufferDumb *dumb_fbs[2]; -+ MetaDrmBufferDumb *dumb_fbs[3]; - } cpu; - - gboolean noted_primary_gpu_copy_ok; -@@ -97,9 +98,13 @@ struct _MetaOnscreenNative - struct { - struct gbm_surface *surface; - MetaDrmBuffer *current_fb; -+ MetaDrmBuffer *posted_fb; - MetaDrmBuffer *next_fb; -+ MetaDrmBuffer *stalled_fb; - CoglScanout *current_scanout; -+ CoglScanout *posted_scanout; - CoglScanout *next_scanout; -+ CoglScanout *stalled_scanout; - } gbm; - - #ifdef HAVE_EGL_DEVICE -@@ -124,6 +129,16 @@ struct _MetaOnscreenNative - gulong privacy_screen_changed_handler_id; - gulong color_space_changed_handler_id; - gulong hdr_metadata_changed_handler_id; -+ -+ gboolean needs_flush; -+ -+ unsigned int swaps_pending; -+ -+ struct { -+ int *rectangles; /* 4 x n_rectangles */ -+ int n_rectangles; -+ ClutterFrame *frame; -+ } next_post; - }; - - G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, -@@ -131,44 +146,42 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, - - static GQuark blit_source_quark = 0; - -+static void -+try_post_latest_swap (CoglOnscreen *onscreen); -+ -+static void -+post_finish_frame (MetaOnscreenNative *onscreen_native, -+ MetaKmsUpdate *kms_update); -+ - static gboolean - init_secondary_gpu_state (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - GError **error); - --static void --free_current_bo (CoglOnscreen *onscreen) --{ -- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -- -- g_clear_object (&onscreen_native->gbm.current_fb); -- g_clear_object (&onscreen_native->gbm.current_scanout); --} -- - static void - meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) - { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - -- if (!onscreen_native->gbm.next_fb) -+ if (!onscreen_native->gbm.posted_fb) - return; - -- free_current_bo (onscreen); -+ g_set_object (&onscreen_native->gbm.current_fb, -+ onscreen_native->gbm.posted_fb); -+ g_clear_object (&onscreen_native->gbm.posted_fb); - -- g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); -- g_clear_object (&onscreen_native->gbm.next_fb); - g_set_object (&onscreen_native->gbm.current_scanout, -- onscreen_native->gbm.next_scanout); -- g_clear_object (&onscreen_native->gbm.next_scanout); -+ onscreen_native->gbm.posted_scanout); -+ g_clear_object (&onscreen_native->gbm.posted_scanout); - } - - static void --meta_onscreen_native_clear_next_fb (CoglOnscreen *onscreen) -+meta_onscreen_native_clear_posted_fb (CoglOnscreen *onscreen) - { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - -- g_clear_object (&onscreen_native->gbm.next_fb); -- g_clear_object (&onscreen_native->gbm.next_scanout); -+ g_clear_object (&onscreen_native->gbm.posted_fb); -+ g_clear_object (&onscreen_native->gbm.posted_scanout); - } - - static void -@@ -206,7 +219,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) - - info = cogl_onscreen_pop_head_frame_info (onscreen); - -- g_assert (!cogl_onscreen_peek_head_frame_info (onscreen)); -+ g_return_if_fail (info); - - _cogl_onscreen_notify_frame_sync (onscreen, info); - _cogl_onscreen_notify_complete (onscreen, info); -@@ -242,6 +255,7 @@ notify_view_crtc_presented (MetaRendererView *view, - - meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); -+ try_post_latest_swap (onscreen); - } - - static void -@@ -291,15 +305,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); -- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglFrameInfo *frame_info; - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - -- g_warn_if_fail (!onscreen_native->gbm.next_fb); -- - meta_onscreen_native_notify_frame_complete (onscreen); -+ try_post_latest_swap (onscreen); - } - - static void -@@ -349,7 +361,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); -- meta_onscreen_native_clear_next_fb (onscreen); -+ meta_onscreen_native_clear_posted_fb (onscreen); -+ try_post_latest_swap (onscreen); - } - - static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -410,18 +423,41 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, - } - #endif /* HAVE_EGL_DEVICE */ - --void --meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) -+static void -+drop_stalled_swap (CoglOnscreen *onscreen) - { - CoglFrameInfo *frame_info; -+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - -- meta_onscreen_native_swap_drm_fb (onscreen); -+ /* Remember we can't compare stalled_fb because it's not used by -+ * META_RENDERER_NATIVE_MODE_EGL_DEVICE. So we judge stalled to be whenever -+ * swaps_pending > 1. -+ */ -+ if (onscreen_native->swaps_pending <= 1) -+ return; -+ -+ onscreen_native->swaps_pending--; -+ -+ g_clear_object (&onscreen_native->gbm.stalled_fb); -+ g_clear_object (&onscreen_native->gbm.stalled_scanout); - - frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - meta_onscreen_native_notify_frame_complete (onscreen); - } - -+void -+meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) -+{ -+ drop_stalled_swap (onscreen); -+ -+ /* If the monitor just woke up and the shell is fully idle (has nothing -+ * more to swap) then we just woke to an indefinitely black screen. Let's -+ * fix that using the last swap (which is never classified as "stalled"). -+ */ -+ try_post_latest_swap (onscreen); -+} -+ - static void - apply_transform (MetaCrtcKms *crtc_kms, - MetaKmsPlaneAssignment *kms_plane_assignment, -@@ -505,6 +541,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, - MetaGpuKms *gpu_kms; - MetaDrmBuffer *buffer; - MetaKmsPlaneAssignment *plane_assignment; -+ graphene_rect_t src_rect; -+ MtkRectangle dst_rect; - - COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, - "Meta::OnscreenNative::flip_crtc()"); -@@ -518,16 +556,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: -- graphene_rect_t src_rect; -- MtkRectangle dst_rect; -+ g_set_object (&onscreen_native->gbm.posted_fb, -+ onscreen_native->gbm.next_fb); -+ g_clear_object (&onscreen_native->gbm.next_fb); -+ -+ buffer = onscreen_native->gbm.posted_fb; - -- buffer = onscreen_native->gbm.next_fb; -+ g_set_object (&onscreen_native->gbm.posted_scanout, -+ onscreen_native->gbm.next_scanout); -+ g_clear_object (&onscreen_native->gbm.next_scanout); - -- if (onscreen_native->gbm.next_scanout) -+ if (onscreen_native->gbm.posted_scanout) - { -- cogl_scanout_get_src_rect (onscreen_native->gbm.next_scanout, -+ cogl_scanout_get_src_rect (onscreen_native->gbm.posted_scanout, - &src_rect); -- cogl_scanout_get_dst_rect (onscreen_native->gbm.next_scanout, -+ cogl_scanout_get_dst_rect (onscreen_native->gbm.posted_scanout, - &dst_rect); - } - else -@@ -918,12 +961,17 @@ static MetaDrmBufferDumb * - secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) - { - MetaDrmBufferDumb *current_dumb_fb; -+ const int n_dumb_fbs = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); -+ int i; - - current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb; -- if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0]) -- return secondary_gpu_state->cpu.dumb_fbs[1]; -- else -- return secondary_gpu_state->cpu.dumb_fbs[0]; -+ for (i = 0; i < n_dumb_fbs; i++) -+ { -+ if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[i]) -+ return secondary_gpu_state->cpu.dumb_fbs[(i + 1) % n_dumb_fbs]; -+ } -+ -+ return secondary_gpu_state->cpu.dumb_fbs[0]; - } - - static MetaDrmBuffer * -@@ -1255,10 +1303,17 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, - g_warning ("Page flip failed: %s", error->message); - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); -- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - -- meta_onscreen_native_notify_frame_complete (onscreen); -- meta_onscreen_native_clear_next_fb (onscreen); -+ /* After resuming from suspend, drop_stalled_swap might have done this -+ * already and emptied the frame_info queue. -+ */ -+ if (frame_info) -+ { -+ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; -+ meta_onscreen_native_notify_frame_complete (onscreen); -+ } -+ -+ meta_onscreen_native_clear_posted_fb (onscreen); - } - - static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1279,35 +1334,58 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; -- MetaRenderer *renderer = META_RENDERER (renderer_native); -- MetaBackend *backend = meta_renderer_get_backend (renderer); -- MetaMonitorManager *monitor_manager = -- meta_backend_get_monitor_manager (backend); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -+ MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - MetaDeviceFile *render_device_file; - ClutterFrame *frame = user_data; -- MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); -- MetaKmsUpdate *kms_update; - CoglOnscreenClass *parent_class; -+ gboolean create_timestamp_query = TRUE; - gboolean egl_context_changed = FALSE; -- MetaPowerSave power_save_mode; - g_autoptr (GError) error = NULL; - MetaDrmBufferFlags buffer_flags; - MetaDrmBufferGbm *buffer_gbm; - g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL; - g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; -- MetaKmsCrtc *kms_crtc; -- MetaKmsDevice *kms_device; -+ size_t rectangles_size; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, - "Meta::OnscreenNative::swap_buffers_with_damage()"); - -+ if (meta_is_topic_enabled (META_DEBUG_KMS)) -+ { -+ unsigned int frames_pending = -+ cogl_onscreen_count_pending_frames (onscreen); -+ -+ meta_topic (META_DEBUG_KMS, -+ "Swap buffers: %u frames pending (%s-buffering)", -+ frames_pending, -+ frames_pending == 1 ? "double" : -+ frames_pending == 2 ? "triple" : -+ "?"); -+ } -+ - secondary_gpu_fb = - update_secondary_gpu_state_pre_swap_buffers (onscreen, - rectangles, - n_rectangles); - -+ secondary_gpu_state = onscreen_native->secondary_gpu_state; -+ if (secondary_gpu_state) -+ { -+ MetaRendererNativeGpuData *secondary_gpu_data; -+ -+ secondary_gpu_data = -+ meta_renderer_native_get_gpu_data (renderer_native, -+ secondary_gpu_state->gpu_kms); -+ if (secondary_gpu_data->secondary.copy_mode == -+ META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU) -+ create_timestamp_query = FALSE; -+ } -+ -+ if (create_timestamp_query) -+ cogl_onscreen_egl_maybe_create_timestamp_query (onscreen, frame_info); -+ - parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); - parent_class->swap_buffers_with_damage (onscreen, - rectangles, -@@ -1361,11 +1439,32 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: -- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); -+ if (onscreen_native->gbm.next_fb != NULL) -+ { -+ g_warn_if_fail (onscreen_native->gbm.stalled_fb == NULL); -+ drop_stalled_swap (onscreen); -+ g_assert (onscreen_native->gbm.stalled_fb == NULL); -+ onscreen_native->gbm.stalled_fb = -+ g_steal_pointer (&onscreen_native->gbm.next_fb); -+ onscreen_native->gbm.stalled_scanout = -+ g_steal_pointer (&onscreen_native->gbm.next_scanout); -+ } -+ - if (onscreen_native->secondary_gpu_state) - g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); - else - g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb); -+ -+ if (!meta_drm_buffer_ensure_fb_id (onscreen_native->gbm.next_fb, &error)) -+ { -+ g_warning ("Failed to ensure KMS FB ID on %s: %s", -+ meta_device_file_get_path (render_device_file), -+ error->message); -+ -+ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; -+ meta_onscreen_native_notify_frame_complete (onscreen); -+ return; -+ } - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - break; -@@ -1375,6 +1474,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - #endif - } - -+ clutter_frame_set_result (frame, -+ CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -+ - /* - * If we changed EGL context, cogl will have the wrong idea about what is - * current, making it fail to set it when it needs to. Avoid that by making -@@ -1384,12 +1486,78 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - if (egl_context_changed) - _cogl_winsys_egl_ensure_current (cogl_display); - -- kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); -- kms_device = meta_kms_crtc_get_device (kms_crtc); -+ rectangles_size = n_rectangles * 4 * sizeof (int); -+ onscreen_native->next_post.rectangles = -+ g_realloc (onscreen_native->next_post.rectangles, rectangles_size); -+ memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size); -+ onscreen_native->next_post.n_rectangles = n_rectangles; -+ -+ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); -+ onscreen_native->next_post.frame = clutter_frame_ref (frame); -+ -+ onscreen_native->swaps_pending++; -+ try_post_latest_swap (onscreen); -+} -+ -+static void -+try_post_latest_swap (CoglOnscreen *onscreen) -+{ -+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); -+ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); -+ CoglRenderer *cogl_renderer = cogl_context->display->renderer; -+ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; -+ MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; -+ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; -+ MetaRenderer *renderer = META_RENDERER (renderer_native); -+ MetaBackend *backend = meta_renderer_get_backend (renderer); -+ MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); -+ MetaKms *kms = meta_backend_native_get_kms (backend_native); -+ MetaMonitorManager *monitor_manager = -+ meta_backend_get_monitor_manager (backend); -+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -+ MetaPowerSave power_save_mode; -+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); -+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); -+ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); -+ MetaKmsUpdate *kms_update; -+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL; -+ g_autoptr (ClutterFrame) frame = NULL; -+ MetaFrameNative *frame_native; -+ -+ if (onscreen_native->next_post.frame == NULL || -+ onscreen_native->view == NULL || -+ meta_kms_is_shutting_down (kms)) -+ return; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode == META_POWER_SAVE_ON) - { -+ unsigned int frames_pending = -+ cogl_onscreen_count_pending_frames (onscreen); -+ unsigned int posts_pending; -+ -+ g_assert (frames_pending >= onscreen_native->swaps_pending); -+ posts_pending = frames_pending - onscreen_native->swaps_pending; -+ if (posts_pending > 0) -+ return; /* wait for the next frame notification and then try again */ -+ -+ frame = g_steal_pointer (&onscreen_native->next_post.frame); -+ frame_native = meta_frame_native_from_frame (frame); -+ -+ if (onscreen_native->swaps_pending == 0) -+ { -+ if (frame_native) -+ { -+ kms_update = meta_frame_native_steal_kms_update (frame_native); -+ if (kms_update) -+ post_finish_frame (onscreen_native, kms_update); -+ } -+ return; -+ } -+ -+ drop_stalled_swap (onscreen); -+ onscreen_native->swaps_pending--; -+ - kms_update = meta_frame_native_ensure_kms_update (frame_native, - kms_device); - meta_kms_update_add_result_listener (kms_update, -@@ -1404,15 +1572,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - onscreen_native->crtc, - kms_update, - META_KMS_ASSIGN_PLANE_FLAG_NONE, -- rectangles, -- n_rectangles); -+ onscreen_native->next_post.rectangles, -+ onscreen_native->next_post.n_rectangles); - } - else - { - meta_renderer_native_queue_power_save_page_flip (renderer_native, - onscreen); -- clutter_frame_set_result (frame, -- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - -@@ -1432,8 +1598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - kms_update = meta_frame_native_steal_kms_update (frame_native); - meta_renderer_native_queue_mode_set_update (renderer_native, - kms_update); -- clutter_frame_set_result (frame, -- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1447,8 +1611,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - - meta_frame_native_steal_kms_update (frame_native); - meta_renderer_native_post_mode_set_updates (renderer_native); -- clutter_frame_set_result (frame, -- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; -@@ -1464,8 +1626,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - kms_update); - - meta_renderer_native_post_mode_set_updates (renderer_native); -- clutter_frame_set_result (frame, -- CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; -@@ -1480,7 +1640,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - kms_update = meta_frame_native_steal_kms_update (frame_native); - meta_kms_device_post_update (kms_device, kms_update, - META_KMS_UPDATE_FLAG_NONE); -- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - } - - gboolean -@@ -1551,7 +1710,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, - - g_warning ("Direct scanout page flip failed: %s", error->message); - -- cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout, -+ cogl_scanout_notify_failed (onscreen_native->gbm.posted_scanout, - onscreen); - clutter_stage_view_add_redraw_clip (view, NULL); - clutter_stage_view_schedule_update_now (view); -@@ -1561,7 +1720,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); -- meta_onscreen_native_clear_next_fb (onscreen); -+ meta_onscreen_native_clear_posted_fb (onscreen); - } - - static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1613,6 +1772,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, - return FALSE; - } - -+ /* Our direct scanout frame counts as 1, so more than that means we would -+ * be jumping the queue (and post would fail). -+ */ -+ if (cogl_onscreen_count_pending_frames (onscreen) > 1) -+ { -+ g_set_error_literal (error, -+ COGL_SCANOUT_ERROR, -+ COGL_SCANOUT_ERROR_INHIBITED, -+ "Direct scanout is inhibited during triple buffering"); -+ return FALSE; -+ } -+ - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - -@@ -1728,11 +1899,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, - ClutterFrame *frame) - { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -- MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); -- MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - -- meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), -- kms_crtc); - maybe_update_frame_sync (onscreen_native, frame); - } - -@@ -1848,22 +2015,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); - MetaKmsUpdate *kms_update; -+ unsigned int frames_pending = cogl_onscreen_count_pending_frames (onscreen); -+ unsigned int swaps_pending = onscreen_native->swaps_pending; -+ unsigned int posts_pending = frames_pending - swaps_pending; - -- kms_update = meta_frame_native_steal_kms_update (frame_native); -- if (!kms_update) -+ onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, -+ kms_crtc); -+ -+ if (!meta_frame_native_has_kms_update (frame_native)) - { -- if (meta_kms_device_handle_flush (kms_device, kms_crtc)) -- { -- kms_update = meta_kms_update_new (kms_device); -- meta_kms_update_set_flushing (kms_update, kms_crtc); -- } -- else -+ if (!onscreen_native->needs_flush || posts_pending) - { - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); - return; - } - } - -+ if (posts_pending && !swaps_pending) -+ { -+ g_return_if_fail (meta_frame_native_has_kms_update (frame_native)); -+ g_warn_if_fail (onscreen_native->next_post.frame == NULL); -+ -+ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); -+ onscreen_native->next_post.frame = clutter_frame_ref (frame); -+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -+ return; -+ } -+ -+ kms_update = meta_frame_native_steal_kms_update (frame_native); -+ -+ if (posts_pending && swaps_pending) -+ { -+ MetaFrameNative *older_frame_native; -+ MetaKmsUpdate *older_kms_update; -+ -+ g_return_if_fail (kms_update); -+ g_return_if_fail (onscreen_native->next_post.frame != NULL); -+ -+ older_frame_native = -+ meta_frame_native_from_frame (onscreen_native->next_post.frame); -+ older_kms_update = -+ meta_frame_native_ensure_kms_update (older_frame_native, kms_device); -+ meta_kms_update_merge_from (older_kms_update, kms_update); -+ meta_kms_update_free (kms_update); -+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); -+ return; -+ } -+ -+ if (!kms_update) -+ { -+ kms_update = meta_kms_update_new (kms_device); -+ g_warn_if_fail (onscreen_native->needs_flush); -+ } -+ -+ if (onscreen_native->needs_flush) -+ { -+ meta_kms_update_set_flushing (kms_update, kms_crtc); -+ onscreen_native->needs_flush = FALSE; -+ } -+ -+ post_finish_frame (onscreen_native, kms_update); -+ -+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -+} -+ -+static void -+post_finish_frame (MetaOnscreenNative *onscreen_native, -+ MetaKmsUpdate *kms_update) -+{ -+ MetaCrtc *crtc = onscreen_native->crtc; -+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); -+ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); -+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL; -+ - meta_kms_update_add_result_listener (kms_update, - &finish_frame_result_listener_vtable, - NULL, -@@ -1886,7 +2110,19 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - meta_kms_update_set_flushing (kms_update, kms_crtc); - meta_kms_device_post_update (kms_device, kms_update, - META_KMS_UPDATE_FLAG_NONE); -- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -+} -+ -+void -+meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen) -+{ -+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -+ -+ onscreen_native->swaps_pending = 0; -+ -+ g_clear_object (&onscreen_native->gbm.stalled_fb); -+ g_clear_object (&onscreen_native->gbm.stalled_scanout); -+ g_clear_object (&onscreen_native->gbm.next_fb); -+ g_clear_object (&onscreen_native->gbm.next_scanout); - } - - static gboolean -@@ -2801,8 +3037,11 @@ meta_onscreen_native_dispose (GObject *object) - { - case META_RENDERER_NATIVE_MODE_GBM: - g_clear_object (&onscreen_native->gbm.next_fb); -+ g_clear_object (&onscreen_native->gbm.posted_fb); -+ g_clear_object (&onscreen_native->gbm.current_fb); - g_clear_object (&onscreen_native->gbm.next_scanout); -- free_current_bo (onscreen); -+ g_clear_object (&onscreen_native->gbm.posted_scanout); -+ g_clear_object (&onscreen_native->gbm.current_scanout); - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); -@@ -2836,6 +3075,10 @@ meta_onscreen_native_dispose (GObject *object) - - g_clear_object (&onscreen_native->output); - g_clear_object (&onscreen_native->crtc); -+ -+ g_clear_pointer (&onscreen_native->next_post.rectangles, g_free); -+ g_clear_pointer (&onscreen_native->next_post.frame, clutter_frame_unref); -+ onscreen_native->next_post.n_rectangles = 0; - } - - static void -diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h -index 0e1193325..e30357d19 100644 ---- a/src/backends/native/meta-onscreen-native.h -+++ b/src/backends/native/meta-onscreen-native.h -@@ -48,6 +48,8 @@ void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); - gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - CoglScanout *scanout); - -+void meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen); -+ - void meta_onscreen_native_set_view (CoglOnscreen *onscreen, - MetaRendererView *view); - -diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c -index 893ee4216..3c22b4e86 100644 ---- a/src/backends/native/meta-renderer-native.c -+++ b/src/backends/native/meta-renderer-native.c -@@ -68,6 +68,7 @@ - #include "backends/native/meta-renderer-view-native.h" - #include "cogl/cogl.h" - #include "common/meta-cogl-drm-formats.h" -+#include "common/meta-drm-format-helpers.h" - #include "core/boxes-private.h" - - #ifdef HAVE_EGL_DEVICE -@@ -730,12 +731,18 @@ static gboolean - dummy_power_save_page_flip_cb (gpointer user_data) - { - MetaRendererNative *renderer_native = user_data; -+ GList *old_list = -+ g_steal_pointer (&renderer_native->power_save_page_flip_onscreens); - -- g_list_foreach (renderer_native->power_save_page_flip_onscreens, -+ g_list_foreach (old_list, - (GFunc) meta_onscreen_native_dummy_power_save_page_flip, - NULL); -- g_clear_list (&renderer_native->power_save_page_flip_onscreens, -+ g_clear_list (&old_list, - g_object_unref); -+ -+ if (renderer_native->power_save_page_flip_onscreens != NULL) -+ return G_SOURCE_CONTINUE; -+ - renderer_native->power_save_page_flip_source_id = 0; - - return G_SOURCE_REMOVE; -@@ -747,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na - { - const unsigned int timeout_ms = 100; - -+ if (g_list_find (renderer_native->power_save_page_flip_onscreens, onscreen)) -+ return; -+ - if (!renderer_native->power_save_page_flip_source_id) - { - renderer_native->power_save_page_flip_source_id = -@@ -1528,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer) - } - } - -+static void -+discard_pending_swaps (MetaRenderer *renderer) -+{ -+ GList *views = meta_renderer_get_views (renderer);; -+ GList *l; -+ -+ for (l = views; l; l = l->next) -+ { -+ ClutterStageView *stage_view = l->data; -+ CoglFramebuffer *fb = clutter_stage_view_get_onscreen (stage_view); -+ CoglOnscreen *onscreen; -+ -+ if (!COGL_IS_ONSCREEN (fb)) -+ continue; -+ -+ onscreen = COGL_ONSCREEN (fb); -+ meta_onscreen_native_discard_pending_swaps (onscreen); -+ } -+} -+ - static void - meta_renderer_native_rebuild_views (MetaRenderer *renderer) - { -@@ -1538,6 +1568,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) - MetaRendererClass *parent_renderer_class = - META_RENDERER_CLASS (meta_renderer_native_parent_class); - -+ discard_pending_swaps (renderer); - meta_kms_discard_pending_page_flips (kms); - g_hash_table_remove_all (renderer_native->mode_set_updates); - -diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c -index 41b78ec18..02eccc77d 100644 ---- a/src/backends/x11/nested/meta-stage-x11-nested.c -+++ b/src/backends/x11/nested/meta-stage-x11-nested.c -@@ -186,6 +186,8 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window, - } - - frame_info = cogl_frame_info_new (context, 0); -+ cogl_onscreen_egl_maybe_create_timestamp_query (stage_x11->onscreen, -+ frame_info); - cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info, frame); - - if (!clutter_frame_has_result (frame)) -diff --git a/src/common/meta-cogl-drm-formats.c b/src/common/meta-cogl-drm-formats.c -index 225d6b537..dee5c5134 100644 ---- a/src/common/meta-cogl-drm-formats.c -+++ b/src/common/meta-cogl-drm-formats.c -@@ -24,40 +24,6 @@ - - #include "common/meta-cogl-drm-formats.h" - -- --/** -- * meta_drm_format_to_string: -- * @tmp: temporary buffer -- * @drm_format: DRM fourcc pixel format -- * -- * Returns a pointer to a string naming the given pixel format, -- * usually a pointer to the temporary buffer but not always. -- * Invalid formats may return nonsense names. -- * -- * When calling this, allocate one MetaDrmFormatBuf on the stack to -- * be used as the temporary buffer. -- */ --const char * --meta_drm_format_to_string (MetaDrmFormatBuf *tmp, -- uint32_t drm_format) --{ -- int i; -- -- if (drm_format == DRM_FORMAT_INVALID) -- return "INVALID"; -- -- G_STATIC_ASSERT (sizeof (tmp->s) == 5); -- for (i = 0; i < 4; i++) -- { -- char c = (drm_format >> (i * 8)) & 0xff; -- tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; -- } -- -- tmp->s[i] = 0; -- -- return tmp->s; --} -- - const MetaFormatInfo * - meta_format_info_from_drm_format (uint32_t drm_format) - { -diff --git a/src/common/meta-cogl-drm-formats.h b/src/common/meta-cogl-drm-formats.h -index dbbc88294..d64bbc241 100644 ---- a/src/common/meta-cogl-drm-formats.h -+++ b/src/common/meta-cogl-drm-formats.h -@@ -29,14 +29,6 @@ - - G_BEGIN_DECLS - --typedef struct _MetaDrmFormatBuf --{ -- char s[5]; --} MetaDrmFormatBuf; -- --const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, -- uint32_t drm_format); -- - typedef struct _MetaFormatInfo - { - uint32_t drm_format; -diff --git a/src/common/meta-drm-format-helpers.c b/src/common/meta-drm-format-helpers.c -new file mode 100644 -index 000000000..0fc28dc7a ---- /dev/null -+++ b/src/common/meta-drm-format-helpers.c -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (C) 2020 Georges Basile Stavracas Neto -+ * Copyright (C) 2023 Collabora Ltd. -+ * -+ * 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 "config.h" -+ -+#include "common/meta-drm-format-helpers.h" -+ -+#include -+#include -+ -+/** -+ * meta_drm_format_to_string: -+ * @tmp: temporary buffer -+ * @drm_format: DRM fourcc pixel format -+ * -+ * Returns a pointer to a string naming the given pixel format, -+ * usually a pointer to the temporary buffer but not always. -+ * Invalid formats may return nonsense names. -+ * -+ * When calling this, allocate one MetaDrmFormatBuf on the stack to -+ * be used as the temporary buffer. -+ */ -+const char * -+meta_drm_format_to_string (MetaDrmFormatBuf *tmp, -+ uint32_t drm_format) -+{ -+ int i; -+ -+ if (drm_format == DRM_FORMAT_INVALID) -+ return "INVALID"; -+ -+ G_STATIC_ASSERT (sizeof (tmp->s) == 5); -+ for (i = 0; i < 4; i++) -+ { -+ char c = (drm_format >> (i * 8)) & 0xff; -+ tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; -+ } -+ -+ tmp->s[i] = 0; -+ -+ return tmp->s; -+} -diff --git a/src/common/meta-drm-format-helpers.h b/src/common/meta-drm-format-helpers.h -new file mode 100644 -index 000000000..53834350f ---- /dev/null -+++ b/src/common/meta-drm-format-helpers.h -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2020 Georges Basile Stavracas Neto -+ * Copyright (C) 2023 Collabora Ltd. -+ * -+ * 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 -+ -+typedef struct _MetaDrmFormatBuf -+{ -+ char s[5]; -+} MetaDrmFormatBuf; -+ -+const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, -+ uint32_t drm_format); -diff --git a/src/compositor/edge-resistance.c b/src/compositor/edge-resistance.c -index f3005714b..338886255 100644 ---- a/src/compositor/edge-resistance.c -+++ b/src/compositor/edge-resistance.c -@@ -29,17 +29,6 @@ - #include "core/meta-workspace-manager-private.h" - #include "core/workspace-private.h" - --/* A simple macro for whether a given window's edges are potentially -- * relevant for resistance/snapping during a move/resize operation -- */ --#define WINDOW_EDGES_RELEVANT(window, display) \ -- meta_window_should_be_showing (window) && \ -- (!meta_compositor_get_current_window_drag (display->compositor) || \ -- window != meta_window_drag_get_window (meta_compositor_get_current_window_drag (display->compositor))) && \ -- window->type != META_WINDOW_DESKTOP && \ -- window->type != META_WINDOW_MENU && \ -- window->type != META_WINDOW_SPLASHSCREEN -- - typedef struct _MetaEdgeResistanceData MetaEdgeResistanceData; - - struct _MetaEdgeResistanceData -@@ -52,6 +41,29 @@ struct _MetaEdgeResistanceData - - static GQuark edge_resistance_data_quark = 0; - -+static gboolean -+is_window_relevant_for_edges (MetaWindow *window) -+{ -+ MetaWindowDrag *drag; -+ -+ if (!meta_window_should_be_showing (window)) -+ return FALSE; -+ -+ drag = meta_compositor_get_current_window_drag (window->display->compositor); -+ if (drag && window == meta_window_drag_get_window (drag)) -+ return FALSE; -+ -+ switch (window->type) -+ { -+ case META_WINDOW_DESKTOP: -+ case META_WINDOW_MENU: -+ case META_WINDOW_SPLASHSCREEN: -+ return FALSE; -+ default: -+ return TRUE; -+ } -+} -+ - /* !WARNING!: this function can return invalid indices (namely, either -1 or - * edges->len); this is by design, but you need to remember this. - */ -@@ -879,12 +891,13 @@ static MetaEdgeResistanceData * - compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - { - MetaEdgeResistanceData *edge_data; -- GList *stacked_windows; -- GList *cur_window_iter; -- GList *edges; -+ GList *l; - /* Lists of window positions (rects) and their relative stacking positions */ - int stack_position; -- GSList *obscuring_windows, *window_stacking; -+ g_autoslist (MtkRectangle) obscuring_windows = NULL; -+ g_autoptr (GList) stacked_windows = NULL; -+ g_autoptr (GSList) window_stacking = NULL; -+ g_autoptr (GList) edges = NULL; - /* The portions of the above lists that still remain at the stacking position - * in the layer that we are working on - */ -@@ -910,16 +923,16 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - * those below it instead of going both ways, we also need to keep a - * counter list. Messy, I know. - */ -- obscuring_windows = window_stacking = NULL; -- cur_window_iter = stacked_windows; - stack_position = 0; -- while (cur_window_iter != NULL) -+ for (l = stacked_windows; l; l = l->next) - { -- MetaWindow *cur_window = cur_window_iter->data; -- if (WINDOW_EDGES_RELEVANT (cur_window, display)) -+ MetaWindow *cur_window = l->data; -+ -+ if (is_window_relevant_for_edges (cur_window)) - { - MtkRectangle *new_rect; -- new_rect = g_new (MtkRectangle, 1); -+ -+ new_rect = mtk_rectangle_new_empty (); - meta_window_get_frame_rect (cur_window, new_rect); - obscuring_windows = g_slist_prepend (obscuring_windows, new_rect); - window_stacking = -@@ -927,7 +940,6 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - } - - stack_position++; -- cur_window_iter = cur_window_iter->next; - } - /* Put 'em in bottom to top order */ - rem_windows = obscuring_windows = g_slist_reverse (obscuring_windows); -@@ -940,18 +952,17 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - */ - edges = NULL; - stack_position = 0; -- cur_window_iter = stacked_windows; -- while (cur_window_iter != NULL) -+ for (l = stacked_windows; l; l = l->next) - { -+ MetaWindow *cur_window = l->data; - MtkRectangle cur_rect; -- MetaWindow *cur_window = cur_window_iter->data; - meta_window_get_frame_rect (cur_window, &cur_rect); - - /* Check if we want to use this window's edges for edge - * resistance (note that dock edges are considered screen edges - * which are handled separately - */ -- if (WINDOW_EDGES_RELEVANT (cur_window, display) && -+ if (is_window_relevant_for_edges (cur_window) && - cur_window->type != META_WINDOW_DOCK) - { - GList *new_edges; -@@ -1035,17 +1046,8 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - } - - stack_position++; -- cur_window_iter = cur_window_iter->next; - } - -- /* -- * 4th: Free the extra memory not needed and sort the list -- */ -- g_list_free (stacked_windows); -- /* Free the memory used by the obscuring windows/docks lists */ -- g_slist_free (window_stacking); -- g_slist_free_full (obscuring_windows, g_free); -- - /* Sort the list. FIXME: Should I bother with this sorting? I just - * sort again later in cache_edges() anyway... - */ -@@ -1060,7 +1062,6 @@ compute_resistance_and_snapping_edges (MetaWindowDrag *window_drag) - edges, - workspace_manager->active_workspace->monitor_edges, - workspace_manager->active_workspace->screen_edges); -- g_list_free (edges); - - return edge_data; - } -diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c -index 8f5d1a046..1267dd4f2 100644 ---- a/src/compositor/meta-sync-ring.c -+++ b/src/compositor/meta-sync-ring.c -@@ -544,20 +544,29 @@ gboolean - meta_sync_ring_insert_wait (void) - { - MetaSyncRing *ring = meta_sync_ring_get (); -+ MetaSync *sync; - - if (!ring) - return FALSE; - - g_return_val_if_fail (ring->xdisplay != NULL, FALSE); - -- if (ring->current_sync->state != META_SYNC_STATE_READY) -+ sync = ring->current_sync; -+ -+ if (sync->state == META_SYNC_STATE_WAITING) -+ { -+ meta_gl_delete_sync (sync->gpu_fence); -+ sync->gpu_fence = 0; -+ sync->state = META_SYNC_STATE_READY; -+ } -+ else if (sync->state != META_SYNC_STATE_READY) - { - meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?"); - if (!meta_sync_ring_reboot (ring->xdisplay)) - return FALSE; - } - -- meta_sync_insert (ring->current_sync); -+ meta_sync_insert (sync); - - return TRUE; - } -diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c -index 24597bbf7..0b43f8eb1 100644 ---- a/src/compositor/meta-window-actor-wayland.c -+++ b/src/compositor/meta-window-actor-wayland.c -@@ -350,7 +350,7 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) - ClutterActor *child_actor; - ClutterActorIter iter; - MetaSurfaceActor *topmost_surface_actor = NULL; -- int n_mapped_surfaces = 0; -+ int n_visible_surface_actors = 0; - MetaWindow *window; - ClutterActorBox window_box; - ClutterActorBox surface_box; -@@ -365,11 +365,17 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) - clutter_actor_iter_init (&iter, surface_container); - while (clutter_actor_iter_next (&iter, &child_actor)) - { -+ MetaSurfaceActor *surface_actor; -+ - if (!clutter_actor_is_mapped (child_actor)) - continue; - -- topmost_surface_actor = META_SURFACE_ACTOR (child_actor); -- n_mapped_surfaces++; -+ surface_actor = META_SURFACE_ACTOR (child_actor); -+ if (meta_surface_actor_is_obscured (surface_actor)) -+ continue; -+ -+ topmost_surface_actor = surface_actor; -+ n_visible_surface_actors++; - } - - if (!topmost_surface_actor) -@@ -380,10 +386,10 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) - } - - window = meta_window_actor_get_meta_window (actor); -- if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 1) -+ if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 1) - return topmost_surface_actor; - -- if (meta_window_is_fullscreen (window) && n_mapped_surfaces == 2) -+ if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 2) - { - MetaSurfaceActorWayland *bg_surface_actor = NULL; - MetaWaylandSurface *bg_surface; -@@ -393,10 +399,16 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) - clutter_actor_iter_init (&iter, surface_container); - while (clutter_actor_iter_next (&iter, &child_actor)) - { -+ MetaSurfaceActor *surface_actor; -+ - if (!clutter_actor_is_mapped (child_actor)) - continue; - -- bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (child_actor); -+ surface_actor = META_SURFACE_ACTOR (child_actor); -+ if (meta_surface_actor_is_obscured (surface_actor)) -+ continue; -+ -+ bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (surface_actor); - break; - } - g_assert (bg_surface_actor); -diff --git a/src/core/constraints.c b/src/core/constraints.c -index 9af0f0004..4bd2bc471 100644 ---- a/src/core/constraints.c -+++ b/src/core/constraints.c -@@ -1154,6 +1154,9 @@ constrain_modal_dialog (MetaWindow *window, - meta_window_get_placement_rule (window)) - return TRUE; - -+ if (window->fullscreen) -+ return TRUE; -+ - /* We want to center the dialog on the parent, including the decorations - for both of them. info->current is in client X window coordinates, so we need - to convert them to frame coordinates, apply the centering and then -diff --git a/src/core/window.c b/src/core/window.c -index 47c29d94a..c6c23708e 100644 ---- a/src/core/window.c -+++ b/src/core/window.c -@@ -2227,7 +2227,7 @@ meta_window_show (MetaWindow *window) - window->has_maximize_func) - { - MtkRectangle work_area; -- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); -+ meta_window_get_work_area_current_monitor (window, &work_area); - /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */ - if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) - { -@@ -3101,7 +3101,7 @@ meta_window_unmaximize (MetaWindow *window, - MtkRectangle old_frame_rect, old_buffer_rect; - gboolean has_target_size; - -- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); -+ meta_window_get_work_area_current_monitor (window, &work_area); - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - -@@ -5837,9 +5837,7 @@ void - meta_window_get_work_area_current_monitor (MetaWindow *window, - MtkRectangle *area) - { -- meta_window_get_work_area_for_monitor (window, -- window->monitor->number, -- area); -+ meta_window_get_work_area_for_logical_monitor (window, window->monitor, area); - } - - /** -diff --git a/src/meson.build b/src/meson.build -index a8cf7e197..05df3bfd2 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -579,6 +579,8 @@ if have_wayland - 'core/meta-service-channel.h', - 'wayland/meta-cursor-sprite-wayland.c', - 'wayland/meta-cursor-sprite-wayland.h', -+ 'wayland/meta-drm-timeline.c', -+ 'wayland/meta-drm-timeline.h', - 'wayland/meta-pointer-confinement-wayland.c', - 'wayland/meta-pointer-confinement-wayland.h', - 'wayland/meta-pointer-lock-wayland.c', -@@ -633,6 +635,8 @@ if have_wayland - 'wayland/meta-wayland-keyboard.h', - 'wayland/meta-wayland-legacy-xdg-foreign.c', - 'wayland/meta-wayland-legacy-xdg-foreign.h', -+ 'wayland/meta-wayland-linux-drm-syncobj.c', -+ 'wayland/meta-wayland-linux-drm-syncobj.h', - 'wayland/meta-wayland-outputs.c', - 'wayland/meta-wayland-outputs.h', - 'wayland/meta-wayland-pointer.c', -@@ -869,6 +873,8 @@ if have_wayland or have_native_backend - mutter_sources += [ - 'common/meta-cogl-drm-formats.c', - 'common/meta-cogl-drm-formats.h', -+ 'common/meta-drm-format-helpers.c', -+ 'common/meta-drm-format-helpers.h', - ] - endif - -@@ -1077,6 +1083,7 @@ if have_wayland - ['xdg-output', 'unstable', 'v1', ], - ['xdg-shell', 'stable', ], - ['xwayland-keyboard-grab', 'unstable', 'v1', ], -+ ['linux-drm-syncobj-v1', 'private', ], - ] - if have_wayland_eglstream - wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable('pkgdatadir') -diff --git a/src/tests/mtk/region-tests.c b/src/tests/mtk/region-tests.c -index 7e41a53f0..c9ebc2adb 100644 ---- a/src/tests/mtk/region-tests.c -+++ b/src/tests/mtk/region-tests.c -@@ -26,7 +26,7 @@ test_contains_point (void) - { - g_autoptr (MtkRegion) r1 = NULL; - -- r1 = mtk_region_create_rectangle (mtk_rectangle_new (0, 0, 100, 100)); -+ r1 = mtk_region_create_rectangle (&MTK_RECTANGLE_INIT (0, 0, 100, 100)); - - g_assert (!mtk_region_contains_point (r1, 200, 200)); - g_assert (mtk_region_contains_point (r1, 50, 50)); -diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c -index f5ebc23fe..2f870fdc3 100644 ---- a/src/tests/native-kms-render.c -+++ b/src/tests/native-kms-render.c -@@ -39,6 +39,8 @@ - #include "tests/meta-wayland-test-driver.h" - #include "tests/meta-wayland-test-utils.h" - -+#define N_FRAMES_PER_TEST 30 -+ - typedef struct - { - int number_of_frames_left; -@@ -46,12 +48,15 @@ typedef struct - - struct { - int n_paints; -- uint32_t fb_id; -+ int n_presentations; -+ int n_direct_scanouts; -+ GList *fb_ids; - } scanout; - - gboolean wait_for_scanout; - - struct { -+ int scanouts_attempted; - gboolean scanout_sabotaged; - gboolean fallback_painted; - guint repaint_guard_id; -@@ -101,7 +106,7 @@ meta_test_kms_render_basic (void) - gulong handler_id; - - test = (KmsRenderingTest) { -- .number_of_frames_left = 10, -+ .number_of_frames_left = N_FRAMES_PER_TEST, - .loop = g_main_loop_new (NULL, FALSE), - }; - handler_id = g_signal_connect (stage, "after-update", -@@ -123,7 +128,6 @@ on_scanout_before_update (ClutterStage *stage, - KmsRenderingTest *test) - { - test->scanout.n_paints = 0; -- test->scanout.fb_id = 0; - } - - static void -@@ -135,6 +139,7 @@ on_scanout_before_paint (ClutterStage *stage, - CoglScanout *scanout; - CoglScanoutBuffer *scanout_buffer; - MetaDrmBuffer *buffer; -+ uint32_t fb_id; - - scanout = clutter_stage_view_peek_scanout (stage_view); - if (!scanout) -@@ -143,8 +148,13 @@ on_scanout_before_paint (ClutterStage *stage, - scanout_buffer = cogl_scanout_get_buffer (scanout); - g_assert_true (META_IS_DRM_BUFFER (scanout_buffer)); - buffer = META_DRM_BUFFER (scanout_buffer); -- test->scanout.fb_id = meta_drm_buffer_get_fb_id (buffer); -- g_assert_cmpuint (test->scanout.fb_id, >, 0); -+ fb_id = meta_drm_buffer_get_fb_id (buffer); -+ g_assert_cmpuint (fb_id, >, 0); -+ test->scanout.fb_ids = g_list_append (test->scanout.fb_ids, -+ GUINT_TO_POINTER (fb_id)); -+ -+ /* Triple buffering, but no higher */ -+ g_assert_cmpuint (g_list_length (test->scanout.fb_ids), <=, 2); - } - - static void -@@ -173,12 +183,12 @@ on_scanout_presented (ClutterStage *stage, - MetaDeviceFile *device_file; - GError *error = NULL; - drmModeCrtc *drm_crtc; -+ uint32_t first_fb_id_expected; - -- if (test->wait_for_scanout && test->scanout.n_paints > 0) -+ if (test->wait_for_scanout && test->scanout.fb_ids == NULL) - return; - -- if (test->wait_for_scanout && test->scanout.fb_id == 0) -- return; -+ test->scanout.n_presentations++; - - device_pool = meta_backend_native_get_device_pool (backend_native); - -@@ -197,15 +207,41 @@ 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); -- if (test->scanout.fb_id == 0) -- g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id); -+ -+ if (test->scanout.fb_ids) -+ { -+ test->scanout.n_direct_scanouts++; -+ first_fb_id_expected = GPOINTER_TO_UINT (test->scanout.fb_ids->data); -+ test->scanout.fb_ids = g_list_delete_link (test->scanout.fb_ids, -+ test->scanout.fb_ids); -+ } - else -- g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id); -+ { -+ first_fb_id_expected = 0; -+ } -+ -+ /* The buffer ID won't match on the first frame because switching from -+ * triple buffered compositing to double buffered direct scanout takes -+ * an extra frame to drain the queue. Thereafter we are in direct scanout -+ * mode and expect the buffer IDs to match. -+ */ -+ if (test->scanout.n_presentations > 1) -+ { -+ if (first_fb_id_expected == 0) -+ g_assert_cmpuint (drm_crtc->buffer_id, !=, first_fb_id_expected); -+ else -+ g_assert_cmpuint (drm_crtc->buffer_id, ==, first_fb_id_expected); -+ } -+ - drmModeFreeCrtc (drm_crtc); - - meta_device_file_release (device_file); - -- g_main_loop_quit (test->loop); -+ test->number_of_frames_left--; -+ if (test->number_of_frames_left <= 0) -+ g_main_loop_quit (test->loop); -+ else -+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - } - - typedef enum -@@ -244,7 +280,9 @@ meta_test_kms_render_client_scanout (void) - g_assert_nonnull (wayland_test_client); - - test = (KmsRenderingTest) { -+ .number_of_frames_left = N_FRAMES_PER_TEST, - .loop = g_main_loop_new (NULL, FALSE), -+ .scanout = {0}, - .wait_for_scanout = TRUE, - }; - -@@ -270,7 +308,8 @@ meta_test_kms_render_client_scanout (void) - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - g_main_loop_run (test.loop); - -- g_assert_cmpuint (test.scanout.fb_id, >, 0); -+ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); -+ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); - - g_debug ("Unmake fullscreen"); - window = meta_find_window_from_title (test_context, "dma-buf-scanout-test"); -@@ -292,10 +331,15 @@ meta_test_kms_render_client_scanout (void) - g_assert_cmpint (buffer_rect.y, ==, 10); - - test.wait_for_scanout = FALSE; -+ test.number_of_frames_left = N_FRAMES_PER_TEST; -+ test.scanout.n_presentations = 0; -+ test.scanout.n_direct_scanouts = 0; -+ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - g_main_loop_run (test.loop); - -- g_assert_cmpuint (test.scanout.fb_id, ==, 0); -+ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); -+ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, 0); - - g_debug ("Moving back to 0, 0"); - meta_window_move_frame (window, TRUE, 0, 0); -@@ -307,10 +351,15 @@ meta_test_kms_render_client_scanout (void) - g_assert_cmpint (buffer_rect.y, ==, 0); - - test.wait_for_scanout = TRUE; -+ test.number_of_frames_left = N_FRAMES_PER_TEST; -+ test.scanout.n_presentations = 0; -+ test.scanout.n_direct_scanouts = 0; -+ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - g_main_loop_run (test.loop); - -- g_assert_cmpuint (test.scanout.fb_id, >, 0); -+ g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); -+ g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); - - g_signal_handler_disconnect (stage, before_update_handler_id); - g_signal_handler_disconnect (stage, before_paint_handler_id); -@@ -364,6 +413,15 @@ on_scanout_fallback_before_paint (ClutterStage *stage, - if (!scanout) - return; - -+ test->scanout_fallback.scanouts_attempted++; -+ -+ /* The first scanout candidate frame will get composited due to triple -+ * buffering draining the queue to drop to double buffering. So don't -+ * sabotage that first frame. -+ */ -+ if (test->scanout_fallback.scanouts_attempted < 2) -+ return; -+ - g_assert_false (test->scanout_fallback.scanout_sabotaged); - - if (is_atomic_mode_setting (kms_device)) -@@ -401,6 +459,15 @@ on_scanout_fallback_paint_view (ClutterStage *stage, - g_clear_handle_id (&test->scanout_fallback.repaint_guard_id, - g_source_remove); - test->scanout_fallback.fallback_painted = TRUE; -+ test->scanout_fallback.scanout_sabotaged = FALSE; -+ } -+ else if (test->scanout_fallback.scanouts_attempted == 1) -+ { -+ /* Now that we've seen the first scanout attempt that was inhibited by -+ * triple buffering, try a second frame. The second one should scanout -+ * and will be sabotaged. -+ */ -+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - } - } - -@@ -410,11 +477,11 @@ on_scanout_fallback_presented (ClutterStage *stage, - ClutterFrameInfo *frame_info, - KmsRenderingTest *test) - { -- if (!test->scanout_fallback.scanout_sabotaged) -- return; -+ if (test->scanout_fallback.fallback_painted) -+ g_main_loop_quit (test->loop); - -- g_assert_true (test->scanout_fallback.fallback_painted); -- g_main_loop_quit (test->loop); -+ test->number_of_frames_left--; -+ g_assert_cmpint (test->number_of_frames_left, >, 0); - } - - static void -@@ -443,6 +510,7 @@ meta_test_kms_render_client_scanout_fallback (void) - g_assert_nonnull (wayland_test_client); - - test = (KmsRenderingTest) { -+ .number_of_frames_left = N_FRAMES_PER_TEST, - .loop = g_main_loop_new (NULL, FALSE), - }; - -diff --git a/src/tests/wayland-test-clients/buffer-transform.c b/src/tests/wayland-test-clients/buffer-transform.c -index cb78489b4..8591e88d6 100644 ---- a/src/tests/wayland-test-clients/buffer-transform.c -+++ b/src/tests/wayland-test-clients/buffer-transform.c -@@ -22,11 +22,6 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; --static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; -- - static gboolean waiting_for_configure = FALSE; - static gboolean fullscreen = 0; - static uint32_t window_width = 0; -@@ -88,7 +83,9 @@ static const struct xdg_surface_listener xdg_surface_listener = { - }; - - static void --draw_main (gboolean rotated) -+draw_main (WaylandDisplay *display, -+ struct wl_surface *surface, -+ gboolean rotated) - { - static uint32_t color0 = 0xffffffff; - static uint32_t color1 = 0xff00ffff; -@@ -139,7 +136,7 @@ draw_main (gboolean rotated) - } - - static void --wait_for_configure (void) -+wait_for_configure (WaylandDisplay *display) - { - waiting_for_configure = TRUE; - while (waiting_for_configure || window_width == 0) -@@ -153,6 +150,11 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ struct wl_surface *surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - surface = wl_compositor_create_surface (display->compositor); -@@ -163,9 +165,9 @@ main (int argc, - - xdg_toplevel_set_fullscreen(xdg_toplevel, NULL); - wl_surface_commit (surface); -- wait_for_configure (); -+ wait_for_configure (display); - -- draw_main (FALSE); -+ draw_main (display, surface, FALSE); - wl_surface_commit (surface); - wait_for_effects_completed (display, surface); - -@@ -185,7 +187,7 @@ main (int argc, - wl_surface_commit (surface); - wait_for_view_verified (display, 3); - -- draw_main (TRUE); -+ draw_main (display, surface, TRUE); - wl_surface_set_buffer_transform (surface, WL_OUTPUT_TRANSFORM_90); - wl_surface_commit (surface); - wait_for_view_verified (display, 4); -@@ -202,7 +204,5 @@ main (int argc, - wl_surface_commit (surface); - wait_for_view_verified (display, 7); - -- g_clear_object (&display); -- - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/dma-buf-scanout.c b/src/tests/wayland-test-clients/dma-buf-scanout.c -index bc499164e..d71763947 100644 ---- a/src/tests/wayland-test-clients/dma-buf-scanout.c -+++ b/src/tests/wayland-test-clients/dma-buf-scanout.c -@@ -55,11 +55,7 @@ typedef enum - WINDOW_STATE_FULLSCREEN, - } WindowState; - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static GList *active_buffers; - -@@ -84,7 +80,7 @@ static const struct wl_buffer_listener buffer_listener = { - }; - - static void --init_surface (void) -+init_surface (struct xdg_toplevel *xdg_toplevel) - { - xdg_toplevel_set_title (xdg_toplevel, "dma-buf-scanout-test"); - xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); -@@ -92,8 +88,9 @@ init_surface (void) - } - - static void --draw_main (int width, -- int height) -+draw_main (WaylandDisplay *display, -+ int width, -+ int height) - { - WaylandBuffer *buffer; - DmaBufFormat *format; -@@ -140,9 +137,11 @@ handle_xdg_toplevel_configure (void *user_data, - int32_t height, - struct wl_array *states) - { -+ WaylandDisplay *display; - g_assert (width > 0 || prev_width > 0); - g_assert (height > 0 || prev_width > 0); - -+ display = user_data; - if (width > 0 && height > 0) - { - prev_width = width; -@@ -156,7 +155,7 @@ handle_xdg_toplevel_configure (void *user_data, - - window_state = parse_xdg_toplevel_state (states); - -- draw_main (width, height); -+ draw_main (display, width, height); - } - - static void -@@ -196,6 +195,7 @@ handle_xdg_surface_configure (void *user_data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = user_data; - struct wl_callback *frame_callback; - - xdg_surface_ack_configure (xdg_surface, serial); -@@ -223,6 +223,10 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); - wl_display_roundtrip (display->display); -@@ -230,11 +234,11 @@ main (int argc, - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); -- xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); -+ xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, display); - -- init_surface (); -+ init_surface (xdg_toplevel); - - running = TRUE; - while (running) -@@ -244,7 +248,6 @@ main (int argc, - } - - g_list_free_full (active_buffers, (GDestroyNotify) g_object_unref); -- g_object_unref (display); - - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/fractional-scale.c b/src/tests/wayland-test-clients/fractional-scale.c -index 4ed55ebe3..f62aa2033 100644 ---- a/src/tests/wayland-test-clients/fractional-scale.c -+++ b/src/tests/wayland-test-clients/fractional-scale.c -@@ -23,12 +23,8 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - static struct wp_viewport *viewport; --static struct wp_fractional_scale_v1 *fractional_scale_obj; - - static gboolean running; - static gboolean waiting_for_configure; -@@ -43,6 +39,8 @@ handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; -+ - wl_callback_destroy (callback); - test_driver_sync_point (display->test_driver, sync_point++, NULL); - } -@@ -52,7 +50,7 @@ static const struct wl_callback_listener frame_listener = { - }; - - static void --maybe_redraw (void) -+maybe_redraw (WaylandDisplay *display) - { - struct wl_callback *callback; - uint32_t buffer_width; -@@ -72,7 +70,7 @@ maybe_redraw (void) - wp_viewport_set_destination (viewport, logical_width, logical_height); - - callback = wl_surface_frame (surface); -- wl_callback_add_listener (callback, &frame_listener, NULL); -+ wl_callback_add_listener (callback, &frame_listener, display); - - wl_surface_commit (surface); - -@@ -112,10 +110,11 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; - xdg_surface_ack_configure (xdg_surface, serial); - waiting_for_configure = FALSE; - -- maybe_redraw (); -+ maybe_redraw (display); - } - - static const struct xdg_surface_listener xdg_surface_listener = { -@@ -126,6 +125,7 @@ static void handle_preferred_scale (void *data, - struct wp_fractional_scale_v1 *fractional_scale_obj, - uint32_t wire_scale) - { -+ WaylandDisplay *display = data; - float new_fractional_buffer_scale; - - new_fractional_buffer_scale = wire_scale / 120.0; -@@ -136,7 +136,7 @@ static void handle_preferred_scale (void *data, - - fractional_buffer_scale = new_fractional_buffer_scale; - waiting_for_scale = FALSE; -- maybe_redraw (); -+ maybe_redraw (display); - } - - static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { -@@ -147,11 +147,16 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ struct wp_fractional_scale_v1 *fractional_scale_obj; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (xdg_toplevel, "fractional-scale"); -@@ -163,7 +168,7 @@ main (int argc, - surface); - wp_fractional_scale_v1_add_listener (fractional_scale_obj, - &fractional_scale_listener, -- NULL); -+ display); - - wl_surface_commit (surface); - -diff --git a/src/tests/wayland-test-clients/fullscreen.c b/src/tests/wayland-test-clients/fullscreen.c -index 9690f6e85..804be4eb2 100644 ---- a/src/tests/wayland-test-clients/fullscreen.c -+++ b/src/tests/wayland-test-clients/fullscreen.c -@@ -24,11 +24,7 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static gboolean running; - -@@ -58,6 +54,8 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; -+ - draw_surface (display, surface, 10, 10, 0x1f109f20); - xdg_surface_ack_configure (xdg_surface, serial); - wl_surface_commit (surface); -@@ -81,12 +79,16 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (xdg_toplevel, "fullscreen"); -diff --git a/src/tests/wayland-test-clients/idle-inhibit.c b/src/tests/wayland-test-clients/idle-inhibit.c -index 23079e879..953db2b92 100644 ---- a/src/tests/wayland-test-clients/idle-inhibit.c -+++ b/src/tests/wayland-test-clients/idle-inhibit.c -@@ -24,7 +24,6 @@ - - #include "idle-inhibit-unstable-v1-client-protocol.h" - --static WaylandDisplay *display; - struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; - - static void -@@ -59,7 +58,8 @@ main (int argc, - char **argv) - { - struct wl_registry *registry; -- WaylandSurface *surface; -+ g_autoptr (WaylandSurface) surface; -+ g_autoptr (WaylandDisplay) display = NULL; - struct zwp_idle_inhibitor_v1 *inhibitor; - - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); -diff --git a/src/tests/wayland-test-clients/invalid-subsurfaces.c b/src/tests/wayland-test-clients/invalid-subsurfaces.c -index 103456e93..2cf0d4ecf 100644 ---- a/src/tests/wayland-test-clients/invalid-subsurfaces.c -+++ b/src/tests/wayland-test-clients/invalid-subsurfaces.c -@@ -24,33 +24,16 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; -- --static void --connect_to_display (void) --{ -- g_assert_null (display); -- -- display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); -- g_assert_nonnull (display); --} -- --static void --clean_up_display (void) --{ -- g_clear_object (&display); --} -- - static void - test_circular_subsurfaces1 (void) - { -+ g_autoptr (WaylandDisplay) display = NULL; - struct wl_surface *surface1; - struct wl_subsurface *subsurface1; - struct wl_surface *surface2; - struct wl_subsurface *subsurface2; - -- connect_to_display (); -- -+ display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); - surface1 = wl_compositor_create_surface (display->compositor); - surface2 = wl_compositor_create_surface (display->compositor); - g_assert_nonnull (surface1); -@@ -66,13 +49,12 @@ test_circular_subsurfaces1 (void) - g_assert_nonnull (subsurface2); - - g_assert_cmpint (wl_display_roundtrip (display->display), ==, -1); -- -- clean_up_display (); - } - - static void - test_circular_subsurfaces2 (void) - { -+ g_autoptr (WaylandDisplay) display = NULL; - struct wl_surface *surface1; - struct wl_subsurface *subsurface1; - struct wl_surface *surface2; -@@ -80,7 +62,7 @@ test_circular_subsurfaces2 (void) - struct wl_surface *surface3; - struct wl_subsurface *subsurface3; - -- connect_to_display (); -+ display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); - - surface1 = wl_compositor_create_surface (display->compositor); - surface2 = wl_compositor_create_surface (display->compositor); -@@ -103,8 +85,6 @@ test_circular_subsurfaces2 (void) - g_assert_nonnull (subsurface3); - - g_assert_cmpint (wl_display_roundtrip (display->display), ==, -1); -- -- clean_up_display (); - } - - int -diff --git a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c b/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c -index bd75dc995..4ffda8d5a 100644 ---- a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c -+++ b/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c -@@ -22,23 +22,19 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static gboolean running; - - static void --init_surface (void) -+init_surface (struct xdg_toplevel *xdg_toplevel) - { - xdg_toplevel_set_title (xdg_toplevel, "bogus window geometry"); - wl_surface_commit (surface); - } - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, surface, 700, 500, 0xff00ff00); - } -@@ -69,13 +65,14 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; - static gboolean sent_invalid_once = FALSE; - - if (sent_invalid_once) - return; - - xdg_surface_set_window_geometry (xdg_surface, 0, 0, 0, 0); -- draw_main (); -+ draw_main (display); - wl_surface_commit (surface); - - sent_invalid_once = TRUE; -@@ -91,15 +88,19 @@ static const struct xdg_surface_listener xdg_surface_listener = { - static void - test_empty_window_geometry (void) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -- init_surface (); -+ init_surface (xdg_toplevel); - - running = TRUE; - while (running) -@@ -110,7 +111,6 @@ test_empty_window_geometry (void) - - g_clear_pointer (&xdg_toplevel, xdg_toplevel_destroy); - g_clear_pointer (&xdg_surface, xdg_surface_destroy); -- g_clear_object (&display); - } - - int -diff --git a/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c b/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c -index 0ddaa4a04..b46a88563 100644 ---- a/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c -+++ b/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c -@@ -23,33 +23,28 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; -- --static struct wl_registry *wl_registry; - static struct wl_seat *wl_seat; - static struct wl_pointer *wl_pointer; - static uint32_t enter_serial; - - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - struct wl_surface *cursor_surface; --struct wl_cursor_theme *cursor_theme; - struct wl_cursor *cursor; - struct wl_cursor *cursor2; - - static gboolean running; - - static void --init_surface (void) -+init_surface (struct xdg_toplevel *xdg_toplevel) - { - xdg_toplevel_set_title (xdg_toplevel, "kms-cursor-hotplug-helper"); - wl_surface_commit (surface); - } - - static void --draw_main (int width, -- int height) -+draw_main (WaylandDisplay *display, -+ int width, -+ int height) - { - draw_surface (display, surface, width, height, 0xff00ff00); - } -@@ -89,7 +84,9 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -- draw_main (100, 100); -+ WaylandDisplay *display = data; -+ -+ draw_main (display, 100, 100); - xdg_surface_ack_configure (xdg_surface, serial); - wl_surface_commit (surface); - } -@@ -251,6 +248,12 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct wl_registry *wl_registry; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ struct wl_cursor_theme *cursor_theme; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - wl_registry = wl_display_get_registry (display->display); - wl_registry_add_listener (wl_registry, ®istry_listener, display); -@@ -260,7 +263,7 @@ main (int argc, - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -@@ -271,7 +274,7 @@ main (int argc, - g_assert_nonnull (cursor); - g_assert_nonnull (cursor2); - -- init_surface (); -+ init_surface (xdg_toplevel); - wl_surface_commit (surface); - - running = TRUE; -diff --git a/src/tests/wayland-test-clients/single-pixel-buffer.c b/src/tests/wayland-test-clients/single-pixel-buffer.c -index ed98939a3..d350e4d8e 100644 ---- a/src/tests/wayland-test-clients/single-pixel-buffer.c -+++ b/src/tests/wayland-test-clients/single-pixel-buffer.c -@@ -22,13 +22,7 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; --static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - static struct wl_buffer *buffer; --static struct wl_surface *subsurface_surface; --static struct wl_subsurface *subsurface; - - static gboolean waiting_for_configure = FALSE; - static gboolean fullscreen = 0; -@@ -91,7 +85,7 @@ static const struct xdg_surface_listener xdg_surface_listener = { - }; - - static void --wait_for_configure (void) -+wait_for_configure (WaylandDisplay *display) - { - waiting_for_configure = TRUE; - while (waiting_for_configure || window_width == 0) -@@ -114,7 +108,7 @@ static const struct wl_buffer_listener buffer_listener = { - }; - - static void --wait_for_buffer_released (void) -+wait_for_buffer_released (WaylandDisplay *display) - { - while (buffer) - { -@@ -127,8 +121,14 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; - struct wp_viewport *viewport; - struct wp_viewport *subsurface_viewport; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ struct wl_surface *subsurface_surface; -+ struct wl_subsurface *subsurface; -+ struct wl_surface *surface; - - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - -@@ -140,7 +140,7 @@ main (int argc, - - xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); - wl_surface_commit (surface); -- wait_for_configure (); -+ wait_for_configure (display); - - viewport = wp_viewporter_get_viewport (display->viewporter, surface); - wp_viewport_set_destination (viewport, window_width, window_height); -@@ -157,7 +157,7 @@ main (int argc, - wait_for_effects_completed (display, surface); - wait_for_view_verified (display, 0); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - subsurface_surface = wl_compositor_create_surface (display->compositor); - subsurface = wl_subcompositor_get_subsurface (display->subcompositor, -@@ -184,7 +184,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 1); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -197,7 +197,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 0); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -210,7 +210,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 2); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -223,7 +223,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 3); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -236,7 +236,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 4); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -249,7 +249,7 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 5); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - - buffer = - wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -@@ -262,9 +262,43 @@ main (int argc, - wl_surface_commit (subsurface_surface); - wait_for_view_verified (display, 6); - -- wait_for_buffer_released (); -+ wait_for_buffer_released (display); - -- g_clear_object (&display); -+ /* Test reuse */ -+ -+ buffer = -+ wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_mgr, -+ 0x70707070, -+ 0x00000000, -+ 0x70707070, -+ 0x70707070); -+ wl_surface_attach (subsurface_surface, buffer, 0, 0); -+ wl_surface_commit (subsurface_surface); -+ wait_for_view_verified (display, 7); -+ -+ wl_subsurface_destroy (subsurface); -+ wl_surface_destroy (subsurface_surface); -+ -+ subsurface_surface = wl_compositor_create_surface (display->compositor); -+ subsurface = wl_subcompositor_get_subsurface (display->subcompositor, -+ subsurface_surface, -+ surface); -+ wl_subsurface_set_desync (subsurface); -+ wl_subsurface_set_position (subsurface, 30, 30); -+ wl_surface_commit (surface); -+ -+ subsurface_viewport = wp_viewporter_get_viewport (display->viewporter, -+ subsurface_surface); -+ wp_viewport_set_destination (subsurface_viewport, -+ window_width - 60, -+ window_height - 60); -+ -+ wl_buffer_add_listener (buffer, &buffer_listener, NULL); -+ wl_surface_attach (subsurface_surface, buffer, 0, 0); -+ wl_surface_commit (subsurface_surface); -+ wait_for_view_verified (display, 8); -+ -+ wait_for_buffer_released (display); - - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/subsurface-corner-cases.c b/src/tests/wayland-test-clients/subsurface-corner-cases.c -index c3b239b2c..449bcb83d 100644 ---- a/src/tests/wayland-test-clients/subsurface-corner-cases.c -+++ b/src/tests/wayland-test-clients/subsurface-corner-cases.c -@@ -22,12 +22,6 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; --static struct wl_surface *toplevel_surface, *child_surface, *grandchild_surface; --static struct wl_subsurface *child, *grandchild; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; -- - static gboolean waiting_for_configure = FALSE; - static gboolean fullscreen = 0; - static uint32_t window_width = 0; -@@ -75,7 +69,8 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { - }; - - static void --draw_toplevel (void) -+draw_toplevel (WaylandDisplay *display, -+ struct wl_surface *toplevel_surface) - { - draw_surface (display, toplevel_surface, - window_width, window_height, -@@ -97,7 +92,8 @@ static const struct xdg_surface_listener xdg_surface_listener = { - }; - - static void --draw_child (void) -+draw_child (WaylandDisplay *display, -+ struct wl_surface *child_surface) - { - draw_surface (display, child_surface, - window_width / 2, window_height / 2, -@@ -105,7 +101,8 @@ draw_child (void) - } - - static void --draw_grandchild (void) -+draw_grandchild (WaylandDisplay *display, -+ struct wl_surface *grandchild_surface) - { - draw_surface (display, grandchild_surface, - window_width / 2, window_height / 2, -@@ -113,7 +110,7 @@ draw_grandchild (void) - } - - static void --wait_for_configure (void) -+wait_for_configure (WaylandDisplay *display) - { - waiting_for_configure = TRUE; - while (waiting_for_configure || window_width == 0) -@@ -127,6 +124,12 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ struct wl_surface *toplevel_surface, *child_surface, *grandchild_surface; -+ struct wl_subsurface *child, *grandchild; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - toplevel_surface = wl_compositor_create_surface (display->compositor); -@@ -138,9 +141,9 @@ main (int argc, - - xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); - wl_surface_commit (toplevel_surface); -- wait_for_configure (); -+ wait_for_configure (display); - -- draw_toplevel (); -+ draw_toplevel (display, toplevel_surface); - wl_surface_commit (toplevel_surface); - wait_for_effects_completed (display, toplevel_surface); - -@@ -148,7 +151,7 @@ main (int argc, - child = wl_subcompositor_get_subsurface (display->subcompositor, - child_surface, - toplevel_surface); -- draw_child (); -+ draw_child (display, child_surface); - wl_surface_commit (child_surface); - /* No toplevel commit → sub-surface must not be mapped yet */ - wait_for_view_verified (display, 0); -@@ -174,7 +177,7 @@ main (int argc, - /* Toplevel commit → sub-surface must be unmapped */ - wait_for_view_verified (display, 5); - -- draw_child (); -+ draw_child (display, child_surface); - wl_surface_commit (child_surface); - wl_subsurface_set_desync (child); - wl_surface_attach (child_surface, NULL, 0, 0); -@@ -182,7 +185,7 @@ main (int argc, - /* Desync sub-surface must have been unmapped */ - wait_for_view_verified (display, 6); - -- draw_child (); -+ draw_child (display, child_surface); - wl_surface_commit (child_surface); - wl_subsurface_set_sync (child); - wl_subsurface_destroy (child); -@@ -192,7 +195,7 @@ main (int argc, - child = wl_subcompositor_get_subsurface (display->subcompositor, - child_surface, - toplevel_surface); -- draw_child (); -+ draw_child (display, child_surface); - wl_surface_commit (child_surface); - /* No toplevel commit → sub-surface must not be mapped yet */ - wait_for_view_verified (display, 8); -@@ -209,7 +212,7 @@ main (int argc, - child = wl_subcompositor_get_subsurface (display->subcompositor, - child_surface, - toplevel_surface); -- draw_child (); -+ draw_child (display, child_surface); - wl_surface_commit (child_surface); - wl_surface_commit (toplevel_surface); - /* New sub-surface → placement below toplevel must not have taken effect */ -@@ -219,7 +222,7 @@ main (int argc, - grandchild = wl_subcompositor_get_subsurface (display->subcompositor, - grandchild_surface, - child_surface); -- draw_grandchild (); -+ draw_grandchild (display, grandchild_surface); - wl_subsurface_set_position (grandchild, window_width / 4, window_height / 4); - wl_surface_commit (grandchild_surface); - wl_surface_commit (child_surface); -@@ -236,7 +239,7 @@ main (int argc, - grandchild = wl_subcompositor_get_subsurface (display->subcompositor, - grandchild_surface, - child_surface); -- draw_grandchild (); -+ draw_grandchild (display, grandchild_surface); - wl_subsurface_set_position (grandchild, window_width / 4, window_height / 4); - wl_surface_commit (grandchild_surface); - wl_surface_commit (child_surface); -@@ -244,7 +247,5 @@ main (int argc, - /* New grandchild must be placed above its parent */ - wait_for_view_verified (display, 14); - -- g_clear_object (&display); -- - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/subsurface-parent-unmapped.c b/src/tests/wayland-test-clients/subsurface-parent-unmapped.c -index 7fc83b07d..40c72ea33 100644 ---- a/src/tests/wayland-test-clients/subsurface-parent-unmapped.c -+++ b/src/tests/wayland-test-clients/subsurface-parent-unmapped.c -@@ -23,36 +23,32 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; --static struct wl_registry *registry; - static struct wl_seat *seat; - static struct wl_pointer *pointer; - - static struct wl_surface *toplevel_surface; - static struct xdg_surface *toplevel_xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static struct wl_surface *popup_surface; - static struct xdg_surface *popup_xdg_surface; - static struct xdg_popup *xdg_popup; - - static struct wl_surface *subsurface_surface; --static struct wl_subsurface *subsurface; - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, toplevel_surface, 200, 200, 0xff00ffff); - } - - static void --draw_popup (void) -+draw_popup (WaylandDisplay *display) - { - draw_surface (display, popup_surface, 100, 100, 0xff005500); - } - - static void --draw_subsurface (void) -+draw_subsurface (WaylandDisplay *display) - { - draw_surface (display, subsurface_surface, 100, 50, 0xff001f00); - } -@@ -83,8 +79,10 @@ handle_toplevel_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; -+ - xdg_surface_ack_configure (xdg_surface, serial); -- draw_main (); -+ draw_main (display); - wl_surface_commit (toplevel_surface); - wl_display_flush (display->display); - } -@@ -125,6 +123,8 @@ handle_popup_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; -+ - wl_callback_destroy (callback); - test_driver_sync_point (display->test_driver, 0, popup_surface); - } -@@ -138,16 +138,17 @@ handle_popup_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; - struct wl_callback *frame_callback; - -- draw_popup (); -+ draw_popup (display); - -- draw_subsurface (); -+ draw_subsurface (display); - wl_surface_commit (subsurface_surface); - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (popup_surface); -- wl_callback_add_listener (frame_callback, &frame_listener, NULL); -+ wl_callback_add_listener (frame_callback, &frame_listener, display); - wl_surface_commit (popup_surface); - wl_display_flush (display->display); - } -@@ -164,6 +165,7 @@ pointer_handle_button (void *data, - uint32_t button, - uint32_t state) - { -+ WaylandDisplay *display = data; - struct xdg_positioner *positioner; - static int click_count = 0; - -@@ -174,7 +176,7 @@ pointer_handle_button (void *data, - popup_xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, - popup_surface); - xdg_surface_add_listener (popup_xdg_surface, -- &popup_xdg_surface_listener, NULL); -+ &popup_xdg_surface_listener, display); - positioner = xdg_wm_base_create_positioner (display->xdg_wm_base); - xdg_positioner_set_size (positioner, 100, 100); - xdg_positioner_set_anchor_rect (positioner, 0, 0, 1, 1); -@@ -219,10 +221,12 @@ seat_handle_capabilities (void *data, - struct wl_seat *wl_seat, - enum wl_seat_capability caps) - { -+ WaylandDisplay *display = data; -+ - if (caps & WL_SEAT_CAPABILITY_POINTER) - { - pointer = wl_seat_get_pointer (wl_seat); -- wl_pointer_add_listener (pointer, &pointer_listener, NULL); -+ wl_pointer_add_listener (pointer, &pointer_listener, display); - } - } - -@@ -263,10 +267,12 @@ handle_registry_global (void *data, - const char *interface, - uint32_t version) - { -+ WaylandDisplay *display = data; -+ - if (strcmp (interface, "wl_seat") == 0) - { - seat = wl_registry_bind (registry, id, &wl_seat_interface, 1); -- wl_seat_add_listener (seat, &seat_listener, NULL); -+ wl_seat_add_listener (seat, &seat_listener, display); - } - } - -@@ -286,12 +292,17 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct wl_registry *registry; -+ struct xdg_toplevel *xdg_toplevel; -+ struct wl_subsurface *subsurface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); - - registry = wl_display_get_registry (display->display); -- wl_registry_add_listener (registry, ®istry_listener, NULL); -+ wl_registry_add_listener (registry, ®istry_listener, display); - wl_display_roundtrip (display->display); - wl_display_roundtrip (display->display); - -@@ -311,7 +322,7 @@ main (int argc, - toplevel_xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, - toplevel_surface); - xdg_surface_add_listener (toplevel_xdg_surface, -- &toplevel_xdg_surface_listener, NULL); -+ &toplevel_xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (toplevel_xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (xdg_toplevel, "subsurface-parent-unmapped"); -@@ -331,7 +342,5 @@ main (int argc, - return EXIT_FAILURE; - } - -- g_clear_object (&display); -- - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c b/src/tests/wayland-test-clients/subsurface-remap-toplevel.c -index e23aacabb..c1bb90ea5 100644 ---- a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c -+++ b/src/tests/wayland-test-clients/subsurface-remap-toplevel.c -@@ -32,13 +32,9 @@ typedef enum _State - STATE_WAIT_FOR_FRAME_2 - } State; - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; - static struct xdg_toplevel *xdg_toplevel; - --static struct wl_surface *subsurface_surface; - static struct wl_subsurface *subsurface; - - static struct wl_callback *frame_callback; -@@ -72,7 +68,7 @@ static const struct wl_callback_listener actor_destroy_listener = { - }; - - static void --reset_surface (void) -+reset_surface (WaylandDisplay *display) - { - struct wl_callback *callback; - -@@ -86,13 +82,14 @@ reset_surface (void) - } - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, surface, 700, 500, 0xff00ff00); - } - - static void --draw_subsurface (void) -+draw_subsurface (WaylandDisplay *display, -+ struct wl_surface *subsurface_surface) - { - draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); - } -@@ -123,10 +120,11 @@ handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: -- reset_surface (); -+ reset_surface (display); - break; - case STATE_WAIT_FOR_FRAME_2: - exit (EXIT_SUCCESS); -@@ -150,16 +148,17 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; - switch (state) - { - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_1; - break; - case STATE_WAIT_FOR_CONFIGURE_2: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_2; - break; - case STATE_WAIT_FOR_ACTOR_DESTROYED: -@@ -172,7 +171,7 @@ handle_xdg_surface_configure (void *data, - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); -- wl_callback_add_listener (frame_callback, &frame_listener, NULL); -+ wl_callback_add_listener (frame_callback, &frame_listener, display); - wl_surface_commit (surface); - wl_display_flush (display->display); - } -@@ -185,11 +184,15 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_surface *xdg_surface; -+ struct wl_surface *subsurface_surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -@@ -198,7 +201,7 @@ main (int argc, - subsurface_surface, - surface); - wl_subsurface_set_position (subsurface, 100, 100); -- draw_subsurface (); -+ draw_subsurface (display, subsurface_surface); - wl_surface_commit (subsurface_surface); - - init_surface (); -@@ -211,7 +214,5 @@ main (int argc, - return EXIT_FAILURE; - } - -- g_clear_object (&display); -- - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/subsurface-reparenting.c b/src/tests/wayland-test-clients/subsurface-reparenting.c -index f537e0727..7a4c99577 100644 ---- a/src/tests/wayland-test-clients/subsurface-reparenting.c -+++ b/src/tests/wayland-test-clients/subsurface-reparenting.c -@@ -34,8 +34,6 @@ typedef enum _State - STATE_WAIT_FOR_FRAME_3 - } State; - --static WaylandDisplay *display; -- - static struct wl_surface *surface; - static struct xdg_surface *xdg_surface; - static struct xdg_toplevel *xdg_toplevel; -@@ -47,16 +45,16 @@ static struct wl_callback *frame_callback; - - static State state; - --static void init_surfaces (void); -+static void init_surfaces (WaylandDisplay *display); - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, surface, 700, 500, 0xff00ff00); - } - - static void --draw_subsurface (void) -+draw_subsurface (WaylandDisplay *display) - { - draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); - } -@@ -87,10 +85,11 @@ actor_destroyed (void *data, - struct wl_callback *callback, - uint32_t serial) - { -+ WaylandDisplay *display = data; - g_assert_cmpint (state, ==, STATE_WAIT_FOR_ACTOR_DESTROYED); - - wl_subsurface_destroy (subsurface); -- init_surfaces (); -+ init_surfaces (display); - state = STATE_WAIT_FOR_CONFIGURE_2; - - wl_callback_destroy (callback); -@@ -101,12 +100,12 @@ static const struct wl_callback_listener actor_destroy_listener = { - }; - - static void --reset_surface (void) -+reset_surface (WaylandDisplay *display) - { - struct wl_callback *callback; - - callback = test_driver_sync_actor_destroyed (display->test_driver, surface); -- wl_callback_add_listener (callback, &actor_destroy_listener, NULL); -+ wl_callback_add_listener (callback, &actor_destroy_listener, display); - - xdg_toplevel_destroy (xdg_toplevel); - xdg_surface_destroy (xdg_surface); -@@ -120,10 +119,12 @@ handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: -- reset_surface (); -+ reset_surface (display); - break; - case STATE_WAIT_FOR_FRAME_2: - exit (EXIT_SUCCESS); -@@ -141,16 +142,18 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_1; - break; - case STATE_WAIT_FOR_CONFIGURE_2: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_2; - break; - default: -@@ -160,7 +163,7 @@ handle_xdg_surface_configure (void *data, - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); -- wl_callback_add_listener (frame_callback, &frame_listener, NULL); -+ wl_callback_add_listener (frame_callback, &frame_listener, display); - wl_surface_commit (surface); - wl_display_flush (display->display); - } -@@ -170,11 +173,11 @@ static const struct xdg_surface_listener xdg_surface_listener = { - }; - - static void --init_surfaces (void) -+init_surfaces (WaylandDisplay *display) - { - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (xdg_toplevel, "subsurface-reparenting-test"); -@@ -190,13 +193,14 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - subsurface_surface = wl_compositor_create_surface (display->compositor); -- draw_subsurface (); -+ draw_subsurface (display); - wl_surface_commit (subsurface_surface); - -- init_surfaces (); -+ init_surfaces (display); - state = STATE_WAIT_FOR_CONFIGURE_1; - - while (TRUE) -diff --git a/src/tests/wayland-test-clients/xdg-activation.c b/src/tests/wayland-test-clients/xdg-activation.c -index a1e78758f..b97a599c2 100644 ---- a/src/tests/wayland-test-clients/xdg-activation.c -+++ b/src/tests/wayland-test-clients/xdg-activation.c -@@ -24,18 +24,15 @@ - - #include "xdg-activation-v1-client-protocol.h" - --static WaylandDisplay *display; --static struct wl_registry *registry; - static struct xdg_activation_v1 *activation; - - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static gboolean running; - - static void --init_surface (const char *token) -+init_surface (struct xdg_toplevel *xdg_toplevel, -+ const char *token) - { - xdg_toplevel_set_title (xdg_toplevel, "startup notification client"); - xdg_activation_v1_activate (activation, token, surface); -@@ -43,7 +40,7 @@ init_surface (const char *token) - } - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, surface, 700, 500, 0xff00ff00); - } -@@ -74,7 +71,9 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -- draw_main (); -+ WaylandDisplay *display = data; -+ -+ draw_main (display); - wl_surface_commit (surface); - - g_assert_cmpint (wl_display_roundtrip (display->display), !=, -1); -@@ -126,7 +125,7 @@ static const struct xdg_activation_token_v1_listener token_listener = { - }; - - static char * --get_token (void) -+get_token (WaylandDisplay *display) - { - struct xdg_activation_token_v1 *token; - char *token_string = NULL; -@@ -151,6 +150,11 @@ get_token (void) - static void - test_startup_notifications (void) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct wl_registry *registry; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ - g_autofree char *token = NULL; - - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_NONE); -@@ -162,15 +166,15 @@ test_startup_notifications (void) - - wl_display_roundtrip (display->display); - -- token = get_token (); -+ token = get_token (display); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -- init_surface (token); -+ init_surface (xdg_toplevel, token); - - running = TRUE; - while (running) -@@ -185,7 +189,6 @@ test_startup_notifications (void) - g_clear_pointer (&xdg_surface, xdg_surface_destroy); - g_clear_pointer (&activation, xdg_activation_v1_destroy); - g_clear_pointer (®istry, wl_registry_destroy); -- g_clear_object (&display); - } - - int -diff --git a/src/tests/wayland-test-clients/xdg-apply-limits.c b/src/tests/wayland-test-clients/xdg-apply-limits.c -index c386af283..9c30bfe4a 100644 ---- a/src/tests/wayland-test-clients/xdg-apply-limits.c -+++ b/src/tests/wayland-test-clients/xdg-apply-limits.c -@@ -31,15 +31,9 @@ typedef enum _State - STATE_WAIT_FOR_FRAME_2 - } State; - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; - static struct xdg_toplevel *xdg_toplevel; - --static struct wl_surface *subsurface_surface; --static struct wl_subsurface *subsurface; -- - static struct wl_callback *frame_callback; - - static gboolean running; -@@ -71,7 +65,7 @@ static const struct wl_callback_listener actor_destroy_listener = { - }; - - static void --reset_surface (void) -+reset_surface (WaylandDisplay *display) - { - struct wl_callback *callback; - -@@ -89,13 +83,14 @@ reset_surface (void) - } - - static void --draw_main (void) -+draw_main (WaylandDisplay *display) - { - draw_surface (display, surface, 700, 500, 0xff00ff00); - } - - static void --draw_subsurface (void) -+draw_subsurface (WaylandDisplay *display, -+ struct wl_surface *subsurface_surface) - { - draw_surface (display, subsurface_surface, 500, 300, 0xff007f00); - } -@@ -126,10 +121,12 @@ handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: -- reset_surface (); -+ reset_surface (display); - test_driver_sync_point (display->test_driver, 1, NULL); - break; - case STATE_WAIT_FOR_FRAME_2: -@@ -154,16 +151,18 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_1; - break; - case STATE_WAIT_FOR_CONFIGURE_2: -- draw_main (); -+ draw_main (display); - state = STATE_WAIT_FOR_FRAME_2; - break; - case STATE_WAIT_FOR_ACTOR_DESTROYED: -@@ -176,7 +175,7 @@ handle_xdg_surface_configure (void *data, - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); -- wl_callback_add_listener (frame_callback, &frame_listener, NULL); -+ wl_callback_add_listener (frame_callback, &frame_listener, display); - wl_surface_commit (surface); - wl_display_flush (display->display); - } -@@ -189,11 +188,16 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_surface *xdg_surface; -+ struct wl_surface *subsurface_surface; -+ struct wl_subsurface *subsurface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -@@ -202,7 +206,7 @@ main (int argc, - subsurface_surface, - surface); - wl_subsurface_set_position (subsurface, 100, 100); -- draw_subsurface (); -+ draw_subsurface (display, subsurface_surface); - wl_surface_commit (subsurface_surface); - - init_surface (); -diff --git a/src/tests/wayland-test-clients/xdg-foreign.c b/src/tests/wayland-test-clients/xdg-foreign.c -index f2dbec151..fdc4f9f70 100644 ---- a/src/tests/wayland-test-clients/xdg-foreign.c -+++ b/src/tests/wayland-test-clients/xdg-foreign.c -@@ -24,8 +24,6 @@ - #include "xdg-foreign-unstable-v1-client-protocol.h" - #include "xdg-foreign-unstable-v2-client-protocol.h" - --static WaylandDisplay *display; -- - static struct zxdg_exporter_v1 *exporter_v1; - static struct zxdg_exporter_v2 *exporter_v2; - static struct zxdg_importer_v1 *importer_v1; -@@ -130,10 +128,11 @@ int - main (int argc, - char **argv) - { -- g_autoptr (WaylandSurface) window1; -- g_autoptr (WaylandSurface) window2; -- g_autoptr (WaylandSurface) window3; -- g_autoptr (WaylandSurface) window4; -+ g_autoptr (WaylandSurface) window1 = NULL; -+ g_autoptr (WaylandSurface) window2 = NULL; -+ g_autoptr (WaylandSurface) window3 = NULL; -+ g_autoptr (WaylandSurface) window4 = NULL; -+ g_autoptr (WaylandDisplay) display = NULL; - g_autofree char *handle1 = NULL; - g_autofree char *handle3 = NULL; - struct wl_registry *registry; -@@ -222,7 +221,5 @@ main (int argc, - return EXIT_FAILURE; - } - -- g_object_unref (display); -- - return EXIT_SUCCESS; - } -diff --git a/src/tests/wayland-test-clients/xdg-toplevel-bounds.c b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c -index 861ae515b..d3c72dad6 100644 ---- a/src/tests/wayland-test-clients/xdg-toplevel-bounds.c -+++ b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c -@@ -29,11 +29,7 @@ typedef enum _State - STATE_WAIT_FOR_FRAME_1, - } State; - --static WaylandDisplay *display; -- - static struct wl_surface *surface; --static struct xdg_surface *xdg_surface; --static struct xdg_toplevel *xdg_toplevel; - - static struct wl_callback *frame_callback; - -@@ -44,15 +40,16 @@ static int32_t pending_bounds_width; - static int32_t pending_bounds_height; - - static void --init_surface (void) -+init_surface (struct xdg_toplevel *xdg_toplevel) - { - xdg_toplevel_set_title (xdg_toplevel, "toplevel-bounds-test"); - wl_surface_commit (surface); - } - - static void --draw_main (int width, -- int height) -+draw_main (WaylandDisplay *display, -+ int width, -+ int height) - { - draw_surface (display, surface, width, height, 0xff00ff00); - } -@@ -94,6 +91,8 @@ handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: -@@ -114,6 +113,8 @@ handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) - { -+ WaylandDisplay *display = data; -+ - switch (state) - { - case STATE_INIT: -@@ -122,7 +123,8 @@ handle_xdg_surface_configure (void *data, - g_assert (pending_bounds_width > 0); - g_assert (pending_bounds_height > 0); - -- draw_main (pending_bounds_width - 10, -+ draw_main (display, -+ pending_bounds_width - 10, - pending_bounds_height - 10); - state = STATE_WAIT_FOR_FRAME_1; - break; -@@ -132,7 +134,7 @@ handle_xdg_surface_configure (void *data, - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); -- wl_callback_add_listener (frame_callback, &frame_listener, NULL); -+ wl_callback_add_listener (frame_callback, &frame_listener, display); - wl_surface_commit (surface); - wl_display_flush (display->display); - } -@@ -154,17 +156,21 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; -+ struct xdg_toplevel *xdg_toplevel; -+ struct xdg_surface *xdg_surface; -+ - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER | - WAYLAND_DISPLAY_CAPABILITY_XDG_SHELL_V4); - g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); - - surface = wl_compositor_create_surface (display->compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); -- xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); -+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, display); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - -- init_surface (); -+ init_surface (xdg_toplevel); - state = STATE_WAIT_FOR_CONFIGURE_1; - - wl_surface_commit (surface); -diff --git a/src/tests/wayland-test-clients/ycbcr.c b/src/tests/wayland-test-clients/ycbcr.c -index 1805abb8d..3ce3ec642 100644 ---- a/src/tests/wayland-test-clients/ycbcr.c -+++ b/src/tests/wayland-test-clients/ycbcr.c -@@ -24,8 +24,6 @@ - - #include "wayland-test-client-utils.h" - --static WaylandDisplay *display; -- - static struct wl_surface *surface; - static struct xdg_surface *xdg_surface; - static struct xdg_toplevel *xdg_toplevel; -@@ -63,8 +61,9 @@ typedef void (*ShaderFunc) (float x, - float *out_cr); - - static void --draw (uint32_t drm_format, -- ShaderFunc shader) -+draw (WaylandDisplay *display, -+ uint32_t drm_format, -+ ShaderFunc shader) - { - WaylandBuffer *buffer; - uint8_t *planes[4]; -@@ -180,7 +179,7 @@ static const struct xdg_surface_listener xdg_surface_listener = { - }; - - static void --wait_for_configure (void) -+wait_for_configure (WaylandDisplay *display) - { - waiting_for_configure = TRUE; - while (waiting_for_configure) -@@ -194,6 +193,7 @@ int - main (int argc, - char **argv) - { -+ g_autoptr (WaylandDisplay) display = NULL; - display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); - - surface = wl_compositor_create_surface (display->compositor); -@@ -205,27 +205,25 @@ main (int argc, - xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); - wl_surface_commit (surface); - -- wait_for_configure (); -+ wait_for_configure (display); - -- draw (DRM_FORMAT_YUYV, shader_luma_gradient); -+ draw (display, DRM_FORMAT_YUYV, shader_luma_gradient); - wl_surface_commit (surface); - wait_for_effects_completed (display, surface); - wait_for_view_verified (display, 0); - -- draw (DRM_FORMAT_YUYV, shader_color_gradient); -+ draw (display, DRM_FORMAT_YUYV, shader_color_gradient); - wl_surface_commit (surface); - wait_for_view_verified (display, 1); - -- draw (DRM_FORMAT_YUV420, shader_luma_gradient); -+ draw (display, DRM_FORMAT_YUV420, shader_luma_gradient); - wl_surface_commit (surface); - wait_for_view_verified (display, 2); - -- draw (DRM_FORMAT_YUV420, shader_color_gradient); -+ draw (display, DRM_FORMAT_YUV420, shader_color_gradient); - wl_surface_commit (surface); - wait_for_view_verified (display, 3); - - g_clear_pointer (&xdg_toplevel, xdg_toplevel_destroy); - g_clear_pointer (&xdg_surface, xdg_surface_destroy); -- -- g_clear_object (&display); - } -diff --git a/src/wayland/meta-drm-timeline.c b/src/wayland/meta-drm-timeline.c -new file mode 100644 -index 000000000..6d86fd19f ---- /dev/null -+++ b/src/wayland/meta-drm-timeline.c -@@ -0,0 +1,269 @@ -+/* -+ * Copyright (C) 2023 NVIDIA Corporation. -+ * -+ * 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 . -+ * -+ * Written by: -+ * Austin Shafer -+ */ -+ -+/** -+ * MetaDrmTimeline -+ * -+ * MetaDrmTimeline is a helper for handling DRM syncobj operations. It -+ * can import DRM syncobjs and export eventfds at a particular point. -+ * -+ * This is heavily inspired by wlroot's wlr_render_timeline, written by -+ * Simon Ser. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#ifdef HAVE_EVENTFD -+#include -+#endif -+ -+#include "meta/util.h" -+#include "wayland/meta-drm-timeline.h" -+ -+enum -+{ -+ PROP_0, -+ -+ PROP_DRM_FD, -+ PROP_SYNCOBJ_FD, -+ -+ N_PROPS -+}; -+ -+typedef struct _MetaDrmTimeline -+{ -+ GObject parent; -+ -+ int drm; -+ int drm_syncobj_fd; -+ uint32_t drm_syncobj; -+} MetaDrmTimeline; -+ -+static GParamSpec *obj_props[N_PROPS]; -+ -+static void initable_iface_init (GInitableIface *initable_iface); -+ -+G_DEFINE_FINAL_TYPE_WITH_CODE (MetaDrmTimeline, meta_drm_timeline, G_TYPE_OBJECT, -+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, -+ initable_iface_init)) -+ -+static void -+meta_drm_timeline_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); -+ -+ switch (prop_id) -+ { -+ case PROP_DRM_FD: -+ g_value_set_int (value, timeline->drm); -+ break; -+ case PROP_SYNCOBJ_FD: -+ g_value_set_int (value, timeline->drm_syncobj_fd); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+meta_drm_timeline_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); -+ int fd; -+ -+ switch (prop_id) -+ { -+ case PROP_DRM_FD: -+ fd = g_value_get_int (value); -+ timeline->drm = fcntl (fd, F_DUPFD_CLOEXEC, 0); -+ break; -+ case PROP_SYNCOBJ_FD: -+ fd = g_value_get_int (value); -+ timeline->drm_syncobj_fd = fcntl (fd, F_DUPFD_CLOEXEC, 0); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static gboolean -+meta_drm_timeline_initable_init (GInitable *initable, -+ GCancellable *cancellable, -+ GError **error) -+{ -+ MetaDrmTimeline *timeline = META_DRM_TIMELINE (initable); -+ -+ if (drmSyncobjFDToHandle (timeline->drm, -+ timeline->drm_syncobj_fd, -+ &timeline->drm_syncobj) != 0) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_FAILED, -+ "Failed to import DRM syncobj"); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void -+initable_iface_init (GInitableIface *initable_iface) -+{ -+ initable_iface->init = meta_drm_timeline_initable_init; -+} -+ -+MetaDrmTimeline * -+meta_drm_timeline_import_syncobj (int fd, -+ int drm_syncobj, -+ GError **error) -+{ -+ MetaDrmTimeline *timeline = g_initable_new (META_TYPE_DRM_TIMELINE, -+ NULL, error, -+ "drm-fd", fd, -+ "syncobj-fd", drm_syncobj, -+ NULL); -+ -+ return timeline; -+} -+ -+int -+meta_drm_timeline_get_eventfd (MetaDrmTimeline *timeline, -+ uint64_t sync_point, -+ GError **error) -+{ -+ g_autofd int fd = -1; -+ -+#ifdef HAVE_EVENTFD -+ fd = eventfd (0, EFD_CLOEXEC); -+ if (fd < 0) -+ return -1; -+ -+ if (drmSyncobjEventfd (timeline->drm, timeline->drm_syncobj, -+ sync_point, fd, 0) != 0) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "DRM_IOCTL_SYNCOBJ_EVENTFD: Failed to export eventfd"); -+ return -1; -+ } -+#endif -+ -+ return g_steal_fd (&fd); -+} -+ -+gboolean -+meta_drm_timeline_set_sync_point (MetaDrmTimeline *timeline, -+ uint64_t sync_point, -+ int sync_fd, -+ GError **error) -+{ -+ uint32_t tmp; -+ -+ /* Import our syncfd at a new release point */ -+ if (drmSyncobjCreate (timeline->drm, 0, &tmp) != 0) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "Failed to create temporary syncobj"); -+ return FALSE; -+ } -+ -+ if (drmSyncobjImportSyncFile (timeline->drm, tmp, sync_fd) != 0) -+ goto end; -+ -+ if (drmSyncobjTransfer (timeline->drm, timeline->drm_syncobj, -+ sync_point, tmp, 0, 0) != 0) -+ goto end; -+ -+ drmSyncobjDestroy (timeline->drm, tmp); -+ return TRUE; -+ -+end: -+ drmSyncobjDestroy (timeline->drm, tmp); -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "Failed to import syncfd at specified point"); -+ return FALSE; -+} -+ -+static void -+meta_drm_timeline_finalize (GObject *object) -+{ -+ MetaDrmTimeline *timeline = META_DRM_TIMELINE (object); -+ -+ drmSyncobjDestroy (timeline->drm, timeline->drm_syncobj); -+ g_clear_fd (&timeline->drm_syncobj_fd, NULL); -+ g_clear_fd (&timeline->drm, NULL); -+ -+ G_OBJECT_CLASS (meta_drm_timeline_parent_class)->finalize (object); -+} -+ -+static void -+meta_drm_timeline_init (MetaDrmTimeline *timeline) -+{ -+ timeline->drm = -1; -+ timeline->drm_syncobj_fd = -1; -+ timeline->drm_syncobj = -1; -+} -+ -+static void -+meta_drm_timeline_class_init (MetaDrmTimelineClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->get_property = meta_drm_timeline_get_property; -+ object_class->set_property = meta_drm_timeline_set_property; -+ object_class->finalize = meta_drm_timeline_finalize; -+ -+ obj_props[PROP_DRM_FD] = -+ g_param_spec_int ("drm-fd", -+ NULL, -+ NULL, -+ 0, INT_MAX, 0, -+ G_PARAM_READWRITE | -+ G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS); -+ -+ obj_props[PROP_SYNCOBJ_FD] = -+ g_param_spec_int ("syncobj-fd", -+ NULL, -+ NULL, -+ 0, INT_MAX, 0, -+ G_PARAM_READWRITE | -+ G_PARAM_CONSTRUCT_ONLY | -+ G_PARAM_STATIC_STRINGS); -+ -+ g_object_class_install_properties (object_class, N_PROPS, obj_props); -+} -diff --git a/src/wayland/meta-drm-timeline.h b/src/wayland/meta-drm-timeline.h -new file mode 100644 -index 000000000..8206e3066 ---- /dev/null -+++ b/src/wayland/meta-drm-timeline.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2023 NVIDIA Corporation. -+ * -+ * 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 . -+ * -+ * Written by: -+ * Austin Shafer -+ */ -+ -+#pragma once -+ -+#include -+#include -+#include -+ -+#define META_TYPE_DRM_TIMELINE (meta_drm_timeline_get_type ()) -+G_DECLARE_FINAL_TYPE (MetaDrmTimeline, meta_drm_timeline, -+ META, DRM_TIMELINE, GObject); -+ -+typedef struct _MetaDrmTimeline MetaDrmTimeline; -+ -+MetaDrmTimeline * meta_drm_timeline_create (int fd, -+ GError **error); -+ -+MetaDrmTimeline * meta_drm_timeline_import_syncobj (int fd, -+ int drm_syncobj, -+ GError **error); -+ -+int meta_drm_timeline_get_eventfd (MetaDrmTimeline *timeline, -+ uint64_t sync_point, -+ GError **error); -+ -+gboolean meta_drm_timeline_set_sync_point (MetaDrmTimeline *timeline, -+ uint64_t sync_point, -+ int sync_fd, -+ GError **error); -diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c -index a2ddcf567..3f64758a5 100644 ---- a/src/wayland/meta-wayland-buffer.c -+++ b/src/wayland/meta-wayland-buffer.c -@@ -49,6 +49,7 @@ - #include "wayland/meta-wayland-buffer.h" - - #include -+#include - - #include "backends/meta-backend-private.h" - #include "clutter/clutter.h" -@@ -57,7 +58,10 @@ - #include "wayland/meta-wayland-dma-buf.h" - #include "wayland/meta-wayland-private.h" - #include "common/meta-cogl-drm-formats.h" -+#include "common/meta-drm-format-helpers.h" - #include "compositor/meta-multi-texture-format-private.h" -+#include "wayland/meta-drm-timeline.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #ifdef HAVE_NATIVE_BACKEND - #include "backends/native/meta-drm-buffer-gbm.h" -@@ -711,12 +715,43 @@ meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer) - void - meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer) - { -+ MetaContext *context = meta_wayland_compositor_get_context (buffer->compositor); -+ MetaBackend *backend = meta_context_get_backend (context); -+ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); -+ CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); -+ MetaWaylandSyncPoint *sync_point; -+ g_autoptr(GError) error = NULL; -+ g_autofd int sync_fd = -1; -+ - g_return_if_fail (buffer->use_count > 0); - - buffer->use_count--; - - if (buffer->use_count == 0 && buffer->resource) -- wl_buffer_send_release (buffer->resource); -+ { -+ wl_buffer_send_release (buffer->resource); -+ -+ sync_fd = cogl_context_get_latest_sync_fd (cogl_context); -+ if (sync_fd < 0) -+ { -+ meta_topic (META_DEBUG_WAYLAND, "Invalid Sync Fd returned by COGL"); -+ return; -+ } -+ -+ for (int i = 0; i < buffer->release_points->len; i++) -+ { -+ sync_point = g_ptr_array_index (buffer->release_points, i); -+ if (!meta_wayland_sync_timeline_set_sync_point (sync_point->timeline, -+ sync_point->sync_point, -+ sync_fd, -+ &error)) -+ { -+ g_warning ("Failed to import sync point: %s", error->message); -+ } -+ } -+ g_ptr_array_remove_range (buffer->release_points, 0, -+ buffer->release_points->len); -+ } - } - - gboolean -@@ -980,6 +1015,7 @@ meta_wayland_buffer_finalize (GObject *object) - - clear_tainted_scanout_onscreens (buffer); - g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); -+ g_clear_pointer (&buffer->release_points, g_ptr_array_unref); - - g_clear_object (&buffer->egl_image.texture); - #ifdef HAVE_WAYLAND_EGLSTREAM -@@ -998,6 +1034,7 @@ meta_wayland_buffer_finalize (GObject *object) - static void - meta_wayland_buffer_init (MetaWaylandBuffer *buffer) - { -+ buffer->release_points = g_ptr_array_new_with_free_func (g_free); - } - - static void -@@ -1090,7 +1127,9 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) - - drm_format = shm_to_drm_format (possible_formats[i]); - format_info = meta_format_info_from_drm_format (drm_format); -- g_assert (format_info); -+ -+ if (!format_info) -+ continue; - - if (!context_supports_format (cogl_context, format_info)) - continue; -diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h -index 23aea7cb2..a0d59f51b 100644 ---- a/src/wayland/meta-wayland-buffer.h -+++ b/src/wayland/meta-wayland-buffer.h -@@ -79,6 +79,8 @@ struct _MetaWaylandBuffer - } single_pixel; - - GHashTable *tainted_scanout_onscreens; -+ -+ GPtrArray *release_points; - }; - - #define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ()) -diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c -index 221df3dc0..5e4ee671c 100644 ---- a/src/wayland/meta-wayland-dma-buf.c -+++ b/src/wayland/meta-wayland-dma-buf.c -@@ -51,11 +51,13 @@ - #include "cogl/cogl-egl.h" - #include "cogl/cogl.h" - #include "common/meta-cogl-drm-formats.h" -+#include "common/meta-drm-format-helpers.h" - #include "compositor/meta-multi-texture-format-private.h" - #include "meta/meta-backend.h" - #include "wayland/meta-wayland-buffer.h" - #include "wayland/meta-wayland-private.h" - #include "wayland/meta-wayland-versions.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #ifdef HAVE_NATIVE_BACKEND - #include "backends/native/meta-drm-buffer-gbm.h" -@@ -1045,6 +1047,39 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, - return &source->base; - } - -+GSource * -+meta_wayland_drm_syncobj_create_source (MetaWaylandBuffer *buffer, -+ MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ MetaWaylandDmaBufSourceDispatch dispatch, -+ gpointer user_data) -+{ -+ MetaWaylandDmaBufSource *source = NULL; -+ g_autofd int sync_fd = -1; -+ g_autoptr(GError) error = NULL; -+ -+ sync_fd = meta_wayland_sync_timeline_get_eventfd (timeline, sync_point, &error); -+ if (sync_fd < 0) -+ { -+ g_warning ("Failed to get sync fd: %s", error->message); -+ return NULL; -+ } -+ -+ if (is_fd_readable (sync_fd)) -+ { -+ return NULL; -+ } -+ -+ source = create_source (buffer, dispatch, user_data); -+ if (!source) -+ return NULL; -+ -+ source->fd_tags[0] = g_source_add_unix_fd (&source->base, sync_fd, G_IO_IN); -+ source->owned_sync_fd[0] = g_steal_fd (&sync_fd); -+ -+ return &source->base; -+} -+ - static void - buffer_params_create_common (struct wl_client *client, - struct wl_resource *params_resource, -diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h -index 8f71dac42..5b2cda734 100644 ---- a/src/wayland/meta-wayland-dma-buf.h -+++ b/src/wayland/meta-wayland-dma-buf.h -@@ -63,6 +63,13 @@ meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer, - MetaWaylandDmaBufSourceDispatch dispatch, - gpointer user_data); - -+GSource * -+meta_wayland_drm_syncobj_create_source (MetaWaylandBuffer *buffer, -+ MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ MetaWaylandDmaBufSourceDispatch dispatch, -+ gpointer user_data); -+ - CoglScanout * - meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, - CoglOnscreen *onscreen, -diff --git a/src/wayland/meta-wayland-linux-drm-syncobj.c b/src/wayland/meta-wayland-linux-drm-syncobj.c -new file mode 100644 -index 000000000..a922415d9 ---- /dev/null -+++ b/src/wayland/meta-wayland-linux-drm-syncobj.c -@@ -0,0 +1,637 @@ -+/* -+ * Copyright (C) 2023 NVIDIA Corporation. -+ * -+ * 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 . -+ * -+ * Written by: -+ * Austin Shafer -+ */ -+ -+#include "config.h" -+ -+#include "backends/native/meta-backend-native-types.h" -+#include "backends/native/meta-device-pool.h" -+#include "backends/native/meta-renderer-native.h" -+#include "meta/util.h" -+#include "wayland/meta-wayland-buffer.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" -+#include "wayland/meta-wayland-private.h" -+#include -+#include -+ -+typedef struct _MetaWaylandDrmSyncobjManager -+{ -+ GObject parent; -+ -+ int drm; -+} MetaWaylandDrmSyncobjManager; -+ -+typedef struct _MetaWaylandSyncobjSurface -+{ -+ GObject parent; -+ -+ struct wl_resource *resource; -+ MetaWaylandSurface *surface; -+ gulong surface_destroy_handler_id; -+} MetaWaylandSyncobjSurface; -+ -+typedef struct _MetaWaylandSyncobjTimeline -+{ -+ GObject parent; -+ -+ MetaDrmTimeline *drm_timeline; -+} MetaWaylandSyncobjTimeline; -+ -+#define META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER (meta_wayland_drm_syncobj_manager_get_type ()) -+G_DECLARE_FINAL_TYPE (MetaWaylandDrmSyncobjManager, meta_wayland_drm_syncobj_manager, -+ META, WAYLAND_DRM_SYNCOBJ_MANAGER, GObject) -+ -+#define META_TYPE_WAYLAND_SYNCOBJ_SURFACE (meta_wayland_syncobj_surface_get_type ()) -+G_DECLARE_FINAL_TYPE (MetaWaylandSyncobjSurface, meta_wayland_syncobj_surface, -+ META, WAYLAND_SYNCOBJ_SURFACE, GObject) -+ -+#define META_TYPE_WAYLAND_SYNCOBJ_TIMELINE (meta_wayland_syncobj_timeline_get_type ()) -+G_DECLARE_FINAL_TYPE (MetaWaylandSyncobjTimeline, meta_wayland_syncobj_timeline, -+ META, WAYLAND_SYNCOBJ_TIMELINE, GObject) -+ -+#define META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER (meta_wayland_drm_syncobj_manager_get_type ()) -+G_DEFINE_FINAL_TYPE (MetaWaylandDrmSyncobjManager, meta_wayland_drm_syncobj_manager, -+ G_TYPE_OBJECT) -+ -+#define META_TYPE_WAYLAND_SYNCOBJ_SURFACE (meta_wayland_syncobj_surface_get_type ()) -+G_DEFINE_FINAL_TYPE (MetaWaylandSyncobjSurface, meta_wayland_syncobj_surface, -+ G_TYPE_OBJECT) -+ -+#define META_TYPE_WAYLAND_SYNCOBJ_TIMELINE (meta_wayland_syncobj_timeline_get_type ()) -+G_DEFINE_FINAL_TYPE (MetaWaylandSyncobjTimeline, meta_wayland_syncobj_timeline, -+ G_TYPE_OBJECT) -+ -+G_DEFINE_FINAL_TYPE (MetaWaylandSyncPoint, meta_wayland_sync_point, G_TYPE_OBJECT); -+ -+static GQuark quark_syncobj_surface; -+ -+static void -+meta_wayland_sync_point_set (MetaWaylandSyncPoint **sync_point_ptr, -+ MetaWaylandSyncobjTimeline *syncobj_timeline, -+ uint32_t point_hi, -+ uint32_t point_lo) -+{ -+ MetaWaylandSyncPoint *sync_point; -+ -+ if (!*sync_point_ptr) -+ *sync_point_ptr = g_object_new (META_TYPE_WAYLAND_SYNC_POINT, NULL); -+ -+ sync_point = *sync_point_ptr; -+ g_set_object (&sync_point->timeline, syncobj_timeline); -+ sync_point->sync_point = (uint64_t)point_hi << 32 | point_lo; -+} -+ -+static void -+meta_wayland_sync_point_finalize (GObject *object) -+{ -+ MetaWaylandSyncPoint *sync = META_WAYLAND_SYNC_POINT (object); -+ -+ g_object_unref (sync->timeline); -+ -+ G_OBJECT_CLASS (meta_wayland_sync_point_parent_class)->finalize (object); -+} -+ -+static void -+meta_wayland_sync_point_init (MetaWaylandSyncPoint *sync) -+{ -+} -+ -+static void -+meta_wayland_sync_point_class_init (MetaWaylandSyncPointClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = meta_wayland_sync_point_finalize; -+} -+ -+static void -+syncobj_timeline_handle_resource_destroy (struct wl_resource *resource) -+{ -+ MetaWaylandSyncobjTimeline *syncobj_timeline = -+ wl_resource_get_user_data (resource); -+ g_object_unref (syncobj_timeline); -+} -+ -+static void -+meta_wayland_syncobj_timeline_finalize (GObject *object) -+{ -+ MetaWaylandSyncobjTimeline *syncobj_timeline = -+ META_WAYLAND_SYNCOBJ_TIMELINE (object); -+ -+ g_clear_object (&syncobj_timeline->drm_timeline); -+ -+ G_OBJECT_CLASS (meta_wayland_syncobj_timeline_parent_class)->finalize (object); -+} -+ -+static void -+meta_wayland_syncobj_timeline_class_init (MetaWaylandSyncobjTimelineClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = meta_wayland_syncobj_timeline_finalize; -+} -+ -+static void -+meta_wayland_syncobj_timeline_init (MetaWaylandSyncobjTimeline *syncobj_timeline) -+{ -+ syncobj_timeline->drm_timeline = NULL; -+} -+ -+static void -+syncobj_timeline_handle_destroy (struct wl_client *client, -+ struct wl_resource *resource) -+{ -+ wl_resource_destroy (resource); -+} -+ -+static const struct wp_linux_drm_syncobj_timeline_v1_interface -+ syncobj_timeline_implementation = -+{ -+ syncobj_timeline_handle_destroy, -+}; -+ -+gboolean -+meta_wayland_sync_timeline_set_sync_point (MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ int sync_fd, -+ GError **error) -+{ -+ return meta_drm_timeline_set_sync_point (timeline->drm_timeline, -+ sync_point, -+ sync_fd, -+ error); -+} -+ -+int -+meta_wayland_sync_timeline_get_eventfd (MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ GError **error) -+{ -+ return meta_drm_timeline_get_eventfd (timeline->drm_timeline, -+ sync_point, -+ error); -+} -+ -+static void -+syncobj_surface_handle_destroy (struct wl_client *client, -+ struct wl_resource *resource) -+{ -+ wl_resource_destroy (resource); -+} -+ -+static void -+syncobj_surface_handle_set_acquire_point (struct wl_client *client, -+ struct wl_resource *resource, -+ struct wl_resource *timeline_resource, -+ uint32_t point_hi, -+ uint32_t point_lo) -+{ -+ MetaWaylandSyncobjSurface *syncobj_surface = wl_resource_get_user_data (resource); -+ MetaWaylandSurface *surface = syncobj_surface->surface; -+ MetaWaylandSyncobjTimeline *syncobj_timeline = -+ wl_resource_get_user_data (timeline_resource); -+ -+ if (!surface) -+ { -+ wl_resource_post_error (resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, -+ "Underlying surface object has been destroyed"); -+ return; -+ } -+ -+ meta_wayland_sync_point_set (&surface->pending_state->drm_syncobj.acquire, -+ syncobj_timeline, -+ point_hi, -+ point_lo); -+} -+ -+static void syncobj_surface_handle_set_release_point (struct wl_client *client, -+ struct wl_resource *resource, -+ struct wl_resource *timeline_resource, -+ uint32_t point_hi, -+ uint32_t point_lo) -+{ -+ MetaWaylandSyncobjSurface *syncobj_surface = wl_resource_get_user_data (resource); -+ MetaWaylandSurface *surface = syncobj_surface->surface; -+ MetaWaylandSyncobjTimeline *syncobj_timeline = -+ wl_resource_get_user_data (timeline_resource); -+ -+ if (!surface) -+ { -+ wl_resource_post_error (resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, -+ "Underlying surface object has been destroyed"); -+ return; -+ } -+ -+ meta_wayland_sync_point_set (&surface->pending_state->drm_syncobj.release, -+ syncobj_timeline, -+ point_hi, -+ point_lo); -+} -+ -+static const struct wp_linux_drm_syncobj_surface_v1_interface -+ syncobj_surface_implementation = -+{ -+ syncobj_surface_handle_destroy, -+ syncobj_surface_handle_set_acquire_point, -+ syncobj_surface_handle_set_release_point, -+}; -+ -+static void -+syncobj_surface_resource_destroyed (MetaWaylandSurface *surface, -+ MetaWaylandSyncobjSurface *syncobj_surface) -+{ -+ g_clear_signal_handler (&syncobj_surface->surface_destroy_handler_id, -+ syncobj_surface->surface); -+ -+ g_object_set_qdata (G_OBJECT (syncobj_surface->surface), -+ quark_syncobj_surface, -+ NULL); -+ -+ syncobj_surface->surface = NULL; -+} -+ -+static void -+syncobj_surface_destructor (struct wl_resource *resource) -+{ -+ MetaWaylandSyncobjSurface *syncobj_surface = -+ wl_resource_get_user_data (resource); -+ -+ if (syncobj_surface->surface) -+ syncobj_surface_resource_destroyed (syncobj_surface->surface, syncobj_surface); -+ -+ g_object_unref (syncobj_surface); -+} -+ -+static void -+meta_wayland_syncobj_surface_class_init (MetaWaylandSyncobjSurfaceClass *klass) -+{ -+} -+ -+static void -+meta_wayland_syncobj_surface_init (MetaWaylandSyncobjSurface *syncobj_surface) -+{ -+} -+ -+static void -+drm_syncobj_manager_handle_destroy (struct wl_client *client, -+ struct wl_resource *resource) -+{ -+ wl_resource_destroy (resource); -+} -+ -+static void -+drm_syncobj_manager_handle_get_surface (struct wl_client *client, -+ struct wl_resource *resource, -+ uint32_t id, -+ struct wl_resource *surface_resource) -+{ -+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); -+ MetaWaylandSyncobjSurface *syncobj_surface = -+ g_object_get_qdata (G_OBJECT (surface), quark_syncobj_surface); -+ struct wl_resource *sync_resource; -+ -+ if (syncobj_surface) -+ { -+ wl_resource_post_error (surface_resource, -+ WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, -+ "DRM Syncobj surface object already created for surface %d", -+ wl_resource_get_id (surface_resource)); -+ return; -+ } -+ -+ sync_resource = -+ wl_resource_create (client, -+ &wp_linux_drm_syncobj_surface_v1_interface, -+ wl_resource_get_version (resource), -+ id); -+ if (sync_resource == NULL) -+ { -+ wl_resource_post_no_memory (resource); -+ return; -+ } -+ -+ syncobj_surface = g_object_new (META_TYPE_WAYLAND_SYNCOBJ_SURFACE, NULL); -+ syncobj_surface->surface = surface; -+ syncobj_surface->surface_destroy_handler_id = -+ g_signal_connect (surface, -+ "destroy", -+ G_CALLBACK (syncobj_surface_resource_destroyed), -+ syncobj_surface); -+ -+ g_object_set_qdata (G_OBJECT (surface), -+ quark_syncobj_surface, -+ syncobj_surface); -+ -+ wl_resource_set_implementation (sync_resource, -+ &syncobj_surface_implementation, -+ syncobj_surface, -+ syncobj_surface_destructor); -+ syncobj_surface->resource = sync_resource; -+} -+ -+static void -+drm_syncobj_manager_handle_import_timeline (struct wl_client *client, -+ struct wl_resource *resource, -+ uint32_t id, -+ int drm_syncobj_fd) -+{ -+ MetaWaylandDrmSyncobjManager *drm_syncobj = wl_resource_get_user_data (resource); -+ g_autoptr (GError) error = NULL; -+ g_autoptr (MetaDrmTimeline) drm_timeline = NULL; -+ g_autoptr (MetaWaylandSyncobjTimeline) syncobj_timeline = NULL; -+ struct wl_resource *timeline_resource; -+ -+ drm_timeline = meta_drm_timeline_import_syncobj (drm_syncobj->drm, -+ drm_syncobj_fd, -+ &error); -+ close (drm_syncobj_fd); -+ if (!drm_timeline) -+ { -+ wl_resource_post_error (resource, -+ WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, -+ "Failed to import DRM syncobj: %s", -+ error->message); -+ return; -+ } -+ -+ syncobj_timeline = g_object_new (META_TYPE_WAYLAND_SYNCOBJ_TIMELINE, NULL); -+ -+ timeline_resource = wl_resource_create (client, -+ &wp_linux_drm_syncobj_timeline_v1_interface, -+ wl_resource_get_version (resource), -+ id); -+ if (timeline_resource == NULL) -+ { -+ wl_resource_post_no_memory (resource); -+ return; -+ } -+ -+ syncobj_timeline->drm_timeline = g_steal_pointer (&drm_timeline); -+ wl_resource_set_implementation (timeline_resource, -+ &syncobj_timeline_implementation, -+ g_steal_pointer (&syncobj_timeline), -+ syncobj_timeline_handle_resource_destroy); -+} -+ -+static const struct wp_linux_drm_syncobj_manager_v1_interface -+ drm_syncobj_manager_implementation = -+{ -+ drm_syncobj_manager_handle_destroy, -+ drm_syncobj_manager_handle_get_surface, -+ drm_syncobj_manager_handle_import_timeline, -+}; -+ -+static void -+meta_wayland_drm_syncobj_manager_finalize (GObject *object) -+{ -+ MetaWaylandDrmSyncobjManager *drm_syncobj = -+ META_WAYLAND_DRM_SYNCOBJ_MANAGER (object); -+ -+ g_clear_fd (&drm_syncobj->drm, NULL); -+ -+ G_OBJECT_CLASS (meta_wayland_drm_syncobj_manager_parent_class)->finalize (object); -+} -+ -+static void -+meta_wayland_drm_syncobj_manager_class_init (MetaWaylandDrmSyncobjManagerClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = meta_wayland_drm_syncobj_manager_finalize; -+ -+ quark_syncobj_surface = g_quark_from_static_string ("drm-syncobj-quark"); -+} -+ -+static void -+meta_wayland_drm_syncobj_manager_init (MetaWaylandDrmSyncobjManager *drm_syncobj) -+{ -+ drm_syncobj->drm = -1; -+} -+ -+static void -+drm_syncobj_manager_bind (struct wl_client *client, -+ void *user_data, -+ uint32_t version, -+ uint32_t id) -+{ -+ MetaWaylandDrmSyncobjManager *drm_syncobj_manager = user_data; -+ struct wl_resource *resource; -+ -+ resource = wl_resource_create (client, -+ &wp_linux_drm_syncobj_manager_v1_interface, -+ version, -+ id); -+ wl_resource_set_implementation (resource, -+ &drm_syncobj_manager_implementation, -+ drm_syncobj_manager, -+ NULL); -+} -+ -+static MetaWaylandDrmSyncobjManager * -+meta_wayland_drm_syncobj_manager_new (MetaWaylandCompositor *compositor, -+ GError **error) -+{ -+ MetaContext *context = -+ meta_wayland_compositor_get_context (compositor); -+ MetaBackend *backend = meta_context_get_backend (context); -+ MetaEgl *egl = meta_backend_get_egl (backend); -+ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); -+ CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); -+ EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); -+ MetaWaylandDrmSyncobjManager *drm_syncobj_manager; -+ EGLDeviceEXT egl_device; -+ g_autofd int drm_fd = -1; -+ EGLAttrib attrib; -+ uint64_t timeline_supported = false; -+ const char *device_path = NULL; -+ -+ g_assert (backend && egl && clutter_backend && cogl_context && egl_display); -+ -+ if (!meta_egl_query_display_attrib (egl, egl_display, -+ EGL_DEVICE_EXT, &attrib, -+ error)) -+ return NULL; -+ -+ egl_device = (EGLDeviceEXT) attrib; -+ -+ if (meta_egl_egl_device_has_extensions (egl, egl_device, NULL, -+ "EGL_EXT_device_drm_render_node", -+ NULL)) -+ { -+ if (!meta_egl_query_device_string (egl, egl_device, -+ EGL_DRM_RENDER_NODE_FILE_EXT, -+ &device_path, error)) -+ return NULL; -+ } -+ -+ if (!device_path && -+ meta_egl_egl_device_has_extensions (egl, egl_device, NULL, -+ "EGL_EXT_device_drm", -+ NULL)) -+ { -+ if (!meta_egl_query_device_string (egl, egl_device, -+ EGL_DRM_DEVICE_FILE_EXT, -+ &device_path, error)) -+ return NULL; -+ } -+ -+ if (!device_path) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "Failed to find EGL device to initialize linux-drm-syncobj-v1"); -+ return NULL; -+ } -+ -+ drm_fd = open (device_path, O_RDWR | O_CLOEXEC); -+ if (drm_fd < 0) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_FAILED, -+ "Failed to open DRM device %s", -+ device_path); -+ return NULL; -+ } -+ -+ if (drmGetCap (drm_fd, DRM_CAP_SYNCOBJ_TIMELINE, &timeline_supported) != 0 -+ || !timeline_supported) -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "Failed to check DRM syncobj timeline capability"); -+ return NULL; -+ } -+ -+#ifdef HAVE_EVENTFD -+ if (drmSyncobjEventfd (drm_fd, 0, 0, -1, 0) != -1 || errno != ENOENT) -+#endif -+ { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ "drmSyncobjEventfd failed: linux-drm-syncobj requires eventfd support"); -+ return NULL; -+ } -+ -+ drm_syncobj_manager = g_object_new (META_TYPE_WAYLAND_DRM_SYNCOBJ_MANAGER, NULL); -+ drm_syncobj_manager->drm = g_steal_fd (&drm_fd); -+ -+ if (!wl_global_create (compositor->wayland_display, -+ &wp_linux_drm_syncobj_manager_v1_interface, -+ 1, -+ drm_syncobj_manager, -+ drm_syncobj_manager_bind)) -+ { -+ g_error ("Failed to create wp_linux_drm_syncobj_manager_v1_interface global"); -+ } -+ -+ return drm_syncobj_manager; -+} -+ -+void -+meta_wayland_drm_syncobj_init (MetaWaylandCompositor *compositor) -+{ -+ g_autoptr (GError) error = NULL; -+ MetaWaylandDrmSyncobjManager *manager = -+ meta_wayland_drm_syncobj_manager_new (compositor, &error); -+ -+ if (!manager) -+ { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) -+ { -+ meta_topic (META_DEBUG_WAYLAND, "Disabling explicit sync: %s", -+ error->message); -+ } -+ else -+ { -+ g_warning ("Failed to create linux-drm-syncobj-manager: %s", -+ error->message); -+ } -+ return; -+ } -+ -+ g_object_set_data_full (G_OBJECT (compositor), "-meta-wayland-drm-syncobj-manager", -+ manager, -+ g_object_unref); -+} -+ -+/* -+ * Validate that the appropriate acquire and release points have been set -+ * for this surface. -+ */ -+bool -+meta_wayland_surface_explicit_sync_validate (MetaWaylandSurface *surface, -+ MetaWaylandSurfaceState *state) -+{ -+ MetaWaylandSyncobjSurface *syncobj_surface = g_object_get_qdata (G_OBJECT (surface), -+ quark_syncobj_surface); -+ -+ if (!syncobj_surface) -+ return TRUE; -+ -+ if (state->buffer) -+ { -+ if (state->buffer->type != META_WAYLAND_BUFFER_TYPE_DMA_BUF) -+ { -+ wl_resource_post_error (syncobj_surface->resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_UNSUPPORTED_BUFFER, -+ "Explicit Sync only supported on dmabuf buffers"); -+ return FALSE; -+ } -+ -+ if (!state->drm_syncobj.acquire) -+ { -+ wl_resource_post_error (syncobj_surface->resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, -+ "No Acquire point provided"); -+ return FALSE; -+ } -+ -+ if (!state->drm_syncobj.release) -+ { -+ wl_resource_post_error (syncobj_surface->resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT, -+ "No Release point provided"); -+ return FALSE; -+ } -+ -+ if (state->drm_syncobj.acquire->timeline == state->drm_syncobj.release->timeline && -+ state->drm_syncobj.acquire->sync_point >= state->drm_syncobj.release->sync_point) -+ { -+ wl_resource_post_error (syncobj_surface->resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, -+ "Invalid Release and Acquire point combination"); -+ return FALSE; -+ } -+ } -+ else if (state->drm_syncobj.acquire || state->drm_syncobj.release) -+ { -+ wl_resource_post_error (syncobj_surface->resource, -+ WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, -+ "Release or Acquire point set but no buffer attached"); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -diff --git a/src/wayland/meta-wayland-linux-drm-syncobj.h b/src/wayland/meta-wayland-linux-drm-syncobj.h -new file mode 100644 -index 000000000..cfe361b7c ---- /dev/null -+++ b/src/wayland/meta-wayland-linux-drm-syncobj.h -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2023 NVIDIA Corporation. -+ * -+ * 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 . -+ * -+ * Written by: -+ * Austin Shafer -+ */ -+ -+#pragma once -+ -+#include -+ -+#include "wayland/meta-wayland-types.h" -+#include "wayland/meta-drm-timeline.h" -+ -+#include "linux-drm-syncobj-v1-server-protocol.h" -+ -+#define META_TYPE_WAYLAND_SYNC_POINT (meta_wayland_sync_point_get_type ()) -+G_DECLARE_FINAL_TYPE (MetaWaylandSyncPoint, -+ meta_wayland_sync_point, -+ META, WAYLAND_SYNC_POINT, -+ GObject) -+ -+typedef struct _MetaWaylandSyncPoint { -+ GObject parent; -+ -+ MetaWaylandSyncobjTimeline *timeline; -+ uint64_t sync_point; -+} MetaWaylandSyncPoint; -+ -+bool -+meta_wayland_surface_explicit_sync_validate (MetaWaylandSurface *surface, -+ MetaWaylandSurfaceState *state); -+ -+void -+meta_wayland_drm_syncobj_init (MetaWaylandCompositor *compositor); -+ -+gboolean -+meta_wayland_sync_timeline_set_sync_point (MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ int sync_fd, -+ GError **error); -+ -+int -+meta_wayland_sync_timeline_get_eventfd (MetaWaylandSyncobjTimeline *timeline, -+ uint64_t sync_point, -+ GError **error); -diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c -index ebbe533c3..ea4d4608c 100644 ---- a/src/wayland/meta-wayland-seat.c -+++ b/src/wayland/meta-wayland-seat.c -@@ -531,6 +531,8 @@ void - meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, - MetaWaylandSurface *surface) - { -+ ClutterSeat *clutter_seat; -+ - if (seat->input_focus == surface) - return; - -@@ -551,16 +553,10 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, - seat); - } - -- if (meta_wayland_seat_has_keyboard (seat)) -- { -- meta_wayland_keyboard_set_focus (seat->keyboard, surface); -- meta_wayland_data_device_set_keyboard_focus (&seat->data_device); -- meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device); -- } -- -- meta_wayland_tablet_seat_set_pad_focus (seat->tablet_seat, surface); -- -- meta_wayland_text_input_set_focus (seat->text_input, surface); -+ clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); -+ meta_wayland_input_invalidate_focus (seat->input_handler, -+ clutter_seat_get_keyboard (clutter_seat), -+ NULL); - } - - MetaWaylandSurface * -diff --git a/src/wayland/meta-wayland-single-pixel-buffer.c b/src/wayland/meta-wayland-single-pixel-buffer.c -index 5b23b917a..be93de802 100644 ---- a/src/wayland/meta-wayland-single-pixel-buffer.c -+++ b/src/wayland/meta-wayland-single-pixel-buffer.c -@@ -122,7 +122,10 @@ meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture *tex_2d; - - if (buffer->single_pixel.texture) -- return TRUE; -+ { -+ *texture = g_object_ref (buffer->single_pixel.texture); -+ return TRUE; -+ } - - data[0] = single_pixel_buffer->b / (UINT32_MAX / 0xff); - data[1] = single_pixel_buffer->g / (UINT32_MAX / 0xff); -diff --git a/src/wayland/meta-wayland-surface-private.h b/src/wayland/meta-wayland-surface-private.h -index 2b61a2fc8..e3a88c0a3 100644 ---- a/src/wayland/meta-wayland-surface-private.h -+++ b/src/wayland/meta-wayland-surface-private.h -@@ -29,6 +29,7 @@ - #include "meta/meta-wayland-surface.h" - #include "wayland/meta-wayland-pointer-constraints.h" - #include "wayland/meta-wayland-types.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #define META_TYPE_WAYLAND_SURFACE_ROLE (meta_wayland_surface_role_get_type ()) - G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRole, meta_wayland_surface_role, -@@ -128,6 +129,12 @@ struct _MetaWaylandSurfaceState - /* xdg_popup */ - MetaWaylandXdgPositioner *xdg_positioner; - uint32_t xdg_popup_reposition_token; -+ -+ /* Explicit Synchronization */ -+ struct { -+ MetaWaylandSyncPoint *acquire; -+ MetaWaylandSyncPoint *release; -+ } drm_syncobj; - }; - - struct _MetaWaylandDragDestFuncs -diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index b132504d3..6dc5006b7 100644 ---- a/src/wayland/meta-wayland-surface.c -+++ b/src/wayland/meta-wayland-surface.c -@@ -48,6 +48,7 @@ - #include "wayland/meta-wayland-viewporter.h" - #include "wayland/meta-wayland-xdg-shell.h" - #include "wayland/meta-window-wayland.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #ifdef HAVE_XWAYLAND - #include "wayland/meta-xwayland-private.h" -@@ -446,6 +447,9 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) - wl_list_init (&state->presentation_feedback_list); - - state->xdg_popup_reposition_token = 0; -+ -+ state->drm_syncobj.acquire = NULL; -+ state->drm_syncobj.release = NULL; - } - - static void -@@ -466,6 +470,8 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) - MetaWaylandFrameCallback *cb, *next; - - g_clear_object (&state->texture); -+ g_clear_object (&state->drm_syncobj.acquire); -+ g_clear_object (&state->drm_syncobj.release); - - g_clear_pointer (&state->surface_damage, mtk_region_unref); - g_clear_pointer (&state->buffer_damage, mtk_region_unref); -@@ -630,6 +636,11 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, - to->xdg_positioner = g_steal_pointer (&from->xdg_positioner); - to->xdg_popup_reposition_token = from->xdg_popup_reposition_token; - } -+ -+ g_set_object (&to->drm_syncobj.acquire, from->drm_syncobj.acquire); -+ g_clear_object (&from->drm_syncobj.acquire); -+ g_set_object (&to->drm_syncobj.release, from->drm_syncobj.release); -+ g_clear_object (&from->drm_syncobj.release); - } - - static void -@@ -914,6 +925,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) - MetaWaylandBuffer *buffer = pending->buffer; - MetaWaylandTransaction *transaction; - MetaWaylandSurface *subsurface_surface; -+ MetaWaylandSyncPoint *release_point = pending->drm_syncobj.release; - - COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, - "Meta::WaylandSurface::commit()"); -@@ -921,6 +933,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) - if (pending->scale > 0) - surface->committed_state.scale = pending->scale; - -+ if (!meta_wayland_surface_explicit_sync_validate (surface, pending)) -+ return; -+ - if (buffer) - { - g_autoptr (GError) error = NULL; -@@ -946,6 +961,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) - - pending->texture = g_object_ref (surface->committed_state.texture); - -+ if (release_point) -+ g_ptr_array_add (buffer->release_points, g_object_ref (release_point)); -+ - g_object_ref (buffer); - meta_wayland_buffer_inc_use_count (buffer); - } -diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c -index 70f2b4047..694ce6dbe 100644 ---- a/src/wayland/meta-wayland-transaction.c -+++ b/src/wayland/meta-wayland-transaction.c -@@ -26,6 +26,7 @@ - #include "wayland/meta-wayland.h" - #include "wayland/meta-wayland-buffer.h" - #include "wayland/meta-wayland-dma-buf.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE) - -@@ -314,6 +315,17 @@ meta_wayland_transaction_dma_buf_dispatch (MetaWaylandBuffer *buffer, - meta_wayland_transaction_maybe_apply (transaction); - } - -+static void -+ensure_buf_sources (MetaWaylandTransaction *transaction) -+{ -+ if (!transaction->buf_sources) -+ { -+ transaction->buf_sources = -+ g_hash_table_new_full (NULL, NULL, NULL, -+ (GDestroyNotify) g_source_destroy); -+ } -+} -+ - static gboolean - meta_wayland_transaction_add_dma_buf_source (MetaWaylandTransaction *transaction, - MetaWaylandBuffer *buffer) -@@ -330,12 +342,35 @@ meta_wayland_transaction_add_dma_buf_source (MetaWaylandTransaction *transaction - if (!source) - return FALSE; - -- if (!transaction->buf_sources) -- { -- transaction->buf_sources = -- g_hash_table_new_full (NULL, NULL, NULL, -- (GDestroyNotify) g_source_destroy); -- } -+ ensure_buf_sources (transaction); -+ -+ g_hash_table_insert (transaction->buf_sources, buffer, source); -+ g_source_attach (source, NULL); -+ g_source_unref (source); -+ -+ return TRUE; -+} -+ -+static gboolean -+meta_wayland_transaction_add_drm_syncobj_source (MetaWaylandTransaction *transaction, -+ MetaWaylandBuffer *buffer, -+ MetaWaylandSyncPoint *acquire) -+{ -+ GSource *source; -+ -+ if (transaction->buf_sources && -+ g_hash_table_contains (transaction->buf_sources, buffer)) -+ return FALSE; -+ -+ source = meta_wayland_drm_syncobj_create_source (buffer, -+ acquire->timeline, -+ acquire->sync_point, -+ meta_wayland_transaction_dma_buf_dispatch, -+ transaction); -+ if (!source) -+ return FALSE; -+ -+ ensure_buf_sources (transaction); - - g_hash_table_insert (transaction->buf_sources, buffer, source); - g_source_attach (source, NULL); -@@ -382,8 +417,11 @@ meta_wayland_transaction_commit (MetaWaylandTransaction *transaction) - { - MetaWaylandBuffer *buffer = entry->state->buffer; - -- if (buffer && -- meta_wayland_transaction_add_dma_buf_source (transaction, buffer)) -+ if ((entry->state->drm_syncobj.acquire && -+ meta_wayland_transaction_add_drm_syncobj_source (transaction, buffer, -+ entry->state->drm_syncobj.acquire)) -+ || (buffer && -+ meta_wayland_transaction_add_dma_buf_source (transaction, buffer))) - maybe_apply = FALSE; - - if (entry->state->subsurface_placement_ops) -diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h -index 40c3bb733..4f224a900 100644 ---- a/src/wayland/meta-wayland-types.h -+++ b/src/wayland/meta-wayland-types.h -@@ -60,6 +60,8 @@ typedef struct _MetaWaylandActivation MetaWaylandActivation; - - typedef struct _MetaWaylandDmaBufManager MetaWaylandDmaBufManager; - -+typedef struct _MetaWaylandSyncobjTimeline MetaWaylandSyncobjTimeline; -+ - typedef struct _MetaWaylandXdgPositioner MetaWaylandXdgPositioner; - - typedef struct _MetaXWaylandManager MetaXWaylandManager; -diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c -index 4298d1eec..56fa77ad6 100644 ---- a/src/wayland/meta-wayland-window-configuration.c -+++ b/src/wayland/meta-wayland-window-configuration.c -@@ -100,14 +100,15 @@ meta_wayland_window_configuration_new_relative (MetaWindow *window, - - MetaWaylandWindowConfiguration * - meta_wayland_window_configuration_new_empty (int bounds_width, -- int bounds_height) -+ int bounds_height, -+ int scale) - { - MetaWaylandWindowConfiguration *configuration; - - configuration = g_new0 (MetaWaylandWindowConfiguration, 1); - *configuration = (MetaWaylandWindowConfiguration) { - .serial = ++global_serial_counter, -- .scale = 1, -+ .scale = scale, - .bounds_width = bounds_width, - .bounds_height = bounds_height, - }; -diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h -index 064e73ea1..fb26344bb 100644 ---- a/src/wayland/meta-wayland-window-configuration.h -+++ b/src/wayland/meta-wayland-window-configuration.h -@@ -68,6 +68,7 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative - int scale); - - MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (int bounds_width, -- int bounds_height); -+ int bounds_height, -+ int scale); - - void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); -diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c -index 28b39577b..ff1b7a11a 100644 ---- a/src/wayland/meta-wayland-xdg-shell.c -+++ b/src/wayland/meta-wayland-xdg-shell.c -@@ -869,6 +869,9 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandWindowConfiguration *configuration; - int bounds_width; - int bounds_height; -+ int geometry_scale; -+ -+ geometry_scale = meta_window_wayland_get_geometry_scale (window); - - if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) - { -@@ -878,7 +881,8 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, - - configuration = - meta_wayland_window_configuration_new_empty (bounds_width, -- bounds_height); -+ bounds_height, -+ geometry_scale); - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); - meta_wayland_window_configuration_free (configuration); - return; -diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c -index 7a24cf6b4..501b69a91 100644 ---- a/src/wayland/meta-wayland.c -+++ b/src/wayland/meta-wayland.c -@@ -57,6 +57,7 @@ - #include "wayland/meta-wayland-tablet-manager.h" - #include "wayland/meta-wayland-transaction.h" - #include "wayland/meta-wayland-xdg-foreign.h" -+#include "wayland/meta-wayland-linux-drm-syncobj.h" - - #ifdef HAVE_XWAYLAND - #include "wayland/meta-wayland-x11-interop.h" -@@ -868,6 +869,7 @@ meta_wayland_compositor_new (MetaContext *context) - meta_wayland_activation_init (compositor); - meta_wayland_transaction_init (compositor); - meta_wayland_idle_inhibit_init (compositor); -+ meta_wayland_drm_syncobj_init (compositor); - - #ifdef HAVE_WAYLAND_EGLSTREAM - { -diff --git a/src/wayland/protocol/linux-drm-syncobj-v1.xml b/src/wayland/protocol/linux-drm-syncobj-v1.xml -new file mode 100644 -index 000000000..2c491eaf4 ---- /dev/null -+++ b/src/wayland/protocol/linux-drm-syncobj-v1.xml -@@ -0,0 +1,261 @@ -+ -+ -+ -+ Copyright 2016 The Chromium Authors. -+ Copyright 2017 Intel Corporation -+ Copyright 2018 Collabora, Ltd -+ Copyright 2021 Simon Ser -+ -+ Permission is hereby granted, free of charge, to any person obtaining a -+ copy of this software and associated documentation files (the "Software"), -+ to deal in the Software without restriction, including without limitation -+ the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ and/or sell copies of the Software, and to permit persons to whom the -+ Software is furnished to do so, subject to the following conditions: -+ -+ The above copyright notice and this permission notice (including the next -+ paragraph) shall be included in all copies or substantial portions of the -+ Software. -+ -+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ DEALINGS IN THE SOFTWARE. -+ -+ -+ -+ This protocol allows clients to request explicit synchronization for -+ buffers. It is tied to the Linux DRM synchronization object framework. -+ -+ Synchronization refers to co-ordination of pipelined operations performed -+ on buffers. Most GPU clients will schedule an asynchronous operation to -+ render to the buffer, then immediately send the buffer to the compositor -+ to be attached to a surface. -+ -+ With implicit synchronization, ensuring that the rendering operation is -+ complete before the compositor displays the buffer is an implementation -+ detail handled by either the kernel or userspace graphics driver. -+ -+ By contrast, with explicit synchronization, DRM synchronization object -+ timeline points mark when the asynchronous operations are complete. When -+ submitting a buffer, the client provides a timeline point which will be -+ waited on before the compositor accesses the buffer, and another timeline -+ point that the compositor will signal when it no longer needs to access the -+ buffer contents for the purposes of the surface commit. -+ -+ Linux DRM synchronization objects are documented at: -+ https://dri.freedesktop.org/docs/drm/gpu/drm-mm.html#drm-sync-objects -+ -+ Warning! The protocol described in this file is currently in the testing -+ phase. Backward compatible changes may be added together with the -+ corresponding interface version bump. Backward incompatible changes can -+ only be done by creating a new major version of the extension. -+ -+ -+ -+ -+ This global is a factory interface, allowing clients to request -+ explicit synchronization for buffers on a per-surface basis. -+ -+ See wp_linux_drm_syncobj_surface_v1 for more information. -+ -+ -+ -+ -+ Destroy this explicit synchronization factory object. Other objects -+ shall not be affected by this request. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Instantiate an interface extension for the given wl_surface to provide -+ explicit synchronization. -+ -+ If the given wl_surface already has an explicit synchronization object -+ associated, the surface_exists protocol error is raised. -+ -+ Graphics APIs, like EGL or Vulkan, that manage the buffer queue and -+ commits of a wl_surface themselves, are likely to be using this -+ extension internally. If a client is using such an API for a -+ wl_surface, it should not directly use this extension on that surface, -+ to avoid raising a surface_exists protocol error. -+ -+ -+ -+ -+ -+ -+ -+ Import a DRM synchronization object timeline. -+ -+ If the FD cannot be imported, the invalid_timeline error is raised. -+ -+ -+ -+ -+ -+ -+ -+ -+ This object represents an explicit synchronization object timeline -+ imported by the client to the compositor. -+ -+ -+ -+ -+ Destroy the synchronization object timeline. Other objects are not -+ affected by this request, in particular timeline points set by -+ set_acquire_point and set_release_point are not unset. -+ -+ -+ -+ -+ -+ -+ This object is an add-on interface for wl_surface to enable explicit -+ synchronization. -+ -+ Each surface can be associated with only one object of this interface at -+ any time. -+ -+ Explicit synchronization is guaranteed to be supported for buffers -+ created with any version of the linux-dmabuf protocol. Compositors are -+ free to support explicit synchronization for additional buffer types. -+ If at surface commit time the attached buffer does not support explicit -+ synchronization, an unsupported_buffer error is raised. -+ -+ As long as the wp_linux_drm_syncobj_surface_v1 object is alive, the -+ compositor may ignore implicit synchronization for buffers attached and -+ committed to the wl_surface. The delivery of wl_buffer.release events -+ for buffers attached to the surface becomes undefined. -+ -+ Clients must set both acquire and release points if and only if a -+ non-null buffer is attached in the same surface commit. See the -+ no_buffer, no_acquire_point and no_release_point protocol errors. -+ -+ If at surface commit time the acquire and release DRM syncobj timelines -+ are identical, the acquire point value must be strictly less than the -+ release point value, or else the conflicting_points protocol error is -+ raised. -+ -+ -+ -+ -+ Destroy this surface synchronization object. -+ -+ Any timeline point set by this object with set_acquire_point or -+ set_release_point since the last commit may be discarded by the -+ compositor. Any timeline point set by this object before the last -+ commit will not be affected. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Set the timeline point that must be signalled before the compositor may -+ sample from the buffer attached with wl_surface.attach. -+ -+ The 64-bit unsigned value combined from point_hi and point_lo is the -+ point value. -+ -+ The acquire point is double-buffered state, and will be applied on the -+ next wl_surface.commit request for the associated surface. Thus, it -+ applies only to the buffer that is attached to the surface at commit -+ time. -+ -+ If an acquire point has already been attached during the same commit -+ cycle, the new point replaces the old one. -+ -+ If the associated wl_surface was destroyed, a no_surface error is -+ raised. -+ -+ If at surface commit time there is a pending acquire timeline point set -+ but no pending buffer attached, a no_buffer error is raised. If at -+ surface commit time there is a pending buffer attached but no pending -+ acquire timeline point set, the no_acquire_point protocol error is -+ raised. -+ -+ -+ -+ -+ -+ -+ -+ -+ Set the timeline point that must be signalled by the compositor when it -+ has finished its usage of the buffer attached with wl_surface.attach -+ for the relevant commit. -+ -+ Once the timeline point is signaled, and assuming the associated buffer -+ is not pending release from other wl_surface.commit requests, no -+ additional explicit or implicit synchronization with the compositor is -+ required to safely re-use the buffer. -+ -+ Note that clients cannot rely on the release point being always -+ signaled after the acquire point: compositors may release buffers -+ without ever reading from them. In addition, the compositor may use -+ different presentation paths for different commits, which may have -+ different release behavior. As a result, the compositor may signal the -+ release points in a different order than the client committed them. -+ -+ Because signaling a timeline point also signals every previous point, -+ it is generally not safe to use the same timeline object for the -+ release points of multiple buffers. The out-of-order signaling -+ described above may lead to a release point being signaled before the -+ compositor has finished reading. To avoid this, it is strongly -+ recommended that each buffer should use a separate timeline for its -+ release points. -+ -+ The 64-bit unsigned value combined from point_hi and point_lo is the -+ point value. -+ -+ The release point is double-buffered state, and will be applied on the -+ next wl_surface.commit request for the associated surface. Thus, it -+ applies only to the buffer that is attached to the surface at commit -+ time. -+ -+ If a release point has already been attached during the same commit -+ cycle, the new point replaces the old one. -+ -+ If the associated wl_surface was destroyed, a no_surface error is -+ raised. -+ -+ If at surface commit time there is a pending release timeline point set -+ but no pending buffer attached, a no_buffer error is raised. If at -+ surface commit time there is a pending buffer attached but no pending -+ release timeline point set, the no_release_point protocol error is -+ raised. -+ -+ -+ -+ -+ -+ -+ diff --git a/staging/mutter/0002-3567.patch b/staging/mutter/3567.patch similarity index 88% rename from staging/mutter/0002-3567.patch rename to staging/mutter/3567.patch index 7e397f5..074930e 100644 --- a/staging/mutter/0002-3567.patch +++ b/staging/mutter/3567.patch @@ -1,5 +1,22 @@ +From 77f2b82c4afe0c22249436e3ddabc2f4d2161b4f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:41:20 +0100 +Subject: [PATCH 1/4] x11-display: Expose UI scaling factor via D-Bus + +This replaces the `legacy-ui-scaling-factor` entry in +`org.gnome.Mutter.DisplayConfig`, with the motivation being to no longer +expose X11 specific state via the monitor configuration API. +--- + .../org.gnome.Mutter.DisplayConfig.xml | 4 -- + data/dbus-interfaces/org.gnome.Mutter.X11.xml | 8 +++ + src/backends/meta-monitor-manager.c | 7 -- + src/meson.build | 5 ++ + src/x11/meta-x11-display.c | 64 ++++++++++++++++++- + 5 files changed, 76 insertions(+), 12 deletions(-) + create mode 100644 data/dbus-interfaces/org.gnome.Mutter.X11.xml + diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml -index 2fe8450a8..86421b7b0 100644 +index b05337d74..7294c57a8 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml @@ -426,10 +426,6 @@ @@ -27,44 +44,8 @@ index 000000000..3d3c8a42f + + + -diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in -index 92c97b12e..54f286daa 100644 ---- a/data/org.gnome.mutter.gschema.xml.in -+++ b/data/org.gnome.mutter.gschema.xml.in -@@ -5,6 +5,7 @@ - - - -+ - - - - - -diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h -index 0760a341a..6ed3fc2c3 100644 ---- a/src/backends/meta-monitor-manager-private.h -+++ b/src/backends/meta-monitor-manager-private.h -@@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error); -+ -+MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index 77743bc72..45033d966 100644 +index 77743bc72..7f98c2d98 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -2051,14 +2051,12 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, @@ -94,16 +75,184 @@ index 77743bc72..45033d966 100644 if (meta_monitor_manager_get_max_screen_size (manager, &max_screen_width, &max_screen_height)) -@@ -4123,3 +4116,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) +diff --git a/src/meson.build b/src/meson.build +index 05df3bfd2..e658f98ca 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -949,6 +949,11 @@ dbus_interfaces = [ + 'interface': 'org.gnome.Mutter.DebugControl.xml', + 'prefix': 'org.gnome.Mutter', + }, ++ { ++ 'name': 'meta-dbus-x11', ++ 'interface': 'org.gnome.Mutter.X11.xml', ++ 'prefix': 'org.gnome.Mutter', ++ }, + ] - return priv->virtual_monitors; + if have_profiler +diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c +index 5c0760daa..55f062714 100644 +--- a/src/x11/meta-x11-display.c ++++ b/src/x11/meta-x11-display.c +@@ -70,7 +70,7 @@ + #include "wayland/meta-xwayland-private.h" + #endif + +-G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++#include "meta-dbus-x11.h" + + static GQuark quark_x11_display_logical_monitor_data = 0; + +@@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData + int xinerama_index; + } MetaX11DisplayLogicalMonitorData; + ++typedef struct _MetaX11DisplayPrivate ++{ ++ MetaDBusX11 *dbus_api; ++ guint dbus_name_id; ++} MetaX11DisplayPrivate; ++ ++G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) ++ + static char *get_screen_name (Display *xdisplay, + int number); + +@@ -151,13 +159,46 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) + g_free (filter); } + ++static void ++on_bus_acquired (GDBusConnection *connection, ++ const char *name, ++ gpointer user_data) ++{ ++ MetaX11Display *x11_display = user_data; ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); + -+MetaLogicalMonitorLayoutMode -+meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) ++ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), ++ connection, ++ "/org/gnome/Mutter/X11", ++ NULL); ++} ++ ++static void ++update_ui_scaling_factor (MetaX11Display *x11_display) +{ -+ return manager->layout_mode; ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ MetaBackend *backend = backend_from_x11_display (x11_display); ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ int ui_scaling_factor; ++ ++ ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); ++ meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); +} ++ + static void + meta_x11_display_dispose (GObject *object) + { + MetaX11Display *x11_display = META_X11_DISPLAY (object); ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); + + x11_display->closing = TRUE; + ++ g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); ++ g_clear_object (&priv->dbus_api); ++ + g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); + + g_clear_list (&x11_display->event_funcs, +@@ -1224,6 +1265,23 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) + on_frames_client_died, x11_display); + } + ++static void ++initialize_dbus_interface (MetaX11Display *x11_display) ++{ ++ MetaX11DisplayPrivate *priv = ++ meta_x11_display_get_instance_private (x11_display); ++ ++ priv->dbus_api = meta_dbus_x11_skeleton_new (); ++ priv->dbus_name_id = ++ g_bus_own_name (G_BUS_TYPE_SESSION, ++ "org.gnome.Mutter.X11", ++ G_BUS_NAME_OWNER_FLAGS_NONE, ++ on_bus_acquired, ++ NULL, NULL, ++ x11_display, NULL); ++ update_ui_scaling_factor (x11_display); ++} ++ + /** + * meta_x11_display_new: + * +@@ -1318,6 +1376,8 @@ meta_x11_display_new (MetaDisplay *display, + x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); + x11_display->display = display; + ++ initialize_dbus_interface (x11_display); ++ + /* here we use XDisplayName which is what the user + * probably put in, vs. DisplayString(display) which is + * canonicalized by XOpenDisplay() +@@ -1974,6 +2034,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, + } + + x11_display->has_xinerama_indices = FALSE; ++ ++ update_ui_scaling_factor (x11_display); + } + + static Bool +-- +2.44.0 + + +From d90ede978c07b8baf4186f5f77bd165e35d60941 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Tue, 20 Feb 2024 23:51:48 +0100 +Subject: [PATCH 2/4] Add an experimental feature for letting Xwayland clients + scale natively + +With the next commits we'll introduce a new mode for scaling of Xwayland apps, +we'll want to put this mode behind an experimental setting though, so add +that setting. +--- + data/org.gnome.mutter.gschema.xml.in | 8 ++++++++ + src/backends/meta-settings-private.h | 1 + + src/backends/meta-settings.c | 2 ++ + 3 files changed, 11 insertions(+) + +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index 92c97b12e..5c3948555 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -5,6 +5,7 @@ + + + ++ + + + + + diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index afbba054a..2081a81b1 100644 --- a/src/backends/meta-settings-private.h @@ -129,6 +278,132 @@ index 3703b23b0..1ae59d636 100644 if (feature) g_message ("Enabling experimental feature '%s'", feature_str); +-- +2.44.0 + + +From 1ac35ab1fcc1dd3416c0d0ec6bdeb739bd79e5a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:42:46 +0100 +Subject: [PATCH 3/4] context: Put Wayland compositor getter in the context + header + +--- + src/meta/meta-context.h | 5 +++++ + src/meta/meta-wayland-compositor.h | 3 --- + src/meta/types.h | 4 ++++ + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h +index ef36bd2c3..2adb9b07e 100644 +--- a/src/meta/meta-context.h ++++ b/src/meta/meta-context.h +@@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, + META_EXPORT + gboolean meta_context_restore_rlimit_nofile (MetaContext *context, + GError **error); ++ ++#ifdef HAVE_WAYLAND ++META_EXPORT ++MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); ++#endif +diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h +index 7f4a50705..3df92fda5 100644 +--- a/src/meta/meta-wayland-compositor.h ++++ b/src/meta/meta-wayland-compositor.h +@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, + META, WAYLAND_COMPOSITOR, + GObject) + +-META_EXPORT +-MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); +- + META_EXPORT + struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); + +diff --git a/src/meta/types.h b/src/meta/types.h +index cbe2a9a3d..8fba4a839 100644 +--- a/src/meta/types.h ++++ b/src/meta/types.h +@@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; + + typedef struct _MetaWorkspaceManager MetaWorkspaceManager; + typedef struct _MetaSelection MetaSelection; ++ ++#ifdef HAVE_WAYLAND ++typedef struct _MetaWaylandCompositor MetaWaylandCompositor; ++#endif +-- +2.44.0 + + +From eec800b7e0d5c6111bfd27e81f6b14f1612c6659 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 12 Dec 2023 22:52:44 +0100 +Subject: [PATCH 4/4] Add experimental mode to use native scaling of Xwayland + clients + +Allow scale-aware Xwayland clients to scale by an integer scale +themselves, instead of letting them render them at 1x scale and then +scaling up the texture, making it look blurry. + +When monitor framebuffers are scaled, this special cases Xwayland and +sends output regions in a way that Xwayland think everything is N times +as large as the logical region, where N is the ceil of the max monitor +scale. + +This is done by introducing a "stage" vs "protocol" coordinate space for +X11, where the "protocol" coordinate space is "stage" multiplied by a +scaling factor. + +We're guarding this behind a new experimental feature +"xwayland-native-scaling", which can only come into effect when enabled +together with "scale-monitor-framebuffer". +--- + src/backends/meta-monitor-manager-private.h | 2 + + src/backends/meta-monitor-manager.c | 6 + + src/compositor/meta-window-actor-x11.c | 22 +- + src/core/frame.c | 106 +++++-- + src/wayland/meta-wayland-cursor-surface.c | 52 ++-- + src/wayland/meta-wayland-outputs.c | 73 ++++- + src/wayland/meta-wayland-pointer.c | 14 + + src/wayland/meta-wayland-private.h | 2 + + src/wayland/meta-wayland-surface.c | 30 +- + src/wayland/meta-window-xwayland.c | 71 ++++- + src/wayland/meta-xwayland-private.h | 1 + + src/wayland/meta-xwayland-surface.c | 10 +- + src/wayland/meta-xwayland.c | 56 ++++ + src/wayland/meta-xwayland.h | 2 + + src/x11/meta-x11-display.c | 196 +++++++++++-- + src/x11/window-props.c | 104 ++++++- + src/x11/window-x11.c | 305 ++++++++++++++++---- + src/x11/window-x11.h | 38 +++ + 18 files changed, 916 insertions(+), 174 deletions(-) + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index 0760a341a..6ed3fc2c3 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * + MetaMonitorsConfig *config, + MetaMonitorsConfigMethod method, + GError **error); ++ ++MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 7f98c2d98..45033d966 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -4116,3 +4116,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) + + return priv->virtual_monitors; + } ++ ++MetaLogicalMonitorLayoutMode ++meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) ++{ ++ return manager->layout_mode; ++} diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c index 7d5e46ac7..577ed2760 100644 --- a/src/compositor/meta-window-actor-x11.c @@ -163,7 +438,7 @@ index 7d5e46ac7..577ed2760 100644 meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); } diff --git a/src/core/frame.c b/src/core/frame.c -index 145f0b7bd..502622598 100644 +index 5feb85480..6f0f3ab83 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -33,6 +33,7 @@ @@ -173,8 +448,8 @@ index 145f0b7bd..502622598 100644 +#include "x11/window-x11.h" #include - #include -@@ -66,6 +67,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, + +@@ -65,6 +66,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, XSetWindowAttributes attrs; gulong create_serial = 0; MetaFrame *frame; @@ -182,7 +457,7 @@ index 145f0b7bd..502622598 100644 if (window->frame) return; -@@ -127,11 +129,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, +@@ -123,11 +125,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, meta_stack_tracker_record_remove (window->display->stack_tracker, meta_window_x11_get_xwindow (window), XNextRequest (x11_display->xdisplay)); @@ -204,7 +479,7 @@ index 145f0b7bd..502622598 100644 window->reparents_pending += 1; /* FIXME handle this error */ mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -201,6 +211,8 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -197,6 +207,8 @@ meta_window_destroy_frame (MetaWindow *window) if (!x11_display->closing) { @@ -213,7 +488,7 @@ index 145f0b7bd..502622598 100644 if (!window->unmanaging) { meta_stack_tracker_record_add (window->display->stack_tracker, -@@ -208,6 +220,14 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -204,6 +216,14 @@ meta_window_destroy_frame (MetaWindow *window) XNextRequest (x11_display->xdisplay)); } @@ -228,7 +503,7 @@ index 145f0b7bd..502622598 100644 XReparentWindow (x11_display->xdisplay, meta_window_x11_get_xwindow (window), x11_display->xroot, -@@ -215,8 +235,7 @@ meta_window_destroy_frame (MetaWindow *window) +@@ -211,8 +231,7 @@ meta_window_destroy_frame (MetaWindow *window) * coordinates here means we'll need to ensure a configure * notify event is sent; see bug 399552. */ @@ -238,7 +513,7 @@ index 145f0b7bd..502622598 100644 window->reparents_pending += 1; } -@@ -270,6 +289,7 @@ meta_frame_query_borders (MetaFrame *frame, +@@ -263,6 +282,7 @@ meta_frame_query_borders (MetaFrame *frame, MetaFrameBorders *borders) { MetaWindow *window = frame->window; @@ -246,9 +521,9 @@ index 145f0b7bd..502622598 100644 MetaX11Display *x11_display = window->display->x11_display; int format, res; Atom type; -@@ -295,12 +315,22 @@ meta_frame_query_borders (MetaFrame *frame, - - if (res == Success && nitems == 4) +@@ -286,12 +306,22 @@ meta_frame_query_borders (MetaFrame *frame, + if (mtk_x11_error_trap_pop_with_return (x11_display->xdisplay) == Success && + res == Success && nitems == 4) { - borders->invisible = (MetaFrameBorder) { - ((long *) data)[0], @@ -273,11 +548,11 @@ index 145f0b7bd..502622598 100644 + borders->invisible.top = top; + borders->invisible.bottom = bottom; } - - g_clear_pointer (&data, XFree); -@@ -321,12 +351,21 @@ meta_frame_query_borders (MetaFrame *frame, - - if (res == Success && nitems == 4) + else + { +@@ -314,12 +344,21 @@ meta_frame_query_borders (MetaFrame *frame, + if (mtk_x11_error_trap_pop_with_return (x11_display->xdisplay) == Success && + res == Success && nitems == 4) { - borders->visible = (MetaFrameBorder) { - ((long *) data)[0], @@ -301,9 +576,9 @@ index 145f0b7bd..502622598 100644 + borders->visible.top = top; + borders->visible.bottom = bottom; } - - g_clear_pointer (&data, XFree); -@@ -370,7 +409,9 @@ meta_frame_sync_to_window (MetaFrame *frame, + else + { +@@ -367,7 +406,9 @@ meta_frame_sync_to_window (MetaFrame *frame, gboolean need_resize) { MetaWindow *window = frame->window; @@ -313,7 +588,7 @@ index 145f0b7bd..502622598 100644 meta_topic (META_DEBUG_GEOMETRY, "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", -@@ -381,12 +422,22 @@ meta_frame_sync_to_window (MetaFrame *frame, +@@ -378,12 +419,22 @@ meta_frame_sync_to_window (MetaFrame *frame, mtk_x11_error_trap_push (x11_display->xdisplay); @@ -340,7 +615,7 @@ index 145f0b7bd..502622598 100644 mtk_x11_error_trap_pop (x11_display->xdisplay); -@@ -423,6 +474,7 @@ static void +@@ -420,6 +471,7 @@ static void send_configure_notify (MetaFrame *frame) { MetaX11Display *x11_display = frame->window->display->x11_display; @@ -348,7 +623,7 @@ index 145f0b7bd..502622598 100644 XEvent event = { 0 }; /* We never get told by the frames client, just reassert the -@@ -432,10 +484,16 @@ send_configure_notify (MetaFrame *frame) +@@ -429,10 +481,16 @@ send_configure_notify (MetaFrame *frame) event.xconfigure.display = x11_display->xdisplay; event.xconfigure.event = frame->xwindow; event.xconfigure.window = frame->xwindow; @@ -369,61 +644,6 @@ index 145f0b7bd..502622598 100644 event.xconfigure.border_width = 0; event.xconfigure.above = None; event.xconfigure.override_redirect = False; -diff --git a/src/meson.build b/src/meson.build -index a8cf7e197..ea2dcb2dd 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -943,6 +943,11 @@ dbus_interfaces = [ - 'interface': 'org.gnome.Mutter.DebugControl.xml', - 'prefix': 'org.gnome.Mutter', - }, -+ { -+ 'name': 'meta-dbus-x11', -+ 'interface': 'org.gnome.Mutter.X11.xml', -+ 'prefix': 'org.gnome.Mutter', -+ }, - ] - - if have_profiler -diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h -index ef36bd2c3..2adb9b07e 100644 ---- a/src/meta/meta-context.h -+++ b/src/meta/meta-context.h -@@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, - META_EXPORT - gboolean meta_context_restore_rlimit_nofile (MetaContext *context, - GError **error); -+ -+#ifdef HAVE_WAYLAND -+META_EXPORT -+MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); -+#endif -diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h -index 7f4a50705..3df92fda5 100644 ---- a/src/meta/meta-wayland-compositor.h -+++ b/src/meta/meta-wayland-compositor.h -@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, - META, WAYLAND_COMPOSITOR, - GObject) - --META_EXPORT --MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); -- - META_EXPORT - struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); - -diff --git a/src/meta/types.h b/src/meta/types.h -index cbe2a9a3d..8fba4a839 100644 ---- a/src/meta/types.h -+++ b/src/meta/types.h -@@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; - - typedef struct _MetaWorkspaceManager MetaWorkspaceManager; - typedef struct _MetaSelection MetaSelection; -+ -+#ifdef HAVE_WAYLAND -+typedef struct _MetaWaylandCompositor MetaWaylandCompositor; -+#endif diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c index 87a8895c8..5a16ce7d8 100644 --- a/src/wayland/meta-wayland-cursor-surface.c @@ -489,7 +709,7 @@ index 87a8895c8..5a16ce7d8 100644 meta_wayland_surface_update_outputs (surface); diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c -index 89ae86445..6a05e887e 100644 +index 89ae86445..55af4b2ac 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -31,6 +31,10 @@ @@ -540,7 +760,7 @@ index 89ae86445..6a05e887e 100644 static void send_xdg_output_events (struct wl_resource *resource, MetaWaylandOutput *wayland_output, -@@ -613,18 +633,27 @@ send_xdg_output_events (struct wl_resource *resource, +@@ -613,18 +633,51 @@ send_xdg_output_events (struct wl_resource *resource, layout = meta_logical_monitor_get_layout (logical_monitor); old_layout = wayland_output->layout; @@ -548,34 +768,60 @@ index 89ae86445..6a05e887e 100644 - old_layout.x != layout.x || old_layout.y != layout.y) + if (is_xwayland_resource (wayland_output, resource)) { +- zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); +- need_done = TRUE; +- } +#ifdef HAVE_XWAYLAND + MetaXWaylandManager *xwayland_manager = + &wayland_output->compositor->xwayland_manager; + int xwayland_scale; -+ + +- if (need_all_events || +- old_layout.width != layout.width || old_layout.height != layout.height) + xwayland_scale = meta_xwayland_get_effective_scale (xwayland_manager); -+ layout.x *= xwayland_scale; -+ layout.y *= xwayland_scale; -+ layout.width *= xwayland_scale; -+ layout.height *= xwayland_scale; + - zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); -- need_done = TRUE; -+ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++ if (need_all_events || ++ old_layout.x != layout.x || old_layout.y != layout.y) ++ { ++ layout.x *= xwayland_scale; ++ layout.y *= xwayland_scale; ++ ++ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); ++ need_done = TRUE; ++ } ++ ++ if (need_all_events || ++ old_layout.width != layout.width || old_layout.height != layout.height) ++ { ++ layout.width *= xwayland_scale; ++ layout.height *= xwayland_scale; ++ ++ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++ need_done = TRUE; ++ } +#endif - } -- -- if (need_all_events || -- old_layout.width != layout.width || old_layout.height != layout.height) ++ } + else { -+ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); - zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); +- zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); - need_done = TRUE; ++ if (need_all_events || ++ old_layout.x != layout.x || old_layout.y != layout.y) ++ { ++ zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); ++ need_done = TRUE; ++ } ++ ++ if (need_all_events || ++ old_layout.width != layout.width || old_layout.height != layout.height) ++ { ++ zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); ++ need_done = TRUE; ++ } } if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) -@@ -745,7 +774,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) +@@ -745,7 +798,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); @@ -623,10 +869,10 @@ index e8d442c03..834753ffd 100644 struct _MetaWaylandCompositor diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index b132504d3..0012798df 100644 +index 6dc5006b7..81ee47bbd 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c -@@ -770,8 +770,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, +@@ -781,8 +781,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL)); } @@ -648,7 +894,7 @@ index b132504d3..0012798df 100644 if (state->has_new_buffer_transform) surface->buffer_transform = state->buffer_transform; -@@ -959,8 +970,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) +@@ -977,8 +988,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaMultiTexture *committed_texture = surface->committed_state.texture; int committed_scale = surface->committed_state.scale; @@ -660,7 +906,7 @@ index b132504d3..0012798df 100644 { if (!surface->role || !META_IS_WAYLAND_CURSOR_SURFACE (surface->role)) { -@@ -1488,6 +1500,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) +@@ -1506,6 +1518,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) g_hash_table_foreach (surface->compositor->outputs, update_surface_output_state, surface); @@ -908,34 +1154,10 @@ index daf9d1abb..ae7a06977 100644 + +int meta_xwayland_get_effective_scale (MetaXWaylandManager *manager); diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c -index 5c0760daa..f67e9e427 100644 +index 55f062714..f67e9e427 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c -@@ -70,7 +70,7 @@ - #include "wayland/meta-xwayland-private.h" - #endif - --G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) -+#include "meta-dbus-x11.h" - - static GQuark quark_x11_display_logical_monitor_data = 0; - -@@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData - int xinerama_index; - } MetaX11DisplayLogicalMonitorData; - -+typedef struct _MetaX11DisplayPrivate -+{ -+ MetaDBusX11 *dbus_api; -+ guint dbus_name_id; -+} MetaX11DisplayPrivate; -+ -+G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) -+ - static char *get_screen_name (Display *xdisplay, - int number); - -@@ -122,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) +@@ -130,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) return meta_context_get_backend (context); } @@ -978,31 +1200,12 @@ index 5c0760daa..f67e9e427 100644 static void meta_x11_display_unmanage_windows (MetaX11Display *x11_display) { -@@ -151,13 +195,68 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) - g_free (filter); - } - -+static void -+on_bus_acquired (GDBusConnection *connection, -+ const char *name, -+ gpointer user_data) -+{ -+ MetaX11Display *x11_display = user_data; -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ -+ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), -+ connection, -+ "/org/gnome/Mutter/X11", -+ NULL); -+} -+ -+static void -+update_ui_scaling_factor (MetaX11Display *x11_display) -+{ -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ MetaBackend *backend = backend_from_x11_display (x11_display); +@@ -180,10 +216,32 @@ update_ui_scaling_factor (MetaX11Display *x11_display) + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); + MetaBackend *backend = backend_from_x11_display (x11_display); +- MetaSettings *settings = meta_backend_get_settings (backend); +- int ui_scaling_factor; + MetaContext *context = meta_backend_get_context (backend); + int ui_scaling_factor = 1; + @@ -1028,26 +1231,12 @@ index 5c0760daa..f67e9e427 100644 + break; + } + } -+ -+ meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); -+} -+ - static void - meta_x11_display_dispose (GObject *object) - { - MetaX11Display *x11_display = META_X11_DISPLAY (object); -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); - x11_display->closing = TRUE; - -+ g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); -+ g_clear_object (&priv->dbus_api); -+ - g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); +- ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); + meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); + } - g_clear_list (&x11_display->event_funcs, -@@ -600,6 +699,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) +@@ -641,6 +699,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) return; meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); @@ -1057,7 +1246,7 @@ index 5c0760daa..f67e9e427 100644 data[0] = monitor_width; data[1] = monitor_height; -@@ -1009,14 +1111,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, +@@ -1050,14 +1111,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, for (l = logical_monitors; l; l = l->next) { @@ -1086,7 +1275,7 @@ index 5c0760daa..f67e9e427 100644 tmp += 4; } -@@ -1045,7 +1155,6 @@ set_work_area_hint (MetaDisplay *display, +@@ -1086,7 +1155,6 @@ set_work_area_hint (MetaDisplay *display, int num_workspaces; GList *l; unsigned long *data, *tmp; @@ -1094,7 +1283,7 @@ index 5c0760daa..f67e9e427 100644 num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); data = g_new (unsigned long, num_workspaces * 4); -@@ -1054,14 +1163,22 @@ set_work_area_hint (MetaDisplay *display, +@@ -1095,14 +1163,22 @@ set_work_area_hint (MetaDisplay *display, for (l = workspace_manager->workspaces; l; l = l->next) { MetaWorkspace *workspace = l->data; @@ -1122,27 +1311,10 @@ index 5c0760daa..f67e9e427 100644 tmp += 4; } -@@ -1224,6 +1341,58 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) - on_frames_client_died, x11_display); +@@ -1282,6 +1358,41 @@ initialize_dbus_interface (MetaX11Display *x11_display) + update_ui_scaling_factor (x11_display); } -+static void -+initialize_dbus_interface (MetaX11Display *x11_display) -+{ -+ MetaX11DisplayPrivate *priv = -+ meta_x11_display_get_instance_private (x11_display); -+ -+ priv->dbus_api = meta_dbus_x11_skeleton_new (); -+ priv->dbus_name_id = -+ g_bus_own_name (G_BUS_TYPE_SESSION, -+ "org.gnome.Mutter.X11", -+ G_BUS_NAME_OWNER_FLAGS_NONE, -+ on_bus_acquired, -+ NULL, NULL, -+ x11_display, NULL); -+ update_ui_scaling_factor (x11_display); -+} -+ +static void +experimental_features_changed (MetaSettings *settings, + MetaExperimentalFeature old_experimental_features, @@ -1181,7 +1353,7 @@ index 5c0760daa..f67e9e427 100644 /** * meta_x11_display_new: * -@@ -1242,6 +1411,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1300,6 +1411,7 @@ meta_x11_display_new (MetaDisplay *display, MetaBackend *backend = meta_context_get_backend (context); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); @@ -1189,16 +1361,7 @@ index 5c0760daa..f67e9e427 100644 g_autoptr (MetaX11Display) x11_display = NULL; Display *xdisplay; Screen *xscreen; -@@ -1318,6 +1488,8 @@ meta_x11_display_new (MetaDisplay *display, - x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); - x11_display->display = display; - -+ initialize_dbus_interface (x11_display); -+ - /* here we use XDisplayName which is what the user - * probably put in, vs. DisplayString(display) which is - * canonicalized by XOpenDisplay() -@@ -1410,7 +1582,7 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1470,7 +1582,7 @@ meta_x11_display_new (MetaDisplay *display, "monitors-changed-internal", G_CALLBACK (on_monitors_changed_internal), x11_display, @@ -1207,7 +1370,7 @@ index 5c0760daa..f67e9e427 100644 init_leader_window (x11_display, ×tamp); x11_display->timestamp = timestamp; -@@ -1503,6 +1675,11 @@ meta_x11_display_new (MetaDisplay *display, +@@ -1563,6 +1675,11 @@ meta_x11_display_new (MetaDisplay *display, meta_prefs_add_listener (prefs_changed_callback, x11_display); @@ -1219,7 +1382,7 @@ index 5c0760daa..f67e9e427 100644 set_work_area_hint (display, x11_display); g_signal_connect_object (display, "workareas-changed", -@@ -1711,16 +1888,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) +@@ -1771,16 +1888,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) } static void @@ -1241,7 +1404,7 @@ index 5c0760daa..f67e9e427 100644 } static void -@@ -1772,8 +1945,37 @@ static void +@@ -1832,8 +1945,37 @@ static void update_cursor_theme (MetaX11Display *x11_display) { MetaBackend *backend = backend_from_x11_display (x11_display); @@ -1260,8 +1423,7 @@ index 5c0760daa..f67e9e427 100644 + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = + &wayland_compositor->xwayland_manager; - -- set_cursor_theme (x11_display->xdisplay, backend); ++ + scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + break; @@ -1275,12 +1437,13 @@ index 5c0760daa..f67e9e427 100644 + size = meta_prefs_get_cursor_size () * scale; + + theme = meta_prefs_get_cursor_theme (); -+ + +- set_cursor_theme (x11_display->xdisplay, backend); + set_cursor_theme (x11_display->xdisplay, theme, size); schedule_reload_x11_cursor (x11_display); if (META_IS_BACKEND_X11 (backend)) -@@ -1781,7 +1983,7 @@ update_cursor_theme (MetaX11Display *x11_display) +@@ -1841,7 +1983,7 @@ update_cursor_theme (MetaX11Display *x11_display) MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); @@ -1289,15 +1452,6 @@ index 5c0760daa..f67e9e427 100644 meta_backend_x11_reload_cursor (backend_x11); } } -@@ -1974,6 +2176,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - } - - x11_display->has_xinerama_indices = FALSE; -+ -+ update_ui_scaling_factor (x11_display); - } - - static Bool diff --git a/src/x11/window-props.c b/src/x11/window-props.c index c18b3eab5..6adb69bb8 100644 --- a/src/x11/window-props.c @@ -1436,7 +1590,7 @@ index c18b3eab5..6adb69bb8 100644 window->size_hints.flags = 0; diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index a60650732..839759bc4 100644 +index 1bc5c57a1..14d334fe0 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) @@ -1745,9 +1899,9 @@ index a60650732..839759bc4 100644 + attrs.border_width, 0, 0, 0, + &priv->border_width, NULL, NULL, NULL); - g_signal_connect (window, "notify::decorated", - G_CALLBACK (meta_window_x11_update_input_region), -@@ -2192,6 +2344,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) + G_OBJECT_CLASS (meta_window_x11_parent_class)->constructed (object); + } +@@ -2188,6 +2340,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) klass->thaw_commits = meta_window_x11_impl_thaw_commits; klass->always_update_shape = meta_window_x11_impl_always_update_shape; klass->process_property_notify = meta_window_x11_impl_process_property_notify; @@ -1756,7 +1910,7 @@ index a60650732..839759bc4 100644 obj_props[PROP_ATTRIBUTES] = g_param_spec_pointer ("attributes", NULL, NULL, -@@ -2468,7 +2622,10 @@ meta_window_x11_update_input_region (MetaWindow *window) +@@ -2459,7 +2613,10 @@ meta_window_x11_update_input_region (MetaWindow *window) else { /* Window has a custom shape. */ @@ -1768,7 +1922,7 @@ index a60650732..839759bc4 100644 } meta_XFree (rects); -@@ -2552,7 +2709,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) +@@ -2543,7 +2700,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) if (rects) { @@ -1780,7 +1934,7 @@ index a60650732..839759bc4 100644 XFree (rects); } } -@@ -2830,6 +2990,7 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2821,6 +2981,7 @@ meta_window_x11_configure_request (MetaWindow *window, { MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); @@ -1788,7 +1942,7 @@ index a60650732..839759bc4 100644 /* Note that x, y is the corner of the window border, * and width, height is the size of the window inside -@@ -2838,15 +2999,25 @@ meta_window_x11_configure_request (MetaWindow *window, +@@ -2829,15 +2990,25 @@ meta_window_x11_configure_request (MetaWindow *window, * requested border here. */ if (event->xconfigurerequest.value_mask & CWBorderWidth) @@ -1822,7 +1976,7 @@ index a60650732..839759bc4 100644 /* Handle stacking. We only handle raises/lowers, mostly because * stack.c really can't deal with anything else. I guess we'll fix -@@ -3341,8 +3512,13 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3332,8 +3503,13 @@ meta_window_x11_client_message (MetaWindow *window, guint32 timestamp; MetaWindowDrag *window_drag; @@ -1838,7 +1992,7 @@ index a60650732..839759bc4 100644 action = event->xclient.data.l[2]; button = event->xclient.data.l[3]; -@@ -3506,6 +3682,7 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3497,6 +3673,7 @@ meta_window_x11_client_message (MetaWindow *window, { MetaGravity gravity; guint value_mask; @@ -1846,7 +2000,7 @@ index a60650732..839759bc4 100644 gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; -@@ -3514,13 +3691,20 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3505,13 +3682,20 @@ meta_window_x11_client_message (MetaWindow *window, if (gravity == 0) gravity = window->size_hints.win_gravity; @@ -1871,7 +2025,7 @@ index a60650732..839759bc4 100644 } else if (event->xclient.message_type == x11_display->atom__NET_ACTIVE_WINDOW && -@@ -3577,11 +3761,15 @@ meta_window_x11_client_message (MetaWindow *window, +@@ -3568,11 +3752,15 @@ meta_window_x11_client_message (MetaWindow *window, else if (event->xclient.message_type == x11_display->atom__GTK_SHOW_WINDOW_MENU) { @@ -1890,7 +2044,7 @@ index a60650732..839759bc4 100644 meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); } -@@ -4103,10 +4291,11 @@ meta_window_x11_configure_notify (MetaWindow *window, +@@ -4094,10 +4282,11 @@ meta_window_x11_configure_notify (MetaWindow *window, g_assert (window->override_redirect); g_assert (window->frame == NULL); @@ -1959,3 +2113,6 @@ index 205eaaa63..fa3fbea6a 100644 + int *stage_y, + int *stage_width, + int *stage_heigth); +-- +2.44.0 + diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index a8cfcb3..a74c74a 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -11,7 +11,7 @@ %global mutter_api_version 14 %global gnome_major_version 46 -%global gnome_version %{gnome_major_version}.0 +%global gnome_version %{gnome_major_version}.1 %global tarball_version %%(echo %{gnome_version} | tr '~' '.') %global _default_patch_fuzz 2 @@ -45,13 +45,8 @@ Patch3: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # which solves the problems reported with #3329 alone Patch4: 0001-modified-3329.patch -# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3304/ -# Nvidia secondary GPU copy acceleration -Patch5: 0003-3304.patch - -# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441/ -# Dynamic triple buffering -Patch6: 0004-1441.patch +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3567 +Patch5: 3567.patch BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) From d7a461410803c2d4739d2064aa5d68d344bfc5a5 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sat, 27 Apr 2024 23:40:48 -0700 Subject: [PATCH 29/41] chore: Add gnome-settings-daemon --- .../gnome-settings-daemon.spec | 206 +++++++++++++++++ .../xwayland-scaling.patch | 208 ++++++++++++++++++ staging/mutter/mutter.spec | 2 +- 3 files changed, 415 insertions(+), 1 deletion(-) create mode 100644 staging/gnome-settings-daemon/gnome-settings-daemon.spec create mode 100644 staging/gnome-settings-daemon/xwayland-scaling.patch diff --git a/staging/gnome-settings-daemon/gnome-settings-daemon.spec b/staging/gnome-settings-daemon/gnome-settings-daemon.spec new file mode 100644 index 0000000..1f01514 --- /dev/null +++ b/staging/gnome-settings-daemon/gnome-settings-daemon.spec @@ -0,0 +1,206 @@ +%global glib2_version 2.58 +%global colord_version 1.4.5 +%global geocode_glib_version 3.26.3 +%global gnome_desktop_version 3.37.1 +%global gsettings_desktop_schemas_version 46~beta +%global gtk3_version 3.15.3 +%global geoclue_version 2.3.1 + +%ifnarch s390 s390x +%global wacom_unit org.gnome.SettingsDaemon.Wacom.service +%else +%global wacom_unit %{nil} +%endif +%global systemd_units org.gnome.SettingsDaemon.A11ySettings.service org.gnome.SettingsDaemon.Color.service org.gnome.SettingsDaemon.Datetime.service org.gnome.SettingsDaemon.Housekeeping.service org.gnome.SettingsDaemon.Keyboard.service org.gnome.SettingsDaemon.MediaKeys.service org.gnome.SettingsDaemon.Power.service org.gnome.SettingsDaemon.PrintNotifications.service org.gnome.SettingsDaemon.Rfkill.service org.gnome.SettingsDaemon.ScreensaverProxy.service org.gnome.SettingsDaemon.Sharing.service org.gnome.SettingsDaemon.Smartcard.service org.gnome.SettingsDaemon.Sound.service org.gnome.SettingsDaemon.UsbProtection.service org.gnome.SettingsDaemon.Wwan.service org.gnome.SettingsDaemon.XSettings.service %%{wacom_unit} + +%global gnome_major_version 46 +%global gnome_version %{gnome_major_version}.0 + +%global tarball_version %%(echo %{gnome_version} | tr '~' '.') +%global major_version %%(echo %{gnome_version} | cut -f 1 -d '~' | cut -f 1 -d '.') + +Name: gnome-settings-daemon +Version: %{gnome_version}.xscaling.9 +Release: %autorelease +Summary: The daemon sharing settings from GNOME to GTK+/KDE applications + +License: GPL-2.0-or-later AND LGPL-2.1-or-later +URL: https://gitlab.gnome.org/GNOME/gnome-settings-daemon +Source0: https://download.gnome.org/sources/%{name}/%{gnome_major_version}/%{name}-%{tarball_version}.tar.xz + +# https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/353 +Patch0: 353.patch + +BuildRequires: gcc +BuildRequires: gettext +BuildRequires: meson >= 0.49.0 +BuildRequires: perl-interpreter +BuildRequires: systemd-rpm-macros +BuildRequires: pkgconfig(alsa) +BuildRequires: pkgconfig(colord) >= %{colord_version} +BuildRequires: pkgconfig(cups) +BuildRequires: pkgconfig(fontconfig) +BuildRequires: pkgconfig(gck-2) +BuildRequires: pkgconfig(gcr-4) +BuildRequires: pkgconfig(geoclue-2.0) >= %{geoclue_version} +BuildRequires: pkgconfig(geocode-glib-2.0) >= %{geocode_glib_version} +BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-desktop-3.0) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} +BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(gweather4) +BuildRequires: pkgconfig(lcms2) >= 2.2 +BuildRequires: pkgconfig(libcanberra-gtk3) +BuildRequires: pkgconfig(libgeoclue-2.0) +BuildRequires: pkgconfig(libnm) +BuildRequires: pkgconfig(libnotify) +BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(libpulse-mainloop-glib) +BuildRequires: pkgconfig(librsvg-2.0) +BuildRequires: pkgconfig(mm-glib) +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(upower-glib) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xi) +BuildRequires: pkgconfig(wayland-client) +%ifnarch s390 s390x +BuildRequires: pkgconfig(libwacom) >= 0.7 +%endif + +Requires: colord >= %{colord_version} +Requires: iio-sensor-proxy +Requires: geoclue2 >= %{geoclue_version} +Requires: geocode-glib2%{?_isa} >= %{geocode_glib_version} +Requires: glib2%{?_isa} >= %{glib2_version} +Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: libgweather4%{?_isa} + +%description +A daemon to share settings from GNOME to other applications. It also +handles global keybindings, as well as a number of desktop-wide settings. + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + +%prep +%autosetup -p1 -n %{name}-%{tarball_version} + +%build +%meson +%meson_build + +%install +%meson_install + +%find_lang %{name} --with-gnome + +%post +%systemd_user_post %{systemd_units} + +%preun +%systemd_user_preun %{systemd_units} + +%files -f %{name}.lang +%license COPYING COPYING.LIB +%doc AUTHORS NEWS README + +# list daemons explicitly, so we notice if one goes missing +# some of these don't have a separate gschema +%{_libexecdir}/gsd-datetime +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Datetime.desktop + +%{_libexecdir}/gsd-housekeeping +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Housekeeping.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml + +%{_libexecdir}/gsd-keyboard +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Keyboard.desktop + +%{_libexecdir}/gsd-media-keys +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.MediaKeys.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.media-keys.gschema.xml + +%{_libexecdir}/gsd-backlight-helper +%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.power.policy +%{_libexecdir}/gsd-power +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Power.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.power.gschema.xml + +%{_libexecdir}/gsd-print-notifications +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.PrintNotifications.desktop +%{_libexecdir}/gsd-printer + +%{_libexecdir}/gsd-rfkill +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Rfkill.desktop + +%{_libexecdir}/gsd-screensaver-proxy +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.ScreensaverProxy.desktop + +%{_libexecdir}/gsd-smartcard +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Smartcard.desktop + +%{_libexecdir}/gsd-sound +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Sound.desktop + +%{_libexecdir}/gsd-usb-protection +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.UsbProtection.desktop + +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.peripherals.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.peripherals.wacom.gschema.xml +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Wacom.desktop + +%ifnarch s390 s390x +%{_libexecdir}/gsd-wacom +%{_libexecdir}/gsd-wacom-oled-helper +%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.wacom.policy +%endif + +%{_libexecdir}/gsd-xsettings +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.XSettings.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.xsettings.gschema.xml + +%{_libexecdir}/gsd-a11y-settings +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.A11ySettings.desktop + +%{_libexecdir}/gsd-color +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Color.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.color.gschema.xml + +%{_libexecdir}/gsd-sharing +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Sharing.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.sharing.gschema.xml + +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Wwan.desktop +%{_libexecdir}/gsd-wwan +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.wwan.gschema.xml + +%dir %{_libdir}/gnome-settings-daemon-%{gnome_major_version} +%{_libdir}/gnome-settings-daemon-%{gnome_major_version}/libgsd.so + +%{_sysconfdir}/xdg/Xwayland-session.d/00-xrdb +%{_userunitdir}/gnome-session-x11-services-ready.target.wants/ +%{_userunitdir}/gnome-session-x11-services.target.wants/ +%{lua: for service in string.gmatch(rpm.expand('%{systemd_units}'), "[^%s]+") do print(rpm.expand('%{_userunitdir}/')..service..'\n') end} +%{_userunitdir}/*.target +%{_udevrulesdir}/61-gnome-settings-daemon-rfkill.rules +%{_datadir}/gnome-settings-daemon/ +%{_datadir}/GConf/gsettings/gnome-settings-daemon.convert + +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.enums.xml +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.gschema.xml + +%files devel +%{_includedir}/gnome-settings-daemon-%{gnome_major_version} +%{_libdir}/pkgconfig/gnome-settings-daemon.pc + +%changelog +%autochangelog diff --git a/staging/gnome-settings-daemon/xwayland-scaling.patch b/staging/gnome-settings-daemon/xwayland-scaling.patch new file mode 100644 index 0000000..4475144 --- /dev/null +++ b/staging/gnome-settings-daemon/xwayland-scaling.patch @@ -0,0 +1,208 @@ +From 325ea8da548bac876d7c707b616e1bb4190305f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 13 Dec 2023 17:31:07 +0100 +Subject: [PATCH] xsettings: Get UI scaling factor from dedicated D-Bus API + +Instead of getting the UI scaling factor from the display configuration +API, get it from a new X11 properties API exposed by mutter. +--- + plugins/xsettings/gsd-xsettings-manager.c | 140 ++++++++-------------- + 1 file changed, 53 insertions(+), 87 deletions(-) + +diff --git a/plugins/xsettings/gsd-xsettings-manager.c b/plugins/xsettings/gsd-xsettings-manager.c +index f8ec6ebc..8a8f069f 100644 +--- a/plugins/xsettings/gsd-xsettings-manager.c ++++ b/plugins/xsettings/gsd-xsettings-manager.c +@@ -609,81 +609,47 @@ get_dpi_from_gsettings (GsdXSettingsManager *manager) + return dpi * factor; + } + +-static gboolean +-get_legacy_ui_scale (GVariantIter *properties, +- int *scale) +-{ +- const char *key; +- GVariant *value; +- +- *scale = 0; +- +- while (g_variant_iter_loop (properties, "{&sv}", &key, &value)) { +- if (!g_str_equal (key, "legacy-ui-scaling-factor")) +- continue; +- +- *scale = g_variant_get_int32 (value); +- break; +- } +- +- if (*scale < 1) { +- g_warning ("Failed to get current UI legacy scaling factor"); +- *scale = 1; +- return FALSE; +- } +- +- return TRUE; +-} +- +-#define MODE_FORMAT "(siiddada{sv})" +-#define MODES_FORMAT "a" MODE_FORMAT +- +-#define MONITOR_SPEC_FORMAT "(ssss)" +-#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})" +-#define MONITORS_FORMAT "a" MONITOR_FORMAT +- +-#define LOGICAL_MONITOR_FORMAT "(iiduba" MONITOR_SPEC_FORMAT "a{sv})" +-#define LOGICAL_MONITORS_FORMAT "a" LOGICAL_MONITOR_FORMAT +- +-#define CURRENT_STATE_FORMAT "(u" MONITORS_FORMAT LOGICAL_MONITORS_FORMAT "a{sv})" +- + static int + get_window_scale (GsdXSettingsManager *manager) + { + g_autoptr(GError) error = NULL; +- g_autoptr(GVariant) current_state = NULL; ++ g_autoptr(GVariant) res = NULL; ++ g_autoptr(GVariant) ui_scaling_factor_variant = NULL; + g_autoptr(GVariantIter) properties = NULL; +- int scale = 1; +- +- current_state = +- g_dbus_connection_call_sync (manager->dbus_connection, +- "org.gnome.Mutter.DisplayConfig", +- "/org/gnome/Mutter/DisplayConfig", +- "org.gnome.Mutter.DisplayConfig", +- "GetCurrentState", +- NULL, +- NULL, +- G_DBUS_CALL_FLAGS_NO_AUTO_START, +- -1, +- NULL, +- &error); +- if (!current_state) { +- g_warning ("Failed to get current display configuration state: %s", +- error->message); ++ int ui_scaling_factor = 1; ++ ++ res = g_dbus_connection_call_sync (manager->dbus_connection, ++ "org.gnome.Mutter.X11", ++ "/org/gnome/Mutter/X11", ++ "org.freedesktop.DBus.Properties", ++ "Get", ++ g_variant_new ("(ss)", ++ "org.gnome.Mutter.X11", ++ "UiScalingFactor"), ++ NULL, ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, ++ NULL, ++ &error); ++ if (!res) { ++ if (g_error_matches (error, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_NAME_HAS_NO_OWNER)) { ++ /* Mutter X11 interface is not yet on the bus, this is expected ++ * while starting up, it'll appear on the bus right away. ++ */ ++ } else { ++ g_warning ("Failed to get current UI scaling factor: %s", ++ error->message); ++ } ++ + return 1; + } + +- g_variant_get (current_state, +- CURRENT_STATE_FORMAT, +- NULL, +- NULL, +- NULL, +- &properties); +- +- if (!get_legacy_ui_scale (properties, &scale)) +- g_warning ("Failed to get current UI legacy scaling factor"); ++ g_variant_get (res, "(v)", &ui_scaling_factor_variant); ++ g_variant_get (ui_scaling_factor_variant, "i", &ui_scaling_factor); + +- return scale; ++ return ui_scaling_factor; + } + + typedef struct { +@@ -1120,33 +1086,33 @@ setup_xsettings_managers (GsdXSettingsManager *manager) + } + + static void +-monitors_changed (GsdXSettingsManager *manager) ++ui_scaling_factor_changed (GsdXSettingsManager *manager) + { + update_xft_settings (manager); + queue_notify (manager); + } + + static void +-on_monitors_changed (GDBusConnection *connection, +- const gchar *sender_name, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *signal_name, +- GVariant *parameters, +- gpointer data) ++on_mutter_x11_properties_changed (GDBusConnection *connection, ++ const gchar *sender_name, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ gpointer data) + { + GsdXSettingsManager *manager = data; +- monitors_changed (manager); ++ ui_scaling_factor_changed (manager); + } + + static void +-on_display_config_name_appeared_handler (GDBusConnection *connection, +- const gchar *name, +- const gchar *name_owner, +- gpointer data) ++on_mutter_x11_name_appeared_handler (GDBusConnection *connection, ++ const gchar *name, ++ const gchar *name_owner, ++ gpointer data) + { + GsdXSettingsManager *manager = data; +- monitors_changed (manager); ++ ui_scaling_factor_changed (manager); + } + + static void +@@ -1422,20 +1388,20 @@ gsd_xsettings_manager_start (GsdXSettingsManager *manager, + + manager->monitors_changed_id = + g_dbus_connection_signal_subscribe (manager->dbus_connection, +- "org.gnome.Mutter.DisplayConfig", +- "org.gnome.Mutter.DisplayConfig", +- "MonitorsChanged", +- "/org/gnome/Mutter/DisplayConfig", ++ "org.gnome.Mutter.X11", ++ "org.freedesktop.DBus.Properties", ++ "PropertiesChanged", ++ "/org/gnome/Mutter/X11", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, +- on_monitors_changed, ++ on_mutter_x11_properties_changed, + manager, + NULL); + manager->display_config_watch_id = + g_bus_watch_name_on_connection (manager->dbus_connection, +- "org.gnome.Mutter.DisplayConfig", ++ "org.gnome.Mutter.X11", + G_BUS_NAME_WATCHER_FLAGS_NONE, +- on_display_config_name_appeared_handler, ++ on_mutter_x11_name_appeared_handler, + NULL, + manager, + NULL); +-- +GitLab + diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index a74c74a..6f2b115 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,7 +16,7 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.8 +Version: %{gnome_version}.xscaling.9 Release: %autorelease Summary: Window and compositing manager based on Clutter From 253224df2d053b2f57b024fb04f8895233af02a8 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sat, 27 Apr 2024 23:42:50 -0700 Subject: [PATCH 30/41] chore: Add kf6-kio and gnome-shell for switcheroo --- ...Work-around-failing-fingerprint-auth.patch | 67 + staging/gnome-shell/3193.patch | 98 ++ staging/gnome-shell/changelog | 1484 +++++++++++++++++ staging/gnome-shell/gitignore | 227 +++ .../gnome-shell-favourite-apps-firefox.patch | 38 + staging/gnome-shell/gnome-shell.spec | 242 +++ .../gnome-shell/optional-portal-helper.patch | 47 + ...sfiltereng_private-a-VERSION-and-SOV.patch | 30 + staging/kf6-kio/1556.patch | 57 + ...75d315f389df0a440ed62b842ce83dc9a27e.patch | 34 + staging/kf6-kio/kf6-kio.spec | 297 ++++ 11 files changed, 2621 insertions(+) create mode 100644 staging/gnome-shell/0001-gdm-Work-around-failing-fingerprint-auth.patch create mode 100644 staging/gnome-shell/3193.patch create mode 100644 staging/gnome-shell/changelog create mode 100644 staging/gnome-shell/gitignore create mode 100644 staging/gnome-shell/gnome-shell-favourite-apps-firefox.patch create mode 100644 staging/gnome-shell/gnome-shell.spec create mode 100644 staging/gnome-shell/optional-portal-helper.patch create mode 100644 staging/kf6-kio/0001-Give-the-kuriikwsfiltereng_private-a-VERSION-and-SOV.patch create mode 100644 staging/kf6-kio/1556.patch create mode 100644 staging/kf6-kio/6e7775d315f389df0a440ed62b842ce83dc9a27e.patch create mode 100644 staging/kf6-kio/kf6-kio.spec diff --git a/staging/gnome-shell/0001-gdm-Work-around-failing-fingerprint-auth.patch b/staging/gnome-shell/0001-gdm-Work-around-failing-fingerprint-auth.patch new file mode 100644 index 0000000..2baa7b6 --- /dev/null +++ b/staging/gnome-shell/0001-gdm-Work-around-failing-fingerprint-auth.patch @@ -0,0 +1,67 @@ +From ff73f820b1398e5d60b8984b0003db46ad70b8ec Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 28 Apr 2021 16:50:03 +0200 +Subject: [PATCH] gdm: Work around failing fingerprint auth + +On Fedora we have the problem that fingerprint auth fails immediately if +the PAM configuration has not been updated and no prints are enrolled. + +So, consider a verification failure within one second to be a service +failure instead. +--- + js/gdm/util.js | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/js/gdm/util.js b/js/gdm/util.js +index 97df6d687e..371953cb25 100644 +--- a/js/gdm/util.js ++++ b/js/gdm/util.js +@@ -109,6 +109,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._defaultService = null; + this._preemptingService = null; + this._fingerprintReaderType = FingerprintReaderType.NONE; ++ this._fprintStartTime = -1; + + this._messageQueue = []; + this._messageQueueTimeoutId = 0; +@@ -669,6 +670,10 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._hold.acquire(); + try { + this._activeServices.add(serviceName); ++ ++ if (serviceName == FINGERPRINT_SERVICE_NAME) ++ this._fprintStartTime = GLib.get_monotonic_time(); ++ + if (this._userName) { + await this._userVerifier.call_begin_verification_for_user( + serviceName, this._userName, this._cancellable); +@@ -763,6 +768,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + const cancellable = this._cancellable; + this._fingerprintFailedId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + FINGERPRINT_ERROR_TIMEOUT_WAIT, () => { ++ log("Generating _verificationFailed!"); + this._fingerprintFailedId = 0; + if (!cancellable.is_cancelled()) + this._verificationFailed(serviceName, false); +@@ -829,6 +835,18 @@ export class ShellUserVerifier extends Signals.EventEmitter { + if (serviceName === FINGERPRINT_SERVICE_NAME) { + if (this._fingerprintFailedId) + GLib.source_remove(this._fingerprintFailedId); ++ ++ // On Fedora we have the problem that fingerprint auth fails ++ // immediately if the PAM configuration has not been updated and no ++ // prints are enrolled. ++ // So, consider a verification failure within one second to be a service ++ // failure instead. ++ if (this._fprintStartTime > GLib.get_monotonic_time() - GLib.USEC_PER_SEC) { ++ log("Fingerprint service failed almost immediately, considering it unavailable."); ++ log("Please fix your configuration by running: authselect select --force sssd with-fingerprint with-silent-lastlog"); ++ this._onServiceUnavailable(this._client, serviceName, null); ++ return; ++ } + } + + // For Not Listed / enterprise logins, immediately reset +-- +2.43.2 + diff --git a/staging/gnome-shell/3193.patch b/staging/gnome-shell/3193.patch new file mode 100644 index 0000000..d4dd536 --- /dev/null +++ b/staging/gnome-shell/3193.patch @@ -0,0 +1,98 @@ +From c8c05c4a142f3de9c17a9ca83692dda364abccc8 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Thu, 15 Feb 2024 16:05:40 +0100 +Subject: [PATCH] shell-app: Improve discrete GPU detection + +--- + .../net.hadess.SwitcherooControl.xml | 3 +- + src/shell-app.c | 60 +++++++++++++++++++ + 2 files changed, 62 insertions(+), 1 deletion(-) + +diff --git a/data/dbus-interfaces/net.hadess.SwitcherooControl.xml b/data/dbus-interfaces/net.hadess.SwitcherooControl.xml +index e52bc1a0d25..59a889654f4 100644 +--- a/data/dbus-interfaces/net.hadess.SwitcherooControl.xml ++++ b/data/dbus-interfaces/net.hadess.SwitcherooControl.xml +@@ -38,7 +38,8 @@ + will contain a user-facing name for the GPU, the "Environment" (as) key will + contain an array of even number of strings, each being an environment + variable to set to use the GPU, followed by its value, the "Default" (b) key +- will tag the default (usually integrated) GPU. ++ will tag the default GPU, the "Discrete" (b) key tags if the GPU is a ++ dedicated component. + --> + + +diff --git a/src/shell-app.c b/src/shell-app.c +index 371bc6cf762..39f220ba954 100644 +--- a/src/shell-app.c ++++ b/src/shell-app.c +@@ -1300,6 +1300,66 @@ apply_discrete_gpu_env (GAppLaunchContext *context, + } + + num_children = g_variant_n_children (variant); ++ ++ // Check if the Default GPU is Discrete ++ for (i = 0; i < num_children; i++) ++ { ++ g_autoptr(GVariant) gpu = NULL; ++ g_autoptr(GVariant) env = NULL; ++ g_autoptr(GVariant) default_variant = NULL; ++ g_autoptr(GVariant) discrete_variant = NULL; ++ g_autofree const char **env_s = NULL; ++ ++ gpu = g_variant_get_child_value (variant, i); ++ if (!gpu || ++ !g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}"))) ++ continue; ++ ++ /* Skip over non-default GPUs */ ++ default_variant = g_variant_lookup_value (gpu, "Default", NULL); ++ if (!default_variant || !g_variant_get_boolean (default_variant)) ++ continue; ++ ++ /* break out if default GPU is not discrete */ ++ discrete_variant = g_variant_lookup_value (gpu, "Discrete", NULL); ++ if (!discrete_variant || !g_variant_get_boolean (discrete_variant)) ++ break; ++ ++ // Default GPU is discrete, no need to do anything ++ return; ++ } ++ ++ // Find the first Discrete GPU ++ for (i = 0; i < num_children; i++) ++ { ++ g_autoptr(GVariant) gpu = NULL; ++ g_autoptr(GVariant) env = NULL; ++ g_autoptr(GVariant) discrete_variant = NULL; ++ g_autofree const char **env_s = NULL; ++ guint j; ++ ++ gpu = g_variant_get_child_value (variant, i); ++ if (!gpu || ++ !g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}"))) ++ continue; ++ ++ /* Skip over non-discrete GPUs */ ++ discrete_variant = g_variant_lookup_value (gpu, "Discrete", NULL); ++ if (!discrete_variant || !g_variant_get_boolean (discrete_variant)) ++ continue; ++ ++ env = g_variant_lookup_value (gpu, "Environment", NULL); ++ if (!env) ++ continue; ++ ++ env_s = g_variant_get_strv (env, NULL); ++ for (j = 0; env_s[j] != NULL; j = j + 2) ++ g_app_launch_context_setenv (context, env_s[j], env_s[j+1]); ++ return; ++ } ++ ++ // fallback to old behavior ++ // find the first non-Default GPU + for (i = 0; i < num_children; i++) + { + g_autoptr(GVariant) gpu = NULL; +-- +GitLab + diff --git a/staging/gnome-shell/changelog b/staging/gnome-shell/changelog new file mode 100644 index 0000000..260698e --- /dev/null +++ b/staging/gnome-shell/changelog @@ -0,0 +1,1484 @@ +* Sat Mar 25 2023 Adam Williamson - 44.0-4 +- Backport MR #2725 - *another* fix for screenshot notifications + +* Fri Mar 24 2023 Adam Williamson - 44.0-3 +- Backport a fix for screenshot notifications + +* Sun Mar 19 2023 Florian Müllner - 44.0-2 +- Fix timed logout + Resolves: #2177853 + +* Sun Mar 19 2023 Florian Müllner - 44.0-1 +- Update to 44.0 + +* Tue Mar 14 2023 Dominik Mierzejewski - 44~rc-2 +- Recommend gnome-bluetooth instead of requiring it + Resolves rhbz#2172653 + +* Mon Mar 06 2023 Florian Müllner - 44~rc-1 +- Update to 44.rc + +* Sun Mar 05 2023 Ray Strode - 44~beta-3 +- Fix slowdown in at shutdown + Resolves: #2174753 + +* Mon Feb 20 2023 Adam Williamson - 44~beta-2 +- Rebuild without changes for Bodhi reasons + +* Tue Feb 14 2023 Florian Müllner - 44~beta-1 +- Update to 44.beta + +* Thu Jan 19 2023 Fedora Release Engineering - 43.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Nov 21 2022 Adam Williamson - 43.1-4 +- Backport MR #2548 to fix keyboard shortcut inhibiting + +* Thu Nov 17 2022 Jonas Ådahl - 43.1-3 +- Backport missing screencast if gstreamer1-vaapi is installed + +* Wed Nov 16 2022 Adam Williamson - 43.1-2 +- Backport MR #2534 to fix layout switching in password entries + +* Fri Nov 04 2022 Florian Müllner - 43.1-1 +- Update to 43.1 + +* Tue Oct 11 2022 Adam Williamson - 43.0-3 +- Backport MR2508 to fix OSK space entry (#2131837) + +* Thu Sep 22 2022 Kalev Lember - 43.0-2 +- Backport MR2487 and MR2495 to fix input sources sorting (#2121110) + +* Sat Sep 17 2022 Florian Müllner - 43.0-1 +- Update to 43.0 + +* Thu Sep 15 2022 Kalev Lember - 43~rc-3 +- Backport a fix for initial setup session input sources sorting (#2121110) + +* Tue Sep 06 2022 Kalev Lember - 43~rc-2 +- Backport upstream fix to fix boot options (#2124043) + +* Sun Sep 04 2022 Florian Müllner - 43~rc-1 +- Update to 43.rc + +* Fri Sep 02 2022 Kalev Lember - 43~beta-3 +- Add missing dep on gcr + +* Thu Aug 11 2022 Kalev Lember - 43~beta-2 +- Bump minimum required gjs version + +* Wed Aug 10 2022 Florian Müllner - 43~beta-1 +- Update to 43.beta + +* Thu Jul 21 2022 Fedora Release Engineering - 43~alpha-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Tue Jul 19 2022 Milan Crha - 43~alpha-2 +- Rebuilt for evolution-data-server soname version bump +- Add patch to port to gcr4 + +* Sun Jul 10 2022 Florian Müllner - 43~alpha-1 +- Update to 43.alpha + +* Sat May 28 2022 Florian Müllner - 42.2-1 +- Update to 42.2 + +* Fri May 06 2022 Florian Müllner - 42.1-1 +- Update to 42.1 + +* Mon Apr 18 2022 Florian Müllner - 42.0-3 +- Fix monitor config switches with p (#2073406) +- Fix stuck cover pane after startup animation (#2063156) + +* Tue Mar 15 2022 Adam Williamson - 42.0-2 +- Backport MR #2242 to fix new user default folder creation (#2064473) + +* Sun Mar 13 2022 Florian Müllner - 42.0-1 +- Update to 42.0 + +* Wed Mar 09 2022 Adam Williamson - 42~rc-2 +- Backport MR #2238 to fix crashes on first login + +* Mon Mar 07 2022 Florian Müllner - 42~rc-1 +- Update to 42.rc + +* Tue Mar 01 2022 Adam Williamson - 42~beta-4 +- Update the MR #2185 backport + +* Tue Mar 01 2022 Adam Williamson - 42~beta-3 +- Backport MR #2185 to fix some styling issues at lower resolutions + +* Wed Feb 16 2022 David King - 42~beta-2 +- Update some dependency versions + +* Tue Feb 15 2022 Florian Müllner - 42~beta-1 +- Update to 42.beta + +* Thu Jan 20 2022 Fedora Release Engineering - 42~alpha-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Fri Jan 14 2022 David King - 42~alpha-2 +- Fix gweather4 dependency + +* Fri Jan 14 2022 David King - 42~alpha-1 +- Update to 42.alpha +- Use pkgconfig for BuildRequires + +* Fri Oct 29 2021 Adam Williamson - 41.0-8 +- Backport MR #2011 to further fix unexpected scrolling (#2017192) + +* Wed Oct 27 2021 Ray Strode - 41.0-7 +- Use correct patch for fixing unlock screen confusion + +* Tue Oct 26 2021 Jonas Ådahl - 41.0-6 +- Work around crashy tear down + +* Tue Oct 26 2021 Ray Strode - 41.0-5 +- Fix unlock screen confusion when hitting escape too much + +* Tue Oct 12 2021 Ray Strode - 41.0-4 +- Fix StPasswordEntry crash + Resolves: #2009637 + +* Thu Oct 07 2021 Adam Williamson - 41.0-3 +- Backport MR #1983 to fix wrong OSD icons (#2011872) + +* Tue Oct 05 2021 Kalev Lember - 41.0-2 +- Backport upstream patch to fix scrolling to incorrect positions + +* Sun Sep 19 2021 Florian Müllner - 41.0-1 +- Update to 41.0 + +* Tue Sep 14 2021 Ray Strode - 41~rc.1-2 +- Drop extra capabilities from gnome-shell. They're optional and they break shutdown from the login screen with new glibs. + Resolves: #1996998 + +* Tue Sep 07 2021 Florian Müllner - 41~rc.1-1 +- Update to 41.rc.1 + +* Sun Sep 05 2021 Florian Müllner - 41~rc-1 +- Update to 41.rc + +* Wed Aug 18 2021 Florian Müllner - 41~beta-1 +- Update to 41.beta + +* Thu Jul 22 2021 Fedora Release Engineering - 40.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Jul 12 2021 Florian Müllner - 40.3-1 +- Update to 40.3 + +* Thu Jun 10 2021 Florian Müllner - 40.2-1 +- Update to 40.2 + +* Thu May 13 2021 Florian Müllner - 40.1-1 +- Update to 40.1 + +* Fri Apr 30 2021 Kalev Lember - 40.0-6 +- Move gnome-tour dep here from gnome-initial-setup (#1955179) + +* Wed Apr 28 2021 Benjamin Berg - 40.0-5 +- Update fix for password auth after background service failure + Related: #1942443 + +* Fri Apr 23 2021 Benjamin Berg - 40.0-4 +- Fix password auth after secondary service failure + Related: #1942443 + +* Tue Apr 13 2021 Adam Williamson - 40.0-3 +- Fix scrolling between workspaces/app grid pages with PgUp/PgDn + +* Tue Apr 13 2021 Ray Strode - 40.0-2 +- Fix timed login when user list is disabled + Resolves: #1940618 + +* Sat Mar 20 2021 Florian Müllner - 40.0-1 +- Update to 40.0 + +* Mon Mar 15 2021 Florian Müllner - 40.0~rc-1 +- Update to 40.rc + +* Thu Mar 11 2021 Kalev Lember - 40.0~beta-4.20210304git7a57528bd +- Recommend gnome-session-xsession rather than hard-require it + +* Mon Mar 08 2021 Florian Müllner - 40.0~beta-3.20210304git40.7a57528bd +- Fix crash after launching apps via drag-and-drop + +* Thu Mar 04 2021 Florian Müllner - 40.0~beta-2.20210304git40.7a57528bd +- Build snapshot of current upstream + +* Tue Feb 23 2021 Florian Müllner - 40.0~beta-1 +- Update to 40.beta + +* Mon Feb 22 2021 Kalev Lember - 40.0~alpha.1.1-9.20210212git829a096ba +- Add missing requires on gstreamer1-plugins-good and xdg-user-dirs-gtk (#1931342) + +* Sun Feb 14 2021 Florian Müllner - 40.0~alpha.1.1-8.20210212git829a096ba +- Only open app picker on left-click/touch + +* Sun Feb 14 2021 Florian Müllner - 40.0~alpha.1.1-7.20210212git829a096ba +- Don't open app picker when clicking minimap + +* Fri Feb 12 2021 Florian Müllner - 40.0~alpha.1.1-6.20210212git829a096ba +- Update snapshot to current upstream +- Allow opening app picker by clicking overview background + +* Fri Feb 12 2021 Milan Crha - 40.0~alpha.1.1-5.20210202git9ce666ac1 +- Rebuilt for evolution-data-server soname version bump + +* Tue Feb 02 2021 Florian Müllner - 40.0~alpha.1.1-4.20210202git9ce666ac1 +- Build snapshot of current upstream + +* Tue Jan 26 2021 Fedora Release Engineering - 40.0~alpha.1.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Jan 19 2021 Kalev Lember - 40.0~alpha.1.1-2 +- Require libgweather >= 40~alpha for new application_id property + +* Mon Jan 18 2021 Florian Müllner - 40.alpha.1.1-1 +- Update to 40.alpha.1.1 + +* Fri Jan 15 2021 Florian Müllner - 40.alpha.1-1 +- Update to 40.alpha.1 + +* Wed Dec 02 2020 Florian Müllner - 40.alpha-1 +- Update to 40.alpha + +* Tue Oct 13 2020 Florian Müllner - 3.38.1-2 +- Fix crash on size change (non-)transitions + +* Mon Oct 05 2020 Florian Müllner - 3.38.1-1 +- Update to 3.38.1 + +* Tue Sep 29 2020 David King - 3.38.0-2 +- Better specify xdg-desktop-portal-gtk dependency (#1882894) + +* Mon Sep 14 2020 Florian Müllner - 3.38.0-1 +- Update to 3.38.0 + +* Thu Sep 10 2020 Kalev Lember - 3.37.92-5 +- Set minimum gnome-settings-daemon version for Screencast proxy changes + +* Wed Sep 09 2020 Kalev Lember - 3.37.92-4 +- Add missing pipewire-gstreamer dependency for screen recorder + +* Sun Sep 06 2020 Florian Müllner - 3.37.92-1 +- Update to 3.37.92 + +* Wed Sep 02 2020 Florian Müllner - 3.37.91-3 +- Add missing pipewire dependency for screen recorder + +* Wed Aug 26 2020 Kalev Lember - 3.37.91-2 +- Add PolicyKit-authentication-agent virtual provides + +* Mon Aug 24 2020 Florian Müllner - 3.37.91-1 +- Update to 3.37.91 + +* Sun Aug 23 2020 Kalev Lember - 3.37.90-2 +- Backport a fix for launching apps under X11 (#1870234) + +* Fri Aug 14 2020 Florian Müllner - 3.37.90-1 +- Update to 3.37.90 + +* Sat Aug 01 2020 Fedora Release Engineering - 3.37.3-4 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 3.37.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 13 2020 Milan Crha - 3.37.3-2 +- Rebuilt for evolution-data-server soname version bump + +* Tue Jul 07 2020 Florian Müllner - 3.37.3-1 +- Update to 3.37.3 + +* Fri Jul 03 2020 Milan Crha - 3.37.2-2 +- Rebuilt for evolution-data-server soname version bump + +* Wed Jun 03 2020 Florian Müllner - 3.37.2-1 +- Update to 3.37.2 + +* Wed May 20 2020 Stephen Gallagher - 3.37.1-3 +- Fix crashes when locking the screen while certain extensions are active +- Resolves: rhbz#1817082 + +* Mon May 04 2020 Adam Williamson - 3.37.1-2 +- Fix panel to show input methods (MR #1235) + +* Thu Apr 30 2020 Florian Müllner - 3.36.1-2 +- Backport fixup for spring animation fix + +* Tue Mar 31 2020 Florian Müllner - 3.36.1-1 +- Update to 3.36.1 +- Remove gnome-extensions-app subpackage (will move to a separate .spec) + +* Wed Mar 25 2020 Ray Strode - 3.36.0-4 +- Clear environment on logout + Fixes log in to Xorg right after log out from wayland + Resolves: #1815487 + +* Wed Mar 11 2020 Adam Williamson - 3.36.0-3 +- Backport fix for input method preedit issue (MR #1084) + +* Tue Mar 10 2020 Adam Williamson - 3.36.0-2 +- Backport fix for ibus failing to start automatically (MR #1080) + +* Sat Mar 07 2020 Florian Müllner - 3.36.0-1 +- Update to 3.36.0 + +* Sun Mar 01 2020 Florian Müllner - 3.35.92-1 +- Update to 3.35.92 + +* Tue Feb 18 2020 Florian Müllner - 3.35.91-1 +- Update to 3.35.91 + +* Fri Feb 07 2020 Kalev Lember - 3.35.90-2 +- Adjust the favorites patch to include the apps we install by default + +* Thu Feb 06 2020 Florian Müllner - 3.35.90-1 +- Update to 3.35.90 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.35.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 16 2020 Kalev Lember - 3.35.3-2 +- Rebuilt for libgnome-desktop soname bump + +* Sun Jan 05 2020 Florian Müllner - 3.35.3-2 +- Update to 3.35.3 + +* Wed Dec 11 2019 Florian Müllner - 3.35.2-1 +- Udpate to 3.35.2 + +* Sat Oct 12 2019 Florian Müllner - 3.35.1-1 +- Update to 3.35.1 + +* Sat Oct 12 2019 Adam Williamson - 3.34.1-2 +- Backport MR #754 to fix #1749433 + +* Wed Oct 09 2019 Florian Müllner - 3.34.1-1 +- Update to 3.34.1 + +* Tue Sep 24 2019 Debarshi Ray - 3.34.0-3 +- Stop NOTIFY_SOCKET from leaking into the GNOME environment + +* Fri Sep 20 2019 Florian Müllner - 3.34.0-2 +- Fix disappearing icons in frequent view + +* Mon Sep 09 2019 Florian Müllner - 3.34.0-1 +- Update to 3.34.0 + +* Thu Sep 05 2019 Kalev Lember - 3.33.92-1 +- Update to 3.33.92 + +* Mon Aug 26 2019 Kalev Lember - 3.33.91-1 +- Update to 3.33.91 + +* Fri Aug 23 2019 Adam Williamson - 3.33.90-2 +- Revert commit that causes #1740897 (overview type-to-search bug) + Resolves: #1740897 + +* Sat Aug 10 2019 Florian Müllner - 3.33.90-1 +- Update to 3.33.90 + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sat Jul 20 2019 Florian Müllner - 3.33.4-1 +- Update to 3.33.4 + +* Mon Jun 24 2019 Florian Mülllner - 3.33.3-1 +- Update to 3.33.3 + +* Wed May 22 2019 Florian Müllner - 3.33.2-1 +- Update to 3.33.2 + +* Wed May 22 2019 Kalev Lember - 3.33.1-2 +- Rebuild for libecal-2.0 + +* Tue May 14 2019 Florian Müllner - 3.33.1-1 +- Update to 3.33.1 + +* Wed Apr 17 2019 Florian Müllner - 3.32.1-1 +- Update to 3.32.1 + +* Wed Apr 17 2019 Adam Williamson - 3.32.0-3 +- Backport MR #463 and MR #494 to fix a couple of bugs + Resolves: #1696270 + Resolves: #1690429 + +* Sat Mar 23 2019 Phil Wyett - 3.32.0-2 +- Update source URL +- Add gcc BuildRequires +- Update versions required for gjs and mutter + +* Tue Mar 12 2019 Florian Müllner - 3.32.0-1 +- Update to 3.32.0 + +* Tue Mar 05 2019 Florian Müllner - 3.31.92-1 +- Update to 3.31.92 + +* Thu Feb 21 2019 Florian Müllner - 3.31.91-1 +- Update to 3.31.91 + +* Mon Feb 11 2019 Adam Williamson - 3.31.90-2 +- Backport MR #402 to fix missing logo on login screen + +* Thu Feb 07 2019 Florian Müllner - 3.31.90-1 +- Update to 3.31.90 + +* Thu Jan 31 2019 Fedora Release Engineering - 3.31.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Thu Jan 10 2019 Florian Müllner - 3.31.4-1 +- Update to 3.31.4 + +* Fri Dec 14 2018 Adam Williamson - 3.31.2-3 +- Backport several bugfix commits from current git master + +* Fri Nov 30 2018 Adam Williamson - 3.31.2-2 +- Backport PR #293 to fix 'empty input method indicator' bug + +* Wed Nov 14 2018 Florian Müllner - 3.31.2-1 +- Update to 3.31.2 + +* Mon Nov 12 2018 Mohan Boddu - 3.30.1-3 +- Rebuilt for evolution-data-server soname bump + +* Tue Oct 23 2018 Jonas Ådahl - 3.30.1-2 +- Backport keyboard layout change fixes (rhbz#1637418) + +* Mon Oct 08 2018 Florian Müllner - 3.30.1-1 +- Update to 3.30.1 + +* Thu Sep 27 2018 Hans de Goede - 3.30.0-9 +- Add downstream patches implementing the "Boot Options" menu from: + https://wiki.gnome.org/Design/OS/BootOptions + +* Sat Sep 22 2018 Adam Williamson - 3.30.0-8 +- Backport fix for IBus type issue (GGO MR #228) + +* Wed Sep 19 2018 Adam Williamson - 3.30.0-7 +- Replace dnd fix from -5 with upstream version (GGO MR #209) +- Fix a window destroy crash which can occur with new gjs (GGO #539) +- Fix a window menu issue on multi-monitor systems (GGO MR #227) +- Fix hover and active states for some buttons (GGO #523) + +* Wed Sep 19 2018 Adam Williamson - 3.30.0-6 +- Fix missing key description in ssh key unlock prompt (GGO #574) + +* Wed Sep 19 2018 Ray Strode - 3.30.0-5 +- Fix lock up when dropping icon on dash + Resolves: #1630134 + +* Tue Sep 18 2018 Adam Williamson - 3.30.0-4 +- Fix connecting to wifi from user menu (RHBZ #1628263) + +* Sat Sep 15 2018 Adam Williamson - 3.30.0-3 +- Backport fix for GGO #140 from upstream master + +* Thu Sep 13 2018 Kalev Lember - 3.30.0-2 +- Require xdg-desktop-portal-gtk + +* Tue Sep 04 2018 Florian Müllner - 3.30.0-1 +- Update to 3.30.0 + +* Wed Aug 29 2018 Florian Müllner - 3.29.92-1 +- Update to 3.29.92 + +* Mon Aug 20 2018 Florian Müllner - 3.29.91-1 +- Update to 3.29.91 + +* Thu Aug 09 2018 Debarshi Ray - 3.29.90-2 +- Remove telepathy-logger and telepathy-glib runtime dependencies + +* Wed Aug 01 2018 Florian Müllner - 3.29.90-1 +- Update to 3.29.90 + +* Wed Jul 18 2018 Florian Müllner - 3.29.4-1 +- Update to 3.29.4 + +* Fri Jul 13 2018 Fedora Release Engineering - 3.29.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu May 24 2018 Florian Müllner - 3.29.2-1 +- Update to 3.29.2 + +* Wed May 09 2018 Florian Müllner - 3.29.1-3 +- Fix automatic connection to wireless networks without stored secrets + +* Sun Apr 29 2018 Adam Williamson - 3.29.1-2 +- Backport fix for password entry modifier key issues (#1569211) + +* Wed Apr 25 2018 Florian Müllner - 3.29.1-1 +- Update to 3.29.1 + +* Tue Apr 24 2018 Ray Strode - 3.28.1-2 +- pull polkit cancel lock up from upstream + Resolves: #1568213 + +* Fri Apr 13 2018 Florian Müllner - 3.28.1-1 +- Update to 3.28.1 + +* Mon Mar 12 2018 Florian Müllner - 3.28.0-1 +- Update to 3.28.0 + +* Mon Mar 05 2018 Florian Müllner - 3.27.92-1 +- Update to 3.27.92 + +* Thu Feb 22 2018 Lubomir Rintel - 3.27.91-2 +- Replace libnm-gtk with libnma + +* Wed Feb 21 2018 Florian Müllner - 3.27.91-1 +- Update to 3.27.91 + +* Wed Feb 07 2018 Kalev Lember - 3.27.1-5 +- Rebuilt for evolution-data-server soname bump + +* Mon Jan 22 2018 Adam Williamson - 3.27.1-4 +- Backport fix for crasher bug BGO #788931 (#1469129) + +* Tue Dec 19 2017 Kalev Lember - 3.27.1-3 +- Explicitly require libnm-gtk (#1509496) + +* Wed Nov 08 2017 Milan Crha - 3.27.1-2 +- Rebuild for newer libical + +* Tue Oct 17 2017 Florian Müllner - 3.27.1-1 +- Update to 3.27.1 + +* Wed Oct 04 2017 Florian Müllner - 3.26.1-1 +- Update to 3.26.1 + +* Thu Sep 21 2017 Florian Müllner - 3.26.0-2 +- Fix crash on fast status icon remapping + +* Tue Sep 12 2017 Florian Müllner - 3.26.0-1 +- Update to 3.26.0 + +* Tue Aug 22 2017 Florian Müllner - 3.25.91-1 +- Update to 3.25.91 + +* Fri Aug 11 2017 Kevin Fenzi - 3.25.90-2 +- Rebuild with older working rpm + +* Thu Aug 10 2017 Florian Müllner - 3.25.90-1 +- Update to 3.25.90 + +* Wed Aug 02 2017 Fedora Release Engineering - 3.25.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 3.25.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jul 20 2017 Florian Müllner - 3.25.4-1 +- Update to 3.25.4 + +* Wed Jun 21 2017 Florian Müllner - 3.25.3-1 +- Update to 3.25.3 + +* Thu May 25 2017 Florian Müllner - 3.25.2-1 +- Update to 3.25.2 + +* Thu Apr 27 2017 Florian Müllner - 3.25.1-1 +- Update to 3.25.1 + +* Tue Apr 11 2017 Florian Müllner - 3.24.1-1 +- Update to 3.24.1 + +* Mon Mar 20 2017 Florian Müllner - 3.24.0-1 +- Update to 3.24.0 + +* Thu Mar 16 2017 Igor Gnatenko - 3.23.92-2 +- Fix wrong runtime requirements + +* Tue Mar 14 2017 Florian Müllner - 3.23.92-1 +- Update to 3.23.92 + +* Wed Mar 01 2017 Florian Müllner - 3.23.91-1 +- Update to 3.23.91 + +* Thu Feb 16 2017 Florian Müllner - 3.23.90-1 +- Update to 3.23.90 + +* Tue Feb 14 2017 Richard Hughes - 3.23.3-1 +- Update to 3.23.3 + +* Fri Feb 10 2017 Fedora Release Engineering - 3.23.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Dec 19 2016 Miro Hrončok - 3.23.2-3 +- Rebuild for Python 3.6 + +* Tue Dec 6 2016 Rui Matos - 3.23.2-2 +- Tighten mutter version dependency for plugin API changes + Resolves: #1401886 + +* Wed Nov 23 2016 Florian Müllner - 3.23.2-1 +- Update to 3.23.2 + +* Sun Oct 30 2016 Florian Müllner - 3.23.1-1 +- Update to 3.23.1 + +* Fri Oct 21 2016 Bastien Nocera - 3.22.1-2 +- Add patches to allow launching on discrete GPU when available + +* Tue Oct 11 2016 Florian Müllner - 3.22.1 +- Update to 3.22.1 + +* Mon Sep 19 2016 Florian Müllner - 3.22.0 +- Update to 3.22.0 + +* Tue Sep 13 2016 Florian Müllner - 3.21.92 +- Update to 3.21.92 + +* Fri Sep 09 2016 Kalev Lember - 3.21.91-2 +- Drop libgsystem dependency + +* Tue Aug 30 2016 Florian Müllner - 3.21.91 +- Update to 3.21.91 + +* Sat Aug 20 2016 Florian Müllner - 3.21.90.1-1 +- Update to 3.21.90.1 + (Fixes a corrupt .desktop file that made it from the build directory into + the 3.21.90 tarball) + +* Fri Aug 19 2016 Florian Müllner - 3.21.90-1 +- Update to 3.21.90 + +* Wed Jul 20 2016 Florian Müllner - 3.21.4-1 +- Update to 3.21.4 + +* Mon Jul 18 2016 Milan Crha - 3.21.3-2 +- Rebuild for newer evolution-data-server + +* Tue Jun 21 2016 Florian Müllner - 3.21.3-1 +- Update to 3.21.3 + +* Tue Jun 21 2016 Milan Crha - 3.21.2-2 +- Rebuild for newer evolution-data-server + +* Thu May 26 2016 Florian Müllner - 3.21.2-1 +- Update to 3.21.2 + +* Fri Apr 29 2016 Florian Müllner - 3.21.1-1 +- Update to 3.21.1 + +* Fri Apr 15 2016 David Tardon - 3.20.1-2 +- rebuild for ICU 57.1 + +* Wed Apr 13 2016 Florian Müllner - 3.20.1-1 +- Update to 3.20.1 + +* Tue Mar 22 2016 Florian Müllner - 3.20.0-1 +- Update to 3.20.0 + +* Wed Mar 16 2016 Florian Müllner - 3.19.92-1 +- Update to 3.19.92 + +* Thu Mar 03 2016 Florian Müllner - 3.19.91-1 +- Update to 3.19.91 + +* Fri Feb 19 2016 Florian Müllner - 3.19.90-1 +- Update to 3.19.90 + +* Tue Feb 16 2016 Milan Crha - 3.19.4-3 +- Rebuild for newer evolution-data-server + +* Wed Feb 03 2016 Fedora Release Engineering - 3.19.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 21 2016 Florian Müllner - 3.19.4-1 +- Update to 3.19.4 + +* Mon Jan 18 2016 David Tardon - 3.19.3-2 +- rebuild for libical 2.0.0 + +* Thu Dec 17 2015 Florian Müllner - 3.19.3-1 +- Update to 3.19.3 + +* Tue Dec 01 2015 Kalev Lember - 3.19.2-2 +- Bump gsettings-desktop-schemas dep to 3.19.2 + +* Wed Nov 25 2015 Florian Müllner - 3.19.2-1 +- Update to 3.19.2 + +* Tue Nov 10 2015 Ray Strode 3.19.1-3.20151110 +- Update to git snapshot + +* Sun Nov 01 2015 Kalev Lember - 3.19.1-2 +- Fix gnome-shell crashing in gdm mode (#1276833) + +* Thu Oct 29 2015 Florian Müllner - 3.19.1-1 +- Update to 3.19.1 + +* Thu Oct 15 2015 Florian Müllner - 3.18.1-1 +- Update to 3.18.1 + +* Mon Sep 21 2015 Florian Müllner - 3.18.0-1 +- Update to 3.18.0 + +* Wed Sep 16 2015 Florian Müllner - 3.17.92-1 +- Update to 3.17.92 + +* Thu Sep 03 2015 Florian Müllner - 3.17.91-1 +- Update to 3.17.91 + +* Thu Aug 20 2015 Florian Müllner - 3.17.90-1 +- Update to 3.17.90 + +* Wed Aug 19 2015 Kalev Lember - 3.17.4-2 +- Create empty directories for extensions and search providers +- Move desktop file validation to %%check section +- Use make_install macro + +* Thu Jul 23 2015 Florian Müllner - 3.17.4-1 +- Update to 3.17.4 + +* Wed Jul 22 2015 Milan Crha - 3.17.3-3 +- Rebuild for newer evolution-data-server + +* Sat Jul 04 2015 Kalev Lember - 3.17.3-2 +- Require gobject-introspection 1.45.3 + +* Thu Jul 02 2015 Florian Müllner - 3.17.3-1 +- Update to 3.17.3 + +* Wed Jun 17 2015 Fedora Release Engineering - 3.17.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 27 2015 Florian Müllner - 3.17.2-1 +- Update to 3.17.2 + +* Thu Apr 30 2015 Florian Müllner - 3.17.1-1 +- Update to 3.17.1 + +* Tue Apr 28 2015 Milan Crha - 3.16.1-2 +- Rebuild for newer evolution-data-server + +* Tue Apr 14 2015 Florian Müllner - 3.16.1-1 +- Update to 3.16.1 + +* Mon Mar 23 2015 Florian Müllner - 3.16.0-1 +- Update to 3.16.0 + +* Tue Mar 17 2015 Kalev Lember - 3.15.92-2 +- Update minimum dep versions +- Use license macro for the COPYING file + +* Tue Mar 17 2015 Florian Müllner - 3.15.92-1 +- Update to 3.15.92 + +* Tue Mar 17 2015 Ray Strode 3.15.91-2 +- Drop dep on NetworkManager-config-connectivity-fedora + It's already required by fedora-release-workstation + +* Wed Mar 04 2015 Florian Müllner - 3.15.91-1 +- Update to 3.15.91 + +* Fri Feb 20 2015 Florian Müllner - 3.15.90-1 +- Update to 3.15.90 + +* Tue Feb 17 2015 Milan Crha - 3.15.4-2 +- Rebuild against newer evolution-data-server + +* Wed Jan 21 2015 Florian Müllner - 3.15.4-1 +- Update to 3.15.4 + +* Fri Dec 19 2014 Florian Müllner - 3.15.3-1 +- Update to 3.15.3 + +* Thu Nov 27 2014 Florian Müllner - 3.15.2-1 +- Update to 3.15.2 + +* Thu Oct 30 2014 Florian Müllner - 3.15.1-1 +- Update to 3.15.1 + +* Tue Oct 14 2014 Florian Müllner - 3.14.1-1 +- Update to 3.14.1 + +* Tue Sep 23 2014 Kalev Lember - 3.14.0-2 +- Drop unused gnome-menus dependency + +* Mon Sep 22 2014 Florian Müllner - 3.14.0-1 +- Update to 3.14.0 + +* Wed Sep 17 2014 Florian Müllner - 3.13.92-1 +- Update to 3.13.92 + +* Wed Sep 03 2014 Florian Müllner - 3.13.91-1 +- Update to 3.13.91 + +* Wed Aug 20 2014 Florian Müllner - 3.13.90-1 +- Update to 3.13.90 + +* Sat Aug 16 2014 Fedora Release Engineering - 3.13.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Thu Jul 31 2014 Milan Crha - 3.13.4-3 +- Rebuild against newer evolution-data-server + +* Mon Jul 28 2014 Adel Gadllah - 3.13.4-2 +- Require NetworkManager-config-connectivity-fedora + +* Wed Jul 23 2014 Florian Müllner - 3.13.4-1 +- Update to 3.13.4 + +* Tue Jul 22 2014 Kalev Lember - 3.13.3-2 +- Rebuilt for gobject-introspection 1.41.4 + +* Fri Jun 27 2014 Florian Müllner - 3.13.3-1 +- New gobject-introspection has been built, drop the last patch again + +* Wed Jun 25 2014 Florian Müllner - 3.13.3-1 +- Revert annotation updates until we get a new gobject-introspection build + +* Wed Jun 25 2014 Florian Müllner - 3.13.3-1 +- Update to 3.13.3 + +* Sat Jun 07 2014 Fedora Release Engineering - 3.13.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 27 2014 Florian Müllner - 3.13.2-1 +- Update to 3.13.2 + +* Thu May 01 2014 Kalev Lember - 3.13.1-2 +- Pull in libgsystem + +* Wed Apr 30 2014 Florian Müllner - 3.13.1-1 +- Update to 3.13.1 + +* Tue Apr 15 2014 Florian Müllner - 3.12.1-1 +- Update to 3.12.1 + +* Sat Apr 05 2014 Kalev Lember - 3.12.0-2 +- Update dep versions + +* Tue Mar 25 2014 Florian Müllner - 3.12.0-1 +- Update to 3.12.0 + +* Wed Mar 19 2014 Florian Müllner - 3.11.92-1 +- Update to 3.11.92 + +* Wed Mar 12 2014 Adam Williamson - 3.11.91-2 +- update to final revision of background bug fix from upstream (BGO #722149) + +* Thu Mar 06 2014 Florian Müllner - 3.11.91-1 +- Update to 3.11.91 + +* Mon Mar 03 2014 Adam Williamson - 3.11.90-5 +- backport fixes to fix drag-and-drop workspace creation (BGO #724686) + +* Wed Feb 26 2014 Adam Williamson - 3.11.90-4 +- backport a couple of bugfixes from BGO for things that annoy me + +* Sat Feb 22 2014 Florian Müllner - 3.11.90-3 +- Add dependency on gnome-control-center - several panels are referenced + by a number of menu items + +* Thu Feb 20 2014 Kalev Lember - 3.11.90-2 +- Rebuilt for cogl soname bump + +* Thu Feb 20 2014 Florian Müllner - 3.11.90-1 +- Update to 3.11.90 + +* Mon Feb 10 2014 Peter Hutterer - 3.11.5-3 +- Rebuild for libevdev soname bump + +* Wed Feb 05 2014 Adam Williamson - 3.11.5-2 +- build against new gjs (and hence mozjs24) + +* Wed Feb 05 2014 Richard Hughes - 3.11.5-1 +- Update to 3.11.5 + +* Mon Feb 03 2014 Milan Crha - 3.11.4-2 +- Rebuild against newer evolution-data-server + +* Thu Jan 16 2014 Florian Müllner - 3.11.4-1 +- Update to 3.11.4 + +* Tue Jan 14 2014 Milan Crha - 3.11.3-2 +- Rebuild against newer evolution-data-server + +* Fri Dec 20 2013 Florian Müllner - 3.11.3-1 +- Update to 3.11.3 + +* Thu Nov 21 2013 Milan Crha - 3.11.2-3 +- Rebuild for new libical (RH bug #1023020) + +* Tue Nov 19 2013 Milan Crha - 3.11.2-2 +- Rebuild against newer evolution-data-server + +* Wed Nov 13 2013 Florian Müllner - 3.11.2-1 +- Update to 3.11.2 + +* Wed Oct 30 2013 Florian Müllner - 3.11.1-1 +- Update to 3.11.1 + +* Fri Oct 25 2013 Florian Müllner - 3.10.1-2 +- Rebuild for new e-d-s + +* Tue Oct 15 2013 Florian Müllner - 3.10.1-1 +- Update to 3.10.1 + +* Wed Sep 25 2013 Kalev Lember - 3.10.0.1-1 +- Update to 3.10.0.1 + +* Tue Sep 24 2013 Florian Müllner - 3.10.0-1 +- Update to 3.10.0 + +* Wed Sep 18 2013 Matthias Clasen - 3.9.92-3 +- Build against mutter-wayland + +* Tue Sep 17 2013 Florian Müllner - 3.9.92-1 +- Update to 3.9.92 + +* Tue Sep 03 2013 Florian Müllner - 3.9.91-1 +- Update to 3.9.91 + +* Thu Aug 22 2013 Florian Müllner - 3.9.90-1 +- Update to 3.9.90 + +* Mon Aug 19 2013 Adam Williamson - 3.9.5-3 +- Rebuild for new e-d-s + +* Sat Aug 10 2013 Kalev Lember - 3.9.5-2 +- Drop the bluez revert patch as we now have new enough gnome-bluetooth + +* Tue Jul 30 2013 Florian Müllner - 3.9.5 +- Update to 3.9.5 + +* Mon Jul 29 2013 Adam Williamson - 3.9.4-2 +- rebuild against updated evolution-data-server + +* Wed Jul 10 2013 Florian Müllner - 3.9.4-1 +- Update to 3.9.4 + +* Wed Jul 10 2013 Milan Crha - 3.9.3-3 +- Rebuild against newer evolution-data-server + +* Wed Jul 10 2013 Kalev Lember - 3.9.3-2 +- Add a downstream patch to revert back to bluez 4 + +* Tue Jun 18 2013 Florian Müllner - 3.9.3-1 +- Update to 3.9.3 + +* Tue May 28 2013 Florian Müllner - 3.9.2-1 +- Update to 3.9.2 + +* Sat May 25 2013 Rex Dieter 3.9.1-3 +- rebuild (libical) + +* Wed May 01 2013 Kalev Lember - 3.9.1-2 +- Add missing telepathy-logger runtime dep +- Depend on gnome-session-xsession so that it gets pulled in for + typical GNOME installs + +* Wed May 01 2013 Florian Müllner - 3.9.1-1 +- Update to 3.9.1 + +* Tue Apr 16 2013 Florian Müllner - 3.8.1-1 +- Update to 3.8.1 + +* Thu Mar 28 2013 Adel Gadllah - 3.8.0.1-2 +- Ship the perf tool + +* Wed Mar 27 2013 Ray Strode - 3.8.0.1-1 +- Update to 3.8.0.1 + +* Tue Mar 26 2013 Florian Müllner - 3.8.0-1 +- Update to 3.8.0 + +* Tue Mar 19 2013 Florian Müllner - 3.7.92-1 +- Update to 3.7.92 + +* Tue Mar 05 2013 Florian Müllner - 3.7.91-1 +- Update to 3.7.91 + +* Wed Feb 20 2013 Florian Müllner - 3.7.90-1 +- Update to 3.7.90 + +* Wed Feb 06 2013 Kalev Lember - 3.7.5-2 +- Rebuilt for libgcr soname bump + +* Wed Feb 06 2013 Florian Müllner - 3.7.5-1 +- Update to 3.7.5 + +* Fri Jan 25 2013 Peter Robinson 3.7.4.1-2 +- Rebuild for new cogl + +* Thu Jan 17 2013 Florian Müllner - 3.7.4.1-1 +- Update to 3.7.4.1 + +* Tue Jan 15 2013 Florian Müllner - 3.7.4-1 +- Update to 3.7.4 + +* Wed Jan 09 2013 Richard Hughes - 3.7.3.1-1 +- Update to 3.7.3.1 + +* Tue Dec 18 2012 Florian Müllner 3.7.3-1 +- Update to 3.7.3 + +* Mon Dec 17 2012 Adam Jackson 3.7.2-3 +- Also don't mangle rpath on power + +* Mon Dec 10 2012 Adam Jackson 3.7.2-2 +- Disable bluetooth on power + +* Mon Nov 19 2012 Florian Müllner - 3.7.2-1 +- Update to 3.7.2 + +* Tue Nov 13 2012 Dan Horák - 3.7.1-2 +- don't Require: gnome-bluetooth on s390(x) + +* Fri Nov 09 2012 Kalev Lember - 3.7.1-1 +- Update to 3.7.1 + +* Wed Oct 31 2012 Brian Pepple - 3.6.1-5 +- Rebuild against latest telepathy-logger + +* Thu Oct 25 2012 Milan Crha - 3.6.1-4 +- Rebuild against newer evolution-data-server + +* Sat Oct 20 2012 Dan Horák - 3.6.1-3 +- explicit BR: control-center as it isn't brought in indirectly on s390(x) + +* Thu Oct 18 2012 Florian Müllner - 3.6.1-2 +- Remove avoid-redhat-menus patch + + The standard way of supporting a desktop-specific menu layout is + to set XDG_MENU_PREFIX (which we made gnome-session do now). + +* Mon Oct 15 2012 Florian Müllner - 3.6.1-1 +- Update to 3.6.1 + +* Tue Sep 25 2012 Florian Müllner - 3.6.0-1 +- Update to 3.6.0 + +* Wed Sep 19 2012 Florian Müllner - 3.5.92-1 +- Update to 3.5.92 + +* Tue Sep 11 2012 Florian Müllner - 3.5.91-1 +- Update dependencies + +* Tue Sep 04 2012 Richard Hughes - 3.5.91-1 +- Update to 3.5.91 + +* Tue Aug 28 2012 Matthias Clasen - 3.5.90-3 +- Rebuild against new cogl/clutter + +* Mon Aug 27 2012 Debarshi Ray - 3.5.90-2 +- Rebuild for new libcamel and synchronize gnome-bluetooth Requires with + BuildRequires. + +* Wed Aug 22 2012 Richard Hughes - 3.5.90-1 +- Update to 3.5.90 + +* Tue Aug 14 2012 Debarshi Ray - 3.5.5-2 +- Add Requires: gnome-bluetooth >= 3.5.5 + +* Mon Aug 13 2012 Debarshi Ray - 3.5.5-1 +- Update to 3.5.5 + +* Fri Jul 27 2012 Fedora Release Engineering - 3.5.4-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Jul 21 2012 Kalev Lember - 3.5.4-4 +- Tighten runtime requires + +* Thu Jul 19 2012 Matthias Clasen - 3.5.4-3 +- Add a gdm-libs dependency + +* Wed Jul 18 2012 Colin Walters - 3.5.4-2 +- Bump release + +* Wed Jul 18 2012 Ray Strode 3.5.4-1 +- Update to 3.5.4 + +* Tue Jun 26 2012 Matthias Clasen - 3.5.3-2 +- Rebuild against new e-d-s + +* Tue Jun 26 2012 Matthias Clasen - 3.5.3-1 +- Update to 3.5.3 + +* Thu Jun 07 2012 Richard Hughes - 3.5.2-2 +- Remove upstreamed patch + +* Thu Jun 07 2012 Richard Hughes - 3.5.2-1 +- Update to 3.5.2 + +* Mon May 28 2012 Peter Robinson - 3.4.1-6 +- Cherry pick F17 changes, bump build for new evo soname + +* Wed May 16 2012 Owen Taylor - 3.4.1-5 +- New version of unmount notification + +* Tue May 15 2012 Owen Taylor - 3.4.1-4 +- Add a patch to display a notification until it's safe to remove a drive (#819492) + +* Fri Apr 20 2012 Owen Taylor - 3.4.1-3 +- Add a patch from upstream to avoid a crash when Evolution is not installed (#814401) + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-2 +- Silence glib-compile-schemas scriplets + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-1 +- Update to 3.4.1 + +* Thu Apr 5 2012 Owen Taylor - 3.4.0-2 +- Change gnome-shell-favourite-apps-firefox.patch to also patch the JS code + to handle the transition from mozilla-firefox.desktop to firefox.desktop. + (#808894, reported by Jonathan Kamens) + +* Tue Mar 27 2012 Richard Hughes - 3.4.0-1 +- Update to 3.4.0 + +* Wed Mar 21 2012 Matthias Clasen - 3.3.92-1 +- Update to 3.3.92 + +* Sat Mar 10 2012 Matthias Clasen - 3.3.90-2 +- Rebuild for new cogl + +* Sat Feb 25 2012 Matthias Clasen - 3.3.90-1 +- Update to 3.3.90 + +* Thu Feb 9 2012 Matthias Clasen - 3.3.5-2 +- Depend on accountsservice-libs (#755112) + +* Tue Feb 7 2012 Matthias Clasen - 3.3.5-1 +- Update to 3.3.5 + +* Fri Jan 20 2012 Matthias Clasen - 3.3.4-1 +- Update to 3.3.4 + +* Thu Jan 19 2012 Matthias Clasen - 3.3.3-2 +- Rebuild for new cogl + +* Thu Jan 5 2012 Matthias Clasen - 3.3.3-1 +- Update to 3.3.3 + +* Sun Nov 27 2011 Peter Robinson - 3.3.2-2 +- Rebuild for new clutter and e-d-s + +* Wed Nov 23 2011 Matthias Clasen - 3.3.2-1 +- Update to 3.3.2 + +* Wed Nov 09 2011 Kalev Lember - 3.2.1-6 +- Adapt to firefox desktop file name change in F17 + +* Thu Nov 03 2011 Adam Jackson 3.2.1-5 +- Build with -Wno-error=disabled-declarations for the moment + +* Wed Nov 02 2011 Brian Pepple - 3.2.1-4 +- Rebuld against tp-logger. + +* Sun Oct 30 2011 Bruno Wolff III - 3.2.1-3 +- Rebuild for new evolution-data-server + +* Wed Oct 26 2011 Fedora Release Engineering - 3.2.1-2 +- Rebuilt for glibc bug#747377 + +* Wed Oct 19 2011 Matthias Clasen - 3.2.1-1 +- Update to 3.2.1 + +* Wed Sep 28 2011 Ray Strode 3.2.0-2 +- rebuild + +* Mon Sep 26 2011 Owen Taylor - 3.2.0-1 +- Update to 3.2.0 + +* Tue Sep 20 2011 Matthias Clasen - 3.1.92-1 +- Update to 3.1.92 + +* Fri Sep 16 2011 Kalev Lember - 3.1.91.1-2 +- Tighten dependencies by specifying the required arch (#739130) + +* Wed Sep 14 2011 Owen Taylor - 3.1.91.1-1 +- Update to 3.1.91.1 (adds browser plugin) + Update Requires + +* Thu Sep 08 2011 Dan Horák - 3.1.91-3 +- workaround a chrpath issue on s390(x) + +* Wed Sep 07 2011 Kalev Lember - 3.1.91-2 +- Replace Epiphany with Firefox in the default favourite apps + +* Wed Sep 7 2011 Matthias Clasen - 3.1.91-1 +- Update to 3.1.91 + +* Thu Sep 1 2011 Matthias Clasen - 3.1.90.1-2 +- Require caribou + +* Wed Aug 31 2011 Matthias Clasen - 3.1.90.1-1 +- Update to 3.1.90.1 + +* Wed Aug 31 2011 Adam Williamson - 3.1.4-3.gite7b9933 +- rebuild against e-d-s + +* Fri Aug 19 2011 Matthias Clasen - 3.1.4-2.gite7b9933 +- git snapshot that builds against gnome-menus 3.1.5 + +* Thu Aug 18 2011 Matthew Barnes - 3.1.5-1 +- Rebuild against newer eds libraries. + +* Wed Jul 27 2011 Matthias Clasen - 3.1.4-1 +- Update to 3.1.4 + +* Wed Jul 27 2011 Matthias Clasen - 3.1.3-4 +- Rebuild + +* Tue Jul 26 2011 Matthias Clasen - 3.1.3-3 +- Add necessary requires + +* Mon Jul 25 2011 Matthias Clasen - 3.1.3-2 +- Rebuild + +* Tue Jul 5 2011 Peter Robinson - 3.1.3-1 +- Upstream 3.1.3 dev release + +* Mon Jun 27 2011 Adam Williamson - 3.0.2-4 +- add fixes from f15 branch (gjs dep and rpath) + +* Wed Jun 22 2011 Owen Taylor - 3.0.2-3 +- Add a patch from upstream to avoid g_file_get_contents() + +* Fri Jun 17 2011 Tomas Bzatek - 3.0.2-2 +- Rebuilt for new gtk3 and gnome-desktop3 + +* Wed May 25 2011 Owen Taylor - 3.0.2-1 +- Update to 3.0.2 + +* Tue May 10 2011 Dan Williams - 3.0.1-4 +- Fix initial connections to WPA Enterprise access points (#699014) +- Fix initial connections to mobile broadband networks + +* Thu Apr 28 2011 Dan Horák - 3.0.1-3 +- no bluetooth on s390(x) + +* Wed Apr 27 2011 Owen Taylor - 3.0.1-2 +- Add a patch from upstream to fix duplicate applications in application display + +* Mon Apr 25 2011 Owen Taylor - 3.0.1-1 +- Update to 3.0.1 + +* Mon Apr 11 2011 Colin Walters - 3.0.0.2-2 +- We want to use the GNOME menus which has the designed categories, + not the legacy redhat-menus. + +* Fri Apr 08 2011 Nils Philippsen - 3.0.0.2-1 +- Update to 3.0.0.2 (fixes missing import that was preventing extensions from + loading.) +- Update source URL + +* Tue Apr 5 2011 Owen Taylor - 3.0.0.1-1 +- Update to 3.0.0.1 (fixes bug where network menu could leave + Clutter event handling stuck.) + +* Mon Apr 4 2011 Owen Taylor - 3.0.0-1 +- Update to 3.0.0 + +* Tue Mar 29 2011 Brian Pepple - 2.91.93-3 +- Bump + +* Tue Mar 29 2011 Brian Pepple - 2.91.93-2 +- Rebuild for new tp-logger + +* Mon Mar 28 2011 Owen Taylor - 2.91.93-1 +- Update to 2.91.93. + +* Fri Mar 25 2011 Ray Strode 2.91.92-3 +- Adjustments for More nm-client api changes. +- Fix VPN indicator + +* Thu Mar 24 2011 Christopher Aillon - 2.91.92-2 +- Make activating vpn connections work from the shell indicator + +* Wed Mar 23 2011 Matthias Clasen - 2.91.92-1 +- Update to 2.91.92 + +* Wed Mar 16 2011 Michel Salim - 2.91.91-2 +- Fix alt-tab behavior on when primary display is not leftmost (# 683932) + +* Tue Mar 8 2011 Owen Taylor - 2.91.91-1 +- Update to 2.91.91 + +* Tue Feb 22 2011 Matthias Clasen - 2.91.90-2 +- Require upower and polkit at runtime + +* Tue Feb 22 2011 Matthias Clasen - 2.91.90-1 +- Update to 2.91.90 + +* Thu Feb 10 2011 Matthias Clasen - 2.91.6-6 +- Rebuild against newer gtk + +* Tue Feb 08 2011 Fedora Release Engineering - 2.91.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Feb 3 2011 Bill Nottingham - 2.91.6-4 +- buildrequire gnome-bluetooth to fix bluetooth status icon (#674874) + +* Wed Feb 2 2011 Matthias Clasen - 2.91.6-3 +- Rebuild against newer gtk + +* Tue Feb 1 2011 Owen Taylor - 2.91.6-2 +- Build-requires evolution-data-server-devel + +* Tue Feb 1 2011 Owen Taylor - 2.91.6-1 +- Update to 2.91.6 + +* Thu Jan 13 2011 Mattihas Clasen - 2.91.5-3 +- Drop desktop-effects dependency + +* Wed Jan 12 2011 Colin Walters - 2.91.5-2 +- BR latest g-i, handles flags as arguments better + +* Tue Jan 11 2011 Matthias Clasen - 2.91.5-1 +- Update to 2.91.5 + +* Sat Jan 8 2011 Matthias Clasen - 2.91.4-1 +- Update to 2.91.4 +- Rebuild against new gtk + +* Fri Dec 3 2010 Matthias Clasen - 2.91.3-2 +- Rebuild aginst new gtk + +* Mon Nov 29 2010 Owen Taylor - 2.91.2-1 +- Update to 2.91.3 + +* Thu Nov 18 2010 Owen Taylor - 2.91.2-3 +- Add another memory-management crasher fix from upstream + +* Mon Nov 15 2010 Owen Taylor - 2.91.2-2 +- Add a patch from upstream fixing a memory-management crasher + +* Tue Nov 9 2010 Owen Taylor - 2.91.2-1 +- Update to 2.91.2 + +* Mon Nov 1 2010 Owen Taylor - 2.91.1-1 +- Update to 2.91.1 +- Add libcroco-devel to BuildRequires, apparently it was getting + pulled in indirectly before +- Add libcanberra-devel and pulseaudio-libs-devel BuildRequires + +* Mon Oct 4 2010 Owen Taylor - 2.91.0-1 +- Update to 2.91.0 +- Remove patch to disable VBlank syncing + +* Thu Aug 12 2010 Colin Walters - 2.31.5-7 +- Add patch to disable vblank syncing + +* Tue Jul 13 2010 Colin Walters - 2.31.5-5 +- Run glib-compile-schemas + +* Tue Jul 13 2010 Colin Walters - 2.31.5-4 +- Bless stuff in files section + +* Tue Jul 13 2010 Colin Walters - 2.31.5-3 +- Axe gnome-desktop-devel + +* Tue Jul 13 2010 Adel Gadllah - 2.31.5-2 +- BuildRequire gnome-desktop3-devel, gtk3 + +* Mon Jul 12 2010 Colin Walters - 2.31.5-1 +- New upstream version +- Drop rpath goop, shouldn't be necessary any more + +* Fri Jun 25 2010 Colin Walters - 2.31.2-3 +- Drop gir-repository-devel build dependency + +* Fri May 28 2010 Adam Miller - 2.31.2-2 +- Added new version requirements for dependencies based on upstream releases +- Added new file listings for gnome-shell-clock-preferences binary and .desktop +- Added gnome-shell man page file listing + +* Wed May 26 2010 Adam Miller - 2.31.2-1 +- New upstream release + +* Fri Mar 26 2010 Colin Walters - 2.29.1-3 +- Specify V=1 for build, readd smp_mflags since parallel is fixed upstream + +* Thu Mar 25 2010 Adam Miller - 2.29.1-2 +- Bumped for new version of mutter and clutter +- Added version requirement to gjs-devel because of dependency of build + +* Wed Mar 24 2010 Adam Miller - 2.29.1-1 +- Update to latest version 2.29.1 + +* Sun Feb 21 2010 Bastien Nocera 2.28.1-0.2.20100128git +- Require json-glib +- Rebuild for new clutter with json split out +- Fix deprecation in COGL + +* Thu Jan 28 2010 Adam Miller - 2.28.1-0.1.20100128git +- New git snapshot +- Fixed Version for alphatag use + +* Fri Jan 15 2010 Adam Miller - 2.28.0.20101015git-1 +- Added dependency on a git build of gobject-introspect to solve some breakage +- Also went ahead and made a new git tarball + +* Tue Jan 12 2010 Adam Miller - 2.28.0.20100112git-1 +- New git snapshot + +* Mon Dec 07 2009 Adam Miller - 2.28.0.20091206git-5 +- Added libtool, glib-gettext for the libtoolize dep of git snapshot + +* Mon Dec 07 2009 Adam Miller - 2.28.0.20091206git-4 +- Added gnome-common needed by autogen.sh in git snapshot build + +* Sun Dec 06 2009 Adam Miller - 2.28.0.20091206git-3 +- Added the autotools needed to build the git snapshot to the build requires + +* Sun Dec 06 2009 Adam Miller - 2.28.0.20091206git-2 +- Fixed the setup naming issue with the git snapshot directory naming + +* Sun Dec 06 2009 Adam Miller - 2.28.0.20091206git-1 +- Update to git snapshot on 20091206 + +* Wed Oct 7 2009 Owen Taylor - 2.28.0-2 +- Update to 2.28.0 + +* Tue Sep 15 2009 Owen Taylor - 2.27.3-1 +- Update to 2.27.3 + +* Fri Sep 4 2009 Owen Taylor - 2.27.2-2 +- Test for gobject-introspection version should be >= not > + +* Fri Sep 4 2009 Owen Taylor - 2.27.2-1 +- Update to 2.27.2 +- Add an explicit dep on gobject-introspection 0.6.5 which is required + for the new version + +* Sat Aug 29 2009 Owen Taylor - 2.27.1-4 +- Fix GConf %%preun script to properly be for package removal + +* Fri Aug 28 2009 Owen Taylor - 2.27.1-3 +- Replace libgnomeui with gnome-desktop in BuildRequires + +* Fri Aug 28 2009 Owen Taylor - 2.27.1-2 +- BuildRequire intltool +- Add find_lang + +* Fri Aug 28 2009 Owen Taylor - 2.27.1-1 +- Update to 2.27.1 +- Update Requires, add desktop-effects + +* Wed Aug 12 2009 Owen Taylor - 2.27.0-4 +- Add an explicit dependency on GConf2 for pre/post + +* Tue Aug 11 2009 Owen Taylor - 2.27.0-3 +- Add missing BuildRequires on gir-repository-devel + +* Tue Aug 11 2009 Owen Taylor - 2.27.0-2 +- Temporarily use a non-parallel-build until gnome-shell is fixed + +* Mon Aug 10 2009 Owen Taylor - 2.27.0-1 +- Initial version + diff --git a/staging/gnome-shell/gitignore b/staging/gnome-shell/gitignore new file mode 100644 index 0000000..45e7102 --- /dev/null +++ b/staging/gnome-shell/gitignore @@ -0,0 +1,227 @@ +gnome-shell-2.31.5.tar.bz2 +/gnome-shell-2.91.0.tar.bz2 +/gnome-shell-2.91.1.tar.bz2 +/gnome-shell-2.91.2.tar.bz2 +/gnome-shell-2.91.3.tar.bz2 +/gnome-shell-2.91.4.tar.bz2 +/gnome-shell-2.91.5.tar.bz2 +/gnome-shell-2.91.6.tar.bz2 +/gnome-shell-2.91.90.tar.bz2 +/gnome-shell-2.91.91.tar.bz2 +/gnome-shell-2.91.92.tar.bz2 +/gnome-shell-2.91.93.tar.bz2 +/gnome-shell-3.0.0.tar.bz2 +/gnome-shell-3.0.0.1.tar.bz2 +/gnome-shell-3.0.0.2.tar.bz2 +/gnome-shell-3.0.1.tar.bz2 +/gnome-shell-3.0.2.tar.bz2 +/gnome-shell-3.1.3.tar.bz2 +/gnome-shell-3.1.4.tar.xz +/gnome-shell-3.1.4-gite7b9933.tar.bz2 +/gnome-shell-3.1.90.1.tar.xz +/gnome-shell-3.1.91.tar.xz +/gnome-shell-3.1.91.1.tar.xz +/gnome-shell-3.1.92.tar.xz +/gnome-shell-3.2.0.tar.xz +/gnome-shell-3.2.1.tar.xz +/gnome-shell-3.3.2.tar.xz +/gnome-shell-3.3.3.tar.xz +/gnome-shell-3.3.4.tar.xz +/gnome-shell-3.3.5.tar.xz +/gnome-shell-3.3.90.tar.xz +/gnome-shell-3.3.92.tar.xz +/gnome-shell-3.4.0.tar.xz +/gnome-shell-3.4.1.tar.xz +/gnome-shell-3.5.2.tar.xz +/gnome-shell-3.5.3.tar.xz +/gnome-shell-3.5.4.tar.xz +/gnome-shell-3.5.5.tar.xz +/gnome-shell-3.5.90.tar.xz +/gnome-shell-3.5.91.tar.xz +/gnome-shell-3.5.92.tar.xz +/gnome-shell-3.6.0.tar.xz +/gnome-shell-3.6.1.tar.xz +/gnome-shell-3.7.1.tar.xz +/gnome-shell-3.7.2.tar.xz +/gnome-shell-3.7.3.tar.xz +/gnome-shell-3.7.3.1.tar.xz +/gnome-shell-3.7.4.tar.xz +/gnome-shell-3.7.4.1.tar.xz +/gnome-shell-3.7.5.tar.xz +/gnome-shell-3.7.90.tar.xz +/gnome-shell-3.7.91.tar.xz +/gnome-shell-3.7.92.tar.xz +/gnome-shell-3.8.0.tar.xz +/gnome-shell-3.8.0.1.tar.xz +/gnome-shell-3.8.1.tar.xz +/gnome-shell-3.9.1.tar.xz +/gnome-shell-3.9.2.tar.xz +/gnome-shell-3.9.3.tar.xz +/gnome-shell-3.9.4.tar.xz +/gnome-shell-3.9.5.tar.xz +/gnome-shell-3.9.90.tar.xz +/gnome-shell-3.9.91.tar.xz +/gnome-shell-3.9.92.tar.xz +/gnome-shell-3.10.0.tar.xz +/gnome-shell-3.10.0.1.tar.xz +/gnome-shell-3.10.1.tar.xz +/gnome-shell-3.11.1.tar.xz +/gnome-shell-3.11.2.tar.xz +/gnome-shell-3.11.3.tar.xz +/gnome-shell-3.11.4.tar.xz +/gnome-shell-3.11.5.tar.xz +/gnome-shell-3.11.90.tar.xz +/gnome-shell-3.11.91.tar.xz +/gnome-shell-3.11.92.tar.xz +/gnome-shell-3.12.0.tar.xz +/gnome-shell-3.12.1.tar.xz +/gnome-shell-3.13.1.tar.xz +/gnome-shell-3.13.2.tar.xz +/gnome-shell-3.13.3.tar.xz +/gnome-shell-3.13.4.tar.xz +/gnome-shell-3.13.90.tar.xz +/gnome-shell-3.13.91.tar.xz +/gnome-shell-3.13.92.tar.xz +/gnome-shell-3.14.0.tar.xz +/gnome-shell-3.14.1.tar.xz +/gnome-shell-3.15.1.tar.xz +/gnome-shell-3.15.2.tar.xz +/gnome-shell-3.15.3.tar.xz +/gnome-shell-3.15.4.tar.xz +/gnome-shell-3.15.90.tar.xz +/gnome-shell-3.15.91.tar.xz +/gnome-shell-3.15.92.tar.xz +/gnome-shell-3.16.0.tar.xz +/gnome-shell-3.16.1.tar.xz +/gnome-shell-3.17.1.tar.xz +/gnome-shell-3.17.2.tar.xz +/gnome-shell-3.17.3.tar.xz +/gnome-shell-3.17.4.tar.xz +/gnome-shell-3.17.90.tar.xz +/gnome-shell-3.17.91.tar.xz +/gnome-shell-3.17.92.tar.xz +/gnome-shell-3.18.0.tar.xz +/gnome-shell-3.18.1.tar.xz +/gnome-shell-3.19.1.tar.xz +/gnome-shell-3.19.2.tar.xz +/gnome-shell-3.19.3.tar.xz +/gnome-shell-3.19.4.tar.xz +/gnome-shell-3.19.90.tar.xz +/gnome-shell-3.19.91.tar.xz +/gnome-shell-3.19.92.tar.xz +/gnome-shell-3.20.0.tar.xz +/gnome-shell-3.20.1.tar.xz +/gnome-shell-3.21.1.tar.xz +/gnome-shell-3.21.2.tar.xz +/gnome-shell-3.21.3.tar.xz +/gnome-shell-3.21.4.tar.xz +/gnome-shell-3.21.90.tar.xz +/gnome-shell-3.21.90.1.tar.xz +/gnome-shell-3.21.91.tar.xz +/gnome-shell-3.21.92.tar.xz +/gnome-shell-3.22.0.tar.xz +/gnome-shell-3.22.1.tar.xz +/gnome-shell-3.23.1.tar.xz +/gnome-shell-3.23.2.tar.xz +/gnome-shell-3.23.3.tar.xz +/gnome-shell-3.23.90.tar.xz +/gnome-shell-3.23.91.tar.xz +/gnome-shell-3.23.92.tar.xz +/gnome-shell-3.24.0.tar.xz +/gnome-shell-3.24.1.tar.xz +/gnome-shell-3.25.1.tar.xz +/gnome-shell-3.25.2.tar.xz +/gnome-shell-3.25.3.tar.xz +/gnome-shell-3.25.4.tar.xz +/gnome-shell-3.25.90.tar.xz +/gnome-shell-3.25.91.tar.xz +/gnome-shell-3.26.0.tar.xz +/gnome-shell-3.26.1.tar.xz +/gnome-shell-3.27.1.tar.xz +/gnome-shell-3.27.91.tar.xz +/gnome-shell-3.27.92.tar.xz +/gnome-shell-3.28.0.tar.xz +/gnome-shell-3.28.1.tar.xz +/gnome-shell-3.29.1.tar.xz +/gnome-shell-3.29.2.tar.xz +/gnome-shell-3.29.4.tar.xz +/gnome-shell-3.29.90.tar.xz +/gnome-shell-3.29.91.tar.xz +/gnome-shell-3.29.92.tar.xz +/gnome-shell-3.30.0.tar.xz +/gnome-shell-3.30.1.tar.xz +/gnome-shell-3.31.2.tar.xz +/gnome-shell-3.31.4.tar.xz +/gnome-shell-3.31.90.tar.xz +/gnome-shell-3.31.91.tar.xz +/gnome-shell-3.31.92.tar.xz +/gnome-shell-3.32.0.tar.xz +/gnome-shell-3.32.1.tar.xz +/gnome-shell-3.33.1.tar.xz +/gnome-shell-3.33.2.tar.xz +/gnome-shell-3.33.3.tar.xz +/gnome-shell-3.33.4.tar.xz +/gnome-shell-3.33.90.tar.xz +/gnome-shell-3.33.91.tar.xz +/gnome-shell-3.33.92.tar.xz +/gnome-shell-3.34.0.tar.xz +/gnome-shell-3.34.1.tar.xz +/gnome-shell-3.35.1.tar.xz +/gnome-shell-3.35.2.tar.xz +/gnome-shell-3.35.3.tar.xz +/gnome-shell-3.35.90.tar.xz +/gnome-shell-3.35.91.tar.xz +/gnome-shell-3.35.92.tar.xz +/gnome-shell-3.36.0.tar.xz +/gnome-shell-3.36.1.tar.xz +/gnome-shell-3.37.1.tar.xz +/gnome-shell-3.37.2.tar.xz +/gnome-shell-3.37.3.tar.xz +/gnome-shell-3.37.90.tar.xz +/gnome-shell-3.37.91.tar.xz +/gnome-shell-3.37.92.tar.xz +/gnome-shell-3.38.0.tar.xz +/gnome-shell-3.38.1.tar.xz +/gnome-shell-40.alpha.tar.xz +/gnome-shell-40.alpha.1.tar.xz +/gnome-shell-40.alpha.1.1.tar.xz +/gnome-shell-40.alpha.1.1-94-g9ce666ac1.tar.xz +/gnome-shell-40.alpha.1.1-228-g829a096ba.tar.xz +/gnome-shell-40.beta.tar.xz +/gnome-shell-40.beta-79-g7a57528bd.tar.xz +/gnome-shell-40.rc.tar.xz +/gnome-shell-40.0.tar.xz +/gnome-shell-40.1.tar.xz +/gnome-shell-40.2.tar.xz +/gnome-shell-40.3.tar.xz +/gnome-shell-41.beta.tar.xz +/gnome-shell-41.rc.tar.xz +/gnome-shell-41.rc.1.tar.xz +/gnome-shell-41.0.tar.xz +/gnome-shell-42.alpha.tar.xz +/gnome-shell-42.beta.tar.xz +/gnome-shell-42.rc.tar.xz +/gnome-shell-42.0.tar.xz +/gnome-shell-42.1.tar.xz +/gnome-shell-42.2.tar.xz +/gnome-shell-43.alpha.tar.xz +/gnome-shell-43.beta.tar.xz +/gnome-shell-43.rc.tar.xz +/gnome-shell-43.0.tar.xz +/gnome-shell-43.1.tar.xz +/gnome-shell-44.beta.tar.xz +/gnome-shell-44.rc.tar.xz +/gnome-shell-44.0.tar.xz +/gnome-shell-44.1.tar.xz +/gnome-shell-44.2.tar.xz +/gnome-shell-45.alpha.tar.xz +/gnome-shell-45.beta.tar.xz +/gnome-shell-45.beta.1.tar.xz +/gnome-shell-45.rc.tar.xz +/gnome-shell-45.0.tar.xz +/gnome-shell-45.1.tar.xz +/gnome-shell-45.2.tar.xz +/gnome-shell-46.alpha.tar.xz +/gnome-shell-46.beta.tar.xz +/gnome-shell-46.rc.tar.xz +/gnome-shell-46.0.tar.xz diff --git a/staging/gnome-shell/gnome-shell-favourite-apps-firefox.patch b/staging/gnome-shell/gnome-shell-favourite-apps-firefox.patch new file mode 100644 index 0000000..326f827 --- /dev/null +++ b/staging/gnome-shell/gnome-shell-favourite-apps-firefox.patch @@ -0,0 +1,38 @@ +From 551b8979483e127471c726fd1db1d52e063a7d81 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 17 Sep 2014 07:11:12 +0200 +Subject: [PATCH] Replace Web with Firefox in default favorites + +--- + data/org.gnome.shell.gschema.xml.in | 2 +- + js/ui/appFavorites.js | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in +index f4fa86d013..86b4bf85ee 100644 +--- a/data/org.gnome.shell.gschema.xml.in ++++ b/data/org.gnome.shell.gschema.xml.in +@@ -50,7 +50,7 @@ + + + +- [ 'org.gnome.Epiphany.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.TextEditor.desktop'] ++ [ 'org.mozilla.firefox.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.TextEditor.desktop'] + List of desktop file IDs for favorite applications + + The applications corresponding to these identifiers +diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js +index 576df3800d..1f55a3c881 100644 +--- a/js/ui/appFavorites.js ++++ b/js/ui/appFavorites.js +@@ -51,6 +51,7 @@ const RENAMED_DESKTOP_IDS = { + 'gnotski.desktop': 'org.gnome.Klotski.desktop', + 'gtali.desktop': 'org.gnome.Tali.desktop', + 'iagno.desktop': 'org.gnome.Reversi.desktop', ++ 'firefox.desktop': 'org.mozilla.firefox.desktop', + 'nautilus.desktop': 'org.gnome.Nautilus.desktop', + 'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop', + 'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop', +-- +2.43.0 + diff --git a/staging/gnome-shell/gnome-shell.spec b/staging/gnome-shell/gnome-shell.spec new file mode 100644 index 0000000..d1c4462 --- /dev/null +++ b/staging/gnome-shell/gnome-shell.spec @@ -0,0 +1,242 @@ +%global tarball_version %%(echo %{version} | tr '~' '.') +%global major_version 46 + +Name: gnome-shell +Version: %{major_version}.0 +Release: %autorelease.bazzite.{{{ git_dir_version }}} +Summary: Window management and application launching for GNOME + +License: GPL-2.0-or-later +URL: https://wiki.gnome.org/Projects/GnomeShell +Source0: https://download.gnome.org/sources/gnome-shell/%{major_version}/%{name}-%{tarball_version}.tar.xz + +# Replace Epiphany with Firefox in the default favourite apps list +Patch: gnome-shell-favourite-apps-firefox.patch + +# No portal helper if WebKitGTK is not installed +Patch: optional-portal-helper.patch + +# Some users might have a broken PAM config, so we really need this +# downstream patch to stop trying on configuration errors. +Patch: 0001-gdm-Work-around-failing-fingerprint-auth.patch + +# shell-app: improve discrete GPU detectio +# https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3193 +Patch: 3193.patch + +%define eds_version 3.45.1 +%define gnome_desktop_version 44.0-7 +%define glib2_version 2.56.0 +%define gobject_introspection_version 1.49.1 +%define gjs_version 1.73.1 +%define gtk4_version 4.0.0 +%define adwaita_version 1.0.0 +%define mutter_version 46.0 +%define polkit_version 0.100 +%define gsettings_desktop_schemas_version 46~beta +%define ibus_version 1.5.2 +%define gnome_bluetooth_version 1:42.3 +%define gstreamer_version 1.4.5 +%define pipewire_version 0.3.0 +%define gnome_settings_daemon_version 3.37.1 + +BuildRequires: bash-completion +BuildRequires: gcc +BuildRequires: meson +BuildRequires: git +BuildRequires: pkgconfig(ibus-1.0) >= %{ibus_version} +BuildRequires: desktop-file-utils +BuildRequires: pkgconfig(libedataserver-1.2) >= %{eds_version} +BuildRequires: pkgconfig(gcr-4) +BuildRequires: pkgconfig(gjs-1.0) >= %{gjs_version} +BuildRequires: pkgconfig(gio-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-autoar-0) +BuildRequires: pkgconfig(gnome-desktop-4) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gobject-introspection-1.0) >= %{gobject_introspection_version} +BuildRequires: mesa-libGL-devel +BuildRequires: mesa-libEGL-devel +BuildRequires: pkgconfig(libnm) +BuildRequires: pkgconfig(polkit-agent-1) >= %{polkit_version} +BuildRequires: pkgconfig(libstartup-notification-1.0) +BuildRequires: pkgconfig(libsystemd) +# for screencast recorder functionality +BuildRequires: pkgconfig(gstreamer-base-1.0) >= %{gstreamer_version} +BuildRequires: pkgconfig(libpipewire-0.3) >= %{pipewire_version} +BuildRequires: pkgconfig(gtk4) >= %{gtk4_version} +BuildRequires: gettext >= 0.19.6 +BuildRequires: python3 + +# for barriers +BuildRequires: libXfixes-devel >= 5.0 +# used in unused BigThemeImage +BuildRequires: librsvg2-devel +BuildRequires: mutter-devel >= %{mutter_version} +BuildRequires: pkgconfig(libpulse) +%ifnarch s390 s390x ppc ppc64 ppc64p7 +BuildRequires: gnome-bluetooth-libs-devel >= %{gnome_bluetooth_version} +%endif +# Bootstrap requirements +BuildRequires: gtk-doc +%ifnarch s390 s390x +Recommends: gnome-bluetooth%{?_isa} >= %{gnome_bluetooth_version} +%endif +Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} +%if 0%{?rhel} != 7 +# Disabled on RHEL 7 to allow logging into KDE session by default +Recommends: gnome-session-xsession +%endif +Requires: gcr%{?_isa} +Requires: gobject-introspection%{?_isa} >= %{gobject_introspection_version} +Requires: gjs%{?_isa} >= %{gjs_version} +Requires: gtk4%{?_isa} >= %{gtk4_version} +Requires: libadwaita%{_isa} >= %{adwaita_version} +Requires: libnma-gtk4%{?_isa} +# needed for loading SVG's via gdk-pixbuf +Requires: librsvg2%{?_isa} +Requires: mutter%{?_isa} >= %{mutter_version} +Requires: upower%{?_isa} +Requires: polkit%{?_isa} >= %{polkit_version} +Requires: gnome-desktop4%{?_isa} >= %{gnome_desktop_version} +Requires: glib2%{?_isa} >= %{glib2_version} +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gnome-settings-daemon%{?_isa} >= %{gnome_settings_daemon_version} +Requires: gstreamer1%{?_isa} >= %{gstreamer_version} +# needed for screen recorder +Requires: gstreamer1-plugins-good%{?_isa} +Requires: pipewire-gstreamer%{?_isa} +Requires: xdg-user-dirs-gtk +# needed for schemas +Requires: at-spi2-atk%{?_isa} +# needed for on-screen keyboard +Requires: ibus%{?_isa} >= %{ibus_version} +# needed for "show keyboard layout" +Requires: tecla +# needed for the user menu +Requires: accountsservice-libs%{?_isa} +Requires: gdm-libs%{?_isa} +# needed for settings items in menus +Requires: gnome-control-center +# needed by some utilities +Requires: python3%{_isa} +# needed for the dual-GPU launch menu +Requires: switcheroo-control +# needed for clocks/weather integration +Requires: geoclue2-libs%{?_isa} +Requires: libgweather4%{?_isa} +# for gnome-extensions CLI tool +Requires: gettext +# needed for thunderbolt support +Recommends: bolt%{?_isa} +# Needed for launching flatpak apps etc +# 1.8.0 is needed for source type support in the screencast portal. +Requires: xdg-desktop-portal-gtk >= 1.8.0 +Requires: xdg-desktop-portal-gnome +# needed by the welcome dialog +Recommends: gnome-tour + +%if !0%{?rhel} +# needed for captive portal helper +Recommends: webkitgtk6.0%{?_isa} +%endif + +# https://github.com/containers/composefs/pull/229#issuecomment-1838735764 +%if 0%{?rhel} >= 10 +ExcludeArch: %{ix86} +%endif + +Provides: desktop-notification-daemon = %{version}-%{release} +Provides: PolicyKit-authentication-agent = %{version}-%{release} +Provides: bundled(gvc) +Provides: bundled(libcroco) = 0.6.13 + +%if 0%{?rhel} +# In Fedora, fedora-obsolete-packages obsoletes caribou +Obsoletes: caribou < 0.4.21-10 +Obsoletes: caribou-antler < 0.4.21-10 +Obsoletes: caribou-devel < 0.4.21-10 +Obsoletes: caribou-gtk2-module < 0.4.21-10 +Obsoletes: caribou-gtk3-module < 0.4.21-10 +Obsoletes: python-caribou < 0.4.21-10 +Obsoletes: python2-caribou < 0.4.21-10 +Obsoletes: python3-caribou < 0.4.21-10 +%endif + +# https://bugzilla.redhat.com/show_bug.cgi?id=1740897 +Conflicts: gnome-shell-extension-background-logo < 3.34.0 + +%description +GNOME Shell provides core user interface functions for the GNOME 3 desktop, +like switching to windows and launching applications. GNOME Shell takes +advantage of the capabilities of modern graphics hardware and introduces +innovative user interface concepts to provide a visually attractive and +easy to use experience. + +%prep +%autosetup -S git -n %{name}-%{tarball_version} + +%build +%meson -Dextensions_app=false +%meson_build + +%install +%meson_install + +# Create empty directories where other packages can drop extensions +mkdir -p %{buildroot}%{_datadir}/gnome-shell/extensions +mkdir -p %{buildroot}%{_datadir}/gnome-shell/search-providers + +%find_lang %{name} + +%check +desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.desktop +desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Extensions.desktop +desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop + +%files -f %{name}.lang +%license COPYING +%doc NEWS README.md +%{_bindir}/gnome-shell +%{_bindir}/gnome-extensions +%{_bindir}/gnome-shell-extension-prefs +%{_bindir}/gnome-shell-extension-tool +%{_bindir}/gnome-shell-test-tool +%{_datadir}/glib-2.0/schemas/*.xml +%{_datadir}/glib-2.0/schemas/00_org.gnome.shell.gschema.override +%{_datadir}/applications/org.gnome.Shell.Extensions.desktop +%{_datadir}/applications/org.gnome.Shell.desktop +%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop +%{_datadir}/bash-completion/completions/gnome-extensions +%{_datadir}/gnome-control-center/keybindings/50-gnome-shell-launchers.xml +%{_datadir}/gnome-control-center/keybindings/50-gnome-shell-screenshots.xml +%{_datadir}/gnome-control-center/keybindings/50-gnome-shell-system.xml +%{_datadir}/gnome-shell/ +%{_datadir}/dbus-1/services/org.gnome.ScreenSaver.service +%{_datadir}/dbus-1/services/org.gnome.Shell.CalendarServer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Extensions.service +%{_datadir}/dbus-1/services/org.gnome.Shell.HotplugSniffer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Notifications.service +%{_datadir}/dbus-1/services/org.gnome.Shell.PortalHelper.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Screencast.service +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.Extensions.xml +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.Introspect.xml +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.PadOsd.xml +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screencast.xml +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml +%{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider.xml +%{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider2.xml +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.Extensions.svg +%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.Extensions-symbolic.svg +%{_userunitdir}/org.gnome.Shell-disable-extensions.service +%{_userunitdir}/org.gnome.Shell.target +%{_userunitdir}/org.gnome.Shell@wayland.service +%{_userunitdir}/org.gnome.Shell@x11.service +%{_libdir}/gnome-shell/ +%{_libexecdir}/gnome-shell-calendar-server +%{_libexecdir}/gnome-shell-perf-helper +%{_libexecdir}/gnome-shell-hotplug-sniffer +%{_libexecdir}/gnome-shell-portal-helper +%{_mandir}/man1/gnome-extensions.1* +%{_mandir}/man1/gnome-shell.1* + +%changelog +%autochangelog diff --git a/staging/gnome-shell/optional-portal-helper.patch b/staging/gnome-shell/optional-portal-helper.patch new file mode 100644 index 0000000..901b0d0 --- /dev/null +++ b/staging/gnome-shell/optional-portal-helper.patch @@ -0,0 +1,47 @@ +diff --git a/js/portalHelper/main.js b/js/portalHelper/main.js +index 7000089fa..d9a768a3f 100644 +--- a/js/portalHelper/main.js ++++ b/js/portalHelper/main.js +@@ -3,7 +3,13 @@ import Gio from 'gi://Gio'; + import GLib from 'gi://GLib'; + import GObject from 'gi://GObject'; + import Gtk from 'gi://Gtk?version=4.0'; +-import WebKit from 'gi://WebKit?version=6.0'; ++ ++let WebKit; ++try { ++ WebKit = (await import('gi://WebKit?version=6.0')).default; ++} catch { ++ WebKit = null; ++} + + import * as Gettext from 'gettext'; + import {programInvocationName, programArgs} from 'system'; +@@ -365,5 +371,9 @@ class WebPortalHelper extends Adw.Application { + Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); + Gettext.textdomain(Config.GETTEXT_PACKAGE); + +-const app = new WebPortalHelper(); +-await app.runAsync([programInvocationName, ...programArgs]); ++if (WebKit) { ++ const app = new WebPortalHelper(); ++ await app.runAsync([programInvocationName, ...programArgs]); ++} else { ++ log('WebKit typelib is not installed, captive portal helper will be disabled'); ++} +diff --git a/js/ui/status/network.js b/js/ui/status/network.js +index 322d7d91a..afca42e31 100644 +--- a/js/ui/status/network.js ++++ b/js/ui/status/network.js +@@ -2147,7 +2147,9 @@ class Indicator extends SystemIndicator { + await this._portalHelperProxy.init_async( + GLib.PRIORITY_DEFAULT, null); + } catch (e) { +- console.error(`Error launching the portal helper: ${e.message}`); ++ // Timeout is expected if WebKit is unavailable ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.TIMED_OUT)) ++ console.error(`Error launching the portal helper: ${e.message}`); + } + } + + diff --git a/staging/kf6-kio/0001-Give-the-kuriikwsfiltereng_private-a-VERSION-and-SOV.patch b/staging/kf6-kio/0001-Give-the-kuriikwsfiltereng_private-a-VERSION-and-SOV.patch new file mode 100644 index 0000000..6f1529a --- /dev/null +++ b/staging/kf6-kio/0001-Give-the-kuriikwsfiltereng_private-a-VERSION-and-SOV.patch @@ -0,0 +1,30 @@ +From 0cc287336b32e601e70b26d60d9335abde538a18 Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Mon, 16 Oct 2023 17:57:16 -0700 +Subject: [PATCH] Give the kuriikwsfiltereng_private a VERSION and SOVERSION + (#26) + +Signed-off-by: Adam Williamson +--- + src/urifilters/ikws/CMakeLists.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/urifilters/ikws/CMakeLists.txt b/src/urifilters/ikws/CMakeLists.txt +index 7d42584c3..393588993 100644 +--- a/src/urifilters/ikws/CMakeLists.txt ++++ b/src/urifilters/ikws/CMakeLists.txt +@@ -1,6 +1,11 @@ + add_subdirectory(searchproviders) + + add_library(kuriikwsfiltereng_private kuriikwsfiltereng.cpp searchprovider.cpp searchproviderregistry.cpp) ++set_target_properties(kuriikwsfiltereng_private PROPERTIES ++ VERSION ${KIO_VERSION} ++ SOVERSION ${KIO_SOVERSION} ++ EXPORT_NAME kuriikwsfiltereng_private ++) + generate_export_header(kuriikwsfiltereng_private) # We need this to be a shared lib, because otherwise we have duplicate Q_GLOBAL_STATICs + target_link_libraries(kuriikwsfiltereng_private PUBLIC KF6::KIOGui) + install(TARGETS kuriikwsfiltereng_private ${KF_INSTALL_TARGETS_DEFAULT_ARGS}) +-- +2.41.0 + diff --git a/staging/kf6-kio/1556.patch b/staging/kf6-kio/1556.patch new file mode 100644 index 0000000..4aa62d9 --- /dev/null +++ b/staging/kf6-kio/1556.patch @@ -0,0 +1,57 @@ +From 73e8c790f08dba536a5cf4e56c9dd4f3a68d16cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20Dr=C3=B6gehoff?= +Date: Thu, 15 Feb 2024 14:38:21 +0100 +Subject: [PATCH] Improve discrete GPU detection using switcheroo-control + +--- + src/gui/gpudetection.cpp | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/src/gui/gpudetection.cpp b/src/gui/gpudetection.cpp +index 5c4e1c60ac..492e3654da 100644 +--- a/src/gui/gpudetection.cpp ++++ b/src/gui/gpudetection.cpp +@@ -62,6 +62,40 @@ static bool checkGpuWithSwitcheroo() + QList gpus; + arg >> gpus; + ++ if (gpus.length() < 2) { ++ // Skip checking for Default or Discrete GPUs when 1 or no GPU is available ++ return false; ++ } ++ ++ // Check if the Default GPU is Discrete ++ for (const auto &gpu : gpus) { ++ bool defaultGpu = qvariant_cast(gpu[QStringLiteral("Default")]); ++ if (defaultGpu) { ++ bool discreteGpu = qvariant_cast(gpu.value(QStringLiteral("Discrete"), false)); ++ if (discreteGpu) { ++ // If the default GPU is Discret there is no need to apply the env vars ++ s_gpuCheck = GpuCheck::Present; ++ return true; ++ } ++ break; ++ } ++ } ++ ++ // Find the first Discrete GPU ++ for (const auto &gpu : gpus) { ++ bool discreteGpu = qvariant_cast(gpu.value(QStringLiteral("Discrete"), false)); ++ if (!discreteGpu) { ++ s_gpuCheck = GpuCheck::Present; ++ QStringList envList = qvariant_cast(gpu[QStringLiteral("Environment")]); ++ for (int i = 0; i + 1 < envList.size(); i += 2) { ++ s_gpuEnv.insert(envList[i], envList[i + 1]); ++ } ++ return true; ++ } ++ } ++ ++ // fallback to old behavior ++ // find the first non-Default GPU + for (const auto &gpu : gpus) { + bool defaultGpu = qvariant_cast(gpu[QStringLiteral("Default")]); + if (!defaultGpu) { +-- +GitLab + diff --git a/staging/kf6-kio/6e7775d315f389df0a440ed62b842ce83dc9a27e.patch b/staging/kf6-kio/6e7775d315f389df0a440ed62b842ce83dc9a27e.patch new file mode 100644 index 0000000..2c9b594 --- /dev/null +++ b/staging/kf6-kio/6e7775d315f389df0a440ed62b842ce83dc9a27e.patch @@ -0,0 +1,34 @@ +From 6e7775d315f389df0a440ed62b842ce83dc9a27e Mon Sep 17 00:00:00 2001 +From: Nicolas Fella +Date: Fri, 1 Mar 2024 22:16:07 +0100 +Subject: [PATCH] [kterminallauncherjob] Inherit default process environment + from parent + +Before Qt 6.3, an empty (default constructed) QProcessEnvironment caused +QProcess to incorrectly inherit the environment variables from the parent +process. This was fixed in qtbase 5fc9c02a695. + +CommandLauncherJob was adjusted for this in 916984940f64e07db9b4d152be9f2a87dda0cfb4, +however here we are overriding its default env with our own default-constructed one + +BUG: 482107 +--- + src/gui/kterminallauncherjob.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/gui/kterminallauncherjob.cpp b/src/gui/kterminallauncherjob.cpp +index c4e83fb11b..edd99327bd 100644 +--- a/src/gui/kterminallauncherjob.cpp ++++ b/src/gui/kterminallauncherjob.cpp +@@ -22,7 +22,7 @@ public: + QString m_fullCommand; // "xterm -e ls" + QString m_desktopName; + QByteArray m_startupId; +- QProcessEnvironment m_environment; ++ QProcessEnvironment m_environment{QProcessEnvironment::InheritFromParent}; + }; + + KTerminalLauncherJob::KTerminalLauncherJob(const QString &command, QObject *parent) +-- +GitLab + diff --git a/staging/kf6-kio/kf6-kio.spec b/staging/kf6-kio/kf6-kio.spec new file mode 100644 index 0000000..ce55819 --- /dev/null +++ b/staging/kf6-kio/kf6-kio.spec @@ -0,0 +1,297 @@ +%global framework kio + +%global stable_kf6 stable +%global majmin_ver_kf6 6.1 + +Name: kf6-%{framework} +Version: %{majmin_ver_kf6}.0 +Release: 2%{?dist}.bazzite.{{{ git_dir_version }}} +Summary: KDE Frameworks 6 Tier 3 solution for filesystem abstraction + +License: BSD-2-Clause AND BSD-3-Clause AND CC0-1.0 AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-only AND LGPL-2.0-only AND LGPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND LGPL-3.0-only AND (GPL-2.0-only OR GPL-3.0-only) AND (LGPL-2.1-only OR LGPL-3.0-only) AND MIT +URL: https://invent.kde.org/frameworks/%{framework} + +Source0: https://download.kde.org/%{stable_kf6}/frameworks/%{majmin_ver_kf6}/%{framework}-%{version}.tar.xz + +# https://invent.kde.org/frameworks/kio/-/issues/26 +# I'm not sending this upstream because I'm not sure it's really +# exactly what upstream will want, but it solves the practical +# issue for us for now +Patch0: 0001-Give-the-kuriikwsfiltereng_private-a-VERSION-and-SOV.patch + +%if 0%{?flatpak} +# Disable the help: and ghelp: protocol for Flatpak builds, to avoid depending +# on the docbook stack. +Patch101: kio-no-help-protocol.patch +%endif + +# https://invent.kde.org/frameworks/kio/-/merge_requests/1556 +Patch201: 1556.patch + +BuildRequires: extra-cmake-modules >= %{version} +BuildRequires: gcc-c++ +BuildRequires: kf6-rpm-macros +BuildRequires: cmake +BuildRequires: cmake(KF6Archive) +BuildRequires: cmake(KF6Crash) +BuildRequires: cmake(KF6Solid) +BuildRequires: switcheroo-control +BuildRequires: cmake(KF6ColorScheme) +BuildRequires: cmake(KF6Config) +BuildRequires: cmake(KF6CoreAddons) +BuildRequires: cmake(KF6DBusAddons) +BuildRequires: cmake(KF6DocTools) +BuildRequires: cmake(KF6GuiAddons) +BuildRequires: cmake(KF6I18n) +BuildRequires: cmake(KF6Service) +BuildRequires: qt6-qtbase-private-devel +BuildRequires: cmake(KF6Bookmarks) +BuildRequires: cmake(KF6Completion) +BuildRequires: cmake(KF6ConfigWidgets) +BuildRequires: cmake(KF6IconThemes) +BuildRequires: cmake(KF6ItemViews) +BuildRequires: cmake(KF6JobWidgets) +BuildRequires: cmake(KF6WindowSystem) +BuildRequires: cmake(KF6Notifications) +BuildRequires: cmake(KF6Wallet) +BuildRequires: cmake(KF6WidgetsAddons) +BuildRequires: cmake(KF6XmlGui) + +BuildRequires: libacl-devel +%if !0%{?flatpak} +BuildRequires: libxml2-devel +BuildRequires: libxslt-devel +%endif +BuildRequires: pkgconfig(blkid) +BuildRequires: pkgconfig(mount) +BuildRequires: pkgconfig(xkbcommon) +BuildRequires: zlib-devel + +BuildRequires: qt6-qtbase-devel +BuildRequires: cmake(Qt6UiPlugin) +BuildRequires: cmake(Qt6Qml) + +BuildRequires: cmake(KF6KDED) +BuildRequires: cmake(Qt6Core5Compat) + +Requires: %{name}-core%{?_isa} = %{version}-%{release} +Requires: %{name}-widgets%{?_isa} = %{version}-%{release} +Requires: %{name}-file-widgets%{?_isa} = %{version}-%{release} +Requires: %{name}-gui%{?_isa} = %{version}-%{release} + +Requires: kf6-kded + +%description +KDE Frameworks 6 Tier 3 solution for filesystem abstraction + +%package devel +Summary: Development files for %{name} +Requires: %{name} = %{version}-%{release} +Requires: kf6-kbookmarks-devel +Requires: cmake(KF6Completion) +Requires: cmake(KF6Config) +Requires: cmake(KF6CoreAddons) +Requires: cmake(KF6ItemViews) +Requires: cmake(KF6JobWidgets) +Requires: cmake(KF6Service) +Requires: cmake(KF6Solid) +Requires: cmake(KF6XmlGui) +Requires: cmake(KF6WindowSystem) +Requires: qt6-qtbase-devel +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + +%package doc +Summary: Documentation files for %{name} +Requires: %{name}-core = %{version}-%{release} +BuildArch: noarch +%description doc +Documentation for %{name}. + +%package core +Summary: Core components of the KIO Framework +%{?kf6_kinit_requires} +Requires: %{name}-core-libs%{?_isa} = %{version}-%{release} +Requires: %{name}-doc = %{version}-%{release} +Requires: kf6-filesystem +Recommends: switcheroo-control +%description core +KIOCore library provides core non-GUI components for working with KIO. + +%package core-libs +Summary: Runtime libraries for KIO Core +Requires: %{name}-core%{?_isa} = %{version}-%{release} +%description core-libs +%{summary}. + +%package widgets +Summary: Widgets for KIO Framework +## org.kde.klauncher6 service referenced from : widgets/krun.cpp +## included here for completeness, even those -core already has a dependency. +%{?kf6_kinit_requires} +Requires: %{name}-core%{?_isa} = %{version}-%{release} +%description widgets +KIOWidgets contains classes that provide generic job control, progress +reporting, etc. + +%package widgets-libs +Summary: Runtime libraries for KIO Widgets library +Requires: %{name}-widgets%{?_isa} = %{version}-%{release} +%description widgets-libs +%{summary}. + +%package file-widgets +Summary: Widgets for file-handling for KIO Framework +Requires: %{name}-widgets%{?_isa} = %{version}-%{release} +%description file-widgets +The KIOFileWidgets library provides the file selection dialog and +its components. + +%package gui +Summary: Gui components for the KIO Framework +Requires: %{name}-core%{?_isa} = %{version}-%{release} +%description gui +%{summary}. + +%package qch-doc +Summary: Developer Documentation files for %{name} +BuildArch: noarch +%description qch-doc +Developer Documentation files for %{name} for use with KDevelop or QtCreator. + + +%prep +%autosetup -n %{framework}-%{version} -p1 + + +%build +%cmake_kf6 +%cmake_build + + +%install +%cmake_install +%find_lang %{name} --all-name --with-man --with-html + +%files +%license LICENSES/*.txt +%doc README.md + +%files core +%{_kf6_libexecdir}/kioexec +%{_kf6_libexecdir}/kiod6 +%{_kf6_libexecdir}/kioworker +%{_kf6_bindir}/ktelnetservice6 +%{_kf6_bindir}/ktrash6 +%{_kf6_plugindir}/kio/ +%{_kf6_plugindir}/kded/ +%{_kf6_plugindir}/kiod/ +%{_kf6_datadir}/kf6/searchproviders/*.desktop +%{_kf6_datadir}/applications/*.desktop +%{_datadir}/dbus-1/services/org.kde.*.service +%{_kf6_datadir}/qlogging-categories6/*categories + +%files core-libs +%{_kf6_libdir}/libKF6KIOCore.so.* + +%files doc -f %{name}.lang + +%files gui +%{_kf6_libdir}/libKF6KIOGui.so.* + +%files widgets +%dir %{_kf6_plugindir}/urifilters/ +%{_kf6_plugindir}/urifilters/*.so +%{_kf6_libdir}/libkuriikwsfiltereng_private.so.* + +%files widgets-libs +%{_kf6_libdir}/libKF6KIOWidgets.so.* + +%files file-widgets +%{_kf6_libdir}/libKF6KIOFileWidgets.so.* + +%files devel +%{_kf6_includedir}/* +%{_kf6_libdir}/*.so +%{_kf6_libdir}/cmake/KF6KIO/ +%{_kf6_datadir}/kdevappwizard/templates/kioworker6.tar.bz2 +%{_kf6_qtplugindir}/designer/kio6widgets.so +%{_qt6_docdir}/*.tags + +%files qch-doc +%{_qt6_docdir}/*.qch + +%changelog +* Thu Apr 18 2024 Jan Grulich - 6.1.0-2 +- Rebuild (qt6) + +* Wed Apr 10 2024 Marc Deop i Argemí - 6.1.0-1 +- 6.1.0 + +* Thu Apr 04 2024 Jan Grulich - 6.0.0-7 +- Re-enable docs + +* Thu Apr 04 2024 Jan Grulich - 6.0.0-6 +- Rebuild (qt6) + +* Fri Mar 15 2024 Marie Loise Nolden - 6.0.0-5 +- add 6e7775d315f389df0a440ed62b842ce83dc9a27e.patch +[kterminallauncherjob] Inherit default process environment from parent + +* Mon Mar 11 2024 Yaakov Selkowitz - 6.0.0-4 +- Soften switcheroo-control dependency + +* Sat Mar 09 2024 Marie Loise Nolden - 6.0.0-3 +- add missing BuildArch: noarch to -doc package + +* Sat Mar 2 2024 Marie Loise Nolden - 6.0.0-2 +- move qt designer plugin to -devel + +* Wed Feb 21 2024 Marc Deop i Argemí - 6.0.0-1 +- 6.0.0 + +* Fri Feb 16 2024 Jan Grulich - 5.249.0-2 +- Rebuild (qt6) + +* Wed Jan 31 2024 Marc Deop i Argemí - 5.249.0-1 +- 5.249.0 + +* Thu Jan 25 2024 Fedora Release Engineering - 5.248.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sun Jan 21 2024 Fedora Release Engineering - 5.248.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Wed Jan 10 2024 Marc Deop i Argemí - 5.248.0-1 +- 5.248.0 + +* Tue Jan 09 2024 Marie Loise Nolden - 5.247.0-2 +- add doc package for KF6 API + +* Wed Dec 20 2023 Marc Deop i Argemí - 5.247.0-1 +- 5.247.0 + +* Sat Dec 02 2023 Justin Zobel - 5.246.0-1 +- Update to 5.246.0 + +* Wed Nov 29 2023 Jan Grulich - 5.245.0-3 +- Rebuild (qt6) + +* Mon Nov 20 2023 Alessandro Astone - 5.245.0-2 +- Add back kuriikwsfiltereng SOVERSION patch + +* Thu Nov 09 2023 Steve Cossette - 5.245.0-1 +- 5.245.0 + +* Tue Oct 17 2023 Jan Grulich - 5.240.0^20231010.060359.1c34fd4-4 +- Rebuild (qt6) + +* Mon Oct 16 2023 Adam Williamson - 5.240.0^20231010.060359.1c34fd4-3 +- Give kuriikwsfiltereng_private library a proper soname to fix deps + +* Mon Oct 09 2023 Steve Cossette - 5.240.0^20231010.060359.1c34fd4-2 +- Fixed a problem with the -doc subpackage building differently on different arches. + +* Mon Oct 09 2023 Steve Cossette - 5.240.0^20231010.060359.1c34fd4-1 +- Initial Release From a5316474cb4041d452317099524a642a304e636a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sat, 27 Apr 2024 23:51:03 -0700 Subject: [PATCH 31/41] chore: Fix patch name --- .../gnome-settings-daemon/{xwayland-scaling.patch => 353.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename staging/gnome-settings-daemon/{xwayland-scaling.patch => 353.patch} (100%) diff --git a/staging/gnome-settings-daemon/xwayland-scaling.patch b/staging/gnome-settings-daemon/353.patch similarity index 100% rename from staging/gnome-settings-daemon/xwayland-scaling.patch rename to staging/gnome-settings-daemon/353.patch From 1bfacaba35d6e60129bba8b8d55f7436f719f843 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 00:07:03 -0700 Subject: [PATCH 32/41] chore: Remove version check from mutter-devel --- staging/gnome-shell/gnome-shell.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/gnome-shell/gnome-shell.spec b/staging/gnome-shell/gnome-shell.spec index d1c4462..8bb7f1a 100644 --- a/staging/gnome-shell/gnome-shell.spec +++ b/staging/gnome-shell/gnome-shell.spec @@ -70,7 +70,7 @@ BuildRequires: python3 BuildRequires: libXfixes-devel >= 5.0 # used in unused BigThemeImage BuildRequires: librsvg2-devel -BuildRequires: mutter-devel >= %{mutter_version} +BuildRequires: mutter-devel BuildRequires: pkgconfig(libpulse) %ifnarch s390 s390x ppc ppc64 ppc64p7 BuildRequires: gnome-bluetooth-libs-devel >= %{gnome_bluetooth_version} From 7abcc8980da47bd2f94393d8e3fb5fec0d90b49a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 00:10:53 -0700 Subject: [PATCH 33/41] Revert "chore: Remove version check from mutter-devel" This reverts commit 1bfacaba35d6e60129bba8b8d55f7436f719f843. --- staging/gnome-shell/gnome-shell.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/gnome-shell/gnome-shell.spec b/staging/gnome-shell/gnome-shell.spec index 8bb7f1a..d1c4462 100644 --- a/staging/gnome-shell/gnome-shell.spec +++ b/staging/gnome-shell/gnome-shell.spec @@ -70,7 +70,7 @@ BuildRequires: python3 BuildRequires: libXfixes-devel >= 5.0 # used in unused BigThemeImage BuildRequires: librsvg2-devel -BuildRequires: mutter-devel +BuildRequires: mutter-devel >= %{mutter_version} BuildRequires: pkgconfig(libpulse) %ifnarch s390 s390x ppc ppc64 ppc64p7 BuildRequires: gnome-bluetooth-libs-devel >= %{gnome_bluetooth_version} From e3f2623cd4372dc093f4af805cd9f6194978f6ac Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 00:24:52 -0700 Subject: [PATCH 34/41] chore: Adjust versions --- staging/gnome-settings-daemon/gnome-settings-daemon.spec | 4 ++-- staging/gnome-shell/gnome-shell.spec | 2 +- staging/kf6-kio/kf6-kio.spec | 2 +- staging/mutter/mutter.spec | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/staging/gnome-settings-daemon/gnome-settings-daemon.spec b/staging/gnome-settings-daemon/gnome-settings-daemon.spec index 1f01514..6d35ed8 100644 --- a/staging/gnome-settings-daemon/gnome-settings-daemon.spec +++ b/staging/gnome-settings-daemon/gnome-settings-daemon.spec @@ -20,8 +20,8 @@ %global major_version %%(echo %{gnome_version} | cut -f 1 -d '~' | cut -f 1 -d '.') Name: gnome-settings-daemon -Version: %{gnome_version}.xscaling.9 -Release: %autorelease +Version: %{gnome_version} +Release: %autorelease.xscaling.{{{ git_dir_version }}} Summary: The daemon sharing settings from GNOME to GTK+/KDE applications License: GPL-2.0-or-later AND LGPL-2.1-or-later diff --git a/staging/gnome-shell/gnome-shell.spec b/staging/gnome-shell/gnome-shell.spec index d1c4462..c66f250 100644 --- a/staging/gnome-shell/gnome-shell.spec +++ b/staging/gnome-shell/gnome-shell.spec @@ -3,7 +3,7 @@ Name: gnome-shell Version: %{major_version}.0 -Release: %autorelease.bazzite.{{{ git_dir_version }}} +Release: %autorelease.switcheroo.{{{ git_dir_version }}} Summary: Window management and application launching for GNOME License: GPL-2.0-or-later diff --git a/staging/kf6-kio/kf6-kio.spec b/staging/kf6-kio/kf6-kio.spec index ce55819..ecf59ac 100644 --- a/staging/kf6-kio/kf6-kio.spec +++ b/staging/kf6-kio/kf6-kio.spec @@ -5,7 +5,7 @@ Name: kf6-%{framework} Version: %{majmin_ver_kf6}.0 -Release: 2%{?dist}.bazzite.{{{ git_dir_version }}} +Release: 2%{?dist}.switcheroo.{{{ git_dir_version }}} Summary: KDE Frameworks 6 Tier 3 solution for filesystem abstraction License: BSD-2-Clause AND BSD-3-Clause AND CC0-1.0 AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-only AND LGPL-2.0-only AND LGPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND LGPL-3.0-only AND (GPL-2.0-only OR GPL-3.0-only) AND (LGPL-2.1-only OR LGPL-3.0-only) AND MIT diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 6f2b115..92f1f75 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,8 +16,8 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version}.xscaling.9 -Release: %autorelease +Version: %{gnome_version} +Release: %autorelease.xscaling.{{{ git_dir_version }}} Summary: Window and compositing manager based on Clutter License: GPLv2+ From b9532cab9344bfca0b6ee893e2f01903c21a80c0 Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 28 Apr 2024 07:42:42 -0600 Subject: [PATCH 35/41] feat(wolfi): Swap fake su-exec sudo for actual sudo Signed-off-by: RJ Trujillo --- wolfi/ublue-base.yaml | 5 ++--- wolfi/ublue-base/sudo | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100755 wolfi/ublue-base/sudo diff --git a/wolfi/ublue-base.yaml b/wolfi/ublue-base.yaml index 54b0fd5..9e2e71e 100644 --- a/wolfi/ublue-base.yaml +++ b/wolfi/ublue-base.yaml @@ -44,7 +44,7 @@ package: - procps - rsync - shadow - - su-exec + - sudo - tcpdump - tree - tzdata @@ -74,8 +74,7 @@ pipeline: mkdir -p "${{targets.contextdir}}"/usr/bin mkdir -p "${{targets.contextdir}}"/usr/local/bin - # Setup fake sudo and pinentry - install -Dm755 sudo "${{targets.contextdir}}"/usr/bin/sudo + # Setup fake pinentry install -Dm755 pinentry "${{targets.contextdir}}"/usr/bin/pinentry # Get Distrobox-host-exec and host-spawn diff --git a/wolfi/ublue-base/sudo b/wolfi/ublue-base/sudo deleted file mode 100755 index f458bb7..0000000 --- a/wolfi/ublue-base/sudo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -/sbin/su-exec root "$@" From 31af528a1412bbd8ab51f20cbcc5b9ca26ccc665 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 08:46:39 -0700 Subject: [PATCH 36/41] Increase autorelease to force mutter to be considered newer --- staging/mutter/mutter.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 92f1f75..794315a 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -17,7 +17,7 @@ Name: mutter Version: %{gnome_version} -Release: %autorelease.xscaling.{{{ git_dir_version }}} +Release: 100.%autorelease.xscaling.{{{ git_dir_version }}} Summary: Window and compositing manager based on Clutter License: GPLv2+ From efe31d72f29fd26349b3070c765bb81563288e58 Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 28 Apr 2024 12:36:17 -0600 Subject: [PATCH 37/41] fix(bluefin-cli): Swap su-exec for sudo in firstrun scripts Signed-off-by: RJ Trujillo --- .../profile.d/00-bluefin-cli-brew-firstrun.sh | 18 +++++++++--------- .../00-bluefin-cli-brew-firstrun.fish | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh index 29f450f..5d1678b 100644 --- a/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh +++ b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh @@ -6,7 +6,7 @@ if test "$(id -u)" -gt "0"; then if test ! -f /etc/linuxbrew.firstrun; then printf "\nBluefin-CLI First Run Setup\n\n" printf "Setting up sudo for %s%s%s%s...\t\t\t " "$bold" "$blue" "$USER" "$normal" - echo "#$(id -u) ALL = (root) NOPASSWD:ALL" | su-exec root tee -a /etc/sudoers > /dev/null + echo "#$(id -u) ALL = (root) NOPASSWD:ALL" | sudo tee -a /etc/sudoers > /dev/null printf "%s[ OK ]%s\n" "${blue}" "${normal}" fi @@ -21,27 +21,27 @@ if test "$(id -u)" -gt "0"; then fi fi if test ! -d /home/linuxbrew; then - su-exec root mkdir -p /home/linuxbrew + sudo mkdir -p /home/linuxbrew fi - su-exec root mount --bind "${linuxbrew_home}" /home/linuxbrew - su-exec root cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ - su-exec root chown -R "$(id -u)" /home/linuxbrew + sudo mount --bind "${linuxbrew_home}" /home/linuxbrew + sudo cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ + sudo chown -R "$(id -u)" /home/linuxbrew unset linuxbrew_home printf "%s[ OK ]%s\n" "${blue}" "${normal}" fi if test ! -d /usr/local/share/bash-completion/completions; then printf "Setting up Tab-Completions...\t\t\t " - su-exec root mkdir -p /usr/local/share/bash-completion - su-exec root mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion + sudo mkdir -p /usr/local/share/bash-completion + sudo mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion if test -x /run/host/usr/bin/ujust; then - su-exec root ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust + sudo ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust fi printf "%s[ OK ]%s\n" "${blue}" "${normal}" fi if test ! -f /etc/linuxbrew.firstrun; then - su-exec root touch /etc/linuxbrew.firstrun + sudo touch /etc/linuxbrew.firstrun printf "\nBluefin-CLI first run complete!\n\n" fi fi diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish index 3dc3bb0..64b71ed 100644 --- a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish +++ b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish @@ -5,7 +5,7 @@ if test "$(id -u)" -gt "0" if test ! -f /etc/linuxbrew.firstrun printf "\nBluefin-CLI First Run Setup\n\n" printf "Setting up sudo for %s%s%s...\t\t\t " "$bold" "$USER" "$normal" - echo "#$UID ALL = (root) NOPASSWD:ALL" | su-exec root tee -a /etc/sudoers > /dev/null + echo "#$UID ALL = (root) NOPASSWD:ALL" | sudo tee -a /etc/sudoers > /dev/null printf "%s[ OK ]%s\n" "$blue" "$normal" end @@ -19,27 +19,27 @@ if test "$(id -u)" -gt "0" mkdir -p "$linuxbrew_home" end if test ! -d /home/linuxbrew - su-exec root mkdir -p /home/linuxbrew + sudo mkdir -p /home/linuxbrew end - su-exec root mount --bind "$linuxbrew_home" /home/linuxbrew - su-exec root cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ - su-exec root chown -R "$UID" /home/linuxbrew + sudo mount --bind "$linuxbrew_home" /home/linuxbrew + sudo cp -R /home/homebrew/.linuxbrew /home/linuxbrew/ + sudo chown -R "$UID" /home/linuxbrew set -e linuxbrew_home printf "%s[ OK ]%s\n" "$blue" "$normal" end if test ! -d /usr/local/share/bash-completion/completions printf "Setting up Tab-Completions...\t\t\t " - su-exec root mkdir -p /usr/local/share/bash-completion - su-exec root mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion + sudo mkdir -p /usr/local/share/bash-completion + sudo mount --bind /run/host/usr/share/bash-completion /usr/local/share/bash-completion if test -x /run/host/usr/bin/ujust - su-exec root ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust + sudo ln -fs /usr/bin/distrobox-host-exec /usr/local/bin/ujust end printf "%s[ OK ]%s\n" "$blue" "$normal" end if test ! -f /etc/linuxbrew.firstrun - su-exec root touch /etc/linuxbrew.firstrun + sudo touch /etc/linuxbrew.firstrun printf "\nBluefin-CLI first run complete!\n\n" end end From 0a830aebd4db025759a7fccc35a605aa2a33ad1c Mon Sep 17 00:00:00 2001 From: RJ Trujillo Date: Sun, 28 Apr 2024 12:45:42 -0600 Subject: [PATCH 38/41] fix(bluefin-cli): Remove local repository added at image buildtime Signed-off-by: RJ Trujillo --- .../bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh | 2 ++ .../share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish | 2 ++ 2 files changed, 4 insertions(+) diff --git a/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh index 5d1678b..2f4825d 100644 --- a/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh +++ b/wolfi/bluefin-base/etc/profile.d/00-bluefin-cli-brew-firstrun.sh @@ -41,6 +41,8 @@ if test "$(id -u)" -gt "0"; then fi if test ! -f /etc/linuxbrew.firstrun; then + # Remove local repository added at buildtime + sudo sed -zi "s|\./packages\n||" /etc/apk/repositories sudo touch /etc/linuxbrew.firstrun printf "\nBluefin-CLI first run complete!\n\n" fi diff --git a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish index 64b71ed..0e4fcb4 100644 --- a/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish +++ b/wolfi/bluefin-base/usr/share/fish/vendor_conf.d/00-bluefin-cli-brew-firstrun.fish @@ -39,6 +39,8 @@ if test "$(id -u)" -gt "0" end if test ! -f /etc/linuxbrew.firstrun + # Remove local repository added at buildtime + sudo sed -zi "s|\./packages\n||" /etc/apk/repositories sudo touch /etc/linuxbrew.firstrun printf "\nBluefin-CLI first run complete!\n\n" end From ddeec38c2c0fc2325ad358747251b6268632090e Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 14:12:27 -0700 Subject: [PATCH 39/41] chore: Adjust release tag --- staging/mutter/mutter.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index 794315a..d274c8b 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -17,7 +17,7 @@ Name: mutter Version: %{gnome_version} -Release: 100.%autorelease.xscaling.{{{ git_dir_version }}} +Release: 2%{?dist}.xscaling.{{{ git_dir_version }}} Summary: Window and compositing manager based on Clutter License: GPLv2+ From 3dcd0f807e5bd4d45130d5e1b3596b4f5f3313c3 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 14:21:18 -0700 Subject: [PATCH 40/41] chore: Update gnome-shell to 46.1 --- staging/gnome-shell/gnome-shell.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/staging/gnome-shell/gnome-shell.spec b/staging/gnome-shell/gnome-shell.spec index c66f250..f56b870 100644 --- a/staging/gnome-shell/gnome-shell.spec +++ b/staging/gnome-shell/gnome-shell.spec @@ -1,8 +1,9 @@ %global tarball_version %%(echo %{version} | tr '~' '.') %global major_version 46 +%global minor_version 1 Name: gnome-shell -Version: %{major_version}.0 +Version: %{major_version}.%{minor_version} Release: %autorelease.switcheroo.{{{ git_dir_version }}} Summary: Window management and application launching for GNOME From 72cb9583a0901b81937da7be3ccaf45138d8d92a Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Sun, 28 Apr 2024 14:53:18 -0700 Subject: [PATCH 41/41] chore: Move tags to version for mutter package --- staging/mutter/mutter.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staging/mutter/mutter.spec b/staging/mutter/mutter.spec index d274c8b..46bd363 100644 --- a/staging/mutter/mutter.spec +++ b/staging/mutter/mutter.spec @@ -16,8 +16,8 @@ %global _default_patch_fuzz 2 Name: mutter -Version: %{gnome_version} -Release: 2%{?dist}.xscaling.{{{ git_dir_version }}} +Version: %{gnome_version}.xscaling.{{{ git_dir_version }}} +Release: 2%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+