diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..efa9477
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/mutter-40.4.tar.xz
diff --git a/.mutter.metadata b/.mutter.metadata
new file mode 100644
index 0000000..4344d2e
--- /dev/null
+++ b/.mutter.metadata
@@ -0,0 +1 @@
+e97fff99b075736fc6f0d5bd5713d89983fe99e1 SOURCES/mutter-40.4.tar.xz
diff --git a/SOURCES/0001-Revert-build-Do-not-provide-built-sources-as-libmutt.patch b/SOURCES/0001-Revert-build-Do-not-provide-built-sources-as-libmutt.patch
new file mode 100644
index 0000000..bd18e8a
--- /dev/null
+++ b/SOURCES/0001-Revert-build-Do-not-provide-built-sources-as-libmutt.patch
@@ -0,0 +1,26 @@
+From 3899a01cd6cb00ca686946d3065d58f59f5c2099 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Tue, 17 Nov 2020 14:00:02 +0100
+Subject: [PATCH] Revert "build: Do not provide built sources as libmutter_dep
+ sources"
+
+This reverts commit 4e9a2e479969973bf3063c740ceff149036b3af4.
+---
+ src/meson.build | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/meson.build b/src/meson.build
+index e7c99caee..8fe484ec2 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -955,6 +955,7 @@ libmutter = shared_library(libmutter_name,
+ libmutter_dep = declare_dependency(
+   link_with: libmutter,
+   include_directories: mutter_includes,
++  sources: mutter_built_sources,
+   dependencies: [
+     libmutter_cogl_dep,
+     libmutter_clutter_dep,
+-- 
+2.28.0
+
diff --git a/SOURCES/0001-Test-deny-atomic-KMS-for-tegra-RHBZ-1936991.patch b/SOURCES/0001-Test-deny-atomic-KMS-for-tegra-RHBZ-1936991.patch
new file mode 100644
index 0000000..622ce5f
--- /dev/null
+++ b/SOURCES/0001-Test-deny-atomic-KMS-for-tegra-RHBZ-1936991.patch
@@ -0,0 +1,35 @@
+From a8746403352be96bae7dfd73ac31fe0253f884b8 Mon Sep 17 00:00:00 2001
+From: Adam Williamson <awilliam@redhat.com>
+Date: Tue, 9 Mar 2021 17:21:59 -0800
+Subject: [PATCH] Test: deny atomic KMS for "tegra" (RHBZ #1936991)
+
+Signed-off-by: Adam Williamson <awilliam@redhat.com>
+---
+ data/61-mutter.rules                  | 1 +
+ src/backends/native/meta-kms-device.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/data/61-mutter.rules b/data/61-mutter.rules
+index edc03e6c1..d8e3c5f00 100644
+--- a/data/61-mutter.rules
++++ b/data/61-mutter.rules
+@@ -3,3 +3,4 @@ DRIVERS=="nouveau", SUBSYSTEM=="drm", TAG+="mutter-device-disable-kms-modifiers"
+ DRIVERS=="amdgpu", SUBSYSTEM=="drm", TAG+="mutter-device-disable-kms-modifiers"
+ DRIVERS=="radeon", SUBSYSTEM=="drm", TAG+="mutter-device-disable-kms-modifiers"
+ ENV{ID_PATH}=="platform-vkms", TAG+="mutter-device-ignore"
++DRIVER=="tegra", SUBSYSTEM=="platform", TAG+="mutter-device-disable-atomic-kms"
+diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
+index c388096d5..ef65cf82b 100644
+--- a/src/backends/native/meta-kms-device.c
++++ b/src/backends/native/meta-kms-device.c
+@@ -252,6 +252,7 @@ is_atomic_allowed (const char *driver_name)
+     "vmwgfx",
+     "vboxvideo",
+     "nvidia-drm",
++    "tegra",
+     NULL,
+   };
+ 
+-- 
+2.28.0
+
diff --git a/SOURCES/0001-backend-Clean-up-renderer-after-clutter-backendm.patch b/SOURCES/0001-backend-Clean-up-renderer-after-clutter-backendm.patch
new file mode 100644
index 0000000..e1d9c4d
--- /dev/null
+++ b/SOURCES/0001-backend-Clean-up-renderer-after-clutter-backendm.patch
@@ -0,0 +1,92 @@
+From ff4dc8cc8274dc5f6ed11515e05a341e4e2cec28 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Thu, 12 Aug 2021 14:13:23 -0400
+Subject: [PATCH] backend: Clean up renderer after clutter backendm
+
+commit c4a73e795020722eda3e2bec0c16d96f9f37333b added
+code to cleanup the renderer when the meta backend is
+disposed. Unfortunately, this introduced a crash when
+the window manager is replaced.
+
+This is because cleaning up the renderer involves talking
+to the X server over a display connection that's closed
+two lines higher as part of the clutter_backend_destroy
+call.
+
+This commit fixes the crash by swapping their order.
+---
+ src/backends/meta-backend.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
+index ff84bfe6a..7e8b4ee95 100644
+--- a/src/backends/meta-backend.c
++++ b/src/backends/meta-backend.c
+@@ -216,63 +216,63 @@ meta_backend_dispose (GObject *object)
+ 
+   if (priv->sleep_signal_id)
+     {
+       g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
+       priv->sleep_signal_id = 0;
+     }
+ 
+   if (priv->upower_watch_id)
+     {
+       g_bus_unwatch_name (priv->upower_watch_id);
+       priv->upower_watch_id = 0;
+     }
+ 
+   g_cancellable_cancel (priv->cancellable);
+   g_clear_object (&priv->cancellable);
+   g_clear_object (&priv->system_bus);
+   g_clear_object (&priv->upower_proxy);
+ 
+   g_clear_handle_id (&priv->device_update_idle_id, g_source_remove);
+ 
+   g_clear_pointer (&priv->device_monitors, g_hash_table_destroy);
+ 
+   g_clear_object (&priv->settings);
+ 
+ #ifdef HAVE_PROFILER
+   g_clear_object (&priv->profiler);
+ #endif
+ 
+   g_clear_pointer (&priv->default_seat, clutter_seat_destroy);
+   g_clear_pointer (&priv->stage, clutter_actor_destroy);
+-  g_clear_pointer (&priv->clutter_backend, clutter_backend_destroy);
+   g_clear_object (&priv->renderer);
+   g_clear_list (&priv->gpus, g_object_unref);
++  g_clear_pointer (&priv->clutter_backend, clutter_backend_destroy);
+ 
+   G_OBJECT_CLASS (meta_backend_parent_class)->dispose (object);
+ }
+ 
+ static void
+ meta_backend_destroy (MetaBackend *backend)
+ {
+   g_object_run_dispose (G_OBJECT (backend));
+   g_object_unref (backend);
+ }
+ 
+ static void
+ meta_backend_sync_screen_size (MetaBackend *backend)
+ {
+   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
+   int width, height;
+ 
+   meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
+ 
+   META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
+ }
+ 
+ static void
+ reset_pointer_position (MetaBackend *backend)
+ {
+   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
+   MetaMonitorManager *monitor_manager = priv->monitor_manager;
+   ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend);
+   MetaLogicalMonitor *primary;
+ 
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-constraints-Enforce-X11-size-limits.patch b/SOURCES/0001-constraints-Enforce-X11-size-limits.patch
new file mode 100644
index 0000000..a09a40b
--- /dev/null
+++ b/SOURCES/0001-constraints-Enforce-X11-size-limits.patch
@@ -0,0 +1,85 @@
+From 1ab51efc968d7d3c6244d9b7efcdf4bae4fc0a9d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Wed, 12 Mar 2014 02:04:13 +0100
+Subject: [PATCH] constraints: Enforce X11 size limits
+
+X11 limits windows to a maximum of 32767x32767, enforce that restriction
+to keep insanely huge windows from crashing the WM.
+---
+ src/core/constraints.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/src/core/constraints.c b/src/core/constraints.c
+index 4b1d95338a..eee16dc48f 100644
+--- a/src/core/constraints.c
++++ b/src/core/constraints.c
+@@ -109,6 +109,7 @@ typedef enum
+   PRIORITY_TITLEBAR_VISIBLE = 4,
+   PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
+   PRIORITY_CUSTOM_RULE = 4,
++  PRIORITY_XLIMITS = 4,
+   PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */
+ } ConstraintPriority;
+ 
+@@ -204,6 +205,10 @@ static gboolean constrain_partially_onscreen (MetaWindow         *window,
+                                               ConstraintInfo     *info,
+                                               ConstraintPriority  priority,
+                                               gboolean            check_only);
++static gboolean constrain_xlimits            (MetaWindow         *window,
++                                              ConstraintInfo     *info,
++                                              ConstraintPriority  priority,
++                                              gboolean            check_only);
+ 
+ static void setup_constraint_info        (ConstraintInfo      *info,
+                                           MetaWindow          *window,
+@@ -239,6 +244,7 @@ static const Constraint all_constraints[] = {
+   {constrain_fully_onscreen,     "constrain_fully_onscreen"},
+   {constrain_titlebar_visible,   "constrain_titlebar_visible"},
+   {constrain_partially_onscreen, "constrain_partially_onscreen"},
++  {constrain_xlimits,            "constrain_xlimits"},
+   {NULL,                         NULL}
+ };
+ 
+@@ -1876,3 +1882,39 @@ constrain_partially_onscreen (MetaWindow         *window,
+ 
+   return retval;
+ }
++
++
++#define MAX_WINDOW_SIZE 32767
++
++static gboolean
++constrain_xlimits (MetaWindow         *window,
++                   ConstraintInfo     *info,
++                   ConstraintPriority  priority,
++                   gboolean            check_only)
++{
++  int max_w, max_h;
++  gboolean constraint_already_satisfied;
++
++  if (priority > PRIORITY_XLIMITS)
++    return TRUE;
++
++  max_w = max_h = MAX_WINDOW_SIZE;
++
++  if (window->frame)
++    {
++      MetaFrameBorders borders;
++      meta_frame_calc_borders (window->frame, &borders);
++
++      max_w -= (borders.total.left + borders.total.right);
++      max_h -= (borders.total.top + borders.total.bottom);
++    }
++
++  constraint_already_satisfied = info->current.width < max_w && info->current.height < max_h;
++  if (check_only || constraint_already_satisfied)
++    return constraint_already_satisfied;
++
++  info->current.width = MIN (info->current.width, max_w);
++  info->current.height = MIN (info->current.height, max_h);
++
++  return TRUE;
++}
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch
new file mode 100644
index 0000000..2ff5f1b
--- /dev/null
+++ b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch
@@ -0,0 +1,42 @@
+From 7ac5b7bad8f2d0e61700610f68282f6687cc9d2e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Thu, 21 Jul 2016 15:43:12 +0200
+Subject: [PATCH] events: Don't move (sloppy) focus while buttons are pressed
+
+(https://bugzilla.redhat.com/show_bug.cgi?id=1358535)
+---
+ src/x11/events.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/src/x11/events.c b/src/x11/events.c
+index efa8f9856b..388eff0ac7 100644
+--- a/src/x11/events.c
++++ b/src/x11/events.c
+@@ -839,6 +839,16 @@ crossing_serial_is_ignored (MetaX11Display *x11_display,
+   return FALSE;
+ }
+ 
++static gboolean
++event_has_button_mask (XIEnterEvent *enter_event)
++{
++  int i;
++  for (i = 0; i < enter_event->buttons.mask_len; i++)
++    if (enter_event->buttons.mask[i] != '\0')
++      return TRUE;
++  return FALSE;
++}
++
+ static gboolean
+ handle_input_xevent (MetaX11Display *x11_display,
+                      XIEvent        *input_event,
+@@ -883,6 +893,7 @@ handle_input_xevent (MetaX11Display *x11_display,
+        * avoid races.
+        */
+       if (window && !crossing_serial_is_ignored (x11_display, serial) &&
++          !event_has_button_mask (enter_event) &&
+           enter_event->mode != XINotifyGrab &&
+           enter_event->mode != XINotifyUngrab &&
+           enter_event->detail != XINotifyInferior &&
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch
new file mode 100644
index 0000000..806ad38
--- /dev/null
+++ b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch
@@ -0,0 +1,49 @@
+From 99c74360451a85fca9dacad531ed22adbc1b0805 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 13 Feb 2018 09:44:50 -0500
+Subject: [PATCH] main: be more aggressive in assuming X11 backend
+
+If the session is started by vncserver right now, the
+XDG_SESSION_TYPE won't be X11.  Ideally that would be
+fixed, but for backward compatibility we should default
+to X11 if the session type isn't set to wayland explicitly.
+---
+ src/core/main.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/src/core/main.c b/src/core/main.c
+index a07dda9ecc..0d241f952b 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -407,7 +407,6 @@ find_session_type (void)
+   char *session_id;
+   char *session_type;
+   const char *session_type_env;
+-  gboolean is_tty = FALSE;
+   int ret, i;
+ 
+   ret = sd_pid_get_session (0, &session_id);
+@@ -420,8 +419,7 @@ find_session_type (void)
+         {
+           if (session_type_is_supported (session_type))
+             goto out;
+-          else
+-            is_tty = g_strcmp0 (session_type, "tty") == 0;
++
+           free (session_type);
+         }
+     }
+@@ -453,8 +451,8 @@ find_session_type (void)
+       goto out;
+     }
+ 
+-  /* Legacy support for starting through xinit */
+-  if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")))
++  /* Legacy support for starting through xinit or vncserver */
++  if (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY"))
+     {
+       session_type = strdup ("x11");
+       goto out;
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch b/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch
new file mode 100644
index 0000000..14c9f10
--- /dev/null
+++ b/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch
@@ -0,0 +1,35 @@
+From 6e2ef652cd58136aa668d0c1bd843fe83f11a0ab Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Fri, 26 Oct 2018 08:49:39 +0200
+Subject: [PATCH] wayland: Allow Xwayland grabs on selected apps
+
+Allow Xwayland grabs on a selected set of X11 applications.
+---
+ data/org.gnome.mutter.wayland.gschema.xml.in | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in
+index 8a1878e105..5527a46bc6 100644
+--- a/data/org.gnome.mutter.wayland.gschema.xml.in
++++ b/data/org.gnome.mutter.wayland.gschema.xml.in
+@@ -66,7 +66,7 @@
+           gettext-domain="@GETTEXT_DOMAIN@">
+ 
+     <key name="xwayland-allow-grabs" type="b">
+-      <default>false</default>
++      <default>true</default>
+       <summary>Allow X11 grabs to lock keyboard focus with Xwayland</summary>
+       <description>
+         Allow all keyboard events to be routed to X11 “override redirect”
+@@ -86,7 +86,7 @@
+     </key>
+ 
+     <key name="xwayland-grab-access-rules" type="as">
+-      <default>[]</default>
++      <default>['@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@']</default>
+       <summary>Xwayland applications allowed to issue keyboard grabs</summary>
+       <description>
+         List the resource names or resource class of X11 windows either
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-wayland-Avoid-a-race-in-wl_seat-capabilities.patch b/SOURCES/0001-wayland-Avoid-a-race-in-wl_seat-capabilities.patch
new file mode 100644
index 0000000..5a9783b
--- /dev/null
+++ b/SOURCES/0001-wayland-Avoid-a-race-in-wl_seat-capabilities.patch
@@ -0,0 +1,192 @@
+From 5e4a1290ce75ed94e3f0f457d35a225f2ef3878c Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 28 Nov 2017 10:54:08 +0100
+Subject: [PATCH] wayland: Avoid a race in wl_seat capabilities
+
+The way wl_seat capabilities work, by notifying clients of capabilities
+changes, and clients consequently requesting the relevant interface
+objects (pointer, keyboard, touch) is inherently racy.
+
+On quick VT changes for example, capabilities on the seat will be added
+and removed, and by the time the client receives the capability change
+notification and requests the relevant keyboard, pointer or touch,
+another VT switch might have occurred and the wl_pointer, wl_keyboard or
+wl_touch already destroyed, leading to a protocol error which kills the
+client.
+
+To avoid this, create the objects when requested regardless of the
+capabilities.
+
+Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1797
+Related: https://bugzilla.gnome.org/show_bug.cgi?id=790932
+---
+ src/wayland/meta-wayland-pointer.c | 45 ++++++++++++++++++++++++------
+ src/wayland/meta-wayland-seat.c    |  9 ++----
+ src/wayland/meta-wayland-touch.c   |  8 ------
+ 3 files changed, 40 insertions(+), 22 deletions(-)
+
+diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
+index 3132abfd2..abd779ad7 100644
+--- a/src/wayland/meta-wayland-pointer.c
++++ b/src/wayland/meta-wayland-pointer.c
+@@ -109,7 +109,7 @@ meta_wayland_pointer_client_new (void)
+ }
+ 
+ static void
+-meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
++meta_wayland_pointer_make_resources_inert (MetaWaylandPointerClient *pointer_client)
+ {
+   struct wl_resource *resource, *next;
+ 
+@@ -141,10 +141,25 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
+       wl_list_init (wl_resource_get_link (resource));
+       wl_resource_set_user_data (resource, NULL);
+     }
++}
+ 
++static void
++meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
++{
++  meta_wayland_pointer_make_resources_inert (pointer_client);
+   g_free (pointer_client);
+ }
+ 
++static void
++make_resources_inert_foreach (gpointer key,
++                              gpointer value,
++                              gpointer data)
++{
++  MetaWaylandPointerClient *pointer_client = value;
++
++  meta_wayland_pointer_make_resources_inert (pointer_client);
++}
++
+ static gboolean
+ meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client)
+ {
+@@ -158,8 +173,6 @@ MetaWaylandPointerClient *
+ meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
+                                          struct wl_client   *client)
+ {
+-  if (!pointer->pointer_clients)
+-    return NULL;
+   return g_hash_table_lookup (pointer->pointer_clients, client);
+ }
+ 
+@@ -475,10 +488,6 @@ meta_wayland_pointer_enable (MetaWaylandPointer *pointer)
+   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
+   ClutterSeat *clutter_seat;
+ 
+-  pointer->pointer_clients =
+-    g_hash_table_new_full (NULL, NULL, NULL,
+-                           (GDestroyNotify) meta_wayland_pointer_client_free);
+-
+   pointer->cursor_surface = NULL;
+ 
+   clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
+@@ -508,6 +517,10 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
+   ClutterBackend *clutter_backend = clutter_get_default_backend ();
+   ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
+ 
++  g_hash_table_foreach (pointer->pointer_clients,
++                        make_resources_inert_foreach,
++                        NULL);
++
+   g_signal_handlers_disconnect_by_func (cursor_tracker,
+                                         (gpointer) meta_wayland_pointer_on_cursor_changed,
+                                         pointer);
+@@ -531,7 +544,6 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
+   meta_wayland_pointer_set_focus (pointer, NULL);
+   meta_wayland_pointer_set_current (pointer, NULL);
+ 
+-  g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
+   pointer->cursor_surface = NULL;
+ }
+ 
+@@ -1356,11 +1368,28 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
+   pointer->default_grab.interface = &default_pointer_grab_interface;
+   pointer->default_grab.pointer = pointer;
+   pointer->grab = &pointer->default_grab;
++  pointer->pointer_clients =
++    g_hash_table_new_full (NULL, NULL, NULL,
++                           (GDestroyNotify) meta_wayland_pointer_client_free);
++}
++
++static void
++meta_wayland_pointer_finalize (GObject *object)
++{
++  MetaWaylandPointer *pointer = META_WAYLAND_POINTER (object);
++
++  g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
++
++  G_OBJECT_CLASS (meta_wayland_pointer_parent_class)->finalize (object);
+ }
+ 
+ static void
+ meta_wayland_pointer_class_init (MetaWaylandPointerClass *klass)
+ {
++  GObjectClass *object_class = G_OBJECT_CLASS (klass);
++
++  object_class->finalize = meta_wayland_pointer_finalize;
++
+   signals[FOCUS_SURFACE_CHANGED] = g_signal_new ("focus-surface-changed",
+                                                  G_TYPE_FROM_CLASS (klass),
+                                                  G_SIGNAL_RUN_LAST,
+diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
+index c6390dde7..efce6d6d6 100644
+--- a/src/wayland/meta-wayland-seat.c
++++ b/src/wayland/meta-wayland-seat.c
+@@ -46,8 +46,7 @@ seat_get_pointer (struct wl_client *client,
+   MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
+   MetaWaylandPointer *pointer = seat->pointer;
+ 
+-  if (meta_wayland_seat_has_pointer (seat))
+-    meta_wayland_pointer_create_new_resource (pointer, client, resource, id);
++  meta_wayland_pointer_create_new_resource (pointer, client, resource, id);
+ }
+ 
+ static void
+@@ -58,8 +57,7 @@ seat_get_keyboard (struct wl_client *client,
+   MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
+   MetaWaylandKeyboard *keyboard = seat->keyboard;
+ 
+-  if (meta_wayland_seat_has_keyboard (seat))
+-    meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id);
++  meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id);
+ }
+ 
+ static void
+@@ -70,8 +68,7 @@ seat_get_touch (struct wl_client *client,
+   MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
+   MetaWaylandTouch *touch = seat->touch;
+ 
+-  if (meta_wayland_seat_has_touch (seat))
+-    meta_wayland_touch_create_new_resource (touch, client, resource, id);
++  meta_wayland_touch_create_new_resource (touch, client, resource, id);
+ }
+ 
+ static void
+diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c
+index 002ff16f7..15f0312eb 100644
+--- a/src/wayland/meta-wayland-touch.c
++++ b/src/wayland/meta-wayland-touch.c
+@@ -521,16 +521,8 @@ meta_wayland_touch_create_new_resource (MetaWaylandTouch   *touch,
+                                         struct wl_resource *seat_resource,
+                                         uint32_t            id)
+ {
+-  MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+   struct wl_resource *cr;
+ 
+-  if (!meta_wayland_seat_has_touch (seat))
+-    {
+-      wl_resource_post_error (seat_resource, WL_DISPLAY_ERROR_INVALID_METHOD,
+-                              "Cannot retrieve touch interface without touch capability");
+-      return;
+-    }
+-
+   cr = wl_resource_create (client, &wl_touch_interface, wl_resource_get_version (seat_resource), id);
+   wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource);
+   wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
+-- 
+2.31.1
+
diff --git a/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch
new file mode 100644
index 0000000..36d50b6
--- /dev/null
+++ b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch
@@ -0,0 +1,35 @@
+From 9efcc35102b4c41265e93461b35a1193b3d5822d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+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 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c
+index b7032e0ba..b05d5e158 100644
+--- a/src/compositor/meta-window-actor-x11.c
++++ b/src/compositor/meta-window-actor-x11.c
+@@ -528,6 +528,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 &&
++      window->shape_region != NULL)
++    return FALSE;
+ 
+   /*
+    * Generate shadows for all other windows.
+-- 
+2.23.0
+
diff --git a/SOURCES/glx-stereo-support.patch b/SOURCES/glx-stereo-support.patch
new file mode 100644
index 0000000..8083db4
--- /dev/null
+++ b/SOURCES/glx-stereo-support.patch
@@ -0,0 +1,1242 @@
+From 768818c8d071f066a2ab68f83381829838b5bf29 Mon Sep 17 00:00:00 2001
+From: "Owen W. Taylor" <otaylor@fishsoup.net>
+Date: Thu, 8 May 2014 18:44:15 -0400
+Subject: [PATCH 1/2] Add support for quad-buffer stereo
+
+Track the stereo status of windows using the new EXT_stereo_tree
+GLX extension.
+
+When stereo is enabled or disabled, a restart is triggered via
+meta_restart() after a timeout, setting a _META_ENABLE_STEREO
+property on the root window to indicate whether we should
+turn on a stereo stage for clutter. The property avoids a loop,
+since we need to enable stereo *before* initializing Clutter and GL,
+but we need GL to figure out whether we have stereo windows.
+
+Stereo windows are drawn to the stage using new functionality
+in Cogl to setup a stereo context, select which buffer to draw
+to, and draw either the left or right buffer of a stereo
+texture_from_pixmap.
+---
+ clutter/clutter/clutter-paint-nodes.c        | 103 +++++++++++
+ clutter/clutter/clutter-paint-nodes.h        |  13 ++
+ src/compositor/compositor.c                  |   8 +
+ src/compositor/meta-compositor-x11.c         | 127 +++++++++++++
+ src/compositor/meta-compositor-x11.h         |   6 +
+ src/compositor/meta-shaped-texture-private.h |   5 +-
+ src/compositor/meta-shaped-texture.c         | 176 +++++++++++++++----
+ src/compositor/meta-surface-actor-wayland.c  |   2 +-
+ src/compositor/meta-surface-actor-x11.c      |  55 +++++-
+ src/compositor/meta-surface-actor-x11.h      |   5 +
+ src/compositor/meta-window-actor-private.h   |   5 +
+ src/compositor/meta-window-actor.c           |  22 +++
+ src/core/main.c                              |   4 +
+ src/core/stereo.c                            | 154 ++++++++++++++++
+ src/core/stereo.h                            |  28 +++
+ src/meson.build                              |   2 +
+ src/wayland/meta-wayland-actor-surface.c     |   4 +-
+ 17 files changed, 667 insertions(+), 52 deletions(-)
+ create mode 100644 src/core/stereo.c
+ create mode 100644 src/core/stereo.h
+
+diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
+index f1f7fce318..29a673e9c7 100644
+--- a/clutter/clutter/clutter-paint-nodes.c
++++ b/clutter/clutter/clutter-paint-nodes.c
+@@ -1970,3 +1970,106 @@ clutter_blur_node_new (unsigned int width,
+ out:
+   return (ClutterPaintNode *) blur_node;
+ }
++
++/*
++ * ClutterStereoNode
++ */
++
++struct _ClutterStereoNode
++{
++  ClutterPaintNode parent_instance;
++
++  CoglStereoMode stereo_mode;
++};
++
++struct _ClutterStereoNodeClass
++{
++  ClutterPaintNodeClass parent_class;
++};
++
++G_DEFINE_TYPE (ClutterStereoNode, clutter_stereo_node, CLUTTER_TYPE_PAINT_NODE)
++
++static gboolean
++clutter_stereo_node_pre_draw (ClutterPaintNode    *node,
++                              ClutterPaintContext *paint_context)
++{
++  ClutterStereoNode *stereo_node = CLUTTER_STEREO_NODE (node);
++  CoglFramebuffer *fb =
++   clutter_paint_context_get_framebuffer (paint_context);
++
++  g_warn_if_fail (cogl_framebuffer_get_is_stereo (fb));
++
++  cogl_framebuffer_set_stereo_mode (fb, stereo_node->stereo_mode);
++
++  return TRUE;
++}
++
++static void
++clutter_stereo_node_post_draw (ClutterPaintNode    *node,
++                               ClutterPaintContext *paint_context)
++{
++  CoglFramebuffer *fb =
++   clutter_paint_context_get_framebuffer (paint_context);
++
++  cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
++}
++
++static const char *
++stereo_mode_to_string (CoglStereoMode stereo_mode)
++{
++  switch (stereo_mode)
++    {
++    case COGL_STEREO_BOTH:
++      return "both";
++    case COGL_STEREO_LEFT:
++      return "left";
++    case COGL_STEREO_RIGHT:
++      return "right";
++    }
++
++  g_assert_not_reached ();
++}
++
++static JsonNode *
++clutter_stereo_node_serialize (ClutterPaintNode *node)
++{
++  ClutterStereoNode *stereo_node = CLUTTER_STEREO_NODE (node);
++  g_autoptr (JsonBuilder) builder = NULL;
++  const char *stereo_mode_str;
++
++  builder = json_builder_new ();
++  json_builder_begin_object (builder);
++  json_builder_set_member_name (builder, "stereo-mode");
++  stereo_mode_str = stereo_mode_to_string (stereo_node->stereo_mode);
++  json_builder_add_string_value (builder, stereo_mode_str);
++  json_builder_end_object (builder);
++
++  return json_builder_get_root (builder);
++}
++
++static void
++clutter_stereo_node_class_init (ClutterStereoNodeClass *klass)
++{
++  ClutterPaintNodeClass *node_class;
++
++  node_class = CLUTTER_PAINT_NODE_CLASS (klass);
++  node_class->pre_draw = clutter_stereo_node_pre_draw;
++  node_class->post_draw = clutter_stereo_node_post_draw;
++  node_class->serialize = clutter_stereo_node_serialize;
++}
++
++static void
++clutter_stereo_node_init (ClutterStereoNode *stereo_node)
++{
++}
++
++ClutterPaintNode *
++clutter_stereo_node_new (CoglStereoMode stereo_mode)
++{
++  ClutterStereoNode *stereo_node;
++
++  stereo_node = _clutter_paint_node_create (CLUTTER_TYPE_STEREO_NODE);
++  stereo_node->stereo_mode = stereo_mode;
++
++  return CLUTTER_PAINT_NODE (stereo_node);
++}
+diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h
+index 7f0d12857a..77d1ab05b6 100644
+--- a/clutter/clutter/clutter-paint-nodes.h
++++ b/clutter/clutter/clutter-paint-nodes.h
+@@ -284,6 +284,19 @@ ClutterPaintNode * clutter_blur_node_new (unsigned int width,
+                                           unsigned int height,
+                                           float        sigma);
+ 
++#define CLUTTER_TYPE_STEREO_NODE                (clutter_stereo_node_get_type ())
++#define CLUTTER_STEREO_NODE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STEREO_NODE, ClutterStereoNode))
++#define CLUTTER_IS_STEREO_NODE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STEREO_NODE))
++
++typedef struct _ClutterStereoNode               ClutterStereoNode;
++typedef struct _ClutterStereoNodeClass          ClutterStereoNodeClass;
++
++CLUTTER_EXPORT
++GType clutter_stereo_node_get_type (void) G_GNUC_CONST;
++
++CLUTTER_EXPORT
++ClutterPaintNode * clutter_stereo_node_new (CoglStereoMode stereo_mode);
++
+ G_END_DECLS
+ 
+ #endif /* __CLUTTER_PAINT_NODES_H__ */
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 1770550d4c..a4bd1252ae 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -66,6 +66,7 @@
+ #include "compositor/meta-window-actor-private.h"
+ #include "compositor/meta-window-group-private.h"
+ #include "core/frame.h"
++#include "core/stereo.h"
+ #include "core/util-private.h"
+ #include "core/window-private.h"
+ #include "meta/compositor-mutter.h"
+@@ -910,6 +911,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+     meta_compositor_get_instance_private (compositor);
+   MetaWindowActor *top_window_actor;
+   GList *old_stack;
++  int stereo_window_count = 0;
+ 
+   /* This is painful because hidden windows that we are in the process
+    * of animating out of existence. They'll be at the bottom of the
+@@ -986,12 +988,18 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+        */
+       priv->windows = g_list_prepend (priv->windows, actor);
+ 
++      if (meta_window_actor_is_stereo (actor))
++        stereo_window_count++;
++
+       stack = g_list_remove (stack, window);
+       old_stack = g_list_remove (old_stack, actor);
+     }
+ 
+   sync_actor_stacking (compositor);
+ 
++  if (!meta_is_wayland_compositor ())
++    meta_stereo_set_have_stereo_windows (stereo_window_count > 0);
++
+   top_window_actor = get_top_visible_window_actor (compositor);
+ 
+   if (priv->top_window_actor == top_window_actor)
+diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c
+index 1d0ba4c8d8..afbe3f57e2 100644
+--- a/src/compositor/meta-compositor-x11.c
++++ b/src/compositor/meta-compositor-x11.c
+@@ -31,6 +31,8 @@
+ #include "compositor/meta-sync-ring.h"
+ #include "compositor/meta-window-actor-x11.h"
+ #include "core/display-private.h"
++#include "core/stack-tracker.h"
++#include "core/stereo.h"
+ #include "x11/meta-x11-display-private.h"
+ 
+ struct _MetaCompositorX11
+@@ -50,8 +52,24 @@ struct _MetaCompositorX11
+   gboolean xserver_uses_monotonic_clock;
+   int64_t xserver_time_query_time_us;
+   int64_t xserver_time_offset_us;
++
++  int glx_opcode;
++  gboolean stereo_tree_ext;
++  gboolean have_stereo_windows;
+ };
+ 
++typedef struct
++{
++  int type;
++  unsigned long serial;
++  Bool send_event;
++  Display *display;
++  int extension;
++  int evtype;
++  Drawable window;
++  Bool stereo_tree;
++} StereoNotifyEvent;
++
+ G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR)
+ 
+ static void
+@@ -95,6 +113,27 @@ meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+       if (window)
+         process_damage (compositor_x11, (XDamageNotifyEvent *) xevent, window);
+     }
++  else if (xevent->type == GenericEvent &&
++           xevent->xcookie.extension == compositor_x11->glx_opcode)
++    {
++      if (xevent->xcookie.evtype == GLX_STEREO_NOTIFY_EXT)
++        {
++          StereoNotifyEvent *stereo_event =
++            (StereoNotifyEvent *) (xevent->xcookie.data);
++
++          window = meta_x11_display_lookup_x_window (x11_display,
++                                                     stereo_event->window);
++          if (window)
++            {
++              MetaWindowActor *window_actor = meta_window_actor_from_window (window);
++              MetaDisplay *display = meta_window_get_display (window);
++
++              meta_window_actor_stereo_notify (window_actor,
++                                               stereo_event->stereo_tree);
++              meta_stack_tracker_queue_sync_stack (display->stack_tracker);
++            }
++        }
++    }
+ 
+   if (compositor_x11->have_x11_sync_object)
+     meta_sync_ring_handle_event (xevent);
+@@ -107,6 +146,85 @@ meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+     meta_x11_handle_event (xevent);
+ }
+ 
++#define GLX_STEREO_TREE_EXT        0x20F5
++#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
++#define GLX_STEREO_NOTIFY_EXT      0x00000000
++
++static gboolean
++display_has_stereo_tree_ext (MetaX11Display *x11_display)
++{
++  Display     *xdisplay = x11_display->xdisplay;
++  const char  *extensions_string;
++
++  static const char * (*query_extensions_string) (Display *display,
++                                                  int      screen);
++
++  if (query_extensions_string == NULL)
++    query_extensions_string =
++      (const char * (*) (Display *, int))
++      cogl_get_proc_address ("glXQueryExtensionsString");
++
++  extensions_string = query_extensions_string (xdisplay,
++                                               meta_x11_display_get_screen_number (x11_display));
++
++  return extensions_string && strstr (extensions_string, "EXT_stereo_tree") != 0;
++}
++
++#include <GL/gl.h>
++
++gboolean
++meta_compositor_x11_window_is_stereo (MetaCompositorX11 *compositor_x11,
++                                      Window             xwindow)
++{
++  MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
++  MetaDisplay *display = meta_compositor_get_display (compositor);
++  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
++
++  static int (*query_drawable) (Display      *dpy,
++                                Drawable      draw,
++                                int           attribute,
++                                unsigned int *value);
++
++  if (compositor_x11->stereo_tree_ext)
++    {
++      unsigned int stereo_tree = 0;
++
++      if (query_drawable == NULL)
++        query_drawable =
++          (int (*) (Display *, Drawable, int, unsigned int *))
++          cogl_get_proc_address ("glXQueryDrawable");
++
++      query_drawable (xdisplay, xwindow, GLX_STEREO_TREE_EXT, &stereo_tree);
++
++      return stereo_tree != 0;
++    }
++  else
++    return FALSE;
++}
++
++void
++meta_compositor_x11_select_stereo_notify (MetaCompositorX11 *compositor_x11,
++                                          Window             xwindow)
++{
++  MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
++  MetaDisplay *display = meta_compositor_get_display (compositor);
++  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
++
++  static void (*select_event) (Display      *dpy,
++                               Drawable      draw,
++                               unsigned long event_mask);
++
++  if (compositor_x11->stereo_tree_ext)
++    {
++      if (select_event == NULL)
++        select_event =
++          (void (*) (Display *, Drawable, unsigned long))
++          cogl_get_proc_address ("glXSelectEvent");
++
++      select_event (xdisplay, xwindow, GLX_STEREO_NOTIFY_MASK_EXT);
++    }
++}
++
+ static void
+ determine_server_clock_source (MetaCompositorX11 *compositor_x11)
+ {
+@@ -142,6 +260,7 @@ meta_compositor_x11_manage (MetaCompositor  *compositor,
+   MetaX11Display *x11_display = display->x11_display;
+   Display *xdisplay = meta_x11_display_get_xdisplay (x11_display);
+   int composite_version;
++  int glx_major_opcode, glx_first_event, glx_first_error;
+   MetaBackend *backend = meta_get_backend ();
+   Window xwindow;
+ 
+@@ -166,10 +285,18 @@ meta_compositor_x11_manage (MetaCompositor  *compositor,
+       return FALSE;
+     }
+ 
++  if (XQueryExtension (xdisplay,
++                       "GLX",
++                       &glx_major_opcode, &glx_first_event, &glx_first_error))
++    compositor_x11->glx_opcode = glx_major_opcode;
++
+   determine_server_clock_source (compositor_x11);
+ 
+   meta_x11_display_set_cm_selection (display->x11_display);
+ 
++  compositor_x11->stereo_tree_ext =
++    display_has_stereo_tree_ext (display->x11_display);
++
+   compositor_x11->output = display->x11_display->composite_overlay_window;
+ 
+   xwindow = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
+diff --git a/src/compositor/meta-compositor-x11.h b/src/compositor/meta-compositor-x11.h
+index 42554feb39..61f3cd5950 100644
+--- a/src/compositor/meta-compositor-x11.h
++++ b/src/compositor/meta-compositor-x11.h
+@@ -36,4 +36,10 @@ void meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+ 
+ Window meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11);
+ 
++gboolean meta_compositor_x11_window_is_stereo (MetaCompositorX11 *compositor_x11,
++                                               Window             xwindow);
++
++void meta_compositor_x11_select_stereo_notify (MetaCompositorX11 *compositor_x11,
++                                               Window             xwindow);
++
+ #endif /* META_COMPOSITOR_X11_H */
+diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
+index 2fe1b8ea48..fadad07d69 100644
+--- a/src/compositor/meta-shaped-texture-private.h
++++ b/src/compositor/meta-shaped-texture-private.h
+@@ -31,8 +31,9 @@
+ #include "meta/meta-shaped-texture.h"
+ 
+ MetaShapedTexture *meta_shaped_texture_new (void);
+-void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
+-                                      CoglTexture       *texture);
++void meta_shaped_texture_set_textures (MetaShapedTexture *stex,
++                                       CoglTexture       *texture,
++                                       CoglTexture       *texture_right);
+ void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
+                                             gboolean           is_y_inverted);
+ void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
+diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
+index 6a8af828f0..43170a195d 100644
+--- a/src/compositor/meta-shaped-texture.c
++++ b/src/compositor/meta-shaped-texture.c
+@@ -83,8 +83,10 @@ struct _MetaShapedTexture
+   GObject parent;
+ 
+   MetaTextureTower *paint_tower;
++  MetaTextureTower *paint_tower_right;
+ 
+   CoglTexture *texture;
++  CoglTexture *texture_right;
+   CoglTexture *mask_texture;
+   CoglSnippet *snippet;
+ 
+@@ -151,6 +153,7 @@ static void
+ meta_shaped_texture_init (MetaShapedTexture *stex)
+ {
+   stex->paint_tower = meta_texture_tower_new ();
++  stex->paint_tower_right = NULL;
+ 
+   stex->buffer_scale = 1;
+   stex->texture = NULL;
+@@ -251,11 +254,11 @@ meta_shaped_texture_dispose (GObject *object)
+ 
+   g_clear_handle_id (&stex->remipmap_timeout_id, g_source_remove);
+ 
+-  if (stex->paint_tower)
+-    meta_texture_tower_free (stex->paint_tower);
+-  stex->paint_tower = NULL;
++  g_clear_pointer (&stex->paint_tower, meta_texture_tower_free);
++  g_clear_pointer (&stex->paint_tower_right, meta_texture_tower_free);
+ 
+   g_clear_pointer (&stex->texture, cogl_object_unref);
++  g_clear_pointer (&stex->texture_right, cogl_object_unref);
+ 
+   meta_shaped_texture_set_mask_texture (stex, NULL);
+   meta_shaped_texture_reset_pipelines (stex);
+@@ -521,14 +524,19 @@ paint_clipped_rectangle_node (MetaShapedTexture     *stex,
+ }
+ 
+ static void
+-set_cogl_texture (MetaShapedTexture *stex,
+-                  CoglTexture       *cogl_tex)
++set_cogl_textures (MetaShapedTexture *stex,
++                   CoglTexture       *cogl_tex,
++                   CoglTexture       *cogl_tex_right)
+ {
+   int width, height;
+ 
+   cogl_clear_object (&stex->texture);
++  cogl_clear_object (&stex->texture_right);
+ 
+-  if (cogl_tex != NULL)
++  stex->texture = cogl_tex;
++  stex->texture_right = cogl_tex_right;
++
++  if (cogl_tex)
+     {
+       stex->texture = cogl_object_ref (cogl_tex);
+       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
+@@ -540,6 +548,9 @@ set_cogl_texture (MetaShapedTexture *stex,
+       height = 0;
+     }
+ 
++  if (cogl_tex_right)
++    cogl_object_ref (cogl_tex_right);
++
+   if (stex->tex_width != width ||
+       stex->tex_height != height)
+     {
+@@ -553,8 +564,23 @@ set_cogl_texture (MetaShapedTexture *stex,
+    * previous buffer. We only queue a redraw in response to surface
+    * damage. */
+ 
++  if (cogl_tex_right)
++    {
++      if (!stex->paint_tower_right)
++        stex->paint_tower_right = meta_texture_tower_new ();
++    }
++  else
++    {
++      g_clear_pointer (&stex->paint_tower_right, meta_texture_tower_free);
++    }
++
+   if (stex->create_mipmaps)
+-    meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
++    {
++      meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
++
++      if (stex->paint_tower_right)
++        meta_texture_tower_set_base_texture (stex->paint_tower_right, cogl_tex_right);
++    }
+ }
+ 
+ static gboolean
+@@ -582,6 +608,19 @@ flip_ints (int *x,
+   *y = tmp;
+ }
+ 
++static CoglFramebuffer *
++get_target_framebuffer (ClutterPaintNode    *root_node,
++                        ClutterPaintContext *paint_context)
++{
++  CoglFramebuffer *framebuffer;
++
++  framebuffer = clutter_paint_node_get_framebuffer (root_node);
++  if (!framebuffer)
++    framebuffer = clutter_paint_context_get_framebuffer (paint_context);
++
++  return framebuffer;
++}
++
+ static void
+ do_paint_content (MetaShapedTexture   *stex,
+                   ClutterPaintNode    *root_node,
+@@ -622,9 +661,7 @@ do_paint_content (MetaShapedTexture   *stex,
+    * improves performance, especially with software rendering.
+    */
+ 
+-  framebuffer = clutter_paint_node_get_framebuffer (root_node);
+-  if (!framebuffer)
+-    framebuffer = clutter_paint_context_get_framebuffer (paint_context);
++  framebuffer = get_target_framebuffer (root_node, paint_context);
+ 
+   if (stex->has_viewport_src_rect)
+     {
+@@ -826,13 +863,27 @@ do_paint_content (MetaShapedTexture   *stex,
+ 
+ static CoglTexture *
+ select_texture_for_paint (MetaShapedTexture   *stex,
+-                          ClutterPaintContext *paint_context)
++                          ClutterPaintContext *paint_context,
++                          CoglStereoMode       stereo_mode)
+ {
+   CoglTexture *texture = NULL;
+   int64_t now;
++  gboolean use_right_texture = FALSE;
+ 
+-  if (!stex->texture)
+-    return NULL;
++  switch (stereo_mode)
++    {
++    case COGL_STEREO_LEFT:
++    case COGL_STEREO_BOTH:
++      if (!stex->texture)
++        return NULL;
++      use_right_texture = FALSE;
++      break;
++    case COGL_STEREO_RIGHT:
++      if (!stex->texture_right)
++        return NULL;
++      use_right_texture = TRUE;
++      break;
++    }
+ 
+   now = g_get_monotonic_time ();
+ 
+@@ -843,14 +894,24 @@ select_texture_for_paint (MetaShapedTexture   *stex,
+       if (age >= MIN_MIPMAP_AGE_USEC ||
+           stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
+         {
+-          texture = meta_texture_tower_get_paint_texture (stex->paint_tower,
++          MetaTextureTower *paint_tower;
++
++          if (use_right_texture)
++            paint_tower = stex->paint_tower_right;
++          else
++            paint_tower = stex->paint_tower;
++
++          texture = meta_texture_tower_get_paint_texture (paint_tower,
+                                                           paint_context);
+         }
+     }
+ 
+   if (!texture)
+     {
+-      texture = stex->texture;
++      if (use_right_texture)
++        texture = stex->texture_right;
++      else
++        texture = stex->texture;
+ 
+       if (stex->create_mipmaps)
+         {
+@@ -876,35 +937,57 @@ meta_shaped_texture_paint_content (ClutterContent      *content,
+ {
+   MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
+   ClutterActorBox alloc;
+-  CoglTexture *paint_tex = NULL;
+   uint8_t opacity;
++  CoglFramebuffer *framebuffer;
++  gboolean is_stereo;
+ 
+   if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
+     return;
+ 
+-  /* The GL EXT_texture_from_pixmap extension does allow for it to be
+-   * used together with SGIS_generate_mipmap, however this is very
+-   * rarely supported. Also, even when it is supported there
+-   * are distinct performance implications from:
+-   *
+-   *  - Updating mipmaps that we don't need
+-   *  - Having to reallocate pixmaps on the server into larger buffers
+-   *
+-   * So, we just unconditionally use our mipmap emulation code. If we
+-   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
+-   * see if it was supported (no API currently), and then if and only
+-   * if that was the case, set the clutter texture quality to HIGH.
+-   * Setting the texture quality to high without SGIS_generate_mipmap
+-   * support for TFP textures will result in fallbacks to XGetImage.
+-   */
+-  paint_tex = select_texture_for_paint (stex, paint_context);
+-  if (!paint_tex)
++  if (!stex->texture)
+     return;
+ 
+   opacity = clutter_actor_get_paint_opacity (actor);
+   clutter_actor_get_content_box (actor, &alloc);
+ 
+-  do_paint_content (stex, root_node, paint_context, paint_tex, &alloc, opacity);
++  framebuffer = get_target_framebuffer (root_node, paint_context);
++  is_stereo = (stex->texture_right &&
++               cogl_framebuffer_get_is_stereo (framebuffer));
++
++  if (is_stereo)
++    {
++      CoglTexture *texture_left;
++      CoglTexture *texture_right;
++      g_autoptr (ClutterPaintNode) left_node = NULL;
++      g_autoptr (ClutterPaintNode) right_node = NULL;
++
++      texture_left = select_texture_for_paint (stex, paint_context,
++                                               COGL_STEREO_LEFT);
++      texture_right = select_texture_for_paint (stex, paint_context,
++                                                COGL_STEREO_RIGHT);
++
++      left_node = clutter_stereo_node_new (COGL_STEREO_LEFT);
++      clutter_paint_node_set_static_name (left_node, "MetaShapedTexture (left)");
++      right_node = clutter_stereo_node_new (COGL_STEREO_RIGHT);
++      clutter_paint_node_set_static_name (right_node, "MetaShapedTexture (right)");
++
++      clutter_paint_node_add_child (root_node, left_node);
++      clutter_paint_node_add_child (root_node, right_node);
++
++      do_paint_content (stex, left_node, paint_context,
++                        texture_left, &alloc, opacity);
++      do_paint_content (stex, right_node, paint_context,
++                        texture_right, &alloc, opacity);
++    }
++  else
++    {
++      CoglTexture *texture;
++
++      texture = select_texture_for_paint (stex, paint_context,
++                                          COGL_STEREO_BOTH);
++      do_paint_content (stex, root_node, paint_context,
++                        texture, &alloc, opacity);
++    }
+ }
+ 
+ static gboolean
+@@ -946,6 +1029,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
+       stex->create_mipmaps = create_mipmaps;
+       base_texture = create_mipmaps ? stex->texture : NULL;
+       meta_texture_tower_set_base_texture (stex->paint_tower, base_texture);
++
++      if (stex->paint_tower_right)
++        {
++          base_texture = create_mipmaps ? stex->texture_right : NULL;
++          meta_texture_tower_set_base_texture (stex->paint_tower_right, base_texture);
++        }
+     }
+ }
+ 
+@@ -1079,6 +1168,14 @@ meta_shaped_texture_update_area (MetaShapedTexture     *stex,
+                                   y,
+                                   width,
+                                   height);
++  if (stex->paint_tower_right)
++    {
++      meta_texture_tower_update_area (stex->paint_tower_right,
++                                      x,
++                                      y,
++                                      width,
++                                      height);
++    }
+ 
+   stex->prev_invalidation = stex->last_invalidation;
+   stex->last_invalidation = g_get_monotonic_time ();
+@@ -1098,20 +1195,21 @@ meta_shaped_texture_update_area (MetaShapedTexture     *stex,
+ }
+ 
+ /**
+- * meta_shaped_texture_set_texture:
++ * meta_shaped_texture_set_textures:
+  * @stex: The #MetaShapedTexture
+  * @pixmap: The #CoglTexture to display
+  */
+ void
+-meta_shaped_texture_set_texture (MetaShapedTexture *stex,
+-                                 CoglTexture       *texture)
++meta_shaped_texture_set_textures (MetaShapedTexture *stex,
++                                  CoglTexture       *texture,
++                                  CoglTexture       *texture_right)
+ {
+   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
+ 
+-  if (stex->texture == texture)
++  if (stex->texture == texture && stex->texture_right == texture_right)
+     return;
+ 
+-  set_cogl_texture (stex, texture);
++  set_cogl_textures (stex, texture, texture_right);
+ }
+ 
+ /**
+diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
+index a182ad8513..1ddc83db2b 100644
+--- a/src/compositor/meta-surface-actor-wayland.c
++++ b/src/compositor/meta-surface-actor-wayland.c
+@@ -148,7 +148,7 @@ meta_surface_actor_wayland_dispose (GObject *object)
+ 
+   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+   if (stex)
+-    meta_shaped_texture_set_texture (stex, NULL);
++    meta_shaped_texture_set_textures (stex, NULL, NULL);
+ 
+   if (self->surface)
+     {
+diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c
+index 41ae2dffbc..c7c3d08c36 100644
+--- a/src/compositor/meta-surface-actor-x11.c
++++ b/src/compositor/meta-surface-actor-x11.c
+@@ -30,6 +30,7 @@
+ #include <X11/extensions/Xcomposite.h>
+ 
+ #include "cogl/winsys/cogl-texture-pixmap-x11.h"
++#include "compositor/meta-compositor-x11.h"
+ #include "compositor/meta-cullable.h"
+ #include "compositor/meta-shaped-texture-private.h"
+ #include "compositor/meta-window-actor-private.h"
+@@ -47,6 +48,7 @@ struct _MetaSurfaceActorX11
+   MetaDisplay *display;
+ 
+   CoglTexture *texture;
++  CoglTexture *texture_right;
+   Pixmap pixmap;
+   Damage damage;
+ 
+@@ -62,6 +64,8 @@ struct _MetaSurfaceActorX11
+   guint size_changed : 1;
+ 
+   guint unredirected   : 1;
++
++  guint stereo : 1;
+ };
+ 
+ G_DEFINE_TYPE (MetaSurfaceActorX11,
+@@ -101,7 +105,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
+    * you are supposed to be able to free a GLXPixmap after freeing the underlying
+    * pixmap, but it certainly doesn't work with current DRI/Mesa
+    */
+-  meta_shaped_texture_set_texture (stex, NULL);
++  meta_shaped_texture_set_textures (stex, NULL, NULL);
+   cogl_flush ();
+ 
+   meta_x11_error_trap_push (display->x11_display);
+@@ -110,6 +114,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
+   meta_x11_error_trap_pop (display->x11_display);
+ 
+   g_clear_pointer (&self->texture, cogl_object_unref);
++  g_clear_pointer (&self->texture_right, cogl_object_unref);
+ }
+ 
+ static void
+@@ -119,23 +124,37 @@ set_pixmap (MetaSurfaceActorX11 *self,
+   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+   GError *error = NULL;
+-  CoglTexture *texture;
++  CoglTexturePixmapX11 *texture;
++  CoglTexturePixmapX11 *texture_right;
+ 
+   g_assert (self->pixmap == None);
+   self->pixmap = pixmap;
+ 
+-  texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error));
++  if (self->stereo)
++    texture = cogl_texture_pixmap_x11_new_left (ctx, pixmap, FALSE, &error);
++  else
++    texture = cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, &error);
++
++  if (self->stereo)
++    texture_right = cogl_texture_pixmap_x11_new_right (texture);
++  else
++    texture_right = NULL;
+ 
+   if (error != NULL)
+     {
+       g_warning ("Failed to allocate stex texture: %s", error->message);
+       g_error_free (error);
+     }
+-  else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
++  else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture)))
+     g_warning ("NOTE: Not using GLX TFP!");
+ 
+-  self->texture = texture;
+-  meta_shaped_texture_set_texture (stex, texture);
++  self->texture = COGL_TEXTURE (texture);
++  if (self->stereo)
++    self->texture_right = COGL_TEXTURE (texture_right);
++
++  meta_shaped_texture_set_textures (stex,
++                                    COGL_TEXTURE (texture),
++                                    COGL_TEXTURE (texture_right));;
+ }
+ 
+ static void
+@@ -372,8 +391,8 @@ reset_texture (MetaSurfaceActorX11 *self)
+   /* Setting the texture to NULL will cause all the FBO's cached by the
+    * shaped texture's MetaTextureTower to be discarded and recreated.
+    */
+-  meta_shaped_texture_set_texture (stex, NULL);
+-  meta_shaped_texture_set_texture (stex, self->texture);
++  meta_shaped_texture_set_textures (stex, NULL, NULL);
++  meta_shaped_texture_set_textures (stex, self->texture, self->texture_right);
+ }
+ 
+ MetaSurfaceActor *
+@@ -381,12 +400,18 @@ meta_surface_actor_x11_new (MetaWindow *window)
+ {
+   MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
+   MetaDisplay *display = meta_window_get_display (window);
++  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (display->compositor);
++  Window xwindow;
+ 
+   g_assert (!meta_is_wayland_compositor ());
+ 
+   self->window = window;
+   self->display = display;
+ 
++  xwindow = meta_window_x11_get_toplevel_xwindow (window);
++  self->stereo = meta_compositor_x11_window_is_stereo (compositor_x11, xwindow);
++  meta_compositor_x11_select_stereo_notify (compositor_x11, xwindow);
++
+   g_signal_connect_object (self->display, "gl-video-memory-purged",
+                            G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED);
+ 
+@@ -420,3 +445,17 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
+   self->last_height = height;
+   meta_shaped_texture_set_fallback_size (stex, width, height);
+ }
++
++void
++meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self,
++                                      gboolean             stereo_tree)
++{
++  self->stereo = stereo_tree != FALSE;
++  detach_pixmap (self);
++}
++
++gboolean
++meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self)
++{
++  return self->stereo;
++}
+diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h
+index 0a8517236a..369f631ae0 100644
+--- a/src/compositor/meta-surface-actor-x11.h
++++ b/src/compositor/meta-surface-actor-x11.h
+@@ -57,6 +57,11 @@ gboolean meta_surface_actor_x11_is_visible (MetaSurfaceActorX11 *self);
+ 
+ void meta_surface_actor_x11_handle_updates (MetaSurfaceActorX11 *self);
+ 
++void meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self,
++                                           gboolean             stereo_tree);
++
++gboolean meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self);
++
+ G_END_DECLS
+ 
+ #endif /* __META_SURFACE_ACTOR_X11_H__ */
+diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
+index 64741e4167..d498879902 100644
+--- a/src/compositor/meta-window-actor-private.h
++++ b/src/compositor/meta-window-actor-private.h
+@@ -99,4 +99,9 @@ void meta_window_actor_update_regions (MetaWindowActor *self);
+ 
+ gboolean meta_window_actor_can_freeze_commits (MetaWindowActor *self);
+ 
++void meta_window_actor_stereo_notify (MetaWindowActor *actor,
++                                      gboolean         stereo_tree);
++
++gboolean meta_window_actor_is_stereo (MetaWindowActor *actor);
++
+ #endif /* META_WINDOW_ACTOR_PRIVATE_H */
+diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
+index d4fc9a43a0..56c85e1788 100644
+--- a/src/compositor/meta-window-actor.c
++++ b/src/compositor/meta-window-actor.c
+@@ -1557,3 +1557,25 @@ out:
+   clutter_actor_uninhibit_culling (actor);
+   return surface;
+ }
++
++void
++meta_window_actor_stereo_notify (MetaWindowActor *self,
++                                 gboolean         stereo_tree)
++{
++  MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self);
++
++  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
++    meta_surface_actor_x11_stereo_notify (META_SURFACE_ACTOR_X11 (priv->surface),
++                                          stereo_tree);
++}
++
++gboolean
++meta_window_actor_is_stereo (MetaWindowActor *self)
++{
++  MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self);
++
++  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
++    return meta_surface_actor_x11_is_stereo (META_SURFACE_ACTOR_X11 (priv->surface));
++  else
++    return FALSE;
++}
+diff --git a/src/core/main.c b/src/core/main.c
+index 6dabcfe73e..a07dda9ecc 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -88,6 +88,7 @@
+ #include "meta/meta-backend.h"
+ #include "meta/meta-x11-errors.h"
+ #include "meta/prefs.h"
++#include "stereo.h"
+ #include "ui/ui.h"
+ #include "x11/session.h"
+ 
+@@ -848,6 +849,9 @@ meta_init (void)
+   if (!meta_is_wayland_compositor ())
+     meta_select_display (opt_display_name);
+ 
++  if (!meta_is_wayland_compositor ())
++    meta_stereo_init ();
++
+   meta_init_backend (backend_gtype, n_properties, prop_names, prop_values);
+ 
+   for (i = 0; i < n_properties; i++)
+diff --git a/src/core/stereo.c b/src/core/stereo.c
+new file mode 100644
+index 0000000000..817056527f
+--- /dev/null
++++ b/src/core/stereo.c
+@@ -0,0 +1,154 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * SECTION:stereo
++ * @short_description: Keep track of whether we are a stereo compositor
++ *
++ * With GLX, we need to use a different GL context for stereo and
++ * non-stereo support. Support for multiple GL contexts is unfinished
++ * in Cogl and entirely lacking in Clutter, so it's by far easier
++ * to just restart Mutter when we detect a stereo window.
++ *
++ * A property _MUTTER_ENABLE_STEREO is maintained on the root window
++ * to know whether we should initialize clutter for stereo or not.
++ * When the presence or absence of stereo windows mismatches the
++ * stereo-enabled state for a sufficiently long period of time,
++ * we restart Mutter.
++ */
++
++#include <config.h>
++
++#include <clutter/x11/clutter-x11.h>
++#include <gio/gunixinputstream.h>
++#include <X11/Xatom.h>
++
++#include "display-private.h"
++#include <meta/main.h>
++#include <meta/meta-x11-display.h>
++#include <meta/util.h>
++#include "stereo.h"
++#include "ui/ui.h"
++#include "util-private.h"
++
++static guint stereo_switch_id = 0;
++static gboolean stereo_enabled = FALSE;
++/* -1 so the first time meta_stereo_set_have_stereo_windows() is called
++ * we avoid the short-circuit and set up a timeout to restart
++ * if necessary */
++static gboolean stereo_have_windows = (gboolean)-1;
++static gboolean stereo_restart = FALSE;
++
++#define STEREO_ENABLE_WAIT 1000
++#define STEREO_DISABLE_WAIT 5000
++
++void
++meta_stereo_init (void)
++{
++  Display *xdisplay;
++  Window root;
++  Atom atom_enable_stereo;
++  Atom type;
++  int format;
++  unsigned long n_items, bytes_after;
++  guchar *data;
++
++  xdisplay = XOpenDisplay (NULL);
++  if (xdisplay == NULL)
++    meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
++
++  root = DefaultRootWindow (xdisplay);
++  atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
++
++  XGetWindowProperty (xdisplay, root, atom_enable_stereo,
++                      0, 1, False, XA_INTEGER,
++                      &type, &format, &n_items, &bytes_after, &data);
++  if (type == XA_INTEGER)
++    {
++      if (format == 32 && n_items == 1 && bytes_after == 0)
++        {
++          stereo_enabled = *(long *)data;
++        }
++      else
++        {
++          meta_warning ("Bad value for _MUTTER_ENABLE_STEREO property\n");
++        }
++
++      XFree (data);
++    }
++  else if (type != None)
++    {
++      meta_warning ("Bad type for _MUTTER_ENABLE_STEREO property\n");
++    }
++
++  meta_verbose ("On startup, _MUTTER_ENABLE_STEREO=%s",
++                stereo_enabled ? "yes" : "no");
++  clutter_x11_set_use_stereo_stage (stereo_enabled);
++  XCloseDisplay (xdisplay);
++}
++
++static gboolean
++meta_stereo_switch (gpointer data)
++{
++  stereo_switch_id = 0;
++  stereo_restart = TRUE;
++
++  meta_restart (stereo_have_windows ?
++                _("Enabling stereo...") :
++                _("Disabling stereo..."));
++
++  return FALSE;
++}
++
++void
++meta_stereo_set_have_stereo_windows (gboolean have_windows)
++{
++  have_windows = have_windows != FALSE;
++
++  if (!stereo_restart && have_windows != stereo_have_windows)
++    {
++      MetaDisplay *display = meta_get_display ();
++      Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
++      Window root = DefaultRootWindow (xdisplay);
++      Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
++      long value;
++
++      stereo_have_windows = have_windows;
++
++      if (stereo_have_windows)
++        meta_verbose ("Detected stereo windows\n");
++      else
++        meta_verbose ("No stereo windows detected\n");
++
++      value = stereo_have_windows;
++      XChangeProperty (xdisplay, root,
++                       atom_enable_stereo, XA_INTEGER, 32,
++                       PropModeReplace, (guchar *)&value, 1);
++
++      if (stereo_switch_id != 0)
++        {
++          g_source_remove (stereo_switch_id);
++          stereo_switch_id = 0;
++        }
++
++      if (stereo_have_windows != stereo_enabled)
++        stereo_switch_id = g_timeout_add (stereo_have_windows ? STEREO_ENABLE_WAIT : STEREO_DISABLE_WAIT,
++                                          meta_stereo_switch, NULL);
++    }
++}
+diff --git a/src/core/stereo.h b/src/core/stereo.h
+new file mode 100644
+index 0000000000..ccd1d702a1
+--- /dev/null
++++ b/src/core/stereo.h
+@@ -0,0 +1,28 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef META_STEREO_H
++#define META_STEREO_H
++
++void     meta_stereo_init                    (void);
++void     meta_stereo_set_have_stereo_windows (gboolean have_windows);
++gboolean meta_stereo_is_restart              (void);
++void     meta_stereo_finish_restart          (void);
++
++#endif
+diff --git a/src/meson.build b/src/meson.build
+index 284bdf5220..c56438fbbe 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -394,6 +394,8 @@ mutter_sources = [
+   'core/stack.h',
+   'core/stack-tracker.c',
+   'core/stack-tracker.h',
++  'core/stereo.c',
++  'core/stereo.h',
+   'core/startup-notification.c',
+   'core/startup-notification-private.h',
+   'core/util.c',
+diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
+index 797795f861..d8d1f3ce16 100644
+--- a/src/wayland/meta-wayland-actor-surface.c
++++ b/src/wayland/meta-wayland-actor-surface.c
+@@ -193,7 +193,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
+       snippet = meta_wayland_buffer_create_snippet (buffer);
+       is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer);
+ 
+-      meta_shaped_texture_set_texture (stex, surface->texture);
++      meta_shaped_texture_set_textures (stex, surface->texture, NULL);
+       meta_shaped_texture_set_snippet (stex, snippet);
+       meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
+       meta_shaped_texture_set_buffer_scale (stex, surface->scale);
+@@ -201,7 +201,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
+     }
+   else
+     {
+-      meta_shaped_texture_set_texture (stex, NULL);
++      meta_shaped_texture_set_textures (stex, NULL, NULL);
+     }
+ 
+   surface_rect = (cairo_rectangle_int_t) {
+-- 
+2.31.1
+
+
+From 36517cd245584c5bcd3b730efaf6c3d2e7c9472d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 2 Jun 2021 16:55:45 +0200
+Subject: [PATCH 2/2] compositor: Only check for stereo when using GLX
+
+If EGL Xlib is used, we'll get bogus return value and crash.
+---
+ src/compositor/meta-compositor-x11.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c
+index afbe3f57e2..4345f38b6f 100644
+--- a/src/compositor/meta-compositor-x11.c
++++ b/src/compositor/meta-compositor-x11.c
+@@ -153,9 +153,17 @@ meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+ static gboolean
+ display_has_stereo_tree_ext (MetaX11Display *x11_display)
+ {
++  MetaBackend *backend = meta_get_backend ();
++  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
++  CoglContext *cogl_context =
++    clutter_backend_get_cogl_context (clutter_backend);
++  CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
+   Display     *xdisplay = x11_display->xdisplay;
+   const char  *extensions_string;
+ 
++  if (cogl_renderer_get_winsys_id (cogl_renderer) != COGL_WINSYS_ID_GLX)
++    return FALSE;
++
+   static const char * (*query_extensions_string) (Display *display,
+                                                   int      screen);
+ 
+-- 
+2.31.1
+
diff --git a/SOURCES/legacy-x11-input-configuration.patch b/SOURCES/legacy-x11-input-configuration.patch
new file mode 100644
index 0000000..597e0d7
--- /dev/null
+++ b/SOURCES/legacy-x11-input-configuration.patch
@@ -0,0 +1,819 @@
+From 705818340dec181335b48ab73d6411e639daaeae Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Tue, 1 Jun 2021 11:44:20 +0200
+Subject: [PATCH 1/6] backends/x11: Support synaptics configuration
+
+The code is taken mostly as-is from g-s-d, so we can drag the
+dead horse a bit longer.
+---
+ src/backends/x11/meta-input-settings-x11.c | 275 +++++++++++++++++++++
+ 1 file changed, 275 insertions(+)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 96390285a6..0631fd2fee 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -26,6 +26,7 @@
+ #include "backends/x11/meta-input-settings-x11.h"
+ 
+ #include <gdk/gdkx.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <X11/Xatom.h>
+ #include <X11/extensions/XInput2.h>
+@@ -165,6 +166,184 @@ change_property (ClutterInputDevice *device,
+   meta_XFree (data_ret);
+ }
+ 
++static gboolean
++is_device_synaptics (ClutterInputDevice *device)
++{
++  guchar *has_setting;
++
++  /* We just need looking for a synaptics-specific property */
++  has_setting = get_property (device, "Synaptics Off", XA_INTEGER, 8, 1);
++  if (!has_setting)
++    return FALSE;
++
++  meta_XFree (has_setting);
++  return TRUE;
++}
++
++static void
++change_synaptics_tap_left_handed (ClutterInputDevice *device,
++                                  gboolean            tap_enabled,
++                                  gboolean            left_handed)
++{
++  MetaDisplay *display = meta_get_display ();
++  MetaX11Display *x11_display = display ? display->x11_display : NULL;
++  MetaBackend *backend = meta_get_backend ();
++  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
++  int device_id;
++  XDevice *xdevice;
++  guchar *tap_action, *buttons;
++  guint buttons_capacity = 16, n_buttons;
++
++  device_id = meta_input_device_x11_get_device_id (device);
++  xdevice = XOpenDevice (xdisplay, device_id);
++  if (!xdevice)
++    return;
++
++  tap_action = get_property (device, "Synaptics Tap Action",
++                             XA_INTEGER, 8, 7);
++  if (!tap_action)
++    goto out;
++
++  tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0;
++  tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0;
++  tap_action[6] = tap_enabled ? 2 : 0;
++
++  change_property (device, "Synaptics Tap Action",
++                   XA_INTEGER, 8, tap_action, 7);
++  meta_XFree (tap_action);
++
++  if (x11_display)
++    meta_x11_error_trap_push (x11_display);
++  buttons = g_new (guchar, buttons_capacity);
++  n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice,
++                                       buttons, buttons_capacity);
++
++  while (n_buttons > buttons_capacity)
++    {
++      buttons_capacity = n_buttons;
++      buttons = (guchar *) g_realloc (buttons,
++                                      buttons_capacity * sizeof (guchar));
++
++      n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice,
++                                           buttons, buttons_capacity);
++    }
++
++  buttons[0] = left_handed ? 3 : 1;
++  buttons[2] = left_handed ? 1 : 3;
++  XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons);
++  g_free (buttons);
++
++  if (x11_display && meta_x11_error_trap_pop_with_return (x11_display))
++    {
++      g_warning ("Could not set synaptics touchpad left-handed for %s",
++                 clutter_input_device_get_device_name (device));
++    }
++
++ out:
++  XCloseDevice (xdisplay, xdevice);
++}
++
++static void
++change_synaptics_speed (ClutterInputDevice *device,
++                        gdouble             speed)
++{
++  MetaDisplay *display = meta_get_display ();
++  MetaX11Display *x11_display = display ? display->x11_display : NULL;
++  MetaBackend *backend = meta_get_backend ();
++  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
++  int device_id;
++  XDevice *xdevice;
++  XPtrFeedbackControl feedback;
++  XFeedbackState *states, *state;
++  int i, num_feedbacks, motion_threshold, numerator, denominator;
++  gfloat motion_acceleration;
++
++  device_id = meta_input_device_x11_get_device_id (device);
++  xdevice = XOpenDevice (xdisplay, device_id);
++  if (!xdevice)
++    return;
++  /* Get the list of feedbacks for the device */
++  states = XGetFeedbackControl (xdisplay, xdevice, &num_feedbacks);
++  if (!states)
++    return;
++
++  /* Calculate acceleration and threshold */
++  motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */
++  motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10);
++
++  if (motion_acceleration >= 1.0)
++    {
++      /* we want to get the acceleration, with a resolution of 0.5
++       */
++      if ((motion_acceleration - floor (motion_acceleration)) < 0.25)
++        {
++          numerator = floor (motion_acceleration);
++          denominator = 1;
++        }
++      else if ((motion_acceleration - floor (motion_acceleration)) < 0.5)
++        {
++          numerator = ceil (2.0 * motion_acceleration);
++          denominator = 2;
++        }
++      else if ((motion_acceleration - floor (motion_acceleration)) < 0.75)
++        {
++          numerator = floor (2.0 *motion_acceleration);
++          denominator = 2;
++        }
++      else
++        {
++          numerator = ceil (motion_acceleration);
++          denominator = 1;
++        }
++    }
++  else if (motion_acceleration < 1.0 && motion_acceleration > 0)
++    {
++      /* This we do to 1/10ths */
++      numerator = floor (motion_acceleration * 10) + 1;
++      denominator= 10;
++    }
++  else
++    {
++      numerator = -1;
++      denominator = -1;
++    }
++
++  if (x11_display)
++    meta_x11_error_trap_push (x11_display);
++
++  state = (XFeedbackState *) states;
++
++  for (i = 0; i < num_feedbacks; i++)
++    {
++      if (state->class == PtrFeedbackClass)
++        {
++          /* And tell the device */
++          feedback.class      = PtrFeedbackClass;
++          feedback.length     = sizeof (XPtrFeedbackControl);
++          feedback.id         = state->id;
++          feedback.threshold  = motion_threshold;
++          feedback.accelNum   = numerator;
++          feedback.accelDenom = denominator;
++
++          XChangeFeedbackControl (xdisplay, xdevice,
++                                  DvAccelNum | DvAccelDenom | DvThreshold,
++                                  (XFeedbackControl *) &feedback);
++          break;
++        }
++
++      state = (XFeedbackState *) ((char *) state + state->length);
++    }
++
++  if (x11_display && meta_x11_error_trap_pop_with_return (x11_display))
++    {
++      g_warning ("Could not set synaptics touchpad acceleration for %s",
++                 clutter_input_device_get_device_name (device));
++    }
++
++  XFreeFeedbackList (states);
++  XCloseDevice (xdisplay, xdevice);
++}
++
+ static void
+ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
+                                          ClutterInputDevice       *device,
+@@ -173,6 +352,13 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
+   guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
+   guchar *available;
+ 
++  if (is_device_synaptics (device))
++    {
++      values[0] = mode != G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED;
++      change_property (device, "Synaptics Off", XA_INTEGER, 8, &values, 1);
++      return;
++    }
++
+   available = get_property (device, "libinput Send Events Modes Available",
+                             XA_INTEGER, 8, 2);
+   if (!available)
+@@ -225,6 +411,12 @@ meta_input_settings_x11_set_speed (MetaInputSettings  *settings,
+   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+   gfloat value = speed;
+ 
++  if (is_device_synaptics (device))
++    {
++      change_synaptics_speed (device, speed);
++      return;
++    }
++
+   change_property (device, "libinput Accel Speed",
+                    XInternAtom (xdisplay, "FLOAT", False),
+                    32, &value, 1);
+@@ -251,6 +443,19 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings,
+   else
+     {
+       value = enabled ? 1 : 0;
++
++      if (is_device_synaptics (device))
++        {
++          GSettings *settings;
++
++          settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
++          change_synaptics_tap_left_handed (device,
++                                            g_settings_get_boolean (settings, "tap-to-click"),
++                                            enabled);
++          g_object_unref (settings);
++          return;
++        }
++
+       change_property (device, "libinput Left Handed Enabled",
+                        XA_INTEGER, 8, &value, 1);
+     }
+@@ -274,6 +479,20 @@ meta_input_settings_x11_set_tap_enabled (MetaInputSettings  *settings,
+ {
+   guchar value = (enabled) ? 1 : 0;
+ 
++  if (is_device_synaptics (device))
++    {
++      GDesktopTouchpadHandedness handedness;
++      GSettings *settings;
++
++      settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
++      handedness = g_settings_get_enum (settings, "left-handed");
++      g_object_unref (settings);
++
++      change_synaptics_tap_left_handed (device, enabled,
++                                        handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT);
++      return;
++    }
++
+   change_property (device, "libinput Tapping Enabled",
+                    XA_INTEGER, 8, &value, 1);
+ }
+@@ -307,6 +526,27 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings  *settings,
+ {
+   guchar value = (inverted) ? 1 : 0;
+ 
++  if (is_device_synaptics (device))
++    {
++      gint32 *scrolling_distance;
++
++      scrolling_distance = get_property (device, "Synaptics Scrolling Distance",
++                                         XA_INTEGER, 32, 2);
++      if (scrolling_distance)
++        {
++          scrolling_distance[0] = inverted ?
++            -abs (scrolling_distance[0]) : abs (scrolling_distance[0]);
++          scrolling_distance[1] = inverted ?
++            -abs (scrolling_distance[1]) : abs (scrolling_distance[1]);
++
++          change_property (device, "Synaptics Scrolling Distance",
++                           XA_INTEGER, 32, scrolling_distance, 2);
++          meta_XFree (scrolling_distance);
++        }
++
++      return;
++    }
++
+   change_property (device, "libinput Natural Scrolling Enabled",
+                    XA_INTEGER, 8, &value, 1);
+ }
+@@ -320,6 +560,41 @@ change_scroll_method (ClutterInputDevice           *device,
+   guchar *current = NULL;
+   guchar *available = NULL;
+ 
++  if (is_device_synaptics (device))
++    {
++      switch (method)
++        {
++        case SCROLL_METHOD_FIELD_EDGE:
++          current = get_property (device, "Synaptics Edge Scrolling",
++                                  XA_INTEGER, 8, 3);
++          if (current)
++            {
++              current[0] = enabled;
++              current[1] = enabled;
++              change_property (device, "Synaptics Edge Scrolling",
++                               XA_INTEGER, 8, current, 3);
++              meta_XFree (current);
++            }
++          break;
++        case SCROLL_METHOD_FIELD_2FG:
++          current = get_property (device, "Synaptics Two-Finger Scrolling",
++                                  XA_INTEGER, 8, 2);
++          if (current)
++            {
++              current[0] = enabled;
++              current[1] = enabled;
++              change_property (device, "Synaptics Two-Finger Scrolling",
++                               XA_INTEGER, 8, current, 2);
++              meta_XFree (current);
++            }
++          break;
++        default:
++          break;
++        }
++
++      return;
++    }
++
+   available = get_property (device, "libinput Scroll Methods Available",
+                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
+   if (!available || !available[method])
+-- 
+2.31.1
+
+
+From 50c4733acf56b3b67a2706d32f5c455cb51f9458 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Tue, 13 Feb 2018 11:44:40 +0100
+Subject: [PATCH 2/6] clutter: Extend touchpad device property check for
+ Synaptics
+
+So we reliably get CLUTTER_TOUCHPAD_DEVICE for those. The other heuristics
+to get the device type may fall short.
+---
+ src/backends/x11/meta-seat-x11.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
+index d43834bd7b..73938e22e0 100644
+--- a/src/backends/x11/meta-seat-x11.c
++++ b/src/backends/x11/meta-seat-x11.c
+@@ -246,7 +246,8 @@ is_touch_device (XIAnyClassInfo         **classes,
+ }
+ 
+ static gboolean
+-is_touchpad_device (XIDeviceInfo *info)
++query_exists_device_property (XIDeviceInfo *info,
++                              const char   *property)
+ {
+   gulong nitems, bytes_after;
+   uint32_t *data = NULL;
+@@ -254,7 +255,7 @@ is_touchpad_device (XIDeviceInfo *info)
+   Atom type;
+   Atom prop;
+ 
+-  prop = XInternAtom (clutter_x11_get_default_display (), "libinput Tapping Enabled", True);
++  prop = XInternAtom (clutter_x11_get_default_display (), property, True);
+   if (prop == None)
+     return FALSE;
+ 
+@@ -275,6 +276,18 @@ is_touchpad_device (XIDeviceInfo *info)
+   return TRUE;
+ }
+ 
++static gboolean
++is_touchpad_device (XIDeviceInfo *info)
++{
++  if (query_exists_device_property (info, "libinput Tapping Enabled"))
++    return TRUE;
++
++  if (query_exists_device_property (info, "Synaptics Off"))
++    return TRUE;
++
++  return FALSE;
++}
++
+ static gboolean
+ get_device_ids (XIDeviceInfo  *info,
+                 char         **vendor_id,
+-- 
+2.31.1
+
+
+From 307970305d11cdca1b97c53c85bda8b809ff4f0f Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 9 Oct 2017 18:39:52 +0200
+Subject: [PATCH 3/6] backends/x11: Add a synaptics check for two finger scroll
+ availability
+
+Commit "backends/x11: Support synaptics configuration" added support
+for synaptics two finger scrolling but didn't add the code to check
+that it is available resulting in the upper layer always assuming it
+isn't.
+---
+ src/backends/x11/meta-input-settings-x11.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 0631fd2fee..2ac080127c 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -638,6 +638,17 @@ meta_input_settings_x11_has_two_finger_scroll (MetaInputSettings  *settings,
+   guchar *available = NULL;
+   gboolean has_two_finger = TRUE;
+ 
++  if (is_device_synaptics (device))
++    {
++      available = get_property (device, "Synaptics Capabilities",
++                                XA_INTEGER, 8, 4);
++      if (!available || !available[3])
++          has_two_finger = FALSE;
++
++      meta_XFree (available);
++      return has_two_finger;
++    }
++
+   available = get_property (device, "libinput Scroll Methods Available",
+                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
+   if (!available || !available[SCROLL_METHOD_FIELD_2FG])
+-- 
+2.31.1
+
+
+From cba31f88ddbfb7355de1daa34397aba8e8607765 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 9 Oct 2017 18:55:56 +0200
+Subject: [PATCH 4/6] backends/x11: Add disable while typing support for
+ synaptics
+
+This is basically a copy of the old g-s-d mouse plugin code to manage
+syndaemon when the synaptics driver is being used.
+---
+ src/backends/x11/meta-input-settings-x11.c | 112 +++++++++++++++++++++
+ 1 file changed, 112 insertions(+)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 2ac080127c..2658b82172 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -35,6 +35,9 @@
+ #ifdef HAVE_LIBGUDEV
+ #include <gudev/gudev.h>
+ #endif
++#ifdef __linux
++#include <sys/prctl.h>
++#endif
+ 
+ #include "backends/x11/meta-backend-x11.h"
+ #include "backends/x11/meta-input-device-x11.h"
+@@ -46,6 +49,8 @@ typedef struct _MetaInputSettingsX11Private
+ #ifdef HAVE_LIBGUDEV
+   GUdevClient *udev_client;
+ #endif
++  gboolean syndaemon_spawned;
++  GPid syndaemon_pid;
+ } MetaInputSettingsX11Private;
+ 
+ G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettingsX11, meta_input_settings_x11,
+@@ -344,6 +349,107 @@ change_synaptics_speed (ClutterInputDevice *device,
+   XCloseDevice (xdisplay, xdevice);
+ }
+ 
++/* Ensure that syndaemon dies together with us, to avoid running several of
++ * them */
++static void
++setup_syndaemon (gpointer user_data)
++{
++#ifdef __linux
++  prctl (PR_SET_PDEATHSIG, SIGHUP);
++#endif
++}
++
++static gboolean
++have_program_in_path (const char *name)
++{
++  gchar *path;
++  gboolean result;
++
++  path = g_find_program_in_path (name);
++  result = (path != NULL);
++  g_free (path);
++  return result;
++}
++
++static void
++syndaemon_died (GPid     pid,
++                gint     status,
++                gpointer user_data)
++{
++  MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (user_data);
++  MetaInputSettingsX11Private *priv =
++    meta_input_settings_x11_get_instance_private (settings_x11);
++  GError *error = NULL;
++
++  if (!g_spawn_check_exit_status (status, &error))
++    {
++      if ((WIFSIGNALED (status) && WTERMSIG (status) != SIGHUP) ||
++          error->domain == G_SPAWN_EXIT_ERROR)
++        g_warning ("Syndaemon exited unexpectedly: %s", error->message);
++      g_error_free (error);
++    }
++
++  g_spawn_close_pid (pid);
++  priv->syndaemon_spawned = FALSE;
++}
++
++static void
++set_synaptics_disable_w_typing (MetaInputSettings *settings,
++                                gboolean           state)
++{
++  MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (settings);
++  MetaInputSettingsX11Private *priv =
++    meta_input_settings_x11_get_instance_private (settings_x11);
++
++  if (state)
++    {
++      GError *error = NULL;
++      GPtrArray *args;
++
++      if (priv->syndaemon_spawned)
++        return;
++
++      if (!have_program_in_path ("syndaemon"))
++        return;
++
++      args = g_ptr_array_new ();
++
++      g_ptr_array_add (args, (gpointer)"syndaemon");
++      g_ptr_array_add (args, (gpointer)"-i");
++      g_ptr_array_add (args, (gpointer)"1.0");
++      g_ptr_array_add (args, (gpointer)"-t");
++      g_ptr_array_add (args, (gpointer)"-K");
++      g_ptr_array_add (args, (gpointer)"-R");
++      g_ptr_array_add (args, NULL);
++
++      /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid
++       * double-forking, otherwise syndaemon will immediately get
++       * killed again through (PR_SET_PDEATHSIG when the intermediate
++       * process dies */
++      g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL,
++                     G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL,
++                     &priv->syndaemon_pid, &error);
++
++      priv->syndaemon_spawned = (error == NULL);
++      g_ptr_array_free (args, TRUE);
++
++      if (error)
++        {
++          g_warning ("Failed to launch syndaemon: %s", error->message);
++          g_error_free (error);
++        }
++      else
++        {
++          g_child_watch_add (priv->syndaemon_pid, syndaemon_died, settings);
++        }
++    }
++  else if (priv->syndaemon_spawned)
++    {
++      kill (priv->syndaemon_pid, SIGHUP);
++      priv->syndaemon_spawned = FALSE;
++    }
++}
++
+ static void
+ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
+                                          ClutterInputDevice       *device,
+@@ -468,6 +574,12 @@ meta_input_settings_x11_set_disable_while_typing (MetaInputSettings  *settings,
+ {
+   guchar value = (enabled) ? 1 : 0;
+ 
++  if (is_device_synaptics (device))
++    {
++      set_synaptics_disable_w_typing (settings, enabled);
++      return;
++    }
++
+   change_property (device, "libinput Disable While Typing Enabled",
+                    XA_INTEGER, 8, &value, 1);
+ }
+-- 
+2.31.1
+
+
+From 354d34263534d0c7a5c7f7169d8b4a3dba79491c Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Wed, 13 Jun 2018 13:48:24 +0200
+Subject: [PATCH 5/6] clutter: Only reset scroll axes on slave devices
+
+As a plus, unknown source device IDs will just warn instead of crash.
+---
+ src/backends/x11/meta-seat-x11.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
+index 73938e22e0..6d2c7d3740 100644
+--- a/src/backends/x11/meta-seat-x11.c
++++ b/src/backends/x11/meta-seat-x11.c
+@@ -2362,7 +2362,9 @@ meta_seat_x11_translate_event (MetaSeatX11  *seat,
+               seat->has_pointer_focus = FALSE;
+           }
+ 
+-        meta_input_device_x11_reset_scroll_info (source_device);
++        if (clutter_input_device_get_device_mode (source_device) ==
++            CLUTTER_INPUT_MODE_PHYSICAL)
++          meta_input_device_x11_reset_scroll_info (source_device);
+ 
+         clutter_event_set_device (event, device);
+         clutter_event_set_source_device (event, source_device);
+-- 
+2.31.1
+
+
+From b7f94b5dd09953d5a4c8aee1b79491d71f8c1e0e Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Tue, 10 Oct 2017 19:07:27 +0200
+Subject: [PATCH 6/6] backends/x11: Support plain old X device configuration
+
+We re-use part of the code added to support synaptics and add a few
+bits specific for xorg-x11-drv-evdev devices.
+---
+ src/backends/x11/meta-input-settings-x11.c | 98 +++++++++++++++++-----
+ 1 file changed, 75 insertions(+), 23 deletions(-)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 2658b82172..80bc33c6b5 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -185,10 +185,23 @@ is_device_synaptics (ClutterInputDevice *device)
+   return TRUE;
+ }
+ 
++static gboolean
++is_device_libinput (ClutterInputDevice *device)
++{
++  guchar *has_setting;
++
++  /* We just need looking for a synaptics-specific property */
++  has_setting = get_property (device, "libinput Send Events Modes Available", XA_INTEGER, 8, 2);
++  if (!has_setting)
++    return FALSE;
++
++  meta_XFree (has_setting);
++  return TRUE;
++}
++
+ static void
+-change_synaptics_tap_left_handed (ClutterInputDevice *device,
+-                                  gboolean            tap_enabled,
+-                                  gboolean            left_handed)
++change_x_device_left_handed (ClutterInputDevice *device,
++                             gboolean            left_handed)
+ {
+   MetaDisplay *display = meta_get_display ();
+   MetaX11Display *x11_display = display ? display->x11_display : NULL;
+@@ -196,7 +209,7 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device,
+   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+   int device_id;
+   XDevice *xdevice;
+-  guchar *tap_action, *buttons;
++  guchar *buttons;
+   guint buttons_capacity = 16, n_buttons;
+ 
+   device_id = meta_input_device_x11_get_device_id (device);
+@@ -204,19 +217,6 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device,
+   if (!xdevice)
+     return;
+ 
+-  tap_action = get_property (device, "Synaptics Tap Action",
+-                             XA_INTEGER, 8, 7);
+-  if (!tap_action)
+-    goto out;
+-
+-  tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0;
+-  tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0;
+-  tap_action[6] = tap_enabled ? 2 : 0;
+-
+-  change_property (device, "Synaptics Tap Action",
+-                   XA_INTEGER, 8, tap_action, 7);
+-  meta_XFree (tap_action);
+-
+   if (x11_display)
+     meta_x11_error_trap_push (x11_display);
+   buttons = g_new (guchar, buttons_capacity);
+@@ -240,17 +240,39 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device,
+ 
+   if (x11_display && meta_x11_error_trap_pop_with_return (x11_display))
+     {
+-      g_warning ("Could not set synaptics touchpad left-handed for %s",
++      g_warning ("Could not set left-handed for %s",
+                  clutter_input_device_get_device_name (device));
+     }
+ 
+- out:
+   XCloseDevice (xdisplay, xdevice);
+ }
+ 
+ static void
+-change_synaptics_speed (ClutterInputDevice *device,
+-                        gdouble             speed)
++change_synaptics_tap_left_handed (ClutterInputDevice *device,
++                                  gboolean            tap_enabled,
++                                  gboolean            left_handed)
++{
++  guchar *tap_action;
++
++  tap_action = get_property (device, "Synaptics Tap Action",
++                             XA_INTEGER, 8, 7);
++  if (!tap_action)
++    return;
++
++  tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0;
++  tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0;
++  tap_action[6] = tap_enabled ? 2 : 0;
++
++  change_property (device, "Synaptics Tap Action",
++                   XA_INTEGER, 8, tap_action, 7);
++  meta_XFree (tap_action);
++
++  change_x_device_left_handed (device, left_handed);
++}
++
++static void
++change_x_device_speed (ClutterInputDevice *device,
++                       gdouble             speed)
+ {
+   MetaDisplay *display = meta_get_display ();
+   MetaX11Display *x11_display = display ? display->x11_display : NULL;
+@@ -349,6 +371,23 @@ change_synaptics_speed (ClutterInputDevice *device,
+   XCloseDevice (xdisplay, xdevice);
+ }
+ 
++static void
++change_x_device_scroll_button (ClutterInputDevice *device,
++                               guint               button)
++{
++  guchar value;
++
++  value = button > 0 ? 1 : 0;
++  change_property (device, "Evdev Wheel Emulation",
++                   XA_INTEGER, 8, &value, 1);
++  if (button > 0)
++    {
++      value = button;
++      change_property (device, "Evdev Wheel Emulation Button",
++                       XA_INTEGER, 8, &value, 1);
++    }
++}
++
+ /* Ensure that syndaemon dies together with us, to avoid running several of
+  * them */
+ static void
+@@ -517,9 +556,10 @@ meta_input_settings_x11_set_speed (MetaInputSettings  *settings,
+   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+   gfloat value = speed;
+ 
+-  if (is_device_synaptics (device))
++  if (is_device_synaptics (device) ||
++      !is_device_libinput (device))
+     {
+-      change_synaptics_speed (device, speed);
++      change_x_device_speed (device, speed);
+       return;
+     }
+ 
+@@ -561,6 +601,11 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings,
+           g_object_unref (settings);
+           return;
+         }
++      else if (!is_device_libinput (device) && device_type != CLUTTER_PAD_DEVICE)
++        {
++          change_x_device_left_handed (device, enabled);
++          return;
++        }
+ 
+       change_property (device, "libinput Left Handed Enabled",
+                        XA_INTEGER, 8, &value, 1);
+@@ -778,7 +823,14 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings,
+ {
+   gchar lock = button_lock;
+ 
++  if (!is_device_libinput (device))
++    {
++      change_x_device_scroll_button (device, button);
++      return;
++    }
++
+   change_scroll_method (device, SCROLL_METHOD_FIELD_BUTTON, button != 0);
++
+   change_property (device, "libinput Button Scrolling Button",
+                    XA_CARDINAL, 32, &button, 1);
+   change_property (device, "libinput Button Scrolling Button Lock Enabled",
+-- 
+2.31.1
+
diff --git a/SOURCES/x11-monitor-configuration-patches.patch b/SOURCES/x11-monitor-configuration-patches.patch
new file mode 100644
index 0000000..d0402be
--- /dev/null
+++ b/SOURCES/x11-monitor-configuration-patches.patch
@@ -0,0 +1,1375 @@
+From 9c7c46384ec5e64fbfad84366c93ece52aabd26a Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Tue, 6 Oct 2015 21:16:18 +0200
+Subject: [PATCH 1/9] monitor-manager-xrandr: Work around spurious hotplugs on
+ Xvnc
+
+Xvnc turns its outputs off/on on every mode set which makes us believe
+there was an hotplug when there actually wasn't. Work around this by
+requiring new randr configuration timestamps to be ahead of the last
+set timestamp by at least 100 ms for us to consider them an actual
+hotplug.
+---
+ .../x11/meta-monitor-manager-xrandr.c         | 21 ++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 489a9b4241..1ddc2a7870 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -1100,6 +1100,20 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
+     g_quark_from_static_string ("-meta-monitor-xrandr-data");
+ }
+ 
++static gboolean
++is_xvnc (MetaMonitorManager *manager)
++{
++  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
++  MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
++  GList *l;
++
++  for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
++    if (g_str_has_prefix (meta_output_get_name (l->data), "VNC-"))
++      return TRUE;
++
++  return FALSE;
++}
++
+ gboolean
+ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
+ 					   XEvent                   *event)
+@@ -1110,6 +1124,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
+   XRRScreenResources *resources;
+   gboolean is_hotplug;
+   gboolean is_our_configuration;
++  unsigned int timestamp;
+ 
+   if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
+     return FALSE;
+@@ -1121,7 +1136,11 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
+   gpu_xrandr = META_GPU_XRANDR (gpu);
+   resources = meta_gpu_xrandr_get_resources (gpu_xrandr);
+ 
+-  is_hotplug = resources->timestamp < resources->configTimestamp;
++  timestamp = resources->timestamp;
++  if (is_xvnc (manager))
++    timestamp += 100;
++
++  is_hotplug = (timestamp < resources->configTimestamp);
+   is_our_configuration = (resources->timestamp ==
+                           manager_xrandr->last_xrandr_set_timestamp);
+   if (is_hotplug)
+-- 
+2.31.1
+
+
+From 17d9494cc08e833a6e896daa4f85a15b81df1554 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 4 Jun 2018 16:35:04 -0400
+Subject: [PATCH 2/9] monitor-manager-xrandr: Force an update when resuming
+ from suspend
+
+The stack below us isn't as reliable as we'd like and in some cases
+doesn't generate RRScreenChangeNotify events when e.g. resuming a
+laptop on a dock, meaning that we'd miss newly attached outputs.
+---
+ src/backends/meta-gpu.c                       |  7 ++
+ src/backends/meta-gpu.h                       |  4 +
+ src/backends/x11/meta-gpu-xrandr.c            | 26 ++++-
+ .../x11/meta-monitor-manager-xrandr.c         | 98 +++++++++++++++++--
+ 4 files changed, 125 insertions(+), 10 deletions(-)
+
+diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c
+index ce4353bf01..6b3086e747 100644
+--- a/src/backends/meta-gpu.c
++++ b/src/backends/meta-gpu.c
+@@ -66,6 +66,13 @@ meta_gpu_has_hotplug_mode_update (MetaGpu *gpu)
+   return FALSE;
+ }
+ 
++void
++meta_gpu_poll_hardware (MetaGpu *gpu)
++{
++  if (META_GPU_GET_CLASS (gpu)->poll_hardware)
++    META_GPU_GET_CLASS (gpu)->poll_hardware (gpu);
++}
++
+ gboolean
+ meta_gpu_read_current (MetaGpu  *gpu,
+                        GError  **error)
+diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h
+index 9d12f95a72..37b76bd0fa 100644
+--- a/src/backends/meta-gpu.h
++++ b/src/backends/meta-gpu.h
+@@ -36,8 +36,12 @@ struct _MetaGpuClass
+ 
+   gboolean (* read_current) (MetaGpu  *gpu,
+                              GError  **error);
++  void     (* poll_hardware) (MetaGpu *gpu);
+ };
+ 
++META_EXPORT_TEST
++void meta_gpu_poll_hardware (MetaGpu *gpu);
++
+ META_EXPORT_TEST
+ gboolean meta_gpu_read_current (MetaGpu  *gpu,
+                                 GError  **error);
+diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
+index bc3292d368..6a96e53979 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -46,6 +46,8 @@ struct _MetaGpuXrandr
+ 
+   int max_screen_width;
+   int max_screen_height;
++
++  gboolean need_hardware_poll;
+ };
+ 
+ G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU)
+@@ -86,6 +88,14 @@ get_xmode_name (XRRModeInfo *xmode)
+   return g_strdup_printf ("%dx%d", width, height);
+ }
+ 
++static void
++meta_gpu_xrandr_poll_hardware (MetaGpu *gpu)
++{
++  MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
++
++  gpu_xrandr->need_hardware_poll = TRUE;
++}
++
+ static gboolean
+ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+                               GError  **error)
+@@ -123,8 +133,18 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+   monitor_manager->screen_width = WidthOfScreen (screen);
+   monitor_manager->screen_height = HeightOfScreen (screen);
+ 
+-  resources = XRRGetScreenResourcesCurrent (xdisplay,
+-                                            DefaultRootWindow (xdisplay));
++  if (gpu_xrandr->need_hardware_poll)
++    {
++      resources = XRRGetScreenResources (xdisplay,
++                                         DefaultRootWindow (xdisplay));
++      gpu_xrandr->need_hardware_poll = FALSE;
++    }
++  else
++    {
++      resources = XRRGetScreenResourcesCurrent (xdisplay,
++                                                DefaultRootWindow (xdisplay));
++    }
++
+   if (!resources)
+     {
+       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+@@ -263,6 +283,7 @@ meta_gpu_xrandr_finalize (GObject *object)
+ static void
+ meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr)
+ {
++  gpu_xrandr->need_hardware_poll = TRUE;
+ }
+ 
+ static void
+@@ -274,4 +295,5 @@ meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass)
+   object_class->finalize = meta_gpu_xrandr_finalize;
+ 
+   gpu_class->read_current = meta_gpu_xrandr_read_current;
++  gpu_class->poll_hardware = meta_gpu_xrandr_poll_hardware;
+ }
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 1ddc2a7870..61e13f459d 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -72,6 +72,10 @@ struct _MetaMonitorManagerXrandr
+   Display *xdisplay;
+   int rr_event_base;
+   int rr_error_base;
++
++  guint logind_watch_id;
++  guint logind_signal_sub_id;
++
+   gboolean has_randr15;
+ 
+   xcb_timestamp_t last_xrandr_set_timestamp;
+@@ -96,6 +100,8 @@ typedef struct _MetaMonitorXrandrData
+ 
+ GQuark quark_meta_monitor_xrandr_data;
+ 
++static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr);
++
+ Display *
+ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr)
+ {
+@@ -1009,6 +1015,64 @@ meta_monitor_manager_xrandr_set_output_ctm (MetaOutput          *output,
+   meta_output_xrandr_set_ctm (META_OUTPUT_XRANDR (output), ctm);
+ }
+ 
++static void
++logind_signal_handler (GDBusConnection *connection,
++                       const gchar     *sender_name,
++                       const gchar     *object_path,
++                       const gchar     *interface_name,
++                       const gchar     *signal_name,
++                       GVariant        *parameters,
++                       gpointer         user_data)
++{
++  MetaMonitorManagerXrandr *manager_xrandr = user_data;
++  gboolean suspending;
++
++  if (!g_str_equal (signal_name, "PrepareForSleep"))
++    return;
++
++  g_variant_get (parameters, "(b)", &suspending);
++  if (!suspending)
++    {
++      MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
++
++      meta_gpu_poll_hardware (gpu);
++      meta_monitor_manager_xrandr_update (manager_xrandr);
++    }
++}
++
++static void
++logind_appeared (GDBusConnection *connection,
++                 const gchar     *name,
++                 const gchar     *name_owner,
++                 gpointer         user_data)
++{
++  MetaMonitorManagerXrandr *manager_xrandr = user_data;
++
++  manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection,
++                                                                             "org.freedesktop.login1",
++                                                                             "org.freedesktop.login1.Manager",
++                                                                             "PrepareForSleep",
++                                                                             "/org/freedesktop/login1",
++                                                                             NULL,
++                                                                             G_DBUS_SIGNAL_FLAGS_NONE,
++                                                                             logind_signal_handler,
++                                                                             manager_xrandr,
++                                                                             NULL);
++}
++
++static void
++logind_vanished (GDBusConnection *connection,
++                 const gchar     *name,
++                 gpointer         user_data)
++{
++  MetaMonitorManagerXrandr *manager_xrandr = user_data;
++
++  if (connection && manager_xrandr->logind_signal_sub_id > 0)
++    g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id);
++
++  manager_xrandr->logind_signal_sub_id = 0;
++}
++
+ static void
+ meta_monitor_manager_xrandr_constructed (GObject *object)
+ {
+@@ -1061,12 +1125,23 @@ meta_monitor_manager_xrandr_finalize (GObject *object)
+   g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
+   g_free (manager_xrandr->supported_scales);
+ 
++  if (manager_xrandr->logind_watch_id > 0)
++    g_bus_unwatch_name (manager_xrandr->logind_watch_id);
++  manager_xrandr->logind_watch_id = 0;
++
+   G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
+ }
+ 
+ static void
+ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
+ {
++  manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
++                                                      "org.freedesktop.login1",
++                                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
++                                                      logind_appeared,
++                                                      logind_vanished,
++                                                      manager_xrandr,
++                                                      NULL);
+ }
+ 
+ static void
+@@ -1114,9 +1189,8 @@ is_xvnc (MetaMonitorManager *manager)
+   return FALSE;
+ }
+ 
+-gboolean
+-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
+-					   XEvent                   *event)
++static void
++meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
+ {
+   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
+   MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
+@@ -1126,11 +1200,6 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
+   gboolean is_our_configuration;
+   unsigned int timestamp;
+ 
+-  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
+-    return FALSE;
+-
+-  XRRUpdateConfiguration (event);
+-
+   meta_monitor_manager_read_current_state (manager);
+ 
+   gpu_xrandr = META_GPU_XRANDR (gpu);
+@@ -1165,6 +1234,19 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
+ 
+       meta_monitor_manager_xrandr_rebuild_derived (manager, config);
+     }
++}
++
++gboolean
++meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
++					   XEvent                   *event)
++{
++
++  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
++    return FALSE;
++
++  XRRUpdateConfiguration (event);
++
++  meta_monitor_manager_xrandr_update (manager_xrandr);
+ 
+   return TRUE;
+ }
+-- 
+2.31.1
+
+
+From 7a04949b978ebe96cd088d7bd255fd3f52c7c355 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 24 Feb 2020 16:09:59 +0100
+Subject: [PATCH 3/9] Revert "MetaMonitorManager: ignore hotplug_mode_update at
+ startup"
+
+This reverts commit 183f4b0c13f3dc9565bf5f693f2e5d61ca0199c9.
+---
+ src/backends/meta-monitor-manager.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
+index a75da9329e..c291ddb5d3 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -609,8 +609,7 @@ meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
+ static gboolean
+ should_use_stored_config (MetaMonitorManager *manager)
+ {
+-  return (manager->in_init ||
+-          !meta_monitor_manager_has_hotplug_mode_update (manager));
++  return !meta_monitor_manager_has_hotplug_mode_update (manager);
+ }
+ 
+ MetaMonitorsConfig *
+-- 
+2.31.1
+
+
+From babcf2a6d09136bcf1bf2dc958046aaa0334b85e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Thu, 28 Jan 2016 15:26:33 +0100
+Subject: [PATCH 4/9] monitor-manager: Consider external layout before default
+ linear config
+
+In case of no existing configuration, we use a default layout of
+aligning attached displays horizontally. This sidesteps any layout
+configuration that is done externally, for instance via xorg.conf,
+which is not desirable. Instead, base the initial configuration on
+the existing layout if it passes some sanity checks before falling
+back to the default linear config.
+---
+ src/backends/meta-monitor-config-manager.c | 86 ++++++++++++++++++++++
+ src/backends/meta-monitor-config-manager.h |  2 +
+ src/backends/meta-monitor-manager.c        | 19 +++++
+ 3 files changed, 107 insertions(+)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index 0253e072ff..2f6cc3856f 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -739,6 +739,92 @@ create_preferred_logical_monitor_config (MetaMonitorManager          *monitor_ma
+   return logical_monitor_config;
+ }
+ 
++static MetaLogicalMonitorConfig *
++create_logical_monitor_config_from_output (MetaMonitorManager           *monitor_manager,
++                                           MetaMonitor                  *monitor,
++                                           MetaLogicalMonitorConfig     *primary_logical_monitor_config,
++                                           MetaLogicalMonitorLayoutMode  layout_mode)
++{
++  MetaOutput *output;
++  MetaCrtc *crtc;
++  const MetaCrtcConfig *crtc_config;
++
++  output = meta_monitor_get_main_output (monitor);
++  crtc = meta_output_get_assigned_crtc (output);
++  crtc_config = meta_crtc_get_config (crtc);
++  if (!crtc_config)
++    return NULL;
++
++  return create_preferred_logical_monitor_config (monitor_manager,
++                                                  monitor,
++                                                  (int) crtc_config->layout.origin.x,
++                                                  (int) crtc_config->layout.origin.y,
++                                                  primary_logical_monitor_config,
++                                                  layout_mode);
++}
++
++MetaMonitorsConfig *
++meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager)
++{
++  MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
++  GList *logical_monitor_configs;
++  MetaMonitor *primary_monitor;
++  MetaLogicalMonitorLayoutMode layout_mode;
++  MetaLogicalMonitorConfig *primary_logical_monitor_config;
++  GList *monitors;
++  GList *l;
++
++  if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0)
++    return NULL;
++
++  primary_monitor = find_primary_monitor (monitor_manager);
++  if (!primary_monitor || !meta_monitor_is_active (primary_monitor))
++    return NULL;
++
++  layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
++
++  primary_logical_monitor_config =
++    create_logical_monitor_config_from_output (monitor_manager,
++                                               primary_monitor,
++                                               NULL,
++                                               layout_mode);
++  if (!primary_logical_monitor_config)
++    return NULL;
++
++  primary_logical_monitor_config->is_primary = TRUE;
++  logical_monitor_configs = g_list_append (NULL,
++                                           primary_logical_monitor_config);
++
++  monitors = meta_monitor_manager_get_monitors (monitor_manager);
++  for (l = monitors; l; l = l->next)
++    {
++      MetaMonitor *monitor = l->data;
++      MetaLogicalMonitorConfig *logical_monitor_config;
++
++      if (monitor == primary_monitor)
++        continue;
++
++      if (!meta_monitor_is_active (monitor))
++        continue;
++
++      logical_monitor_config =
++        create_logical_monitor_config_from_output (monitor_manager,
++                                                   monitor,
++                                                   primary_logical_monitor_config,
++                                                   layout_mode);
++      if (!logical_monitor_config)
++        continue;
++
++      logical_monitor_configs = g_list_append (logical_monitor_configs,
++                                               logical_monitor_config);
++    }
++
++  return meta_monitors_config_new (monitor_manager,
++                                   logical_monitor_configs,
++                                   layout_mode,
++                                   META_MONITORS_CONFIG_FLAG_NONE);
++}
++
+ MetaMonitorsConfig *
+ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager)
+ {
+diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
+index 86756a7e33..961d604bd5 100644
+--- a/src/backends/meta-monitor-config-manager.h
++++ b/src/backends/meta-monitor-config-manager.h
+@@ -94,6 +94,8 @@ gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager,
+ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager);
+ 
++META_EXPORT_TEST
++MetaMonitorsConfig * meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager);
+ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager);
+ 
+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
+index c291ddb5d3..96f0d6b84a 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -695,6 +695,25 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+       g_clear_object (&config);
+     }
+ 
++  config = meta_monitor_config_manager_create_current (manager->config_manager);
++  if (config)
++    {
++      if (!meta_monitor_manager_apply_monitors_config (manager,
++                                                       config,
++                                                       method,
++                                                       &error))
++        {
++          g_clear_object (&config);
++          g_warning ("Failed to use current monitor configuration: %s",
++                     error->message);
++          g_clear_error (&error);
++        }
++      else
++        {
++          goto done;
++        }
++    }
++
+   config = meta_monitor_config_manager_create_linear (manager->config_manager);
+   if (config)
+     {
+-- 
+2.31.1
+
+
+From ada8c9b1346fe261a8fa04f68149c79d95c969ac Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Tue, 11 Sep 2018 10:19:44 -0400
+Subject: [PATCH 5/9] monitor-manager: only reuse initial-config if monitor
+ topology matches startup
+
+Right now we try to apply the current monitor config when a new
+monitor is attached.  The current config obviously doesn't include the
+new monitor, so the new monitor isn't lit up.
+
+The only reason we apply the current config at all is to handle the
+startup case:  We want to reuse the config set in Xorg when first
+logging in.
+
+This commit changes the code to look at the *initial config* instead
+of the current config, and only if the new monitor topology matches
+the start up topology.
+---
+ src/backends/meta-monitor-config-manager.c | 20 +++++++++++++++-----
+ src/backends/meta-monitor-config-manager.h |  2 +-
+ src/backends/meta-monitor-manager.c        | 16 +++++++++++++++-
+ 3 files changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index 2f6cc3856f..46249755bc 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -42,6 +42,7 @@ struct _MetaMonitorConfigManager
+   MetaMonitorConfigStore *config_store;
+ 
+   MetaMonitorsConfig *current_config;
++  MetaMonitorsConfig *initial_config;
+   GQueue config_history;
+ };
+ 
+@@ -764,9 +765,10 @@ create_logical_monitor_config_from_output (MetaMonitorManager           *monitor
+ }
+ 
+ MetaMonitorsConfig *
+-meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager)
++meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager)
+ {
+   MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
++  MetaMonitorsConfig *initial_config;
+   GList *logical_monitor_configs;
+   MetaMonitor *primary_monitor;
+   MetaLogicalMonitorLayoutMode layout_mode;
+@@ -774,6 +776,9 @@ meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_man
+   GList *monitors;
+   GList *l;
+ 
++  if (config_manager->initial_config != NULL)
++    return g_object_ref (config_manager->initial_config);
++
+   if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0)
+     return NULL;
+ 
+@@ -819,10 +824,14 @@ meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_man
+                                                logical_monitor_config);
+     }
+ 
+-  return meta_monitors_config_new (monitor_manager,
+-                                   logical_monitor_configs,
+-                                   layout_mode,
+-                                   META_MONITORS_CONFIG_FLAG_NONE);
++  initial_config = meta_monitors_config_new (monitor_manager,
++                                             logical_monitor_configs,
++                                             layout_mode,
++                                             META_MONITORS_CONFIG_FLAG_NONE);
++
++  config_manager->initial_config = g_object_ref (initial_config);
++
++  return initial_config;
+ }
+ 
+ MetaMonitorsConfig *
+@@ -1453,6 +1462,7 @@ meta_monitor_config_manager_dispose (GObject *object)
+     META_MONITOR_CONFIG_MANAGER (object);
+ 
+   g_clear_object (&config_manager->current_config);
++  g_clear_object (&config_manager->initial_config);
+   meta_monitor_config_manager_clear_history (config_manager);
+ 
+   G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object);
+diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
+index 961d604bd5..dc273c961b 100644
+--- a/src/backends/meta-monitor-config-manager.h
++++ b/src/backends/meta-monitor-config-manager.h
+@@ -95,7 +95,7 @@ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager);
+ 
+ META_EXPORT_TEST
+-MetaMonitorsConfig * meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager);
++MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager);
+ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager);
+ 
+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
+index 96f0d6b84a..baf5bf2f9f 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -615,9 +615,11 @@ should_use_stored_config (MetaMonitorManager *manager)
+ MetaMonitorsConfig *
+ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+ {
++  g_autoptr (MetaMonitorsConfig) initial_config = NULL;
+   MetaMonitorsConfig *config = NULL;
+   GError *error = NULL;
+   gboolean use_stored_config;
++  MetaMonitorsConfigKey *current_state_key;
+   MetaMonitorsConfigMethod method;
+   MetaMonitorsConfigMethod fallback_method =
+     META_MONITORS_CONFIG_METHOD_TEMPORARY;
+@@ -628,6 +630,18 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+   else
+     method = META_MONITORS_CONFIG_METHOD_TEMPORARY;
+ 
++  initial_config = meta_monitor_config_manager_create_initial (manager->config_manager);
++
++  if (initial_config)
++    {
++      current_state_key = meta_create_monitors_config_key_for_current_state (manager);
++
++      /* don't ever reuse initial configuration, if the monitor topology changed
++       */
++      if (current_state_key && !meta_monitors_config_key_equal (current_state_key, initial_config->key))
++        g_clear_object (&initial_config);
++    }
++
+   if (use_stored_config)
+     {
+       config = meta_monitor_config_manager_get_stored (manager->config_manager);
+@@ -695,7 +709,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+       g_clear_object (&config);
+     }
+ 
+-  config = meta_monitor_config_manager_create_current (manager->config_manager);
++  config = g_steal_pointer (&initial_config);
+   if (config)
+     {
+       if (!meta_monitor_manager_apply_monitors_config (manager,
+-- 
+2.31.1
+
+
+From baa22f3ac77f549bd36c2a0ea45ba4caee434ddc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 18 Mar 2019 17:08:11 +0100
+Subject: [PATCH 6/9] monitor-config-manager: Use current mode when deriving
+ current config
+
+Instead of overriding the existing mode with the preferred mode of the monitor,
+use the one already configured. Also use the MetaMonitor API for deriving the
+position of the monitor in the screen coordinate space.
+---
+ src/backends/meta-monitor-config-manager.c | 80 +++++++++++++---------
+ 1 file changed, 46 insertions(+), 34 deletions(-)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index 46249755bc..f355879c3e 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -678,21 +678,20 @@ get_monitor_transform (MetaMonitorManager *monitor_manager,
+ }
+ 
+ static MetaLogicalMonitorConfig *
+-create_preferred_logical_monitor_config (MetaMonitorManager          *monitor_manager,
+-                                         MetaMonitor                 *monitor,
+-                                         int                          x,
+-                                         int                          y,
+-                                         MetaLogicalMonitorConfig    *primary_logical_monitor_config,
+-                                         MetaLogicalMonitorLayoutMode layout_mode)
++create_logical_monitor_config (MetaMonitorManager           *monitor_manager,
++                               MetaMonitor                  *monitor,
++                               MetaMonitorMode              *mode,
++                               int                           x,
++                               int                           y,
++                               MetaLogicalMonitorConfig     *primary_logical_monitor_config,
++                               MetaLogicalMonitorLayoutMode  layout_mode)
+ {
+-  MetaMonitorMode *mode;
+   int width, height;
+   float scale;
+   MetaMonitorTransform transform;
+   MetaMonitorConfig *monitor_config;
+   MetaLogicalMonitorConfig *logical_monitor_config;
+ 
+-  mode = meta_monitor_get_preferred_mode (monitor);
+   meta_monitor_mode_get_resolution (mode, &width, &height);
+ 
+   if ((meta_monitor_manager_get_capabilities (monitor_manager) &
+@@ -741,27 +740,40 @@ create_preferred_logical_monitor_config (MetaMonitorManager          *monitor_ma
+ }
+ 
+ static MetaLogicalMonitorConfig *
+-create_logical_monitor_config_from_output (MetaMonitorManager           *monitor_manager,
+-                                           MetaMonitor                  *monitor,
+-                                           MetaLogicalMonitorConfig     *primary_logical_monitor_config,
+-                                           MetaLogicalMonitorLayoutMode  layout_mode)
++create_preferred_logical_monitor_config (MetaMonitorManager           *monitor_manager,
++                                         MetaMonitor                  *monitor,
++                                         int                           x,
++                                         int                           y,
++                                         MetaLogicalMonitorConfig     *primary_logical_monitor_config,
++                                         MetaLogicalMonitorLayoutMode  layout_mode)
+ {
+-  MetaOutput *output;
+-  MetaCrtc *crtc;
+-  const MetaCrtcConfig *crtc_config;
++  return create_logical_monitor_config (monitor_manager,
++                                        monitor,
++                                        meta_monitor_get_preferred_mode (monitor),
++                                        x, y,
++                                        primary_logical_monitor_config,
++                                        layout_mode);
++}
+ 
+-  output = meta_monitor_get_main_output (monitor);
+-  crtc = meta_output_get_assigned_crtc (output);
+-  crtc_config = meta_crtc_get_config (crtc);
+-  if (!crtc_config)
+-    return NULL;
++static MetaLogicalMonitorConfig *
++create_logical_monitor_config_from_monitor (MetaMonitorManager           *monitor_manager,
++                                            MetaMonitor                  *monitor,
++                                            MetaLogicalMonitorConfig     *primary_logical_monitor_config,
++                                            MetaLogicalMonitorLayoutMode  layout_mode)
++{
++  MetaRectangle monitor_layout;
++  MetaMonitorMode *mode;
++
++  meta_monitor_derive_layout (monitor, &monitor_layout);
++  mode = meta_monitor_get_current_mode (monitor);
+ 
+-  return create_preferred_logical_monitor_config (monitor_manager,
+-                                                  monitor,
+-                                                  (int) crtc_config->layout.origin.x,
+-                                                  (int) crtc_config->layout.origin.y,
+-                                                  primary_logical_monitor_config,
+-                                                  layout_mode);
++  return create_logical_monitor_config (monitor_manager,
++                                        monitor,
++                                        mode,
++                                        monitor_layout.x,
++                                        monitor_layout.y,
++                                        primary_logical_monitor_config,
++                                        layout_mode);
+ }
+ 
+ MetaMonitorsConfig *
+@@ -789,10 +801,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man
+   layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
+ 
+   primary_logical_monitor_config =
+-    create_logical_monitor_config_from_output (monitor_manager,
+-                                               primary_monitor,
+-                                               NULL,
+-                                               layout_mode);
++    create_logical_monitor_config_from_monitor (monitor_manager,
++                                                primary_monitor,
++                                                NULL,
++                                                layout_mode);
+   if (!primary_logical_monitor_config)
+     return NULL;
+ 
+@@ -813,10 +825,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man
+         continue;
+ 
+       logical_monitor_config =
+-        create_logical_monitor_config_from_output (monitor_manager,
+-                                                   monitor,
+-                                                   primary_logical_monitor_config,
+-                                                   layout_mode);
++        create_logical_monitor_config_from_monitor (monitor_manager,
++                                                    monitor,
++                                                    primary_logical_monitor_config,
++                                                    layout_mode);
+       if (!logical_monitor_config)
+         continue;
+ 
+-- 
+2.31.1
+
+
+From 52622c80f747a03738823471be9d275c7a2fd8c0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 18 Mar 2019 17:10:37 +0100
+Subject: [PATCH 7/9] monitor-manager: Don't try to derive current config on
+ non-X11
+
+This commit also reworks the initial config state reading some. Appart from
+avoiding trying to inherit from backends where it doesn't make sense, it does
+the following changes:
+
+ * Replace the name "initial" with "inherited", as the initial config in the
+   context of monitor management is the one used initialization. E.g. if there is
+   a applicable configuration in monitors.xml, the initial config is taken from
+   there.
+
+ * Don't make "_create_()" functions have side effects. Previously
+   meta_monitor_config_manager_create_initial() also set state on the config
+   manager object. Instead, add a meta_monitor_config_manager_ensure_inherited()
+   and meta_monitor_manager_get_inherited_config() function to make things more
+   explicit.
+
+ * Don't recreate "is-applicable" logic, just use the existing helper.
+---
+ src/backends/meta-monitor-config-manager.c    | 39 +++++++++++--------
+ src/backends/meta-monitor-config-manager.h    |  5 +++
+ src/backends/meta-monitor-manager-private.h   |  4 +-
+ src/backends/meta-monitor-manager.c           | 32 ++++++++-------
+ .../x11/meta-monitor-manager-xrandr.c         |  3 +-
+ 5 files changed, 49 insertions(+), 34 deletions(-)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index f355879c3e..4b37657d34 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -42,7 +42,7 @@ struct _MetaMonitorConfigManager
+   MetaMonitorConfigStore *config_store;
+ 
+   MetaMonitorsConfig *current_config;
+-  MetaMonitorsConfig *initial_config;
++  MetaMonitorsConfig *inherited_config;
+   GQueue config_history;
+ };
+ 
+@@ -776,11 +776,10 @@ create_logical_monitor_config_from_monitor (MetaMonitorManager           *monito
+                                         layout_mode);
+ }
+ 
+-MetaMonitorsConfig *
+-meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager)
++static MetaMonitorsConfig *
++meta_monitor_config_manager_derive_current (MetaMonitorConfigManager *config_manager)
+ {
+   MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
+-  MetaMonitorsConfig *initial_config;
+   GList *logical_monitor_configs;
+   MetaMonitor *primary_monitor;
+   MetaLogicalMonitorLayoutMode layout_mode;
+@@ -788,12 +787,6 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man
+   GList *monitors;
+   GList *l;
+ 
+-  if (config_manager->initial_config != NULL)
+-    return g_object_ref (config_manager->initial_config);
+-
+-  if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0)
+-    return NULL;
+-
+   primary_monitor = find_primary_monitor (monitor_manager);
+   if (!primary_monitor || !meta_monitor_is_active (primary_monitor))
+     return NULL;
+@@ -836,14 +829,26 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man
+                                                logical_monitor_config);
+     }
+ 
+-  initial_config = meta_monitors_config_new (monitor_manager,
+-                                             logical_monitor_configs,
+-                                             layout_mode,
+-                                             META_MONITORS_CONFIG_FLAG_NONE);
++  return meta_monitors_config_new (monitor_manager,
++                                   logical_monitor_configs,
++                                   layout_mode,
++                                   META_MONITORS_CONFIG_FLAG_NONE);
++}
++
++void
++meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager)
++{
++  if (config_manager->inherited_config)
++    return;
+ 
+-  config_manager->initial_config = g_object_ref (initial_config);
++  config_manager->inherited_config =
++    meta_monitor_config_manager_derive_current (config_manager);
++}
+ 
+-  return initial_config;
++MetaMonitorsConfig *
++meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager)
++{
++  return config_manager->inherited_config;
+ }
+ 
+ MetaMonitorsConfig *
+@@ -1474,7 +1479,7 @@ meta_monitor_config_manager_dispose (GObject *object)
+     META_MONITOR_CONFIG_MANAGER (object);
+ 
+   g_clear_object (&config_manager->current_config);
+-  g_clear_object (&config_manager->initial_config);
++  g_clear_object (&config_manager->inherited_config);
+   meta_monitor_config_manager_clear_history (config_manager);
+ 
+   G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object);
+diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
+index dc273c961b..641ed1bc1a 100644
+--- a/src/backends/meta-monitor-config-manager.h
++++ b/src/backends/meta-monitor-config-manager.h
+@@ -96,6 +96,11 @@ MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigMa
+ 
+ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager);
++
++void meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager);
++
++MetaMonitorsConfig * meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager);
++
+ META_EXPORT_TEST
+ MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager);
+ 
+diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
+index 60c1e90821..571b9000dc 100644
+--- a/src/backends/meta-monitor-manager-private.h
++++ b/src/backends/meta-monitor-manager-private.h
+@@ -44,7 +44,8 @@ typedef enum _MetaMonitorManagerCapability
+ {
+   META_MONITOR_MANAGER_CAPABILITY_NONE = 0,
+   META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 0),
+-  META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 1)
++  META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 1),
++  META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT = (1 << 2),
+ } MetaMonitorManagerCapability;
+ 
+ /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
+@@ -145,6 +146,7 @@ struct _MetaMonitorManager
+   guint panel_orientation_managed : 1;
+ 
+   MetaMonitorConfigManager *config_manager;
++  MetaMonitorsConfig *initial_config;
+ 
+   GnomePnpIds *pnp_ids;
+ 
+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
+index baf5bf2f9f..9e57db94cd 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -612,14 +612,21 @@ should_use_stored_config (MetaMonitorManager *manager)
+   return !meta_monitor_manager_has_hotplug_mode_update (manager);
+ }
+ 
++static gboolean
++can_derive_current_config (MetaMonitorManager *manager)
++{
++  MetaMonitorManagerCapability capabilities;
++
++  capabilities = meta_monitor_manager_get_capabilities (manager);
++  return !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT);
++}
++
+ MetaMonitorsConfig *
+ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+ {
+-  g_autoptr (MetaMonitorsConfig) initial_config = NULL;
+   MetaMonitorsConfig *config = NULL;
+   GError *error = NULL;
+   gboolean use_stored_config;
+-  MetaMonitorsConfigKey *current_state_key;
+   MetaMonitorsConfigMethod method;
+   MetaMonitorsConfigMethod fallback_method =
+     META_MONITORS_CONFIG_METHOD_TEMPORARY;
+@@ -630,17 +637,8 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+   else
+     method = META_MONITORS_CONFIG_METHOD_TEMPORARY;
+ 
+-  initial_config = meta_monitor_config_manager_create_initial (manager->config_manager);
+-
+-  if (initial_config)
+-    {
+-      current_state_key = meta_create_monitors_config_key_for_current_state (manager);
+-
+-      /* don't ever reuse initial configuration, if the monitor topology changed
+-       */
+-      if (current_state_key && !meta_monitors_config_key_equal (current_state_key, initial_config->key))
+-        g_clear_object (&initial_config);
+-    }
++  if (can_derive_current_config (manager))
++    meta_monitor_config_manager_ensure_inherited_config (manager->config_manager);
+ 
+   if (use_stored_config)
+     {
+@@ -709,9 +707,13 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
+       g_clear_object (&config);
+     }
+ 
+-  config = g_steal_pointer (&initial_config);
+-  if (config)
++  config =
++    meta_monitor_config_manager_get_inherited_config (manager->config_manager);
++  if (config &&
++      meta_monitor_manager_is_config_complete (manager, config))
+     {
++      config = g_object_ref (config);
++
+       if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                        config,
+                                                        method,
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 61e13f459d..90ccb74053 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -984,7 +984,8 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager
+ static MetaMonitorManagerCapability
+ meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager)
+ {
+-  return META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED;
++  return (META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED |
++          META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT);
+ }
+ 
+ static gboolean
+-- 
+2.31.1
+
+
+From e15c812ef8525d6dd6db730c1c6a1f8ad839bb09 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 27 Nov 2019 19:03:50 +0100
+Subject: [PATCH 8/9] monitor-manager-xrandr: Move dpms state and screen size
+ updating into helpers
+
+To be used by no-Xrandr fallback path.
+---
+ src/backends/x11/meta-gpu-xrandr.c            | 39 +++++++++++++------
+ .../x11/meta-monitor-manager-xrandr.c         | 18 ++++++---
+ 2 files changed, 40 insertions(+), 17 deletions(-)
+
+diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
+index 6a96e53979..e8361c77bc 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -96,6 +96,32 @@ meta_gpu_xrandr_poll_hardware (MetaGpu *gpu)
+   gpu_xrandr->need_hardware_poll = TRUE;
+ }
+ 
++static void
++update_screen_size (MetaGpuXrandr *gpu_xrandr)
++{
++  MetaGpu *gpu = META_GPU (gpu_xrandr);
++  MetaBackend *backend = meta_gpu_get_backend (gpu);
++  MetaMonitorManager *monitor_manager =
++    meta_backend_get_monitor_manager (backend);
++  MetaMonitorManagerXrandr *monitor_manager_xrandr =
++    META_MONITOR_MANAGER_XRANDR (monitor_manager);
++  Display *xdisplay =
++    meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
++  int min_width, min_height;
++  Screen *screen;
++
++  XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
++                         &min_width,
++                         &min_height,
++                         &gpu_xrandr->max_screen_width,
++                         &gpu_xrandr->max_screen_height);
++
++  screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay));
++  /* This is updated because we called XRRUpdateConfiguration. */
++  monitor_manager->screen_width = WidthOfScreen (screen);
++  monitor_manager->screen_height = HeightOfScreen (screen);
++}
++
+ static gboolean
+ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+                               GError  **error)
+@@ -112,8 +138,6 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+   RROutput primary_output;
+   unsigned int i, j;
+   GList *l;
+-  int min_width, min_height;
+-  Screen *screen;
+   GList *outputs = NULL;
+   GList *modes = NULL;
+   GList *crtcs = NULL;
+@@ -122,16 +146,7 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+     XRRFreeScreenResources (gpu_xrandr->resources);
+   gpu_xrandr->resources = NULL;
+ 
+-  XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
+-                         &min_width,
+-                         &min_height,
+-                         &gpu_xrandr->max_screen_width,
+-                         &gpu_xrandr->max_screen_height);
+-
+-  screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay));
+-  /* This is updated because we called XRRUpdateConfiguration. */
+-  monitor_manager->screen_width = WidthOfScreen (screen);
+-  monitor_manager->screen_height = HeightOfScreen (screen);
++  update_screen_size (gpu_xrandr);
+ 
+   if (gpu_xrandr->need_hardware_poll)
+     {
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 90ccb74053..1b35545a09 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -140,12 +140,9 @@ x11_dpms_state_to_power_save (CARD16 dpms_state)
+ }
+ 
+ static void
+-meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager)
++meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr)
+ {
+-  MetaMonitorManagerXrandr *manager_xrandr =
+-    META_MONITOR_MANAGER_XRANDR (manager);
+-  MetaMonitorManagerClass *parent_class =
+-    META_MONITOR_MANAGER_CLASS (meta_monitor_manager_xrandr_parent_class);
++  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
+   Display *xdisplay = meta_monitor_manager_xrandr_get_xdisplay (manager_xrandr);
+   BOOL dpms_capable, dpms_enabled;
+   CARD16 dpms_state;
+@@ -161,6 +158,17 @@ meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager)
+     power_save_mode = META_POWER_SAVE_UNSUPPORTED;
+ 
+   meta_monitor_manager_power_save_mode_changed (manager, power_save_mode);
++}
++
++static void
++meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager)
++{
++  MetaMonitorManagerXrandr *manager_xrandr =
++    META_MONITOR_MANAGER_XRANDR (manager);
++  MetaMonitorManagerClass *parent_class =
++    META_MONITOR_MANAGER_CLASS (meta_monitor_manager_xrandr_parent_class);
++
++  meta_monitor_manager_xrandr_update_dpms_state (manager_xrandr);
+ 
+   parent_class->read_current_state (manager);
+ }
+-- 
+2.31.1
+
+
+From 49307c3171b086ba5cdebe633f97a217042c8903 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 3 Oct 2018 10:50:47 +0200
+Subject: [PATCH 9/9] monitor-manager/xrandr: Create dummy screen sized monitor
+ if no RANDR
+
+When there is no RANDR support enabled in the X server, we wont get
+notified of any monitors, resulting in mutter believing we're being
+headless. To get at least something working, although with no way
+configuration ability, lets pretend the whole screen is just a single
+monitor with a single output, crtc and mode.
+---
+ src/backends/x11/meta-gpu-xrandr.c            | 86 +++++++++++++++++++
+ .../x11/meta-monitor-manager-xrandr.c         | 22 ++++-
+ .../x11/meta-monitor-manager-xrandr.h         |  4 +
+ 3 files changed, 111 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
+index e8361c77bc..3ecb80bb2c 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -122,6 +122,89 @@ update_screen_size (MetaGpuXrandr *gpu_xrandr)
+   monitor_manager->screen_height = HeightOfScreen (screen);
+ }
+ 
++static gboolean
++read_current_fallback (MetaGpuXrandr            *gpu_xrandr,
++                       MetaMonitorManagerXrandr *monitor_manager_xrandr)
++{
++  MetaGpu *gpu = META_GPU (gpu_xrandr);
++  MetaMonitorManager *monitor_manager =
++    META_MONITOR_MANAGER (monitor_manager_xrandr);
++  g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
++  g_autofree char *mode_name = NULL;
++  MetaCrtcMode *mode;
++  MetaCrtc *crtc;
++  g_autoptr (MetaOutputInfo) output_info = NULL;
++  MetaOutputAssignment output_assignment;
++  MetaOutput *output;
++
++  meta_monitor_manager_xrandr_update_dpms_state (monitor_manager_xrandr);
++  update_screen_size (gpu_xrandr);
++
++  crtc_mode_info = meta_crtc_mode_info_new ();
++  crtc_mode_info->width = monitor_manager->screen_width;
++  crtc_mode_info->height = monitor_manager->screen_height;
++  crtc_mode_info->refresh_rate = 60.0;
++
++  mode_name = g_strdup_printf ("%dx%d",
++                               crtc_mode_info->width,
++                               crtc_mode_info->height);
++  mode = g_object_new (META_TYPE_CRTC_MODE,
++                       "id", 0,
++                       "name", mode_name,
++                       "info", crtc_mode_info,
++                       NULL);
++
++  meta_gpu_take_modes (gpu, g_list_prepend (NULL, mode));
++
++  crtc = g_object_new (META_TYPE_CRTC_XRANDR,
++                       "id", 0,
++                       "gpu", gpu,
++                       NULL);
++  meta_crtc_set_config (crtc,
++                        &(graphene_rect_t) {
++                          .size = {
++                            .width = crtc_mode_info->width, 
++                            .height = crtc_mode_info->width, 
++                          },
++                        },
++                        mode,
++                        META_MONITOR_TRANSFORM_NORMAL);
++
++  meta_gpu_take_crtcs (gpu, g_list_prepend (NULL, crtc));
++
++  output_info = meta_output_info_new ();
++  output_info->name = g_strdup ("X11 Screen");
++  output_info->vendor = g_strdup ("unknown");
++  output_info->product = g_strdup ("unknown");
++  output_info->serial = g_strdup ("unknown");
++  output_info->hotplug_mode_update = TRUE;
++  output_info->suggested_x = -1;
++  output_info->suggested_y = -1;
++  output_info->connector_type = META_CONNECTOR_TYPE_Unknown;
++  output_info->modes = g_new0 (MetaCrtcMode *, 1);
++  output_info->modes[0] = mode;
++  output_info->n_modes = 1;
++  output_info->preferred_mode = mode;
++  output_info->possible_crtcs = g_new0 (MetaCrtc *, 1);
++  output_info->possible_crtcs[0] = crtc;
++  output_info->n_possible_crtcs = 1;
++
++  output = g_object_new (META_TYPE_OUTPUT_XRANDR,
++                         "id", (uint64_t) 0,
++                         "gpu", gpu,
++                         "info", output_info,
++                         NULL);
++
++  output_assignment = (MetaOutputAssignment) {
++    .output = output,
++    .is_primary = TRUE,
++  };
++  meta_output_assign_crtc (output, crtc, &output_assignment);
++  meta_gpu_take_outputs (gpu, g_list_prepend (NULL, output));
++
++  return TRUE;
++}
++
+ static gboolean
+ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+                               GError  **error)
+@@ -142,6 +225,9 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+   GList *modes = NULL;
+   GList *crtcs = NULL;
+ 
++  if (!meta_monitor_manager_xrandr_has_randr (monitor_manager_xrandr))
++    return read_current_fallback (gpu_xrandr, monitor_manager_xrandr);
++
+   if (gpu_xrandr->resources)
+     XRRFreeScreenResources (gpu_xrandr->resources);
+   gpu_xrandr->resources = NULL;
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 1b35545a09..98eb080b6b 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -76,6 +76,7 @@ struct _MetaMonitorManagerXrandr
+   guint logind_watch_id;
+   guint logind_signal_sub_id;
+ 
++  gboolean has_randr;
+   gboolean has_randr15;
+ 
+   xcb_timestamp_t last_xrandr_set_timestamp;
+@@ -108,6 +109,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran
+   return manager_xrandr->xdisplay;
+ }
+ 
++gboolean
++meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr)
++{
++  return manager_xrandr->has_randr;
++}
++
+ gboolean
+ meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
+ {
+@@ -139,7 +146,7 @@ x11_dpms_state_to_power_save (CARD16 dpms_state)
+     }
+ }
+ 
+-static void
++void
+ meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr)
+ {
+   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
+@@ -615,9 +622,18 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager      *mana
+                                                    MetaMonitorsConfigMethod method,
+                                                    GError                 **error)
+ {
++  MetaMonitorManagerXrandr *manager_xrandr =
++  META_MONITOR_MANAGER_XRANDR (manager);
+   GPtrArray *crtc_assignments;
+   GPtrArray *output_assignments;
+ 
++  if (!manager_xrandr->has_randr)
++    {
++      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                   "Tried to change configuration without XRANDR support");
++      return FALSE;
++    }
++
+   if (!config)
+     {
+       if (!manager->in_init)
+@@ -1097,11 +1113,15 @@ meta_monitor_manager_xrandr_constructed (GObject *object)
+ 			  &manager_xrandr->rr_event_base,
+ 			  &manager_xrandr->rr_error_base))
+     {
++      g_warning ("No RANDR support, monitor configuration disabled");
+       return;
+     }
+   else
+     {
+       int major_version, minor_version;
++
++      manager_xrandr->has_randr = TRUE;
++
+       /* We only use ScreenChangeNotify, but GDK uses the others,
+ 	 and we don't want to step on its toes */
+       XRRSelectInput (manager_xrandr->xdisplay,
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h
+index d55b3d2b88..dc75134a56 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.h
++++ b/src/backends/x11/meta-monitor-manager-xrandr.h
+@@ -33,9 +33,13 @@ G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr,
+ 
+ Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr);
+ 
++gboolean meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr);
++
+ gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr);
+ 
+ gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
+                                                     XEvent                   *event);
+ 
++void meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr);
++
+ #endif /* META_MONITOR_MANAGER_XRANDR_H */
+-- 
+2.31.1
+
diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec
new file mode 100644
index 0000000..7b45a0e
--- /dev/null
+++ b/SPECS/mutter.spec
@@ -0,0 +1,1329 @@
+%global gtk3_version 3.19.8
+%global glib_version 2.53.2
+%global gsettings_desktop_schemas_version 40~alpha
+%global json_glib_version 0.12.0
+%global libinput_version 1.4
+%global pipewire_version 0.3.0
+%global mutter_api_version 8
+
+%global tarball_version %%(echo %{version} | tr '~' '.')
+
+Name:          mutter
+Version:       40.4
+Release:       3%{?dist}
+Summary:       Window and compositing manager based on Clutter
+
+License:       GPLv2+
+URL:           http://www.gnome.org
+Source0:       http://download.gnome.org/sources/%{name}/40/%{name}-%{tarball_version}.tar.xz
+
+# Work-around for OpenJDK's compliance test
+Patch0:        0001-window-actor-Special-case-shaped-Java-windows.patch
+
+# To make s390x build pass
+Patch1:        0001-Revert-build-Do-not-provide-built-sources-as-libmutt.patch
+
+# Workaround for RHBZ#1936991 (blocks atomic KMS on "tegra" driver)
+Patch2:        0001-Test-deny-atomic-KMS-for-tegra-RHBZ-1936991.patch
+
+# Allow Xwayland grabs by default, on a selected set of X11 apps (rhbz#1500399)
+Patch3:        0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch
+
+# X11 window management work arounds
+Patch4:        0001-constraints-Enforce-X11-size-limits.patch
+
+# X11/VM monitor configuration patches (rhbz#1265511, rhbz#1618632,
+# rhbz#1497303, rhbz#1690506, rhbz#1776530, rhbz#1365717, rhbz#1690170)
+Patch5:        x11-monitor-configuration-patches.patch
+
+# Sloppy focus fix (rhbz#1358535)
+Patch6:        0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch
+
+# Legacy X11 configuration support (synaptics/plain)
+Patch7:        legacy-x11-input-configuration.patch
+
+# GLX Stereo (nvidia)
+Patch8:        glx-stereo-support.patch
+
+# Work around vncserver not setting the right XDG_SESSION_TYPE
+Patch9:       0001-main-be-more-aggressive-in-assuming-X11-backend.patch
+
+# Fixes --replace
+Patch10:      0001-backend-Clean-up-renderer-after-clutter-backendm.patch
+
+# Fixes a race in wl_seat capabilities (rhbz#1957807)
+# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/77
+Patch11: 0001-wayland-Avoid-a-race-in-wl_seat-capabilities.patch
+
+BuildRequires: chrpath
+BuildRequires: pango-devel
+BuildRequires: startup-notification-devel
+BuildRequires: gnome-desktop3-devel
+BuildRequires: glib2-devel >= %{glib_version}
+BuildRequires: gtk3-devel >= %{gtk3_version}
+BuildRequires: pkgconfig
+BuildRequires: gobject-introspection-devel >= 1.41.0
+BuildRequires: libSM-devel
+BuildRequires: libwacom-devel
+BuildRequires: libX11-devel
+BuildRequires: libXdamage-devel
+BuildRequires: libXext-devel
+BuildRequires: libXfixes-devel
+BuildRequires: libXi-devel
+BuildRequires: libXrandr-devel
+BuildRequires: libXrender-devel
+BuildRequires: libXcursor-devel
+BuildRequires: libXcomposite-devel
+BuildRequires: libxcb-devel
+BuildRequires: libxkbcommon-devel
+BuildRequires: libxkbcommon-x11-devel
+BuildRequires: libxkbfile-devel
+BuildRequires: libXtst-devel
+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(libpipewire-0.3) >= %{pipewire_version}
+BuildRequires: pkgconfig(sysprof-capture-4)
+BuildRequires: sysprof-devel
+BuildRequires: systemd-devel
+BuildRequires: upower-devel
+BuildRequires: xorg-x11-server-Xorg
+BuildRequires: xkeyboard-config-devel
+BuildRequires: zenity
+BuildRequires: desktop-file-utils
+# Bootstrap requirements
+BuildRequires: gtk-doc gnome-common gettext-devel git
+BuildRequires: libcanberra-devel
+BuildRequires: gsettings-desktop-schemas-devel >= %{gsettings_desktop_schemas_version}
+BuildRequires: gnome-settings-daemon-devel
+BuildRequires: meson
+BuildRequires: pkgconfig(gudev-1.0)
+BuildRequires: pkgconfig(libdrm)
+BuildRequires: pkgconfig(gbm)
+BuildRequires: pkgconfig(wayland-server)
+BuildRequires: pkgconfig(wayland-eglstream)
+
+BuildRequires: json-glib-devel >= %{json_glib_version}
+BuildRequires: libgudev1-devel
+BuildRequires: libinput-devel >= %{libinput_version}
+BuildRequires: pkgconfig(xwayland)
+
+Requires: control-center-filesystem
+Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version}
+Requires: gnome-settings-daemon
+Requires: gtk3%{?_isa} >= %{gtk3_version}
+Requires: pipewire%{_isa} >= %{pipewire_version}
+Requires: startup-notification
+Requires: dbus
+Requires: zenity
+
+Requires:      json-glib%{?_isa} >= %{json_glib_version}
+Requires:      libinput%{?_isa} >= %{libinput_version}
+
+# 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
+
+%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 devel
+Summary: Development package for %{name}
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%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}%{?_isa} = %{version}-%{release}
+
+%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}
+
+# Mutter contains a .desktop file so we just need to validate it
+desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop
+
+%ldconfig_scriptlets
+
+%files -f %{name}.lang
+%license COPYING
+%doc NEWS
+%{_bindir}/mutter
+%{_datadir}/applications/*.desktop
+%{_libdir}/lib*.so.*
+%{_libdir}/mutter-%{mutter_api_version}/
+%{_libexecdir}/mutter-restart-helper
+%{_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
+%{_mandir}/man1/mutter.1*
+%{_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
+* Fri Sep 10 2021 Olivier Fourdan <ofourdan@redhat.com> - 40.4-3
+- Fixes a race in wl_seat capabilities
+  Resolves: #1957807
+
+* Wed Aug 27 2021 Florian Müllner <fmuellner@redhat.com> - 40.4-2
+- Remove firstboot(windowmanager) provide
+  Resolves: #1975355
+
+* Wed Aug 18 2021 Florian Müllner <fmuellner@redhat.com> - 40.4-1
+- Update to 40.4
+  Resolves: #1995093
+
+* Thu Aug 12 2021 Ray Strode <rstrode@redhat.com> - 40.3-3
+- Fix crash in shutdown path
+  Related: #1992986
+
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 40.3-2
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Mon Jul 12 2021 Florian Müllner <fmuellner@redhat.com> - 40.3-1
+- Update to 40.3
+  Resolves: #1974211
+
+* Mon Jun 14 2021 Florian Müllner <fmuellner@redhat.com> - 40.2.1-1
+- Update to 40.2.1
+  Resolves: #1971437
+
+* Thu Jun 03 2021 Jonas Ådahl <jadahl@redhat.com> - 40.1-3
+- Forward port downstream patches from RHEL8
+  Resolves: #1965949
+
+* Wed Jun 02 2021 Florian Müllner <fmuellner@redhat.com> - 40.1-2
+- Don't emit ::key-focus-out on destroyed actors
+  Resolves: #1964386
+
+* Thu May 13 2021 Florian Müllner <fmuellner@redhat.com> - 40.1-1
+- Update to 40.1
+  Resolves: #1951146
+
+* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 40.0-5
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Tue Mar 30 2021 Kalev Lember <klember@redhat.com> - 40.0-4
+- Fix enter, space, backspace keys not working with input methods (#1942294)
+- Drop old obsoletes and conflicts
+
+* Mon Mar 29 2021 Jonas Ådahl <jadahl@redhat.com> - 40.0-3
+- Fix crash on resume (rhbz#1941971)
+
+* Fri Mar 26 2021 Kalev Lember <klember@redhat.com> - 40.0-2
+- Rebuild to fix sysprof-capture symbols leaking into libraries consuming it
+
+* Sat Mar 20 2021 Florian Müllner <fmuellner@redhat.com> - 40.0-1
+- Update to 40.0
+
+* Mon Mar 15 2021 Florian Müllner <fmuellner@redhat.com> - 40.0~rc-1
+- Update to 40.rc
+
+* Fri Mar 12 2021 Benjamin Berg <bberg@redhat.com> - 40.0~beta-3
+- Pull in Xwayland autostart fix for non-systemd startup
+  Resolves: #1924908
+
+* Tue Mar 09 2021 Adam Williamson <awilliam@redhat.com> - 40.0~beta-2
+- Add a workaround for RHBZ#1936991 (disable atomic KMS on tegra)
+
+* Mon Feb 22 2021 Florian Müllner <fmuellner@redhat.com> - 40.0~beta-1
+- Update to 40.beta
+
+* Tue Feb 02 2021 Florian Müllner <fmuellner@redhat.com> - 40.0~alpha.1.1-4.20210202gita9d9aee6c
+- Build snapshot of current upstream
+
+* Mon Feb  1 2021 Olivier Fourdan <ofourdan@redhat.com> - 40.0~alpha.1.1-3
+- Add build dependency on Xwayland-devel package (from Xwayland standalone)
+- Do not explicitly disable initfd support.
+
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 40.0~alpha.1.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Thu Jan 14 2021 Florian Müllner <fmuellner@redhat.com> - 40.0~alpha.1.1-1
+- Update to 40.alpha.1.1 to adjust for GSettings schema changes in g-s-d
+
+* Thu Jan 14 2021 Florian Müllner <fmuellner@redhat.com> - 40.0~alpha.1-1
+- Update to 40.alpha.1
+
+* Wed Dec 02 2020 Florian Müllner <fmuellner@redhat.com> - 40.alpha-1
+- Update to 40.alpha
+
+* Mon Oct 05 2020 Florian Müllner <fmuellner@redhat.com> - 3.38.1-1
+- Update to 3.38.1
+
+* Mon Sep 28 2020 Peter Robinson <pbrobinson@fedoraproject.org> - 3.38.0-2
+- Upstream fix for NVidia Jetson devices
+
+* Mon Sep 14 2020 Florian Müllner <fmuellner@redhat.com> - 3.38.0-1
+- Update to 3.38.0
+
+* Sat Sep 05 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.92-1
+- Update to 3.37.92
+
+* Mon Aug 24 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.91-1
+- Update to 3.37.91
+
+* Tue Aug 11 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.90-1
+- Update to 3.37.90
+
+* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.37.3-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Tue Jul 07 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.3-1
+- Update to 3.37.3
+
+* Wed Jun 03 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.2-1
+- Update to 3.37.2
+
+* Thu Apr 30 2020 Florian Müllner <fmuellner@redhat.com> - 3.37.1-1
+- Update to 3.37.1
+
+* Mon Mar 30 2020 Florian Müllner <fmuellner@redhat.com> - 3.36.1-1
+- Update to 3.36.1
+
+* Tue Mar 24 2020 Adam Williamson <awilliam@redhat.com> - 3.36.0-3
+- Backport all patches to git master for various fixes inc (#1809717)
+
+* Mon Mar 23 2020 Adam Williamson <awilliam@redhat.com> - 3.36.0-2
+- Backport fix for preedit cursor position bug (#1812449)
+
+* Sat Mar 07 2020 Florian Müllner <fmuellner@redhat.com> - 3.36.0-1
+- Update to 3.36.0
+
+* Fri Mar 06 2020 Adam Williamson <awilliam@redhat.com> - 3.35.92-3
+- Backport fix for pop-up menus on secondary heads (Gitlab #1098)
+
+* Tue Mar 03 2020 Bastien Nocera <bnocera@redhat.com> - 3.35.92-2
++ mutter-3.35.92-2
+- Fix wayland session not starting up, see https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1103
+
+* Sun Mar 01 2020 Florian Müllner <fmuellner@redhat.com> - 3.35.92-1
+- Update to 3.35.92
+
+* Mon Feb 17 2020 Florian Müllner <fmuellner@redhat.com> - 3.35.91-1
+- Update to 3.35.91
+
+* Thu Feb 06 2020 Florian Müllner <fmuellner@redhat.com> - 3.35.90-1
+- Update to 3.35.90
+
+* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.35.3-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Thu Jan 16 2020 Kalev Lember <klember@redhat.com> - 3.35.3-2
+- Rebuilt for libgnome-desktop soname bump
+
+* Sun Jan 05 2020 Florian Müllner <fmuellner@redhat.com> - 3.35.3-1
+- Update to 3.35.3
+
+* Wed Dec 11 2019 Florian Müllner <fmuellner@redhat.com> - 3.35.2-1
+- Update to 3.35.2
+
+* Tue Oct 29 2019 Florian Müllner <fmuellner@redhat.com> - 3.35.1-3
+- Enable sysprof support
+  The required dependency was missing from rawhide when the feature
+  landed, but there's no reason for keeping it disabled nowadays
+
+* Mon Oct 14 2019 Adam Williamson <awilliam@redhat.com> - 3.35.1-2
+- Update MR #832 backport to fully fix cursor zoom bug (#1749433)
+
+* Sat Oct 12 2019 Florian Müllner <fmuellner@redhat.com> - 3.35.1-1
+- Update to 3.35.1
+
+* Sat Oct 12 2019 Adam Williamson <awilliam@redhat.com> - 3.34.1-2
+- Backport multiple fixes for F31 FE/blocker bugs:
+  MR #832 for #1749433 (also needs change in gnome-shell)
+  MR #840 for #1760254
+  MR #848 for #1751646 and #1759644
+  MR #842 for #1758873
+
+* Wed Oct 09 2019 Florian Müllner <fmuellner@redhat.com> - 3.34.1-1
+- Update to 3.34.1
+
+* Sat Sep 28 2019 Kenneth Topp <toppk@bllue.org> - 3.34.0-5
+- Backport fix for dual special modifier keys bug (#1754867)
+- Backport fix that enables core dumps (#1748145)
+
+* Fri Sep 27 2019 Kenneth Topp <toppk@bllue.org> - 3.34.0-4
+- Backport a patch to prevent crash during animations
+- See upstream issue https://gitlab.gnome.org/GNOME/mutter/issues/815
+
+* Thu Sep 12 2019 Kalev Lember <klember@redhat.com> - 3.34.0-3
+- Update previous patch to final upstream version
+
+* Wed Sep 11 2019 Kalev Lember <klember@redhat.com> - 3.34.0-2
+- Backport a patch to fix xsettings/ibus-x11 initialization (#1750512)
+
+* Mon Sep 09 2019 Florian Müllner <fmuellner@redhat.com> - 3.34.0-1
+- Update to 3.34.0
+
+* Wed Sep 04 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.92-1
+- Update to 3.33.92
+
+* Tue Sep 03 2019 Ray Strode <rstrode@redhat.com> - 3.33.91-2
+- Fix crash dealing with powersaving
+  Resolves: #1747845
+
+* Wed Aug 21 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.91-1
+- Update to 3.33.91
+
+* Sat Aug 10 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.90-1
+- Update to 3.33.90
+
+* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.33.4-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Sun Jul 21 2019 Kalev Lember <klember@redhat.com> - 3.33.4-2
+- Rebuilt for libgnome-desktop soname bump
+
+* Sat Jul 20 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.4-1
+- Update to 3.33.4
+
+* Mon Jun 24 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.3-1
+- Update to 3.33.3
+
+* Wed May 22 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.2-1
+- Update to 3.33.2
+
+* Tue May 14 2019 Florian Müllner <fmuellner@redhat.com> - 3.33.1-1
+- Update to 3.33.1
+
+* Wed Apr 17 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.1-1
+- Update to 3.32.1
+
+* Wed Apr 17 2019 Adam Williamson <awilliam@redhat.com> - 3.32.0-4
+- Backport MR #498 for spinner bug, plus two crasher fixes
+  Resolves: #1692135
+
+* Tue Apr 16 2019 Adam Williamson <awilliam@redhat.com> - 3.32.0-3
+- Rebuild with Meson fix for #1699099
+
+* Mon Mar 25 2019 Adam Williamson <awilliam@redhat.com> - 3.32.0-2
+- Backport work-around for hangul text input bug (rhbz#1632981)
+
+* Tue Mar 12 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.0-1
+- Update to 3.32.0
+
+* Fri Mar 08 2019 Kalev Lember <klember@redhat.com> - 3.31.92-3
+- Backport more inverted colour fixes (#1686649)
+
+* Wed Mar 06 2019 Kalev Lember <klember@redhat.com> - 3.31.92-2
+- Backport a patch to fix inverted colours
+
+* Tue Mar 05 2019 Florian Müllner <fmuellner@redhat.com> - 3.31.92-1
+- Update to 3.31.92
+
+* Thu Feb 21 2019 Florian Müllner <fmuellner@redhat.com> - 3.31.91-1
+- Update to 3.31.91
+
+* Thu Feb 07 2019 Florian Müllner <fmuellner@redhat.com> - 3.31.90-1
+- Update to 3.31.90
+
+* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.31.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Thu Jan 10 2019 Florian Müllner <fmuellner@redhat.com> - 3.31.4-1
+- Update to 3.31.4
+
+* Sat Nov 17 2018 Kalev Lember <klember@redhat.com> - 3.31.2-2
+- Remove libtool .la files from private libs (#1622944)
+
+* Wed Nov 14 2018 Florian Müllner <fmuellner@redhat.com> - 3.31.2-1
+- Update to 3.31.2
+
+* Mon Oct 22 2018 Jonas Ådahl <jadahl@redhat.com> - 3.30.1-5
+- Backport work-around for hangul text input bug (rhbz#1632981)
+
+* Sat Oct 20 2018 Jonas Ådahl <jadahl@redhat.com> - 3.30.1-4
+- Backport a couple of memory leak fixes (rhbz#1641254)
+
+* Thu Oct 11 2018 Jonas Ådahl <jadahl@redhat.com> - 3.30.1-3
+- Fix disabled monitor when laptop lid is closed (rhbz#1638444)
+
+* Thu Oct 11 2018 David Herrmann <dh.herrmann@gmail.com> - 3.30.1-2
+- Reduce 'dbus-x11' dependency to 'dbus'. The xinit script are no longer the
+  canonical way to start dbus, but the 'dbus' package is nowadays required to
+  provide a user and system bus to its dependents.
+
+* Mon Oct 08 2018 Florian Müllner <fmuellner@redhat.com> - 3.30.1-1
+- Update to 3.30.1
+
+* Wed Oct 03 2018 Adam Williamson <awilliam@redhat.com> - 3.30.0-3
+- Backport fix for #1630943 from upstream master
+
+* Thu Sep 06 2018 Mateusz Mikuła <mati865@gmail.com> - 3.30.0-2
+- Enable EGLDevice support
+
+* Tue Sep 04 2018 Florian Müllner <fmuellner@redhat.com> - 3.30.0-1
+- Update to 3.30.0
+
+* Wed Aug 29 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.92-1
+- Update to 3.29.92
+
+* Mon Aug 20 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.91-1
+- Update to 3.29.91
+
+* Wed Aug 01 2018 Jan Grulich <jgrulich@redhat.com> - 3.29.90-2
+- Update libpipewire requirements
+
+* Wed Aug 01 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.90-1
+- Update to 3.29.90
+
+* Tue Jul 24 2018 Adam Williamson <awilliam@redhat.com> - 3.29.4-2
+- Backport MR#175 to fix 90/270 degree screen rotation
+
+* Wed Jul 18 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.4-1
+- Update to 3.29.4
+
+* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.29.2-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Fri Jun 01 2018 Adam Williamson <awilliam@redhat.com> - 3.29.2-2
+- Backport crasher fix from upstream master (#1585360)
+
+* Thu May 24 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.2-1
+- Update to 3.29.2
+
+* Wed Apr 25 2018 Florian Müllner <fmuellner@redhat.com> - 3.29.1-1
+- Update to 3.29.1
+
+* Fri Apr 13 2018 Florian Müllner <fmuellner@redhat.com> - 3.28.1-1
+- Update to 3.28.1
+
+* Mon Mar 12 2018 Florian Müllner <fmuellner@redhat.com> - 3.28.0-1
+- Update to 3.28.0
+
+* Mon Mar 05 2018 Florian Müllner <fmuellner@redhat.com> - 3.27.92-1
+- Update to 3.27.92
+
+* Wed Feb 28 2018 Adam Williamson <awilliam@redhat.com> - 3.27.91-2
+- Backport MR#36 to fix RHBZ #1547691 (GGO #2), mouse issues
+
+* Wed Feb 21 2018 Florian Müllner <fmuellner@redhat.com> - 3.27.91-1
+- Update to 3.27.91
+
+* Tue Feb 13 2018 Björn Esser <besser82@fedoraproject.org> - 3.27.1-4
+- Rebuild against newer gnome-desktop3 package
+- Add patch for adjustments to pipewire 0.1.8 API
+
+* Thu Feb 08 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.27.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Sat Jan 06 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 3.27.1-2
+- Remove obsolete scriptlets
+
+* Mon Oct 30 2017 Florian Müllner <fmuellner@redhat.com> - 3.27.1-1
+- Include 32-bit build fixes
+
+* Tue Oct 17 2017 Florian Müllner <fmuellner@redhat.com> - 3.27.1-1
+- Update to 3.27.1
+
+* Fri Oct 06 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.1-2
+- Fix screencasts
+
+* Wed Oct 04 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.1-1
+- Update to 3.26.1
+
+* Thu Sep 21 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.0-5
+- Adjust to pipewire API break
+
+* Wed Sep 20 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.0-5
+- Enable tablet support
+
+* Tue Sep 12 2017 Adam Williamson <awilliam@redhat.com> - 3.26.0-4
+- Also backport BGO #787570 fix from upstream
+
+* Tue Sep 12 2017 Adam Williamson <awilliam@redhat.com> - 3.26.0-3
+- Backport upstream fixes for crasher bug BGO #787568
+
+* Tue Sep 12 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.0-2
+- Enable remote desktop support
+
+* Tue Sep 12 2017 Florian Müllner <fmuellner@redhat.com> - 3.26.0-1
+- Update to 3.26.0
+
+* Thu Sep 07 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.92-1
+- Update to 3.25.92
+
+* Thu Aug 24 2017 Bastien Nocera <bnocera@redhat.com> - 3.25.91-2
++ mutter-3.25.91-2
+- Fix inverted red and blue channels with newer Mesa
+
+* Tue Aug 22 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.91-1
+- Update to 3.25.91
+
+* Thu Aug 10 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.90-1
+- Update to 3.25.90
+
+* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.25.4-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.25.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Wed Jul 19 2017 Florian Müllner <fmuellner@redhat.con> - 3.25.4-1
+- Update to 3.25.4
+
+* Wed Jun 21 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.3-1
+- Update to 3.25.3
+
+* Wed May 24 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.2-1
+- Update to 3.25.2
+
+* Thu May 18 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.1-2
+- Fix copy+paste of UTF8 strings between X11 and wayland
+
+* Thu Apr 27 2017 Florian Müllner <fmuellner@redhat.com> - 3.25.1-1
+- Update to 3.25.1
+
+* Tue Apr 11 2017 Florian Müllner <fmuellner@redhat.com> - 3.24.1-1
+- Update to 3.24.1
+
+* Mon Mar 20 2017 Florian Müllner <fmuellner@redhat.com> - 3.24.0-1
+- Update to 3.24.0
+
+* Tue Mar 14 2017 Florian Müllner <fmuellner@redhat.com> - 3.23.92-1
+- Update to 3.23.92
+
+* Fri Mar 10 2017 Florian Müllner <fmuellner@redhat.com> - 3.23.91-4
+- Apply startup-notification hack again
+
+* Tue Mar 07 2017 Adam Williamson <awilliam@redhat.com> - 3.23.91-3
+- Backport more color fixes, should really fix BGO #779234, RHBZ #1428559
+
+* Thu Mar 02 2017 Adam Williamson <awilliam@redhat.com> - 3.23.91-2
+- Backport fix for a color issue in 3.23.91 (BGO #779234, RHBZ #1428559)
+
+* Wed Mar 01 2017 Florian Müllner <fmuellner@redhat.com> - 3.23.91-1
+- Update to 3.23.91
+
+* Thu Feb 16 2017 Florian Müllner <fmuellner@redhat.com> - 3.23.90-1
+- Update to 3.23.90
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.23.3-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Thu Dec 15 2016 Florian Müllner <fmuellner@redhat.com> - 3.23.3-1
+- Update to 3.23.3
+
+* Fri Dec 02 2016 Florian Müllner <fmuellner@redhat.com> - 3.23.2-2
+- Fix build error on 32-bit platforms
+
+* Thu Nov 24 2016 Kevin Fenzi <kevin@scrye.com> - 3.23.2-2
+- Some fixes to get building. Still needs patch1 rebased.
+
+* Wed Nov 23 2016 Florian Müllner <fmuellner@redhat.com> - 3.23.2-1
+- Update to 3.23.2
+
+* Tue Nov  8 2016 Matthias Clasen <mclasen@redhat.com> - 3.23.1-2
+- Fix 1376471
+
+* Sun Oct 30 2016 Florian Müllner <fmuellner@redhat.com> - 3.23.1-1
+- Update to 3.23.1
+
+* Tue Oct 18 2016 Kalev Lember <klember@redhat.com> - 3.22.1-3
+- Backport a fix to make gnome-screenshot --area work
+
+* Tue Oct 11 2016 Adam Jackson <ajax@redhat.com> - 3.22.1-2
+- Prefer eglGetPlatformDisplay() to eglGetDisplay()
+
+* Tue Oct 11 2016 Florian Müllner <fmuellner@redhat.com> - 3.22.1-1
+- Update to 3.22.1
+
+* Wed Sep 28 2016 Florian Müllner <fmuellner@redhat.com> - 3.22.0-2
+- Include fix for crash on VT switch
+
+* Mon Sep 19 2016 Florian Müllner <fmuellner@redhat.com> - 3.22.0-1
+- Update to 3.22.0
+
+* Tue Sep 13 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.92-1
+- Update to 3.21.92
+
+* Thu Sep 08 2016 Kalev Lember <klember@redhat.com> - 3.21.91-2
+- wayland/cursor-role: Increase buffer use count on construction (#1373372)
+
+* Tue Aug 30 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.91-1
+- Update to 3.21.91
+
+* Mon Aug 29 2016 Kalev Lember <klember@redhat.com> - 3.21.90-3
+- clutter/evdev: Fix absolute pointer motion events (#1369492)
+
+* Sat Aug 20 2016 Kalev Lember <klember@redhat.com> - 3.21.90-2
+- Update minimum dep versions
+
+* Fri Aug 19 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.90-1
+- Update to 3.21.90
+
+* Wed Jul 20 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.4-1
+- Update to 3.21.4
+- Drop downstream patch
+- Fix build error on 32-bit
+
+* Tue Jun 21 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.3-1
+- Update to 3.21.3
+
+* Fri May 27 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.2-1
+- Update to 3.21.2
+
+* Fri Apr 29 2016 Florian Müllner <fmuellner@redhat.com> - 3.21.1-1
+- Update to 3.21.1
+
+* Wed Apr 13 2016 Florian Müllner <fmuellner@redhat.com> - 3.20.1-1
+- Update to 3.20.1
+
+* Tue Mar 22 2016 Florian Müllner <fmuellner@redhat.com> - 3.20.0-1
+- Update to 3.20.0
+
+* Wed Mar 16 2016 Florian Müllner <fmuellner@redhat.com> - 3.19.92-1
+- Update to 3.19.92
+
+* Thu Mar 03 2016 Florian Müllner <fmuellner@redhat.com> - 3.19.91-2
+- Include fix for invalid cursor wl_buffer access
+
+* Thu Mar 03 2016 Florian Müllner <fmuellner@redhat.com> - 3.19.91-1
+- Update to 3.19.91
+
+* Fri Feb 19 2016 Florian Müllner <fmuellner@redhat.com> - 3.19.90-1
+- Update to 3.19.90
+
+* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 3.19.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Thu Jan 21 2016 Florian Müllner <fmuellner@redhat.com> - 3.19.4-1
+- Update to 3.19.4
+
+* Thu Dec 17 2015 Florian Müllner <fmuellner@redhat.com> - 3.19.3-1
+- Update to 3.19.3
+
+* Wed Nov 25 2015 Florian Müllner <fmuellner@redhat.com> - 3.19.2-1
+- Update to 3.19.2
+
+* Tue Nov 10 2015 Ray Strode <rstrode@redhat.com> 3.19.1-5.20151110git049f1556d
+- Update to git snapshot
+
+* Thu Oct 29 2015 Florian Müllner <fmuellner@redhat.com> - 3.19.1-1
+- Update to 3.19.1
+
+* Wed Oct 21 2015 Ray Strode <rstrode@redhat.com> 3.18.1-4
+- Force the cursor visible on vt switches after setting
+  the crtc to workaround that qxl bug from before in a
+  different situation
+  Related: #1273247
+
+* Wed Oct 21 2015 Kalev Lember <klember@redhat.com> - 3.18.1-3
+- Backport a fix for a common Wayland crash (#1266486)
+
+* Thu Oct 15 2015 Kalev Lember <klember@redhat.com> - 3.18.1-2
+- Bump gnome-shell conflicts version
+
+* Thu Oct 15 2015 Florian Müllner <fmuellner@redhat.com> - 3.18.1-1
+- Update to 3.18.1
+
+* Mon Sep 21 2015 Florian Müllner <fmuellner@redhat.com> - 3.18.0-1
+- Update to 3.18.0
+
+* Wed Sep 16 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.92-1
+- Update to 3.17.92
+
+* Thu Sep 03 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.91-1
+- Update to 3.17.91
+
+* Thu Sep 03 2015 Ray Strode <rstrode@redhat.com> 3.17.90-2
+- Add workaround for qxl cursor visibility wonkiness that we
+  did for f22
+  Related: #1200901
+
+* Thu Aug 20 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.90-1
+- Update to 3.17.90
+
+* Thu Jul 23 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.4-1
+- Update to 3.17.4
+
+* Wed Jul 22 2015 David King <amigadave@amigadave.com> - 3.17.3-2
+- Bump for new gnome-desktop3
+
+* Thu Jul 02 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.3-1
+- Update to 3.17.3
+
+* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.17.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Wed May 27 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.2-1
+- Update to 3.17.2
+
+* Thu Apr 30 2015 Florian Müllner <fmuellner@redhat.com> - 3.17.1-1
+- Update to 3.17.1
+
+* Thu Apr 16 2015 Kalev Lember <kalevlember@gmail.com> - 3.16.1.1-2
+- Bump gnome-shell conflicts version
+
+* Wed Apr 15 2015 Rui Matos <rmatos@redhat.com> - 3.16.1.1-1
+- Update to 3.16.1.1
+
+* Tue Apr 14 2015 Florian Müllner <fmuellner@redhat.com> - 3.16.1-1
+- Update to 3.16.1
+
+* Mon Mar 23 2015 Florian Müllner <fmuellner@redhat.com> - 3.16.0-1
+- Update to 3.16.0
+
+* Tue Mar 17 2015 Kalev Lember <kalevlember@gmail.com> - 3.15.92-2
+- Update minimum dep versions
+- Use license macro for the COPYING file
+
+* Tue Mar 17 2015 Florian Müllner <fmuellner@redhat.com> - 3.15.92-1
+- Update to 3.15.92
+
+* Tue Mar 10 2015 Peter Hutterer <peter.hutterer@redhat.com> - 3.15.91-2
+- Rebuild for libinput soname bump
+
+* Wed Mar 04 2015 Florian Müllner <fmuellner@redhat.com> - 3.15.91-1
+- Update to 3.15.91
+
+* Fri Feb 20 2015 Florian Müllner <fmuellner@redhat.com> - 3.15.90-1
+- Update to 3.15.90
+
+* Mon Feb 02 2015 Adam Williamson <awilliam@redhat.com> - 3.15.4-2
+- backport ad90b7dd to fix BGO #743412 / RHBZ #1185811
+
+* Wed Jan 21 2015 Florian Müllner <fmuellner@redhat.com> - 3.15.4-1
+- Update to 3.15.4
+
+* Mon Jan 19 2015 Peter Hutterer <peter.hutterer@redhat.com> 3.15.3-3
+- Rebuild for libinput soname bump
+
+* Mon Jan 12 2015 Ray Strode <rstrode@redhat.com> 3.15.3-2
+- Add specific BuildRequires for wayland bits, so we don't
+  get wayland support by happenstance.
+- Add BuildRequires for autogoo since ./autogen.sh is run as part of
+  the build process
+
+* Fri Dec 19 2014 Florian Müllner <fmuellner@redhat.com> - 3.15.3-1
+- Revert unsatisfiable wayland requirement
+
+* Fri Dec 19 2014 Florian Müllner <fmuellner@redhat.com> - 3.15.3-1
+- Update to 3.15.3
+
+* Thu Nov 27 2014 Florian Müllner <fmuellner@redhat.com> - 3.15.2-1
+- Update to 3.15.2
+
+* Wed Nov 12 2014 Vadim Rutkovsky <vrutkovs@redhat.com> - 3.15.1-2
+- Build installed tests
+
+* Thu Oct 30 2014 Florian Müllner <fmuellner@redhat.com> - 3.15.1-1
+- Update to 3.15.1
+
+* Tue Oct 21 2014 Florian Müllner <fmuellner@redhat.com> - 3.14.1-2
+- Fix regression in handling raise-on-click option (rhbz#1151918)
+
+* Tue Oct 14 2014 Florian Müllner <fmuellner@redhat.com> - 3.14.1-1
+- Update to 3.14.1
+
+* Fri Oct 03 2014 Adam Williamson <awilliam@redhat.com> - 3.14.0-3
+- backport fix for BGO #737233 / RHBZ #1145952 (desktop right click broken)
+
+* Mon Sep 22 2014 Kalev Lember <kalevlember@gmail.com> - 3.14.0-2
+- Bump gnome-shell conflicts version
+
+* Mon Sep 22 2014 Florian Müllner <fmuellner@redhat.com> - 3.14.0-1
+- Update to 3.14.0
+
+* Wed Sep 17 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.92-1
+- Update to 3.13.92
+
+* Fri Sep 12 2014 Peter Hutterer <peter.hutterer@redhat.com> - 3.13.91-2
+- Rebuild for libinput soname bump
+
+* Wed Sep 03 2014 Florian Müllner <fmuellner@redhat.com> - 3.31.91-1
+- Update to 3.13.91, drop downstream patches
+
+* Tue Aug 26 2014 Adel Gadllah <adel.gadllah@gmail.com> - 3.13.90-4
+- Apply fix for RH #1133166
+
+* Mon Aug 25 2014 Hans de Goede <hdegoede@redhat.com> - 3.13.90-3
+- Add a patch from upstream fixing gnome-shell crashing non stop on
+  multi monitor setups (rhbz#1103221)
+
+* Fri Aug 22 2014 Kevin Fenzi <kevin@scrye.com> 3.13.90-2
+- Rebuild for new wayland
+
+* Wed Aug 20 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.90-1
+- Update to 3.13.90
+
+* Mon Aug 18 2014 Kalev Lember <kalevlember@gmail.com> - 3.13.4-3
+- Rebuilt for upower 0.99.1 soname bump
+
+* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.13.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Wed Jul 23 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.4-1
+- Update to 3.13.4
+
+* Tue Jul 22 2014 Kalev Lember <kalevlember@gmail.com> - 3.13.3-2
+- Rebuilt for gobject-introspection 1.41.4
+
+* Fri Jun 27 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.3-1
+- New gobject-introspection has been built, drop the last patch again
+
+* Wed Jun 25 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.3-1
+- Revert annotation updates until we get a new gobject-introspection build
+
+* Wed Jun 25 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.3-1
+- Update to 3.13.1
+
+* Wed Jun 11 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.2-2
+- Backport fix for legacy fullscreen check
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.13.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Tue May 27 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.2-1
+- Update to 3.13.2, drop upstreamed patches
+
+* Thu May  8 2014 Matthias Clasen <mclasen@redhat.com> - 3.13.1-5
+- Fix shrinking terminals
+
+* Wed May 07 2014 Kalev Lember <kalevlember@gmail.com> - 3.13.1-4
+- Backport an upstream fix for a Wayland session crash
+
+* Wed May 07 2014 Kalev Lember <kalevlember@gmail.com> - 3.13.1-3
+- Install mutter-launch as setuid root
+
+* Thu May 01 2014 Kalev Lember <kalevlember@gmail.com> - 3.13.1-2
+- Obsolete mutter-wayland
+
+* Wed Apr 30 2014 Florian Müllner <fmuellner@redhat.com> - 3.13.1-1
+- Update to 3.13.1
+
+* Tue Apr 15 2014 Florian Müllner <fmuellner@redhat.com> - 3.12.1-1
+- Update to 3.12.1
+
+* Sat Apr 05 2014 Kalev Lember <kalevlember@gmail.com> - 3.12.0-2
+- Update dep versions
+
+* Tue Mar 25 2014 Florian Müllner <fmuellner@redhat.com> - 3.12.0-1
+- Update to 3.12.0
+
+* Wed Mar 19 2014 Florian Müllner <fmuellner@redhat.com> - 3.11.92-1
+- Update to 3.11.92
+
+* Thu Mar 06 2014 Florian Müllner <fmuellner@redhat.com> - 3.11.91-1
+- Update to 3.11.91
+
+* Thu Feb 20 2014 Kalev Lember <kalevlember@gmail.com> - 3.11.90-2
+- Rebuilt for cogl soname bump
+
+* Wed Feb 19 2014 Florian Müllner <fmuellner@redhat.com> - 3.11.90-1
+- Update to 3.11.90
+
+* Wed Feb 19 2014 Richard Hughes <rhughes@redhat.com> - 3.11.5-4
+- Rebuilt for gnome-desktop soname bump
+
+* Mon Feb 10 2014 Peter Hutterer <peter.hutterer@redhat.com> - 3.11.5-3
+- Rebuild for libevdev soname bump
+
+* Wed Feb 05 2014 Richard Hughes <rhughes@redhat.com> - 3.11.5-2
+- Rebuilt for cogl soname bump
+
+* Wed Feb 05 2014 Florian Müllner <fmuellner@redhat.com> - 3.11.5-1
+- Update to 3.11.5
+
+* Wed Jan 15 2014 Florian Müllner <fmuellner@redhat.com> - 3.11.4-1
+- Update to 3.11.4
+
+* Fri Dec 20 2013 Florian Müllner <fmuellner@redhat.com> - 3.11.3-1
+- Update to 3.11.3
+
+* Wed Nov 13 2013 Florian Müllner <fmuellner@redhat.com> - 3.11.2-1
+- Update to 3.11.2
+
+* Wed Oct 30 2013 Florian Müllner <fmuellner@redhat.com> - 3.11.1-1
+- Update to 3.11.1
+
+* Tue Oct 15 2013 Florian Müllner <fmuellner@redhat.com> - 3.10.1.1-1
+- Update to 3.10.1.1
+
+* Mon Oct 14 2013 Florian Müllner <fmuellner@redhat.com> - 3.10.1-1
+- Update to 3.10.1
+
+* Wed Sep 25 2013 Florian Müllner <fmuellner@redhat.com> - 3.10.0.1-1
+- Update to 3.10.0.1
+
+* Mon Sep 23 2013 Florian Müllner <fmuellner@redhat.com> - 3.10.0-1
+- Update to 3.10.0
+
+* Tue Sep 17 2013 Kalev Lember <kalevlember@gmail.com> - 3.9.92-2
+- Update the description and URL
+- Tighten -devel subpackage deps with _isa
+- Use the make_install macro
+
+* Mon Sep 16 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.92-1
+- Update to 3.9.92
+
+* Tue Sep 03 2013 Kalev Lember <kalevlember@gmail.com> - 3.9.91-2
+- Rebuilt for libgnome-desktop soname bump
+
+* Tue Sep 03 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.91-1
+- Update to 3.9.91
+
+* Thu Aug 22 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.90-1
+- Update to 3.9.90
+
+* Fri Aug 09 2013 Kalev Lember <kalevlember@gmail.com> - 3.9.5-2
+- Rebuilt for cogl 1.15.4 soname bump
+
+* Tue Jul 30 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.5-1
+- Update to 3.9.5
+
+* Wed Jul 10 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.4-1
+- Update to 3.9.4
+
+* Tue Jun 18 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.3-1
+- Update to 3.9.3
+
+* Tue May 28 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.2-1
+- Update to 3.9.2
+
+* Wed May 01 2013 Florian Müllner <fmuellner@redhat.com> - 3.9.1-1
+- Update to 3.9.1
+
+* Tue Apr 23 2013 Florian Müllner <fmuellner@redhat.com> - 3.8.1-1
+- Update to 3.8.1
+
+* Tue Mar 26 2013 Florian Müllner <fmuellner@redhat.com> - 3.8.0-1
+- Update to 3.8.0
+
+* Tue Mar 19 2013 Florian Müllner <fmuellner@redhat.com> - 3.7.92-1
+- Update to 3.7.92
+
+* Mon Mar 04 2013 Florian Müllner <fmuellner@redhat.com> - 3.7.91-1
+- Update to 3.7.91
+
+* Wed Feb 20 2013 Florian Müllner <fmuellner@redhat.com> - 3.7.90-1
+- Update to 3.7.90
+
+* Tue Feb 05 2013 Florian Müllner <fmuellner@redhat.com> - 3.7.5-1
+- Update to 3.7.5
+
+* Fri Jan 25 2013 Peter Robinson <pbrobinson@fedoraproject.org> 3.7.4-2
+- Rebuild for new cogl
+
+* Tue Jan 15 2013 Florian Müllner <fmuellner@redhat.com> - 3.7.4-1
+- Update to 3.7.4
+
+* Tue Dec 18 2012 Florian Müllner <fmuellner@redhat.com> - 3.7.3-1
+- Update to 3.7.3
+
+* Mon Nov 19 2012 Florian Müllner <fmuellner@redhat.com> - 3.7.2-1
+- Update to 3.7.2
+
+* Fri Nov 09 2012 Kalev Lember <kalevlember@gmail.com> - 3.7.1-1
+- Update to 3.7.1
+
+* Mon Oct 15 2012 Florian Müllner <fmuellner@redhat.com> - 3.6.1-1
+- Update to 3.6.1
+
+* Tue Sep 25 2012 Florian Müllner <fmuellner@redhat.com> - 3.6.0-1
+- Update to 3.6.0
+
+* Wed Sep 19 2012 Florian Müllner <fmuellner@redhat.com> - 3.5.92-1
+- Update to 3.5.92
+
+* Tue Sep 04 2012 Debarshi Ray <rishi@fedoraproject.org> - 3.5.91-2
+- Rebuild against new cogl
+
+* Tue Sep 04 2012 Debarshi Ray <rishi@fedoraproject.org> - 3.5.91-1
+- Update to 3.5.91
+
+* Tue Aug 28 2012 Matthias Clasen <mclasen@redhat.com> - 3.5.90-2
+- Rebuild against new cogl/clutter
+
+* Tue Aug 21 2012 Richard Hughes <hughsient@gmail.com> - 3.5.90-1
+- Update to 3.5.90
+
+* Tue Aug 07 2012 Richard Hughes <hughsient@gmail.com> - 3.5.5-1
+- Update to 3.5.5
+
+* Fri Jul 27 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.5.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Tue Jul 17 2012 Richard Hughes <hughsient@gmail.com> - 3.5.4-1
+- Update to 3.5.4
+
+* Tue Jun 26 2012 Matthias Clasen <mclasen@redhat.com> - 3.5.3-1
+- Update to 3.5.3
+
+* Fri Jun  8 2012 Matthias Clasen <mclasen@redhat.com> - 3.5.2-3
+- Make resize grip area larger
+
+* Thu Jun 07 2012 Matthias Clasen <mclasen@redhat.com> - 3.5.2-2
+- Don't check for Xinerama anymore - it is now mandatory
+
+* Thu Jun 07 2012 Richard Hughes <hughsient@gmail.com> - 3.5.2-1
+- Update to 3.5.2
+- Remove upstreamed patches
+
+* Wed May 09 2012 Adam Jackson <ajax@redhat.com> 3.4.1-3
+- mutter-never-slice-shape-mask.patch, mutter-use-cogl-texrect-api.patch:
+  Fix window texturing on hardware without ARB_texture_non_power_of_two
+  (#813648)
+
+* Wed Apr 18 2012 Kalev Lember <kalevlember@gmail.com> - 3.4.1-2
+- Silence glib-compile-schemas scriplets
+
+* Wed Apr 18 2012 Kalev Lember <kalevlember@gmail.com> - 3.4.1-1
+- Update to 3.4.1
+- Conflict with gnome-shell versions older than 3.4.1
+
+* Tue Mar 27 2012 Richard Hughes <hughsient@gmail.com> - 3.4.0-1
+- Update to 3.4.0
+
+* Wed Mar 21 2012 Kalev Lember <kalevlember@gmail.com> - 3.3.92-1
+- Update to 3.3.92
+
+* Sat Mar 10 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.90-2
+- Rebuild against new cogl
+
+* Sat Feb 25 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.90-1
+- Update to 3.3.90
+
+* Tue Feb  7 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.5-1
+- Update to 3.3.5
+
+* Fri Jan 20 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.4-1
+- Update to 3.3.4
+
+* Thu Jan 19 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.3-2
+- Rebuild against new cogl
+
+* Thu Jan  5 2012 Matthias Clasen <mclasen@redhat.com> - 3.3.3-1
+- Update to 3.3.3
+
+* Wed Nov 23 2011 Matthias Clasen <mclasen@redhat.com> - 3.3.2-2
+- Rebuild against new clutter
+
+* Tue Nov 22 2011 Matthias Clasen <mclasen@redhat.com> - 3.3.2-1
+- Update to 3.3.2
+
+* Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.1-2
+- Rebuilt for glibc bug#747377
+
+* Wed Oct 19 2011 Matthias Clasen <mclasen@redhat.com> - 3.2.1-1
+- Update to 3.2.1
+
+* Mon Sep 26 2011 Owen Taylor <otaylor@redhat.com> - 3.2.0-1
+- Update to 3.2.0
+
+* Tue Sep 20 2011 Matthias Clasen <mclasen@redhat.com> - 3.1.92-1
+- Update to 3.1.92
+
+* Wed Sep 14 2011 Owen Taylor <otaylor@redhat.com> - 3.1.91.1-1
+- Update to 3.1.91.1
+
+* Wed Aug 31 2011 Matthias Clasen <mclasen@redhat.com> - 3.1.90.1-1
+- Update to 3.1.90.1
+
+* Wed Jul 27 2011 Matthias Clasen <mclasen@redhat.com> - 3.1.4-1
+- Update to 3.1.4
+
+* Wed Jul 27 2011 Matthias Clasen <mclasen@redhat.com> - 3.1.3.1-3
+- Rebuild
+
+* Mon Jul  4 2011 Peter Robinson <pbrobinson@gmail.com> - 3.1.3.1-2
+- rebuild against new clutter/cogl
+
+* Mon Jul 04 2011 Adam Williamson <awilliam@redhat.com> - 3.1.3.1-1
+- Update to 3.1.3.1
+
+* Thu Jun 30 2011 Owen Taylor <otaylor@redhat.com> - 3.1.3-1
+- Update to 3.1.3
+
+* Wed May 25 2011 Owen Taylor <otaylor@redhat.com> - 3.0.2.1-1
+- Update to 3.0.2.1
+
+* Fri Apr 29 2011 Matthias Clasen <mclasen@redhat.com> - 3.0.1-3
+- Actually apply the patch for #700276
+
+* Thu Apr 28 2011 Matthias Clasen <mclasen@redhat.com> - 3.0.1-2
+- Make session saving of gnome-shell work
+
+* Mon Apr 25 2011 Owen Taylor <otaylor@redhat.com> - 3.0.1-1
+- Update to 3.0.1
+
+* Mon Apr  4 2011 Owen Taylor <otaylor@redhat.com> - 3.0.0-1
+- Update to 3.0.0
+
+* Mon Mar 28 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.93-1
+- Update to 2.91.93
+
+* Wed Mar 23 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.92-1
+- Update to 2.91.92
+
+* Mon Mar  7 2011 Owen Taylor <otaylor@redhat.com> - 2.91.91-1
+- Update to 2.91.91
+
+* Tue Mar  1 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.90-2
+- Build against libcanberra, to enable AccessX feedback features
+
+* Tue Feb 22 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.90-1
+- Update to 2.91.90
+
+* Thu Feb 10 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.6-4
+- Rebuild against newer gtk
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.91.6-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Wed Feb  2 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.6-2
+- Rebuild against newer gtk
+
+* Tue Feb  1 2011 Owen Taylor <otaylor@redhat.com> - 2.91.6-1
+- Update to 2.91.6
+
+* Tue Jan 11 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.5-1
+- Update to 2.91.5
+
+* Fri Jan  7 2011 Matthias Clasen <mclasen@redhat.com> - 2.91.4-1
+- Update to 2.91.4
+
+* Fri Dec  3 2010 Matthias Clasen <mclasen@redhat.com> - 2.91.3-2
+- Rebuild against new gtk
+- Drop no longer needed %%clean etc
+
+* Mon Nov 29 2010 Owen Taylor <otaylor@redhat.com> - 2.91.3-1
+- Update to 2.91.3
+
+* Tue Nov  9 2010 Owen Taylor <otaylor@redhat.com> - 2.91.2-1
+- Update to 2.91.2
+
+* Tue Nov  2 2010 Matthias Clasen <mclasen@redhat.com> - 2.91.1-2
+- Rebuild against newer gtk3
+
+* Fri Oct 29 2010 Owen Taylor <otaylor@redhat.com> - 2.91.1-1
+- Update to 2.91.1
+
+* Mon Oct  4 2010 Owen Taylor <otaylor@redhat.com> - 2.91.0-1
+- Update to 2.91.0
+
+* Wed Sep 22 2010 Matthias Clasen <mclasen@redhat.com> - 2.31.5-4
+- Rebuild against newer gobject-introspection
+
+* Wed Jul 14 2010 Colin Walters <walters@verbum.org> - 2.31.5-3
+- Rebuild for new gobject-introspection
+
+* Tue Jul 13 2010 Adel Gadllah <adel.gadllah@gmail.com> - 2.31.5-2
+- Build against gtk3
+
+* Mon Jul 12 2010 Colin Walters <walters@pocket> - 2.31.5-1
+- New upstream version
+
+* Mon Jul 12 2010 Colin Walters <walters@verbum.org> - 2.31.2-5
+- Rebuild against new gobject-introspection
+
+* Tue Jul  6 2010 Colin Walters <walters@verbum.org> - 2.31.2-4
+- Changes to support snapshot builds
+
+* Fri Jun 25 2010 Colin Walters <walters@megatron> - 2.31.2-3
+- drop gir-repository-devel dep
+
+* Wed May 26 2010 Adam Miller <maxamillion@fedoraproject.org> - 2.31.2-2
+- removed "--with-clutter" as configure is claiming it to be an unknown option
+
+* Wed May 26 2010 Adam Miller <maxamillion@fedoraproject.org> - 2.31.2-1
+- New upstream 2.31.2 release
+
+* Thu Mar 25 2010 Peter Robinson <pbrobinson@gmail.com> 2.29.1-1
+- New upstream 2.29.1 release
+
+* Wed Mar 17 2010 Peter Robinson <pbrobinson@gmail.com> 2.29.0-1
+- New upstream 2.29.0 release
+
+* Tue Feb 16 2010 Adam Jackson <ajax@redhat.com> 2.28.1-0.2
+- mutter-2.28.1-add-needed.patch: Fix FTBFS from --no-add-needed
+
+* Thu Feb  4 2010 Peter Robinson <pbrobinson@gmail.com> 2.28.1-0.1
+- Move to git snapshot
+
+* Wed Oct  7 2009 Owen Taylor <otaylor@redhat.com> - 2.28.0-1
+- Update to 2.28.0
+
+* Tue Sep 15 2009 Owen Taylor <otaylor@redhat.com> - 2.27.5-1
+- Update to 2.27.5
+
+* Fri Sep  4 2009 Owen Taylor <otaylor@redhat.com> - 2.27.4-1
+- Remove workaround for #520209
+- Update to 2.27.4
+
+* Sat Aug 29 2009 Owen Taylor <otaylor@redhat.com> - 2.27.3-3
+- Fix %%preun GConf script to properly be for package removal
+
+* Fri Aug 28 2009 Owen Taylor <otaylor@redhat.com> - 2.27.3-2
+- Add a workaround for Red Hat bug #520209
+
+* Fri Aug 28 2009 Owen Taylor <otaylor@redhat.com> - 2.27.3-1
+- Update to 2.27.3, remove mutter-metawindow.patch
+
+* Fri Aug 21 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.2-2
+- Add upstream patch needed by latest mutter-moblin
+
+* Tue Aug 11 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.2-1
+- New upstream 2.27.2 release. Drop upstreamed patches.
+
+* Wed Jul 29 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.1-5
+- Add upstream patches for clutter 1.0
+
+* Wed Jul 29 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.1-4
+- Add patch to fix mutter --replace
+
+* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.27.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Sat Jul 18 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.1-2
+- Updates from review request
+
+* Fri Jul 17 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.1-1
+- Update to official 2.27.1 and review updates
+
+* Thu Jun 18 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.0-0.2
+- Updates from initial reviews
+
+* Thu Jun 18 2009 Peter Robinson <pbrobinson@gmail.com> 2.27.0-0.1
+- Initial packaging