diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d71c898
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/mutter-3.32.2.tar.xz
diff --git a/.mutter.metadata b/.mutter.metadata
new file mode 100644
index 0000000..9e3c1a4
--- /dev/null
+++ b/.mutter.metadata
@@ -0,0 +1 @@
+5068f43514a6212e4b5b5f7f856b7713cbc3d420 SOURCES/mutter-3.32.2.tar.xz
diff --git a/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch b/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch
new file mode 100644
index 0000000..397dc41
--- /dev/null
+++ b/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch
@@ -0,0 +1,907 @@
+From d0ad5ea18bb02112837bcdf7270d58d8ad235a4d 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] 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.
+---
+ src/compositor/compositor-private.h          |   9 ++
+ src/compositor/compositor.c                  | 125 +++++++++++++++
+ src/compositor/meta-shaped-texture-private.h |   5 +-
+ src/compositor/meta-shaped-texture.c         |  84 +++++++++-
+ src/compositor/meta-surface-actor-wayland.c  |   2 +-
+ src/compositor/meta-surface-actor-x11.c      |  54 ++++++-
+ 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-surface.c           |   2 +-
+ 14 files changed, 481 insertions(+), 20 deletions(-)
+ create mode 100644 src/core/stereo.c
+ create mode 100644 src/core/stereo.h
+
+diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
+index 6ab33416c..f70087512 100644
+--- a/src/compositor/compositor-private.h
++++ b/src/compositor/compositor-private.h
+@@ -24,6 +24,10 @@ struct _MetaCompositor
+   gint64          server_time_query_time;
+   gint64          server_time_offset;
+ 
++  int             glx_opcode;
++  guint           stereo_tree_ext : 1;
++  guint           have_stereo_windows : 1;
++
+   guint           server_time_is_monotonic_time : 1;
+ 
+   ClutterActor          *stage, *window_group, *top_window_group, *feedback_group;
+@@ -63,6 +67,11 @@ void     meta_end_modal_for_plugin   (MetaCompositor   *compositor,
+ gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
+                                                       gint64       monotonic_time);
+ 
++gboolean meta_compositor_window_is_stereo     (MetaDisplay *display,
++                                               Window       xwindow);
++void     meta_compositor_select_stereo_notify (MetaDisplay *display,
++                                               Window       xwindow);
++
+ void meta_compositor_flash_window (MetaCompositor *compositor,
+                                    MetaWindow     *window);
+ 
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 2a2c8fb3b..6c08c8fe4 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -69,6 +69,8 @@
+ #include "core/core.h"
+ #include "core/display-private.h"
+ #include "core/frame.h"
++#include "core/stack-tracker.h"
++#include "core/stereo.h"
+ #include "core/util-private.h"
+ #include "core/window-private.h"
+ #include "meta/compositor-mutter.h"
+@@ -514,6 +516,94 @@ redirect_windows (MetaX11Display *x11_display)
+     }
+ }
+ 
++#define GLX_STEREO_TREE_EXT        0x20F5
++#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
++#define GLX_STEREO_NOTIFY_EXT      0x00000000
++
++typedef struct {
++  int type;
++  unsigned long serial;
++  Bool send_event;
++  Display *display;
++  int extension;
++  int evtype;
++  Drawable window;
++  Bool stereo_tree;
++} StereoNotifyEvent;
++
++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_window_is_stereo (MetaDisplay *display,
++                                  Window       xwindow)
++{
++  MetaCompositor *compositor = get_compositor_for_display (display);
++  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->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_select_stereo_notify (MetaDisplay *display,
++                                      Window       xwindow)
++{
++  MetaCompositor *compositor = get_compositor_for_display (display);
++  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
++
++  static void (*select_event) (Display      *dpy,
++                               Drawable      draw,
++                               unsigned long event_mask);
++
++  if (compositor->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);
++    }
++}
++
+ void
+ meta_compositor_manage (MetaCompositor *compositor)
+ {
+@@ -525,6 +615,8 @@ meta_compositor_manage (MetaCompositor *compositor)
+     {
+       xdisplay = display->x11_display->xdisplay;
+       meta_x11_display_set_cm_selection (display->x11_display);
++
++      compositor->stereo_tree_ext = display_has_stereo_tree_ext (display->x11_display);
+     }
+ 
+   compositor->stage = meta_backend_get_stage (backend);
+@@ -822,6 +914,23 @@ meta_compositor_process_event (MetaCompositor *compositor,
+       if (window)
+         process_damage (compositor, (XDamageNotifyEvent *) event, window);
+     }
++  else if (!meta_is_wayland_compositor () &&
++           event->type == GenericEvent &&
++           event->xcookie.extension == compositor->glx_opcode)
++    {
++      if (event->xcookie.evtype == GLX_STEREO_NOTIFY_EXT)
++        {
++          StereoNotifyEvent *stereo_event = (StereoNotifyEvent *)(event->xcookie.data);
++          window = meta_x11_display_lookup_x_window (x11_display, stereo_event->window);
++
++          if (window != NULL)
++            {
++              MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
++              meta_window_actor_stereo_notify (window_actor, stereo_event->stereo_tree);
++              meta_stack_tracker_queue_sync_stack (window->display->stack_tracker);
++            }
++        }
++    }
+ 
+   if (compositor->have_x11_sync_object)
+     meta_sync_ring_handle_event (event);
+@@ -1038,6 +1147,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+ 			    GList	    *stack)
+ {
+   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
+@@ -1113,6 +1223,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+        * near the front of the other.)
+        */
+       compositor->windows = g_list_prepend (compositor->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);
+@@ -1120,6 +1232,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+ 
+   sync_actor_stacking (compositor);
+ 
++  meta_stereo_set_have_stereo_windows (stereo_window_count > 0);
++
+   if (compositor->top_window_actor)
+     g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
+                                           on_top_window_actor_destroyed,
+@@ -1325,6 +1439,17 @@ meta_compositor_new (MetaDisplay *display)
+                                            meta_post_paint_func,
+                                            compositor,
+                                            NULL);
++  if (!meta_is_wayland_compositor ())
++    {
++      Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
++      int glx_major_opcode, glx_first_event, glx_first_error;
++
++      if (XQueryExtension (xdisplay,
++                           "GLX",
++                           &glx_major_opcode, &glx_first_event, &glx_first_error))
++        compositor->glx_opcode = glx_major_opcode;
++    }
++
+   return compositor;
+ }
+ 
+diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
+index a86a2bff0..d0efdd4dc 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"
+ 
+ ClutterActor *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 ea8daa03d..9a00ccd6d 100644
+--- a/src/compositor/meta-shaped-texture.c
++++ b/src/compositor/meta-shaped-texture.c
+@@ -102,8 +102,10 @@ struct _MetaShapedTexture
+   ClutterActor parent;
+ 
+   MetaTextureTower *paint_tower;
++  MetaTextureTower *paint_tower_right;
+ 
+   CoglTexture *texture;
++  CoglTexture *texture_right;
+   CoglTexture *mask_texture;
+   CoglSnippet *snippet;
+ 
+@@ -192,6 +194,7 @@ meta_shaped_texture_init (MetaShapedTexture *stex)
+     clutter_backend_get_cogl_context (clutter_backend);
+ 
+   stex->paint_tower = meta_texture_tower_new ();
++  stex->paint_tower_right = NULL; /* demand create */
+ 
+   stex->texture = NULL;
+   stex->mask_texture = NULL;
+@@ -335,6 +338,9 @@ meta_shaped_texture_dispose (GObject *object)
+     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->opaque_region, cairo_region_destroy);
+ 
+@@ -611,8 +617,9 @@ paint_clipped_rectangle (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;
+ 
+@@ -620,10 +627,13 @@ set_cogl_texture (MetaShapedTexture *stex,
+ 
+   if (stex->texture)
+     cogl_object_unref (stex->texture);
++  if (stex->texture_right)
++    cogl_object_unref (stex->texture_right);
+ 
+   g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy);
+ 
+   stex->texture = cogl_tex;
++  stex->texture_right = cogl_tex_right;
+ 
+   if (cogl_tex != NULL)
+     {
+@@ -637,6 +647,9 @@ set_cogl_texture (MetaShapedTexture *stex,
+       height = 0;
+     }
+ 
++  if (cogl_tex_right != NULL)
++    cogl_object_ref (cogl_tex_right);
++
+   if (stex->tex_width != width ||
+       stex->tex_height != height)
+     {
+@@ -650,8 +663,23 @@ set_cogl_texture (MetaShapedTexture *stex,
+    * previous buffer. We only queue a redraw in response to surface
+    * damage. */
+ 
++  if (cogl_tex_right != NULL)
++    {
++      if (stex->paint_tower_right == NULL)
++        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
+@@ -927,7 +955,9 @@ meta_shaped_texture_paint (ClutterActor *actor)
+ {
+   MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor);
+   CoglTexture *paint_tex;
++  CoglTexture *paint_tex_right = NULL;
+   CoglFramebuffer *fb;
++  gboolean stereo;
+ 
+   if (!stex->texture)
+     return;
+@@ -989,7 +1019,32 @@ meta_shaped_texture_paint (ClutterActor *actor)
+     return;
+ 
+   fb = cogl_get_draw_framebuffer ();
+-  do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region);
++
++  stereo = stex->texture_right && cogl_framebuffer_get_is_stereo (fb);
++
++  if (stereo)
++    {
++      if (stex->create_mipmaps)
++	paint_tex_right = meta_texture_tower_get_paint_texture (stex->paint_tower_right);
++
++      if (!paint_tex_right)
++	paint_tex_right = COGL_TEXTURE (stex->texture_right);
++    }
++  else
++    paint_tex_right = NULL;
++
++  if (stereo)
++    cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT);
++  do_paint (stex, fb, paint_tex, stex->clip_region);
++  if (stereo)
++    cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
++
++  if (paint_tex_right != NULL)
++    {
++      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT);
++      do_paint (stex, fb, paint_tex_right, stex->clip_region);
++      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
++    }
+ }
+ 
+ static void
+@@ -1063,6 +1118,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);
++        }
+     }
+ }
+ 
+@@ -1256,6 +1317,12 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
+                                   clip.y,
+                                   clip.width,
+                                   clip.height);
++  if (stex->paint_tower_right)
++    meta_texture_tower_update_area (stex->paint_tower_right,
++                                    clip.x,
++                                    clip.y,
++                                    clip.width,
++                                    clip.height);
+ 
+   stex->prev_invalidation = stex->last_invalidation;
+   stex->last_invalidation = g_get_monotonic_time ();
+@@ -1302,17 +1369,18 @@ 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));
+ 
+-  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 f8d6c32b7..a75c4dd09 100644
+--- a/src/compositor/meta-surface-actor-wayland.c
++++ b/src/compositor/meta-surface-actor-wayland.c
+@@ -182,7 +182,7 @@ meta_surface_actor_wayland_dispose (GObject *object)
+   MetaShapedTexture *stex =
+     meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+ 
+-  meta_shaped_texture_set_texture (stex, NULL);
++  meta_shaped_texture_set_textures (stex, NULL, NULL);
+   if (self->surface)
+     {
+       g_object_remove_weak_pointer (G_OBJECT (self->surface),
+diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c
+index 244b1e885..3cd164d77 100644
+--- a/src/compositor/meta-surface-actor-x11.c
++++ b/src/compositor/meta-surface-actor-x11.c
+@@ -32,6 +32,7 @@
+ #include "cogl/winsys/cogl-texture-pixmap-x11.h"
+ #include "compositor/meta-cullable.h"
+ #include "compositor/meta-shaped-texture-private.h"
++#include "compositor-private.h"
+ #include "core/window-private.h"
+ #include "meta/meta-x11-errors.h"
+ #include "x11/meta-x11-display-private.h"
+@@ -46,6 +47,7 @@ struct _MetaSurfaceActorX11
+   MetaDisplay *display;
+ 
+   CoglTexture *texture;
++  CoglTexture *texture_right;
+   Pixmap pixmap;
+   Damage damage;
+ 
+@@ -61,6 +63,8 @@ struct _MetaSurfaceActorX11
+   guint size_changed : 1;
+ 
+   guint unredirected   : 1;
++
++  guint stereo : 1;
+ };
+ 
+ G_DEFINE_TYPE (MetaSurfaceActorX11,
+@@ -96,7 +100,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);
+@@ -105,6 +109,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
+@@ -114,23 +119,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));
+   CoglError *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);
+       cogl_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!\n");
+ 
+-  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
+@@ -419,8 +438,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 *
+@@ -428,12 +447,17 @@ 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);
++  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_window_is_stereo (display, xwindow);
++  meta_compositor_select_stereo_notify (display, xwindow);
++
+   g_signal_connect_object (self->display, "gl-video-memory-purged",
+                            G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED);
+ 
+@@ -463,3 +487,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 2c4ed4dd6..3bdd5fdb0 100644
+--- a/src/compositor/meta-surface-actor-x11.h
++++ b/src/compositor/meta-surface-actor-x11.h
+@@ -47,6 +47,11 @@ MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
+ void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
+                                       int width, int height);
+ 
++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 6333f43db..9c1c12d09 100644
+--- a/src/compositor/meta-window-actor-private.h
++++ b/src/compositor/meta-window-actor-private.h
+@@ -76,4 +76,9 @@ MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
+ void meta_window_actor_update_surface (MetaWindowActor *self);
+ MetaWindowActor *meta_window_actor_from_window (MetaWindow *window);
+ 
++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 1c8dc8fe5..11686d00b 100644
+--- a/src/compositor/meta-window-actor.c
++++ b/src/compositor/meta-window-actor.c
+@@ -2031,3 +2031,25 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface)
+   iface->capture_into = meta_window_actor_capture_into;
+   iface->has_damage = meta_window_actor_has_damage;
+ }
++
++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 e8464720f..629f8e94e 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -81,6 +81,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"
+ 
+@@ -589,6 +590,9 @@ meta_init (void)
+ 
+   meta_init_backend (backend_gtype);
+ 
++  if (!meta_is_wayland_compositor ())
++    meta_stereo_init ();
++
+   meta_clutter_init ();
+ 
+ #ifdef HAVE_WAYLAND
+diff --git a/src/core/stereo.c b/src/core/stereo.c
+new file mode 100644
+index 000000000..817056527
+--- /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 000000000..ccd1d702a
+--- /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 9919b5cfb..7cced8f53 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -353,6 +353,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-surface.c b/src/wayland/meta-wayland-surface.c
+index da0acfcbb..ddad1a45c 100644
+--- a/src/wayland/meta-wayland-surface.c
++++ b/src/wayland/meta-wayland-surface.c
+@@ -731,7 +731,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface      *surface,
+               snippet = meta_wayland_buffer_create_snippet (pending->buffer);
+               is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
+ 
+-              meta_shaped_texture_set_texture (stex, texture);
++              meta_shaped_texture_set_textures (stex, texture, NULL);
+               meta_shaped_texture_set_snippet (stex, snippet);
+               meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
+               g_clear_pointer (&snippet, cogl_object_unref);
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch b/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch
new file mode 100644
index 0000000..732b754
--- /dev/null
+++ b/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch
@@ -0,0 +1,55 @@
+From 38d88d4e4286c3ada041561426873e44fdba3c40 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 17 Jan 2020 14:45:00 +0100
+Subject: [PATCH] Create explicit WacomDevices for tablet "touchpad" devices
+
+---
+ src/backends/meta-input-settings.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
+index 28dc387ef9..820a3b201e 100644
+--- a/src/backends/meta-input-settings.c
++++ b/src/backends/meta-input-settings.c
+@@ -521,27 +521,34 @@ static gboolean
+ device_is_tablet_touchpad (MetaInputSettings  *input_settings,
+                            ClutterInputDevice *device)
+ {
++  gboolean is_tablet = FALSE;
+ #ifdef HAVE_LIBWACOM
++  MetaInputSettingsPrivate *priv;
+   WacomIntegrationFlags flags = 0;
+   WacomDevice *wacom_device;
+ 
++  priv = meta_input_settings_get_instance_private (input_settings);
++
+   if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
+     return FALSE;
+ 
+   wacom_device =
+-    meta_input_settings_get_tablet_wacom_device (input_settings,
+-                                                 device);
++    libwacom_new_from_path (priv->wacom_db,
++                            clutter_input_device_get_device_node (device),
++                            WFALLBACK_NONE, NULL);
+   if (wacom_device)
+     {
+       flags = libwacom_get_integration_flags (wacom_device);
+ 
+       if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
+                     WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
+-        return TRUE;
++        is_tablet = TRUE;
++
++      libwacom_destroy (wacom_device);
+     }
+ #endif
+ 
+-  return FALSE;
++  return is_tablet;
+ }
+ 
+ static void
+-- 
+2.25.0.rc2
+
diff --git a/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch b/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch
new file mode 100644
index 0000000..ae7ff46
--- /dev/null
+++ b/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch
@@ -0,0 +1,68 @@
+From abfc64268d4135663fb46c5f3529cd5f082a5c20 Mon Sep 17 00:00:00 2001
+From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
+Date: Sun, 20 Oct 2019 12:04:31 +0200
+Subject: [PATCH] EGL: Include EGL/eglmesaext.h
+
+The eglext.h shipped by libglvnd does not include the Mesa extensions,
+unlike the header shipped in Mesa.
+
+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/876
+---
+ cogl/cogl/meson.build       | 2 +-
+ src/backends/meta-egl-ext.h | 1 +
+ src/backends/meta-egl.c     | 1 +
+ src/backends/meta-egl.h     | 1 +
+ 4 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build
+index cb940420a..8032669e4 100644
+--- a/cogl/cogl/meson.build
++++ b/cogl/cogl/meson.build
+@@ -48,7 +48,7 @@ cogl_gl_header_h = configure_file(
+ built_headers += [cogl_gl_header_h]
+ 
+ if have_egl
+-  cogl_egl_includes_string = '#include <EGL/egl.h>\n#include <EGL/eglext.h>'
++  cogl_egl_includes_string = '#include <EGL/egl.h>\n#include <EGL/eglext.h>\n#include <EGL/eglmesaext.h>'
+ else
+   cogl_egl_includes_string = ''
+ endif
+diff --git a/src/backends/meta-egl-ext.h b/src/backends/meta-egl-ext.h
+index 8705e7d5b..db0b74f76 100644
+--- a/src/backends/meta-egl-ext.h
++++ b/src/backends/meta-egl-ext.h
+@@ -29,6 +29,7 @@
+ 
+ #include <EGL/egl.h>
+ #include <EGL/eglext.h>
++#include <EGL/eglmesaext.h>
+ 
+ /*
+  * This is a little different to the tests shipped with EGL implementations,
+diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
+index 8b953449a..a28eef4ca 100644
+--- a/src/backends/meta-egl.c
++++ b/src/backends/meta-egl.c
+@@ -26,6 +26,7 @@
+ 
+ #include <EGL/egl.h>
+ #include <EGL/eglext.h>
++#include <EGL/eglmesaext.h>
+ #include <gio/gio.h>
+ #include <glib.h>
+ #include <glib-object.h>
+diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h
+index ff37f124f..81b53b32d 100644
+--- a/src/backends/meta-egl.h
++++ b/src/backends/meta-egl.h
+@@ -27,6 +27,7 @@
+ 
+ #include <EGL/egl.h>
+ #include <EGL/eglext.h>
++#include <EGL/eglmesaext.h>
+ #include <glib-object.h>
+ 
+ #define META_EGL_ERROR meta_egl_error_quark ()
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch b/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch
new file mode 100644
index 0000000..f61ecf6
--- /dev/null
+++ b/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch
@@ -0,0 +1,28 @@
+From d9d355bfd8ecfb7dcf65a3810ec30e12f12673ab 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] 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 076dca8cb..0adf2100d 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -527,8 +527,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);
+ }
+ 
+ static gboolean
+-- 
+2.24.1
+
diff --git a/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch b/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch
new file mode 100644
index 0000000..ba10e5e
--- /dev/null
+++ b/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch
@@ -0,0 +1,94 @@
+From dafc9cb414fd47112b972d34c205e73797a3c1c1 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 21 Feb 2020 16:45:35 +0100
+Subject: [PATCH] Skip wacom touchpads when updating setting
+
+---
+ src/backends/meta-input-settings.c | 46 +++++++++++++++++++++++-------
+ 1 file changed, 36 insertions(+), 10 deletions(-)
+
+diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
+index cdff7b346..7d866594a 100644
+--- a/src/backends/meta-input-settings.c
++++ b/src/backends/meta-input-settings.c
+@@ -569,20 +569,33 @@ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
+ 
+   priv = meta_input_settings_get_instance_private (input_settings);
+   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
+-  enabled = device_is_tablet_touchpad (input_settings, device) ||
+-    g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
+ 
+   if (device)
+     {
++      enabled = device_is_tablet_touchpad (input_settings, device) ||
++        g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
+       settings_device_set_bool_setting (input_settings, device,
+                                         input_settings_class->set_tap_enabled,
+                                         enabled);
+     }
+   else
+     {
+-      settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
+-                                 input_settings_class->set_tap_enabled,
+-                                 enabled);
++      const GSList *devices, *l;
++
++      devices = clutter_device_manager_peek_devices (priv->device_manager);
++      for (l = devices; l; l = l->next)
++        {
++          device = l->data;
++
++          if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
++            continue;
++
++          enabled = device_is_tablet_touchpad (input_settings, device) ||
++            g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
++          settings_device_set_bool_setting (input_settings, device,
++                                            input_settings_class->set_tap_enabled,
++                                            enabled);
++        }
+     }
+ }
+ 
+@@ -600,20 +613,33 @@ update_touchpad_tap_and_drag_enabled (MetaInputSettings  *input_settings,
+ 
+   priv = meta_input_settings_get_instance_private (input_settings);
+   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
+-  enabled = device_is_tablet_touchpad (input_settings, device) ||
+-    g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
+ 
+   if (device)
+     {
++      enabled = device_is_tablet_touchpad (input_settings, device) ||
++        g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
+       settings_device_set_bool_setting (input_settings, device,
+                                         input_settings_class->set_tap_and_drag_enabled,
+                                         enabled);
+     }
+   else
+     {
+-      settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
+-                                 input_settings_class->set_tap_and_drag_enabled,
+-                                 enabled);
++      const GSList *devices, *l;
++
++      devices = clutter_device_manager_peek_devices (priv->device_manager);
++      for (l = devices; l; l = l->next)
++        {
++          device = l->data;
++
++          if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
++            continue;
++
++          enabled = device_is_tablet_touchpad (input_settings, device) ||
++            g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
++          settings_device_set_bool_setting (input_settings, device,
++                                            input_settings_class->set_tap_and_drag_enabled,
++                                            enabled);
++        }
+     }
+ }
+ 
+-- 
+2.24.1
+
diff --git a/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch b/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch
new file mode 100644
index 0000000..0420251
--- /dev/null
+++ b/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch
@@ -0,0 +1,80 @@
+From eeff82f534f81b086d10d53124362d9e316e2cf9 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Thu, 12 Dec 2019 18:05:08 +0100
+Subject: [PATCH] backends: Always enable tap-to-click/drag on opaque Wacom
+ tablets
+
+Touch-wise, those are essentially giant touchpads, but have no buttons
+associated to the "touchpad" device (There may be pad buttons, but
+those are not mouse buttons).
+
+Without tap-to-click/drag, touch in those devices is somewhat useless
+out of the box. Have them always enable these features, despite the
+setting.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/968
+---
+ src/backends/meta-input-settings.c | 33 ++++++++++++++++++++++++++++--
+ 1 file changed, 31 insertions(+), 2 deletions(-)
+
+diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
+index 2e6672d9c..28dc387ef 100644
+--- a/src/backends/meta-input-settings.c
++++ b/src/backends/meta-input-settings.c
+@@ -517,6 +517,33 @@ update_touchpad_disable_while_typing (MetaInputSettings  *input_settings,
+     }
+ }
+ 
++static gboolean
++device_is_tablet_touchpad (MetaInputSettings  *input_settings,
++                           ClutterInputDevice *device)
++{
++#ifdef HAVE_LIBWACOM
++  WacomIntegrationFlags flags = 0;
++  WacomDevice *wacom_device;
++
++  if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
++    return FALSE;
++
++  wacom_device =
++    meta_input_settings_get_tablet_wacom_device (input_settings,
++                                                 device);
++  if (wacom_device)
++    {
++      flags = libwacom_get_integration_flags (wacom_device);
++
++      if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
++                    WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
++        return TRUE;
++    }
++#endif
++
++  return FALSE;
++}
++
+ static void
+ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
+                              ClutterInputDevice *device)
+@@ -531,7 +558,8 @@ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
+ 
+   priv = meta_input_settings_get_instance_private (input_settings);
+   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
+-  enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
++  enabled = device_is_tablet_touchpad (input_settings, device) ||
++    g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
+ 
+   if (device)
+     {
+@@ -561,7 +589,8 @@ update_touchpad_tap_and_drag_enabled (MetaInputSettings  *input_settings,
+ 
+   priv = meta_input_settings_get_instance_private (input_settings);
+   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
+-  enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
++  enabled = device_is_tablet_touchpad (input_settings, device) ||
++    g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
+ 
+   if (device)
+     {
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch b/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch
new file mode 100644
index 0000000..9880a83
--- /dev/null
+++ b/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch
@@ -0,0 +1,205 @@
+From 20fcc3e045287c1ca591f3e795b19e120479a89a Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Wed, 12 Feb 2020 20:26:56 +0100
+Subject: [PATCH 1/2] backends/x11: Implement is_grouped for X11
+
+If the devices have a wacom description, compare those. Otherwise,
+look up the devices' VID:PID, if they match they should also be
+grouped.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/971
+---
+ .../clutter/x11/clutter-input-device-xi2.c    | 25 +++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c
+index ae2fa27..9eca34d 100644
+--- a/clutter/clutter/x11/clutter-input-device-xi2.c
++++ b/clutter/clutter/x11/clutter-input-device-xi2.c
+@@ -98,6 +98,31 @@ static gboolean
+ clutter_input_device_xi2_is_grouped (ClutterInputDevice *device,
+                                      ClutterInputDevice *other_device)
+ {
++#ifdef HAVE_LIBWACOM
++  ClutterInputDeviceXI2 *device_x11 = CLUTTER_INPUT_DEVICE_XI2 (device);
++  ClutterInputDeviceXI2 *other_device_x11 = CLUTTER_INPUT_DEVICE_XI2 (other_device);
++
++  if (device_x11->wacom_device &&
++      other_device_x11->wacom_device &&
++      libwacom_compare (device_x11->wacom_device,
++                        other_device_x11->wacom_device,
++                        WCOMPARE_NORMAL) == 0)
++    return TRUE;
++#endif
++
++  /* Devices with the same VID:PID get grouped together */
++  if (clutter_input_device_get_vendor_id (device) &&
++      clutter_input_device_get_product_id (device) &&
++      clutter_input_device_get_vendor_id (other_device) &&
++      clutter_input_device_get_product_id (other_device))
++    {
++      if (strcmp (clutter_input_device_get_vendor_id (device),
++                  clutter_input_device_get_vendor_id (other_device)) == 0 &&
++          strcmp (clutter_input_device_get_product_id (device),
++                  clutter_input_device_get_product_id (other_device)) == 0)
++        return TRUE;
++    }
++
+   return FALSE;
+ }
+ 
+-- 
+2.24.1
+
+
+From 5914ab9ac79ce42da054036c4a8f118a3a868cc0 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 13 Dec 2019 15:26:05 +0100
+Subject: [PATCH 2/2] backends: Check both input settings and mapper for tablet
+ monitors
+
+The upper layers (OSDs basically) want to know the monitor that a
+tablet is currently assigned to, not the monitor just as configured
+through settings.
+
+This broke proper OSD positioning for display-attached tablets since
+commit 87858a4e01d9, as the MetaInputMapper kicks in precisely when
+there is no configured monitor for the given device.
+
+Consulting both about the assigned output will make OSDs pop up
+again in the right place.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/971
+---
+ src/backends/meta-input-mapper-private.h |  3 ++
+ src/backends/meta-input-mapper.c         | 26 ++++++++++++
+ src/backends/meta-input-settings.c       | 54 +++++++++++++++++++++++-
+ 3 files changed, 81 insertions(+), 2 deletions(-)
+
+diff --git a/src/backends/meta-input-mapper-private.h b/src/backends/meta-input-mapper-private.h
+index 3431457..cdfdccd 100644
+--- a/src/backends/meta-input-mapper-private.h
++++ b/src/backends/meta-input-mapper-private.h
+@@ -42,5 +42,8 @@ ClutterInputDevice *
+ meta_input_mapper_get_logical_monitor_device (MetaInputMapper        *mapper,
+                                               MetaLogicalMonitor     *logical_monitor,
+                                               ClutterInputDeviceType  device_type);
++MetaLogicalMonitor *
++meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper,
++                                              ClutterInputDevice *device);
+ 
+ #endif /* META_INPUT_MAPPER_H */
+diff --git a/src/backends/meta-input-mapper.c b/src/backends/meta-input-mapper.c
+index fc4f3bd..fe02ab8 100644
+--- a/src/backends/meta-input-mapper.c
++++ b/src/backends/meta-input-mapper.c
+@@ -675,3 +675,29 @@ meta_input_mapper_get_logical_monitor_device (MetaInputMapper        *mapper,
+ 
+   return NULL;
+ }
++
++MetaLogicalMonitor *
++meta_input_mapper_get_device_logical_monitor (MetaInputMapper    *mapper,
++                                              ClutterInputDevice *device)
++{
++  MetaMapperOutputInfo *output;
++  MetaLogicalMonitor *logical_monitor;
++  GHashTableIter iter;
++  GList *l;
++
++  g_hash_table_iter_init (&iter, mapper->output_devices);
++
++  while (g_hash_table_iter_next (&iter, (gpointer *) &logical_monitor,
++                                 (gpointer *) &output))
++    {
++      for (l = output->input_devices; l; l = l->next)
++        {
++          MetaMapperInputInfo *input = l->data;
++
++          if (input->device == device)
++            return logical_monitor;
++        }
++    }
++
++  return NULL;
++}
+diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
+index b84595e..ab80bee 100644
+--- a/src/backends/meta-input-settings.c
++++ b/src/backends/meta-input-settings.c
+@@ -1937,6 +1937,42 @@ meta_input_settings_get_tablet_settings (MetaInputSettings  *settings,
+   return info ? g_object_ref (info->settings) : NULL;
+ }
+ 
++static ClutterInputDevice *
++find_grouped_pen (MetaInputSettings  *settings,
++                  ClutterInputDevice *device)
++{
++  MetaInputSettingsPrivate *priv;
++  GSList *l, *devices;
++  ClutterInputDeviceType device_type;
++  ClutterInputDevice *pen = NULL;
++
++  device_type = clutter_input_device_get_device_type (device);
++
++  if (device_type == CLUTTER_TABLET_DEVICE ||
++      device_type == CLUTTER_PEN_DEVICE)
++    return device;
++
++  priv = meta_input_settings_get_instance_private (settings);
++  devices = clutter_device_manager_peek_devices (priv->device_manager);
++
++  for (l = devices; l; l = l->next)
++    {
++      ClutterInputDevice *device = l->data;
++
++      device_type = clutter_input_device_get_device_type (l->data);
++
++      if ((device_type == CLUTTER_TABLET_DEVICE ||
++           device_type == CLUTTER_PEN_DEVICE) &&
++          clutter_input_device_is_grouped (device, l->data))
++        {
++          pen = l->data;
++          break;
++        }
++    }
++
++  return pen;
++}
++
+ MetaLogicalMonitor *
+ meta_input_settings_get_tablet_logical_monitor (MetaInputSettings  *settings,
+                                                 ClutterInputDevice *device)
+@@ -1948,13 +1984,27 @@ meta_input_settings_get_tablet_logical_monitor (MetaInputSettings  *settings,
+   g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
+   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
+ 
++  if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
++    {
++      device = find_grouped_pen (settings, device);
++      if (!device)
++        return NULL;
++    }
++
+   priv = meta_input_settings_get_instance_private (settings);
+   info = g_hash_table_lookup (priv->mappable_devices, device);
+   if (!info)
+     return NULL;
+ 
+-  meta_input_settings_find_monitor (settings, info->settings, device,
+-                                    NULL, &logical_monitor);
++  logical_monitor =
++    meta_input_mapper_get_device_logical_monitor (priv->input_mapper, device);
++
++  if (!logical_monitor)
++    {
++      meta_input_settings_find_monitor (settings, info->settings, device,
++                                        NULL, &logical_monitor);
++    }
++
+   return logical_monitor;
+ }
+ 
+-- 
+2.24.1
+
diff --git a/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch b/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch
new file mode 100644
index 0000000..f7fa3b2
--- /dev/null
+++ b/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch
@@ -0,0 +1,30 @@
+From e512c397a640994807f239c570333e9942717ef5 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 13 Dec 2019 17:01:44 +0100
+Subject: [PATCH] backends: Consider pen/eraser devices when looking for
+ matching WacomDevice
+
+Those device types are still in use through the X11 backend, breaking some
+checks around on that backend...
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/972
+---
+ src/backends/meta-input-settings.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
+index 2e6672d9c..18ae52dd7 100644
+--- a/src/backends/meta-input-settings.c
++++ b/src/backends/meta-input-settings.c
+@@ -1589,6 +1589,8 @@ check_add_mappable_device (MetaInputSettings  *input_settings,
+ 
+ #ifdef HAVE_LIBWACOM
+   if (device_type == CLUTTER_TABLET_DEVICE ||
++      device_type == CLUTTER_PEN_DEVICE ||
++      device_type == CLUTTER_ERASER_DEVICE ||
+       device_type == CLUTTER_PAD_DEVICE)
+     {
+       WacomError *error = libwacom_error_new ();
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch b/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch
new file mode 100644
index 0000000..ac6986f
--- /dev/null
+++ b/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch
@@ -0,0 +1,118 @@
+From a8f12e7afdb35ebda581cee6a32b295cb6e643ec Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 13 Dec 2019 14:22:12 +0100
+Subject: [PATCH] backends/x11: Observe multiple pad mode switch buttons in a
+ group
+
+Some tablets like the Cintiq 24HDT have several mode switch buttons
+per group. Those are meant to jump straight to a given mode, however
+we just handle cycling across modes (as most other tablets have a
+single mode switch button per group).
+
+So spice up the mode switch handling so we handle multiple mode
+switch buttons, assigning each of them a mode. If the device only
+has one mode switch button, we do the old-fashioned cycling.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/970
+---
+ .../clutter/x11/clutter-input-device-xi2.c    | 71 ++++++++++++++++---
+ 1 file changed, 60 insertions(+), 11 deletions(-)
+
+diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c
+index 1254aca3a..c33adffc2 100644
+--- a/clutter/clutter/x11/clutter-input-device-xi2.c
++++ b/clutter/clutter/x11/clutter-input-device-xi2.c
+@@ -318,6 +318,57 @@ clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device,
+   return g_array_index (device_xi2->group_modes, guint, group);
+ }
+ 
++static gboolean
++pad_switch_mode (ClutterInputDevice *device,
++                 uint32_t            button,
++                 uint32_t            group,
++                 uint32_t           *mode)
++{
++  ClutterInputDeviceXI2 *device_x11 = CLUTTER_INPUT_DEVICE_XI2 (device);
++  uint32_t n_buttons, n_modes, button_group, next_mode, i;
++  GList *switch_buttons = NULL;
++
++  n_buttons = libwacom_get_num_buttons (device_x11->wacom_device);
++
++  for (i = 0; i < n_buttons; i++)
++    {
++      button_group = clutter_input_device_xi2_get_button_group (device, i);
++      if (button_group == group)
++        switch_buttons = g_list_prepend (switch_buttons, GINT_TO_POINTER (i));
++    }
++
++  switch_buttons = g_list_reverse (switch_buttons);
++  n_modes = clutter_input_device_get_group_n_modes (device, group);
++
++  if (g_list_length (switch_buttons) > 1)
++    {
++      /* If there's multiple switch buttons, we don't toggle but assign a mode
++       * to each of those buttons.
++       */
++      next_mode = g_list_index (switch_buttons, GINT_TO_POINTER (button));
++    }
++  else if (switch_buttons)
++    {
++      uint32_t cur_mode;
++
++      /* If there is a single button, have it toggle across modes */
++      cur_mode = g_array_index (device_x11->group_modes, uint32_t, group);
++      next_mode = (cur_mode + 1) % n_modes;
++    }
++  else
++    {
++      return FALSE;
++    }
++
++  g_list_free (switch_buttons);
++
++  if (next_mode < 0 || next_mode > n_modes)
++    return FALSE;
++
++  *mode = next_mode;
++  return TRUE;
++}
++
+ void
+ clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device,
+                                            guint               button,
+@@ -330,23 +381,21 @@ clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device,
+   gboolean is_mode_switch = FALSE;
+ 
+   button_group = clutter_input_device_xi2_get_button_group (device, button);
+-  is_mode_switch = button_group >= 0;
+ 
+-  /* Assign all non-mode-switch buttons to group 0 so far */
+-  button_group = MAX (0, button_group);
+-
+-  if (button_group >= device_xi2->group_modes->len)
+-    return;
++  if (button_group < 0 || button_group >= device_xi2->group_modes->len)
++    {
++      *group = *mode = 0;
++      return;
++    }
+ 
+   group_mode = &g_array_index (device_xi2->group_modes, guint, button_group);
+ 
+-  if (is_mode_switch && state)
++  if (state)
+     {
+-      guint next, n_modes;
++      uint32_t next_mode;
+ 
+-      n_modes = clutter_input_device_get_group_n_modes (device, button_group);
+-      next = (*group_mode + 1) % n_modes;
+-      *group_mode = next;
++      if (pad_switch_mode (device, button, button_group, &next_mode))
++        *group_mode = next_mode;
+     }
+ 
+   if (group)
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch
new file mode 100644
index 0000000..2dd5bb9
--- /dev/null
+++ b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch
@@ -0,0 +1,349 @@
+From 471174ba6cf517baf8ff73e903202e1c73b6ec74 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Thu, 19 Jan 2017 15:03:41 +0100
+Subject: [PATCH] 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 | 268 +++++++++++++++++++++
+ 1 file changed, 268 insertions(+)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 89f07ee1f..051a1c605 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>
+@@ -162,6 +163,180 @@ 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));
++  XDevice *xdevice;
++  guchar *tap_action, *buttons;
++  guint buttons_capacity = 16, n_buttons;
++
++  xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (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);
++  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));
++  XDevice *xdevice;
++  XPtrFeedbackControl feedback;
++  XFeedbackState *states, *state;
++  int i, num_feedbacks, motion_threshold, numerator, denominator;
++  gfloat motion_acceleration;
++
++  xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device));
++  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,
+@@ -170,6 +345,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)
+@@ -222,6 +404,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);
+@@ -248,6 +436,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);
+     }
+@@ -271,6 +472,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);
+ }
+@@ -293,6 +508,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);
+ }
+@@ -306,6 +542,22 @@ meta_input_settings_x11_set_edge_scroll (MetaInputSettings            *settings,
+   guchar *current = NULL;
+   guchar *available = NULL;
+ 
++  if (is_device_synaptics (device))
++    {
++      current = get_property (device, "Synaptics Edge Scrolling",
++                              XA_INTEGER, 8, 3);
++      if (current)
++        {
++          current[0] = !!edge_scroll_enabled;
++          current[1] = !!edge_scroll_enabled;
++          change_property (device, "Synaptics Edge Scrolling",
++                           XA_INTEGER, 8, current, 3);
++          meta_XFree (current);
++        }
++
++      return;
++    }
++
+   available = get_property (device, "libinput Scroll Methods Available",
+                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
+   if (!available || !available[SCROLL_METHOD_FIELD_EDGE])
+@@ -335,6 +587,22 @@ meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings            *set
+   guchar *current = NULL;
+   guchar *available = NULL;
+ 
++  if (is_device_synaptics (device))
++    {
++      current = get_property (device, "Synaptics Two-Finger Scrolling",
++                              XA_INTEGER, 8, 2);
++      if (current)
++        {
++          current[0] = !!two_finger_scroll_enabled;
++          current[1] = !!two_finger_scroll_enabled;
++          change_property (device, "Synaptics Two-Finger Scrolling",
++                           XA_INTEGER, 8, current, 2);
++          meta_XFree (current);
++        }
++
++      return;
++    }
++
+   available = get_property (device, "libinput Scroll Methods Available",
+                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
+   if (!available || !available[SCROLL_METHOD_FIELD_2FG])
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch
new file mode 100644
index 0000000..96fe26b
--- /dev/null
+++ b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch
@@ -0,0 +1,61 @@
+From 368fdebe8f4f4e0c0e41f5be9961a748f328cb57 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Tue, 13 Feb 2018 11:44:40 +0100
+Subject: [PATCH] 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.
+---
+ .../clutter/x11/clutter-device-manager-xi2.c  | 22 ++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c
+index 87da4b050..297d3acfe 100644
+--- a/clutter/clutter/x11/clutter-device-manager-xi2.c
++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c
+@@ -282,8 +282,9 @@ is_touch_device (XIAnyClassInfo         **classes,
+ }
+ 
+ static gboolean
+-is_touchpad_device (ClutterBackendX11 *backend_x11,
+-                    XIDeviceInfo      *info)
++query_exists_device_property (ClutterBackendX11 *backend_x11,
++                              XIDeviceInfo      *info,
++                              const gchar       *property)
+ {
+   gulong nitems, bytes_after;
+   guint32 *data = NULL;
+@@ -291,7 +292,7 @@ is_touchpad_device (ClutterBackendX11 *backend_x11,
+   Atom type;
+   Atom prop;
+ 
+-  prop = XInternAtom (backend_x11->xdpy, "libinput Tapping Enabled", True);
++  prop = XInternAtom (backend_x11->xdpy, property, True);
+   if (prop == None)
+     return FALSE;
+ 
+@@ -312,6 +313,21 @@ is_touchpad_device (ClutterBackendX11 *backend_x11,
+   return TRUE;
+ }
+ 
++static gboolean
++is_touchpad_device (ClutterBackendX11 *backend_x11,
++                    XIDeviceInfo      *info)
++{
++  if (query_exists_device_property (backend_x11, info,
++                                    "libinput Tapping Enabled"))
++    return TRUE;
++
++  if (query_exists_device_property (backend_x11, info,
++                                    "Synaptics Off"))
++    return TRUE;
++
++  return FALSE;
++}
++
+ static gboolean
+ get_device_ids (ClutterBackendX11  *backend_x11,
+                 XIDeviceInfo       *info,
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch b/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch
new file mode 100644
index 0000000..dd9eeb5
--- /dev/null
+++ b/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch
@@ -0,0 +1,27 @@
+From 2259241e4e6f03bea4e9d746582a9e6a82b3c755 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Wed, 13 Jun 2018 13:48:24 +0200
+Subject: [PATCH] clutter: Only reset scroll axes on slave devices
+
+As a plus, unknown source device IDs will just warn instead of crash.
+---
+ clutter/clutter/x11/clutter-device-manager-xi2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c
+index 297d3acfe..76ef420ed 100644
+--- a/clutter/clutter/x11/clutter-device-manager-xi2.c
++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c
+@@ -1899,7 +1899,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
+             _clutter_input_device_set_stage (device, NULL);
+           }
+ 
+-        _clutter_input_device_reset_scroll_info (source_device);
++        if (clutter_input_device_get_device_mode (source_device) == CLUTTER_INPUT_MODE_SLAVE)
++          _clutter_input_device_reset_scroll_info (source_device);
+ 
+         clutter_event_set_device (event, device);
+         clutter_event_set_source_device (event, source_device);
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch
new file mode 100644
index 0000000..b2965a3
--- /dev/null
+++ b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch
@@ -0,0 +1,37 @@
+From 251ef4ff4bacefac211e21873e10da7fa067dd68 Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Fri, 26 Apr 2019 12:23:18 +0300
+Subject: [PATCH 01/12] cogl: Remove unused OFFSCREEN_BLIT feature flag
+
+This named constant is never used anywhere.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit c08a24bb40ad7aa7746e86251c9dbe6c264b4d7c)
+---
+ cogl/cogl/cogl-types.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
+index 690daa16a..69d304cf0 100644
+--- a/cogl/cogl/cogl-types.h
++++ b/cogl/cogl/cogl-types.h
+@@ -325,7 +325,6 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/
+  * @COGL_FEATURE_SHADERS_GLSL: GLSL support
+  * @COGL_FEATURE_OFFSCREEN: FBO support
+  * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
+- * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs
+  * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
+  * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
+  * @COGL_FEATURE_VBOS: VBO support
+@@ -368,7 +367,6 @@ typedef enum
+   COGL_FEATURE_SHADERS_GLSL           = (1 << 5),
+   COGL_FEATURE_OFFSCREEN              = (1 << 6),
+   COGL_FEATURE_OFFSCREEN_MULTISAMPLE  = (1 << 7),
+-  COGL_FEATURE_OFFSCREEN_BLIT         = (1 << 8),
+   COGL_FEATURE_FOUR_CLIP_PLANES       = (1 << 9),
+   COGL_FEATURE_STENCIL_BUFFER         = (1 << 10),
+   COGL_FEATURE_VBOS		      = (1 << 11),
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch b/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch
new file mode 100644
index 0000000..673608d
--- /dev/null
+++ b/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch
@@ -0,0 +1,136 @@
+From 78bb1fff1155462638b0d6037ccddf1328482842 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 15 Jan 2019 11:01:38 -0500
+Subject: [PATCH 1/9] cogl: add new UNSTABLE_TEXTURES feature
+
+The proprietary nvidia driver garbles texture memory on suspend.
+
+Before we can address that, we need to be able to detect it.
+
+This commit adds a new UNSTABLE_TEXTURES feature that gets set if
+the proprietary nvidia driver is in use.
+---
+ cogl/cogl/cogl-context.h           |  1 +
+ cogl/cogl/cogl-types.h             |  5 ++++-
+ cogl/cogl/winsys/cogl-winsys-egl.c | 11 +++++++++++
+ cogl/cogl/winsys/cogl-winsys-glx.c | 13 +++++++++++--
+ 4 files changed, 27 insertions(+), 3 deletions(-)
+
+diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h
+index d4104625e..a20c54549 100644
+--- a/cogl/cogl/cogl-context.h
++++ b/cogl/cogl/cogl-context.h
+@@ -261,6 +261,7 @@ typedef enum _CoglFeatureID
+   COGL_FEATURE_ID_TEXTURE_RG,
+   COGL_FEATURE_ID_BUFFER_AGE,
+   COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
++  COGL_FEATURE_ID_UNSTABLE_TEXTURES,
+ 
+   /*< private >*/
+   _COGL_N_FEATURE_IDS   /*< skip >*/
+diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
+index 690daa16a..5b980a43c 100644
+--- a/cogl/cogl/cogl-types.h
++++ b/cogl/cogl/cogl-types.h
+@@ -354,6 +354,8 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/
+  *     supported with CoglBufferAccess including write support.
+  * @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
+  *     depth buffer to a texture.
++ * @COGL_FEATURE_UNSTABLE_TEXTURES: Whether textures require redrawing on
++ *     resume or not.
+  *
+  * Flags for the supported features.
+  *
+@@ -383,7 +385,8 @@ typedef enum
+   COGL_FEATURE_MAP_BUFFER_FOR_READ    = (1 << 21),
+   COGL_FEATURE_MAP_BUFFER_FOR_WRITE   = (1 << 22),
+   COGL_FEATURE_ONSCREEN_MULTIPLE      = (1 << 23),
+-  COGL_FEATURE_DEPTH_TEXTURE          = (1 << 24)
++  COGL_FEATURE_DEPTH_TEXTURE          = (1 << 24),
++  COGL_FEATURE_UNSTABLE_TEXTURES      = (1 << 25)
+ } CoglFeatureFlags;
+ 
+ /**
+diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c
+index 903c6492d..dd450d4f3 100644
+--- a/cogl/cogl/winsys/cogl-winsys-egl.c
++++ b/cogl/cogl/winsys/cogl-winsys-egl.c
+@@ -499,6 +499,7 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error)
+   CoglRenderer *renderer = context->display->renderer;
+   CoglDisplayEGL *egl_display = context->display->winsys;
+   CoglRendererEGL *egl_renderer = renderer->winsys;
++  CoglGpuInfo *info;
+ 
+   context->winsys = g_new0 (CoglContextEGL, 1);
+ 
+@@ -511,6 +512,16 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error)
+   if (!_cogl_context_update_features (context, error))
+     return FALSE;
+ 
++  info = &context->gpu;
++
++  if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
++    {
++      context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
++      COGL_FLAGS_SET (context->features,
++                      COGL_FEATURE_ID_UNSTABLE_TEXTURES,
++                      TRUE);
++    }
++
+   if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION)
+     {
+       COGL_FLAGS_SET (context->winsys_features,
+diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
+index 235cfe81f..7e87dc15f 100644
+--- a/cogl/cogl/winsys/cogl-winsys-glx.c
++++ b/cogl/cogl/winsys/cogl-winsys-glx.c
+@@ -830,12 +830,15 @@ update_winsys_features (CoglContext *context, CoglError **error)
+ {
+   CoglGLXDisplay *glx_display = context->display->winsys;
+   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
++  CoglGpuInfo *info;
+ 
+   _COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE);
+ 
+   if (!_cogl_context_update_features (context, error))
+     return FALSE;
+ 
++  info = &context->gpu;
++
+   memcpy (context->winsys_features,
+           glx_renderer->base_winsys_features,
+           sizeof (context->winsys_features));
+@@ -848,7 +851,6 @@ update_winsys_features (CoglContext *context, CoglError **error)
+ 
+   if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer)
+     {
+-      CoglGpuInfo *info = &context->gpu;
+       CoglGpuInfoArchitecture arch = info->architecture;
+ 
+       COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
+@@ -897,7 +899,6 @@ update_winsys_features (CoglContext *context, CoglError **error)
+     }
+   else
+     {
+-      CoglGpuInfo *info = &context->gpu;
+       if (glx_display->have_vblank_counter &&
+ 	  context->display->renderer->xlib_enable_threaded_swap_wait &&
+ 	  info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
+@@ -919,6 +920,14 @@ update_winsys_features (CoglContext *context, CoglError **error)
+         }
+     }
+ 
++  if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
++    {
++      context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
++      COGL_FLAGS_SET (context->features,
++                      COGL_FEATURE_ID_UNSTABLE_TEXTURES,
++                      TRUE);
++    }
++
+   /* We'll manually handle queueing dirty events in response to
+    * Expose events from X */
+   COGL_FLAGS_SET (context->private_features,
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch b/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch
new file mode 100644
index 0000000..5ee31d1
--- /dev/null
+++ b/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch
@@ -0,0 +1,64 @@
+From 5cab6bac4d4fb06e60d3198dc654a5d70fa6240e Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Mon, 16 Dec 2019 13:53:26 +0100
+Subject: [PATCH] core: Let pad mode switch events always go through
+ MetaInputSettings
+
+We used to inhibit all pad actions while the OSD is shown, but one we
+would actually want to handle are mode switches while the OSD is open.
+So it has an opportunity to catch up to the mode switch.
+
+This lets MetaInputSettings reflect the mode switch (eg. when querying
+action labels), so the OSD has an opportunity to update the current
+actions.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/975
+---
+ src/core/events.c | 30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+diff --git a/src/core/events.c b/src/core/events.c
+index d383778629..44f28d0b97 100644
+--- a/src/core/events.c
++++ b/src/core/events.c
+@@ -256,13 +256,31 @@ meta_display_handle_event (MetaDisplay        *display,
+     }
+ #endif
+ 
+-  if (!display->current_pad_osd &&
+-      (event->type == CLUTTER_PAD_BUTTON_PRESS ||
+-       event->type == CLUTTER_PAD_BUTTON_RELEASE ||
+-       event->type == CLUTTER_PAD_RING ||
+-       event->type == CLUTTER_PAD_STRIP))
++  if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
++      event->type == CLUTTER_PAD_BUTTON_RELEASE ||
++      event->type == CLUTTER_PAD_RING ||
++      event->type == CLUTTER_PAD_STRIP)
+     {
+-      if (meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend),
++      gboolean handle_pad_event = TRUE;
++      gboolean is_mode_switch = FALSE;
++
++      if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
++          event->type == CLUTTER_PAD_BUTTON_RELEASE)
++        {
++          ClutterInputDevice *pad;
++          uint32_t button;
++
++          pad = clutter_event_get_source_device (event);
++          button = clutter_event_get_button (event);
++
++          is_mode_switch =
++            clutter_input_device_get_mode_switch_button_group (pad, button) >= 0;
++        }
++
++      handle_pad_event = !display->current_pad_osd || is_mode_switch;
++
++      if (handle_pad_event &&
++          meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend),
+                                                 event))
+         {
+           bypass_wayland = bypass_clutter = TRUE;
+-- 
+2.24.0
+
diff --git a/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch b/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch
new file mode 100644
index 0000000..29e6b88
--- /dev/null
+++ b/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch
@@ -0,0 +1,73 @@
+From bac090f571e6f413ba2a362ed2d70146b7701d16 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 24 Feb 2020 17:37:34 +0100
+Subject: [PATCH] crtc-xrandr: Respect configured RANDR panning
+
+A user may have configured an output to be panning, e.g. using xrandr
+--output <output> --mode <mode> --panning <size>. Respect this by making
+the logical monitor use the panning size, instead of the mode. This
+makes e.g. makes the background cover the whole panning size, and panels
+etc will cover the whole top of the panned area, instead of just the top
+left part covering the monitor if having panned to (0, 0).
+
+No support is added to configuring panning, i.e. a panned monitor
+configuration cannot be stored in monitors.xml.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/1085
+---
+ src/backends/x11/meta-crtc-xrandr.c | 31 +++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c
+index d201b8581..dc3f931e3 100644
+--- a/src/backends/x11/meta-crtc-xrandr.c
++++ b/src/backends/x11/meta-crtc-xrandr.c
+@@ -177,7 +177,14 @@ meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
+                          RRCrtc              crtc_id,
+                          XRRScreenResources *resources)
+ {
++  MetaGpu *gpu = META_GPU (gpu_xrandr);
++  MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
++  MetaMonitorManagerXrandr *monitor_manager_xrandr =
++    META_MONITOR_MANAGER_XRANDR (monitor_manager);
++  Display *xdisplay =
++    meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
+   MetaCrtc *crtc;
++  XRRPanning *panning;
+   unsigned int i;
+   GList *modes;
+ 
+@@ -185,10 +192,26 @@ meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
+ 
+   crtc->gpu = META_GPU (gpu_xrandr);
+   crtc->crtc_id = crtc_id;
+-  crtc->rect.x = xrandr_crtc->x;
+-  crtc->rect.y = xrandr_crtc->y;
+-  crtc->rect.width = xrandr_crtc->width;
+-  crtc->rect.height = xrandr_crtc->height;
++
++  panning = XRRGetPanning (xdisplay, resources, crtc_id);
++  if (panning && panning->width > 0 && panning->height > 0)
++    {
++      crtc->rect = (MetaRectangle) {
++        .x = panning->left,
++        .y = panning->top,
++        .width = panning->width,
++        .height = panning->height,
++      };
++    }
++  else
++    {
++      crtc->rect = (MetaRectangle) {
++        .x = xrandr_crtc->x,
++        .y = xrandr_crtc->y,
++        .width = xrandr_crtc->width,
++        .height = xrandr_crtc->height,
++      };
++    }
+   crtc->is_dirty = FALSE;
+   crtc->transform =
+     meta_monitor_transform_from_xrandr (xrandr_crtc->rotation);
+-- 
+2.24.1
+
diff --git a/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch b/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch
new file mode 100644
index 0000000..88b3a4f
--- /dev/null
+++ b/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch
@@ -0,0 +1,55 @@
+From 62387eb649b7b33d923d5382f85c9210a3bedbe8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Thu, 30 May 2019 16:32:35 +0200
+Subject: [PATCH] enum-types: Use @basename@ in header comment
+
+@filename@ may contain arch-specific bits that introduce unnecessary
+multi-lib issues.
+---
+ clutter/clutter/clutter-enum-types.h.in  | 2 +-
+ cogl/cogl-path/cogl-path-enum-types.h.in | 2 +-
+ src/meta/meta-enum-types.h.in            | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/clutter/clutter/clutter-enum-types.h.in b/clutter/clutter/clutter-enum-types.h.in
+index 2e5b6707e..17f9ee644 100644
+--- a/clutter/clutter/clutter-enum-types.h.in
++++ b/clutter/clutter/clutter-enum-types.h.in
+@@ -13,7 +13,7 @@ G_BEGIN_DECLS
+ /*** END file-header ***/
+ 
+ /*** BEGIN file-production ***/
+-/* enumerations from "@filename@" */
++/* enumerations from "@basename@" */
+ /*** END file-production ***/
+ 
+ /*** BEGIN value-header ***/
+diff --git a/cogl/cogl-path/cogl-path-enum-types.h.in b/cogl/cogl-path/cogl-path-enum-types.h.in
+index 071686acd..2b377ed18 100644
+--- a/cogl/cogl-path/cogl-path-enum-types.h.in
++++ b/cogl/cogl-path/cogl-path-enum-types.h.in
+@@ -9,7 +9,7 @@ G_BEGIN_DECLS
+ /*** END file-header ***/
+ 
+ /*** BEGIN file-production ***/
+-/* enumerations from "@filename@" */
++/* enumerations from "@basename@" */
+ /*** END file-production ***/
+ 
+ /*** BEGIN file-tail ***/
+diff --git a/src/meta/meta-enum-types.h.in b/src/meta/meta-enum-types.h.in
+index 6e3b67b26..bee0196de 100644
+--- a/src/meta/meta-enum-types.h.in
++++ b/src/meta/meta-enum-types.h.in
+@@ -10,7 +10,7 @@ G_BEGIN_DECLS
+ /*** END file-header ***/
+ 
+ /*** BEGIN file-production ***/
+-/* enumerations from "@filename@" */
++/* enumerations from "@basename@" */
+ /*** END file-production ***/
+ 
+ /*** BEGIN file-tail ***/
+-- 
+2.21.0
+
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..69fc6ef
--- /dev/null
+++ b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch
@@ -0,0 +1,42 @@
+From f735f345ad8390a7fb09ef54ca3e0e419d395d1b 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 e363fdbb6..905b5bf9d 100644
+--- a/src/x11/events.c
++++ b/src/x11/events.c
+@@ -832,6 +832,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,
+@@ -876,6 +886,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.21.0
+
diff --git a/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch
new file mode 100644
index 0000000..3ba3963
--- /dev/null
+++ b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch
@@ -0,0 +1,122 @@
+From f108395c32351cda8722130e0e2970827b18e5a9 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Wed, 2 Oct 2019 16:49:28 +0200
+Subject: [PATCH] events: Sync pending pointer events without a window
+
+Mutter issues a synchronous grab on the pointer for unfocused client
+windows to be able to catch the button events first and raise/focus
+client windows accordingly.
+
+When there is a synchronous grab in effect, all events are queued until
+the grabbing client releases the event queue as it processes the events.
+
+Mutter does release the events in its event handler function but does so
+only if it is able to find the window matching the event. If the window
+is a shell widget, that matching may fail and therefore Mutter will not
+release the events, hence causing a freeze in pointer events delivery.
+
+To avoid the issue, make sure we sync the pointer events in case we
+can't find a matching window.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/821
+---
+ src/core/events.c | 62 ++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 51 insertions(+), 11 deletions(-)
+
+diff --git a/src/core/events.c b/src/core/events.c
+index 5b8e49fc7..831cb007b 100644
+--- a/src/core/events.c
++++ b/src/core/events.c
+@@ -50,6 +50,12 @@
+ #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \
+                          (e)->type == CLUTTER_KEY_RELEASE)
+ 
++typedef enum
++{
++  EVENTS_UNFREEZE_SYNC,
++  EVENTS_UNFREEZE_REPLAY,
++} EventsUnfreezeMethod;
++
+ static gboolean
+ stage_has_key_focus (void)
+ {
+@@ -167,6 +173,43 @@ sequence_is_pointer_emulated (MetaDisplay        *display,
+   return FALSE;
+ }
+ 
++static void
++maybe_unfreeze_pointer_events (MetaBackend          *backend,
++                               const ClutterEvent   *event,
++                               EventsUnfreezeMethod  unfreeze_method)
++{
++  Display *xdisplay;
++  int event_mode;
++  int device_id;
++
++  if (event->type != CLUTTER_BUTTON_PRESS)
++    return;
++
++  if (!META_IS_BACKEND_X11 (backend))
++    return;
++
++  device_id = clutter_event_get_device_id (event);
++  switch (unfreeze_method)
++    {
++    case EVENTS_UNFREEZE_SYNC:
++      event_mode = XISyncDevice;
++      meta_verbose ("Syncing events time %u device %i\n",
++                    (unsigned int) event->button.time, device_id);
++      break;
++    case EVENTS_UNFREEZE_REPLAY:
++      event_mode = XIReplayDevice;
++      meta_verbose ("Replaying events time %u device %i\n",
++                    (unsigned int) event->button.time, device_id);
++      break;
++    default:
++      g_assert_not_reached ();
++      return;
++    }
++
++  xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
++  XIAllowEvents (xdisplay, device_id, event_mode, event->button.time);
++}
++
+ static gboolean
+ meta_display_handle_event (MetaDisplay        *display,
+                            const ClutterEvent *event)
+@@ -366,17 +409,7 @@ meta_display_handle_event (MetaDisplay        *display,
+         {
+           /* Only replay button press events, since that's where we
+            * have the synchronous grab. */
+-          if (event->type == CLUTTER_BUTTON_PRESS)
+-            {
+-              if (META_IS_BACKEND_X11 (backend))
+-                {
+-                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+-                  meta_verbose ("Allowing events time %u\n",
+-                                (unsigned int)event->button.time);
+-                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
+-                                 XIReplayDevice, event->button.time);
+-                }
+-            }
++          maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY);
+ 
+           /* If the focus window has an active close dialog let clutter
+            * events go through, so fancy clutter dialogs can get to handle
+@@ -392,6 +425,13 @@ meta_display_handle_event (MetaDisplay        *display,
+ 
+       goto out;
+     }
++  else
++    {
++      /* We could not match the event with a window, make sure we sync
++       * the pointer to discard the sequence and don't keep events frozen.
++       */
++       maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC);
++    }
+ 
+  out:
+   /* If the compositor has a grab, don't pass that through to Wayland */
+-- 
+2.23.0
+
diff --git a/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch b/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch
new file mode 100644
index 0000000..0ed0857
--- /dev/null
+++ b/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch
@@ -0,0 +1,136 @@
+From 80f79e0cc7509b79b38193a006b0d98d03432044 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Mon, 5 Aug 2019 14:39:21 -0400
+Subject: [PATCH] iconcache: Avoid xrender picture formats when creating cairo
+ surface
+
+If an application provides its window icon via wmhints, then mutter
+loads the pixmap specified by the application into a cairo xlib surface. When
+creating the surface it specifies the visual, indirectly, via an XRender
+picture format.
+
+This is suboptimal, since XRender picture formats don't have a way to specify
+16bpp depth, which an application may be using.
+
+In particular, applications are likely to use 16bpp depth pixmaps for their
+icons, if the video card offers a 16bpp framebuffer/root window.
+
+This commit drops the XRender middleman, and just tells cairo a visual to use
+directly.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/715
+---
+ src/x11/iconcache.c | 31 ++++++-------------------------
+ 1 file changed, 6 insertions(+), 25 deletions(-)
+
+diff --git a/src/x11/iconcache.c b/src/x11/iconcache.c
+index 15d72da65..521c77b8d 100644
+--- a/src/x11/iconcache.c
++++ b/src/x11/iconcache.c
+@@ -261,97 +261,78 @@ get_pixmap_geometry (MetaX11Display *x11_display,
+                      Pixmap          pixmap,
+                      int            *w,
+                      int            *h,
+                      int            *d)
+ {
+   Window root_ignored;
+   int x_ignored, y_ignored;
+   guint width, height;
+   guint border_width_ignored;
+   guint depth;
+ 
+   if (w)
+     *w = 1;
+   if (h)
+     *h = 1;
+   if (d)
+     *d = 1;
+ 
+   XGetGeometry (x11_display->xdisplay,
+                 pixmap, &root_ignored, &x_ignored, &y_ignored,
+                 &width, &height, &border_width_ignored, &depth);
+ 
+   if (w)
+     *w = width;
+   if (h)
+     *h = height;
+   if (d)
+     *d = depth;
+ }
+ 
+-static int
+-standard_pict_format_for_depth (int depth)
+-{
+-  switch (depth)
+-    {
+-    case 1:
+-      return PictStandardA1;
+-    case 24:
+-      return PictStandardRGB24;
+-    case 32:
+-      return PictStandardARGB32;
+-    default:
+-      g_assert_not_reached ();
+-    }
+-  return 0;
+-}
+-
+-static XRenderPictFormat *
+-pict_format_for_depth (Display *xdisplay, int depth)
+-{
+-  return XRenderFindStandardFormat (xdisplay, standard_pict_format_for_depth (depth));
+-}
+-
+ static cairo_surface_t *
+ surface_from_pixmap (Display *xdisplay, Pixmap xpixmap,
+                      int width, int height)
+ {
+   Window root_return;
++  XVisualInfo visual_info;
+   int x_ret, y_ret;
+   unsigned int w_ret, h_ret, bw_ret, depth_ret;
+ 
+   if (!XGetGeometry (xdisplay, xpixmap, &root_return,
+                      &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
+     return NULL;
+ 
+-  return cairo_xlib_surface_create_with_xrender_format (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay),
+-                                                        pict_format_for_depth (xdisplay, depth_ret), w_ret, h_ret);
++  if (!XMatchVisualInfo (xdisplay, DefaultScreen (xdisplay),
++                         depth_ret, TrueColor, &visual_info))
++    return NULL;
++
++  return cairo_xlib_surface_create (xdisplay, xpixmap, visual_info.visual, w_ret, h_ret);
+ }
+ 
+ static gboolean
+ try_pixmap_and_mask (MetaX11Display   *x11_display,
+                      Pixmap            src_pixmap,
+                      Pixmap            src_mask,
+                      cairo_surface_t **iconp)
+ {
+   Display *xdisplay = x11_display->xdisplay;
+   cairo_surface_t *icon, *mask = NULL;
+   int w, h, d;
+ 
+   if (src_pixmap == None)
+     return FALSE;
+ 
+   meta_x11_error_trap_push (x11_display);
+ 
+   get_pixmap_geometry (x11_display, src_pixmap, &w, &h, &d);
+   icon = surface_from_pixmap (xdisplay, src_pixmap, w, h);
+ 
+   if (icon && src_mask != None)
+     {
+       get_pixmap_geometry (x11_display, src_mask, &w, &h, &d);
+ 
+       if (d == 1)
+         mask = surface_from_pixmap (xdisplay, src_mask, w, h);
+     }
+ 
+   meta_x11_error_trap_pop (x11_display);
+ 
+-- 
+2.21.0
+
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..495d859
--- /dev/null
+++ b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch
@@ -0,0 +1,49 @@
+From 18d4fbb1fb641e2b507b3adcd13d231145a01cd6 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 629f8e94e..1e1e13367 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -333,7 +333,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);
+@@ -346,8 +345,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);
+         }
+     }
+@@ -379,8 +377,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.21.0
+
diff --git a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch
new file mode 100644
index 0000000..d204242
--- /dev/null
+++ b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch
@@ -0,0 +1,152 @@
+From 4904f1a1e5b881dfd5a051c15acecb3232dc8207 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] 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 | 77 ++++++++++++++++++++++
+ src/backends/meta-monitor-config-manager.h |  2 +
+ src/backends/meta-monitor-manager.c        | 19 ++++++
+ 3 files changed, 98 insertions(+)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index 9a54ce50f..d64ca1f79 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -643,6 +643,83 @@ 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;
++
++    output = meta_monitor_get_main_output (monitor);
++    crtc = meta_output_get_assigned_crtc (output);
++    return create_preferred_logical_monitor_config (monitor_manager,
++                                                    monitor,
++                                                    crtc->rect.x,
++                                                    crtc->rect.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);
++
++  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);
++
++      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 3875e04e9..364a2b36b 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 2d898c757..05b27c6be 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -614,6 +614,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.21.0
+
diff --git a/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch b/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch
new file mode 100644
index 0000000..dc34cee
--- /dev/null
+++ b/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch
@@ -0,0 +1,144 @@
+From 4ad8fd80355189ecbde6c38961335ae4be4db8b3 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Tue, 11 Sep 2018 10:19:44 -0400
+Subject: [PATCH] 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 d64ca1f79..c09edbe00 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;
+ };
+ 
+@@ -663,9 +664,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;
+@@ -673,6 +675,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;
+ 
+@@ -714,10 +719,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 *
+@@ -1256,6 +1265,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 364a2b36b..409611bb0 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 05b27c6be..bb4b44188 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -534,9 +534,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;
+@@ -547,6 +549,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);
+@@ -614,7 +628,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.21.0
+
diff --git a/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch
new file mode 100644
index 0000000..2242c67
--- /dev/null
+++ b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch
@@ -0,0 +1,272 @@
+From 849902beff553de41dd3940b17672ef98f687be5 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 4 Jun 2018 16:35:04 -0400
+Subject: [PATCH] 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         | 96 +++++++++++++++++--
+ 4 files changed, 123 insertions(+), 10 deletions(-)
+
+diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c
+index 3577391e5..946f72387 100644
+--- a/src/backends/meta-gpu.c
++++ b/src/backends/meta-gpu.c
+@@ -64,6 +64,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 701acdc97..a2fd061f7 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 3e8a7318d..90b33d486 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -44,6 +44,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)
+@@ -81,6 +83,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)
+@@ -116,8 +126,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,
+@@ -250,6 +270,7 @@ meta_gpu_xrandr_finalize (GObject *object)
+ static void
+ meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr)
+ {
++  gpu_xrandr->need_hardware_poll = TRUE;
+ }
+ 
+ static void
+@@ -261,4 +282,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 448e51fae..d60f00325 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -71,6 +71,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;
+ 
+   /*
+@@ -102,6 +106,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)
+ {
+@@ -1016,6 +1022,62 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager
+   return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
+ }
+ 
++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)
++    {
++      meta_gpu_poll_hardware (manager_xrandr->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)
+ {
+@@ -1072,12 +1134,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
+@@ -1123,9 +1196,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);
+   MetaGpuXrandr *gpu_xrandr;
+@@ -1134,11 +1206,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 (manager_xrandr->gpu);
+@@ -1173,6 +1240,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.21.0
+
diff --git a/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch b/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch
new file mode 100644
index 0000000..8a0242c
--- /dev/null
+++ b/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch
@@ -0,0 +1,114 @@
+From 078547521dd709d41ac3791322f711030ccc50e9 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 1/2] 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            | 37 +++++++++++++------
+ .../x11/meta-monitor-manager-xrandr.c         | 18 ++++++---
+ 2 files changed, 38 insertions(+), 17 deletions(-)
+
+diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
+index 90b33d486..1884278ca 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -91,6 +91,30 @@ 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);
++  MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
++  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)
+@@ -105,8 +129,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;
+@@ -115,16 +137,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 b8d6342b6..7a0b43ac4 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -146,12 +146,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;
+@@ -167,6 +164,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.23.0
+
diff --git a/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch
new file mode 100644
index 0000000..c487119
--- /dev/null
+++ b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch
@@ -0,0 +1,62 @@
+From 7e21503dc7c3b8321475eb5ccfdb23e71f86c0a0 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Tue, 6 Oct 2015 21:16:18 +0200
+Subject: [PATCH] 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         | 20 ++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
+index 45c81f4eb..448e51fae 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -1110,6 +1110,19 @@ 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);
++  GList *l;
++
++  for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next)
++    if (g_str_has_prefix (((MetaOutput *)l->data)->name, "VNC-"))
++      return TRUE;
++
++  return FALSE;
++}
++
+ gboolean
+ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
+ 					   XEvent                   *event)
+@@ -1119,6 +1132,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;
+@@ -1130,7 +1144,11 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
+   gpu_xrandr = META_GPU_XRANDR (manager_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.21.0
+
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..83f42ff
--- /dev/null
+++ b/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch
@@ -0,0 +1,35 @@
+From 9dfe362f41b8811450cb563c39899fafe8ec2b63 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 48241296e..7a6ab9288 100644
+--- a/data/org.gnome.mutter.wayland.gschema.xml.in
++++ b/data/org.gnome.mutter.wayland.gschema.xml.in
+@@ -60,7 +60,7 @@
+           gettext-domain="@GETTEXT_DOMAIN@">
+ 
+     <key name="xwayland-allow-grabs" type="b">
+-      <default>false</default>
++      <default>true</default>
+       <summary>Allow grabs with Xwayland</summary>
+       <description>
+         Allow keyboard grabs issued by X11 applications running in Xwayland
+@@ -73,7 +73,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.21.0
+
diff --git a/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch b/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch
new file mode 100644
index 0000000..486df56
--- /dev/null
+++ b/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch
@@ -0,0 +1,109 @@
+From f2b3dd318f1165849b45a86251724939b100ef7d Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Mon, 28 Oct 2019 18:07:31 +0100
+Subject: [PATCH] wayland: Check stylus serials on
+ meta_wayland_seat_can_popup()
+
+This allows xdg_popup.grab() to work with styli. Without this check
+we would bail out and emit xdg_popup.popup_done, leaving stylus users
+unable to interact with popup menus, comboboxes, etc...
+
+Closes: https://gitlab.gnome.org/GNOME/mutter/issues/886
+---
+ src/wayland/meta-wayland-seat.c        | 10 +++++++++-
+ src/wayland/meta-wayland-tablet-seat.c | 17 +++++++++++++++++
+ src/wayland/meta-wayland-tablet-seat.h |  2 ++
+ src/wayland/meta-wayland-tablet-tool.c |  7 +++++++
+ src/wayland/meta-wayland-tablet-tool.h |  2 ++
+ 5 files changed, 37 insertions(+), 1 deletion(-)
+
+diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
+index 91fe376ff..cf41d6eb8 100644
+--- a/src/wayland/meta-wayland-seat.c
++++ b/src/wayland/meta-wayland-seat.c
+@@ -504,9 +504,17 @@ gboolean
+ meta_wayland_seat_can_popup (MetaWaylandSeat *seat,
+                              uint32_t         serial)
+ {
++  MetaWaylandCompositor *compositor;
++  MetaWaylandTabletSeat *tablet_seat;
++
++  compositor = meta_wayland_compositor_get_default ();
++  tablet_seat =
++    meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
++
+   return (meta_wayland_pointer_can_popup (seat->pointer, serial) ||
+           meta_wayland_keyboard_can_popup (seat->keyboard, serial) ||
+-          meta_wayland_touch_can_popup (seat->touch, serial));
++          meta_wayland_touch_can_popup (seat->touch, serial) ||
++          meta_wayland_tablet_seat_can_popup (tablet_seat, serial));
+ }
+ 
+ gboolean
+diff --git a/src/wayland/meta-wayland-tablet-seat.c b/src/wayland/meta-wayland-tablet-seat.c
+index b4bc4aa58..b1964714a 100644
+--- a/src/wayland/meta-wayland-tablet-seat.c
++++ b/src/wayland/meta-wayland-tablet-seat.c
+@@ -552,3 +552,20 @@ meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
+   while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad))
+     meta_wayland_tablet_pad_set_focus (pad, surface);
+ }
++
++gboolean
++meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat,
++                                    uint32_t               serial)
++{
++  MetaWaylandTabletTool *tool;
++  GHashTableIter iter;
++
++  g_hash_table_iter_init (&iter, tablet_seat->tools);
++  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool))
++    {
++      if (meta_wayland_tablet_tool_can_popup (tool, serial))
++        return TRUE;
++    }
++
++  return FALSE;
++}
+diff --git a/src/wayland/meta-wayland-tablet-seat.h b/src/wayland/meta-wayland-tablet-seat.h
+index c083dec5f..e3be5f264 100644
+--- a/src/wayland/meta-wayland-tablet-seat.h
++++ b/src/wayland/meta-wayland-tablet-seat.h
+@@ -75,5 +75,7 @@ MetaWaylandTablet     *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylan
+                                                                       MetaWaylandTabletPad  *pad);
+ GList                 *meta_wayland_tablet_seat_lookup_paired_pads   (MetaWaylandTabletSeat *tablet_seat,
+                                                                       MetaWaylandTablet     *tablet);
++gboolean               meta_wayland_tablet_seat_can_popup            (MetaWaylandTabletSeat *tablet_seat,
++                                                                      uint32_t               serial);
+ 
+ #endif /* META_WAYLAND_TABLET_SEAT_H */
+diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c
+index c02831d73..065c834bb 100644
+--- a/src/wayland/meta-wayland-tablet-tool.c
++++ b/src/wayland/meta-wayland-tablet-tool.c
+@@ -1018,3 +1018,10 @@ meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
+   return ((tool->down_serial == serial || tool->button_serial == serial) &&
+           tablet_tool_can_grab_surface (tool, surface));
+ }
++
++gboolean
++meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool,
++                                    uint32_t               serial)
++{
++  return tool->down_serial == serial || tool->button_serial == serial;
++}
+diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h
+index 71bc86643..315e26bde 100644
+--- a/src/wayland/meta-wayland-tablet-tool.h
++++ b/src/wayland/meta-wayland-tablet-tool.h
+@@ -85,5 +85,7 @@ void     meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool  *t
+ gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
+                                                     MetaWaylandSurface    *surface,
+                                                     uint32_t               serial);
++gboolean meta_wayland_tablet_tool_can_popup        (MetaWaylandTabletTool *tool,
++                                                    uint32_t               serial);
+ 
+ #endif /* META_WAYLAND_TABLET_TOOL_H */
+-- 
+2.23.0
+
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..3cf01de
--- /dev/null
+++ b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch
@@ -0,0 +1,35 @@
+From 6bca5f001338d4647e4e21d549c8cdea4bcad669 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.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
+index f850cb222..1c8dc8fe5 100644
+--- a/src/compositor/meta-window-actor.c
++++ b/src/compositor/meta-window-actor.c
+@@ -798,6 +798,14 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
+   if (priv->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 (priv->window->res_name, "sun-awt-X11-XWindowPeer") == 0 &&
++      priv->window->shape_region != NULL)
++    return FALSE;
++
+   /*
+    * Generate shadows for all other windows.
+    */
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch b/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch
new file mode 100644
index 0000000..94a73d8
--- /dev/null
+++ b/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch
@@ -0,0 +1,83 @@
+From eca25ab6a12770a2a767458d9b0129d4fde3995c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
+Date: Tue, 13 Nov 2018 08:31:52 +0100
+Subject: [PATCH 1/2] workspace: Focus only ancestors that are focusable
+
+When destroying a window that has a parent, we initially try to focus one of
+its ancestors. However if no ancestor can be focused, then we should instead
+focus the default focus window instead of trying to request focus for a window
+that can't get focus anyways.
+
+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/308
+(cherry picked from commit eccc791f3b3451216f957e67fec47a73b65ed2b2)
+---
+ src/core/workspace.c | 37 +++++++++++++++++++++++++++----------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+diff --git a/src/core/workspace.c b/src/core/workspace.c
+index f2b2c2c48..58fcfa78c 100644
+--- a/src/core/workspace.c
++++ b/src/core/workspace.c
+@@ -85,6 +85,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData
+   MetaRectangle logical_monitor_work_area;
+ } MetaWorkspaceLogicalMonitorData;
+ 
++typedef struct _MetaWorkspaceFocusableAncestorData
++{
++  MetaWorkspace *workspace;
++  MetaWindow *out_window;
++} MetaWorkspaceFocusableAncestorData;
++
+ static MetaWorkspaceLogicalMonitorData *
+ meta_workspace_get_logical_monitor_data (MetaWorkspace      *workspace,
+                                          MetaLogicalMonitor *logical_monitor)
+@@ -1322,13 +1328,20 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
+ }
+ 
+ static gboolean
+-record_ancestor (MetaWindow *window,
+-                 void       *data)
++find_focusable_ancestor (MetaWindow *window,
++                         gpointer    user_data)
+ {
+-  MetaWindow **result = data;
++  MetaWorkspaceFocusableAncestorData *data = user_data;
++
++  if (!window->unmanaging && meta_window_is_focusable (window) &&
++      meta_window_located_on_workspace (window, data->workspace) &&
++      meta_window_showing_on_its_workspace (window))
++    {
++      data->out_window = window;
++      return FALSE;
++    }
+ 
+-  *result = window;
+-  return FALSE; /* quit with the first ancestor we find */
++  return TRUE;
+ }
+ 
+ /* Focus ancestor of not_this_one if there is one */
+@@ -1350,11 +1363,15 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
+   if (not_this_one)
+     {
+       MetaWindow *ancestor;
+-      ancestor = NULL;
+-      meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
+-      if (ancestor != NULL &&
+-          meta_window_located_on_workspace (ancestor, workspace) &&
+-          meta_window_showing_on_its_workspace (ancestor))
++      MetaWorkspaceFocusableAncestorData data;
++
++      data = (MetaWorkspaceFocusableAncestorData) {
++        .workspace = workspace,
++      };
++      meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data);
++      ancestor = data.out_window;
++
++      if (ancestor)
+         {
+           meta_topic (META_DEBUG_FOCUS,
+                       "Focusing %s, ancestor of %s\n",
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-workspace-manager-Expose-layout-properties.patch b/SOURCES/0001-workspace-manager-Expose-layout-properties.patch
new file mode 100644
index 0000000..908fe67
--- /dev/null
+++ b/SOURCES/0001-workspace-manager-Expose-layout-properties.patch
@@ -0,0 +1,80 @@
+From 52536a44e96aa34d3ec3b9332adaa15a6399fc3e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Tue, 4 Jun 2019 21:21:37 +0200
+Subject: [PATCH] workspace-manager: Expose layout properties
+
+gnome-shell hardcodes a vertical one-column workspace layout, and
+while not supporting arbitrary grids is very much by design, it
+currently doesn't have a choice: We simply don't expose the workspace
+layout we use.
+
+Change that to allow gnome-shell to be a bit more flexible with the
+workspace layouts it supports.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/618
+---
+ src/core/meta-workspace-manager.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c
+index 8e1f03fe8..fbae34c73 100644
+--- a/src/core/meta-workspace-manager.c
++++ b/src/core/meta-workspace-manager.c
+@@ -50,6 +50,9 @@ enum
+ {
+   PROP_0,
+ 
++  PROP_LAYOUT_COLUMNS,
++  PROP_LAYOUT_ROWS,
++
+   PROP_N_WORKSPACES
+ };
+ 
+@@ -68,6 +71,12 @@ meta_workspace_manager_get_property (GObject    *object,
+ 
+   switch (prop_id)
+     {
++    case PROP_LAYOUT_COLUMNS:
++      g_value_set_int (value, workspace_manager->columns_of_workspaces);
++      break;
++    case PROP_LAYOUT_ROWS:
++      g_value_set_int (value, workspace_manager->rows_of_workspaces);
++      break;
+     case PROP_N_WORKSPACES:
+       g_value_set_int (value, meta_workspace_manager_get_n_workspaces (workspace_manager));
+       break;
+@@ -154,6 +163,22 @@ meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass)
+                   0, NULL, NULL, NULL,
+                   G_TYPE_NONE, 0);
+ 
++  g_object_class_install_property (object_class,
++                                   PROP_LAYOUT_COLUMNS,
++                                   g_param_spec_int ("layout-columns",
++                                                     "Layout columns",
++                                                     "Number of columns in layout",
++                                                     -1, G_MAXINT, 1,
++                                                     G_PARAM_READABLE));
++
++  g_object_class_install_property (object_class,
++                                   PROP_LAYOUT_ROWS,
++                                   g_param_spec_int ("layout-rows",
++                                                     "Layout rows",
++                                                     "Number of rows in layout",
++                                                     -1, G_MAXINT, -1,
++                                                     G_PARAM_READABLE));
++
+   g_object_class_install_property (object_class,
+                                    PROP_N_WORKSPACES,
+                                    g_param_spec_int ("n-workspaces",
+@@ -474,6 +499,8 @@ meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_
+                 workspace_manager->columns_of_workspaces,
+                 workspace_manager->vertical_workspaces,
+                 workspace_manager->starting_corner);
++  g_object_notify (G_OBJECT (workspace_manager), "layout-columns");
++  g_object_notify (G_OBJECT (workspace_manager), "layout-rows");
+ }
+ 
+ /**
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch b/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch
new file mode 100644
index 0000000..5303bbc
--- /dev/null
+++ b/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch
@@ -0,0 +1,53 @@
+From 57b3a2ea620f754cfd38f1ed4851dd8223efbcab Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Thu, 28 Nov 2019 22:50:36 +0100
+Subject: [PATCH] x11: Check wacom button flags to determine whether button is
+ mode switch
+
+Checking the leds is not really accurate, since some devices have mode
+switch buttons without leds. Check in the button flags whether they are
+mode switch buttons for any of ring/ring2/strip/strip2, and return the
+appropriate group.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/952
+---
+ .../clutter/x11/clutter-input-device-xi2.c    | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c
+index 1254aca3ae..4e5e2fd12c 100644
+--- a/clutter/clutter/x11/clutter-input-device-xi2.c
++++ b/clutter/clutter/x11/clutter-input-device-xi2.c
+@@ -155,14 +155,25 @@ clutter_input_device_xi2_get_button_group (ClutterInputDevice *device,
+ 
+   if (device_xi2->wacom_device)
+     {
++      WacomButtonFlags flags;
++
+       if (button >= libwacom_get_num_buttons (device_xi2->wacom_device))
+         return -1;
+ 
+-      return libwacom_get_button_led_group (device_xi2->wacom_device,
+-                                            'A' + button);
++      flags = libwacom_get_button_flag (device_xi2->wacom_device,
++                                        'A' + button);
++
++      if (flags &
++          (WACOM_BUTTON_RING_MODESWITCH |
++           WACOM_BUTTON_TOUCHSTRIP_MODESWITCH))
++        return 0;
++      if (flags &
++          (WACOM_BUTTON_RING2_MODESWITCH |
++           WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH))
++        return 1;
+     }
+-  else
+-    return -1;
++
++  return -1;
+ }
+ #endif
+ 
+-- 
+2.24.0
+
diff --git a/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch b/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch
new file mode 100644
index 0000000..3cb0623
--- /dev/null
+++ b/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch
@@ -0,0 +1,163 @@
+From 063db6c9a7504a4d7baae28f7899bd661c459c41 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Mon, 14 Jan 2019 11:11:01 -0500
+Subject: [PATCH 2/9] backend: switch to using generated logind proxy
+
+Right now we listen to prepare-for-sleep using
+raw gdbus calls.
+
+This commit switches it over to use a generated
+proxy, which will become useful in a future commit,
+for adding suspending inhibitors.
+---
+ src/backends/meta-backend.c    | 60 ++++++++++++++++++++++------------
+ src/org.freedesktop.login1.xml | 13 ++++++++
+ 2 files changed, 52 insertions(+), 21 deletions(-)
+
+diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
+index 23ab2faec..5d71977c6 100644
+--- a/src/backends/meta-backend.c
++++ b/src/backends/meta-backend.c
+@@ -65,6 +65,7 @@
+ #include "meta/main.h"
+ #include "meta/meta-backend.h"
+ #include "meta/util.h"
++#include "meta-dbus-login1.h"
+ 
+ #ifdef HAVE_REMOTE_DESKTOP
+ #include "backends/meta-dbus-session-watcher.h"
+@@ -145,10 +146,12 @@ struct _MetaBackendPrivate
+   GDBusProxy *upower_proxy;
+   gboolean lid_is_closed;
+ 
+-  guint sleep_signal_id;
+   GCancellable *cancellable;
+   GDBusConnection *system_bus;
+ 
++  Login1Manager *logind_proxy;
++  int            inhibit_sleep_fd;
++
+   gboolean was_headless;
+ };
+ typedef struct _MetaBackendPrivate MetaBackendPrivate;
+@@ -156,6 +159,10 @@ typedef struct _MetaBackendPrivate MetaBackendPrivate;
+ static void
+ initable_iface_init (GInitableIface *initable_iface);
+ 
++
++static void prepare_for_sleep_cb (MetaBackend *backend,
++                                  gboolean     suspending);
++
+ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
+                                   G_ADD_PRIVATE (MetaBackend)
+                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+@@ -177,8 +184,6 @@ meta_backend_finalize (GObject *object)
+   g_clear_object (&priv->remote_access_controller);
+ #endif
+ 
+-  if (priv->sleep_signal_id)
+-    g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
+   if (priv->upower_watch_id)
+     g_bus_unwatch_name (priv->upower_watch_id);
+   g_cancellable_cancel (priv->cancellable);
+@@ -764,13 +769,8 @@ meta_backend_create_renderer (MetaBackend *backend,
+ }
+ 
+ static void
+-prepare_for_sleep_cb (GDBusConnection *connection,
+-                      const gchar     *sender_name,
+-                      const gchar     *object_path,
+-                      const gchar     *interface_name,
+-                      const gchar     *signal_name,
+-                      GVariant        *parameters,
+-                      gpointer         user_data)
++prepare_for_sleep_cb (MetaBackend *backend,
++                      gboolean     suspending)
+ {
+   gboolean suspending;
+ 
+@@ -780,12 +780,31 @@ prepare_for_sleep_cb (GDBusConnection *connection,
+   meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
+ }
+ 
++static Login1Manager *
++get_logind_proxy (GCancellable *cancellable,
++                  GError      **error)
++{
++  Login1Manager *proxy;
++
++  proxy =
++    login1_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
++                                           G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
++                                           "org.freedesktop.login1",
++                                           "/org/freedesktop/login1",
++                                           cancellable, error);
++  if (!proxy)
++    g_prefix_error (error, "Could not get logind proxy: ");
++
++  return proxy;
++}
++
+ static void
+ system_bus_gotten_cb (GObject      *object,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+ {
+   MetaBackendPrivate *priv;
++  g_autoptr (GError) error = NULL;
+   GDBusConnection *bus;
+ 
+   bus = g_bus_get_finish (res, NULL);
+@@ -794,17 +813,16 @@ system_bus_gotten_cb (GObject      *object,
+ 
+   priv = meta_backend_get_instance_private (user_data);
+   priv->system_bus = bus;
+-  priv->sleep_signal_id =
+-    g_dbus_connection_signal_subscribe (priv->system_bus,
+-                                        "org.freedesktop.login1",
+-                                        "org.freedesktop.login1.Manager",
+-                                        "PrepareForSleep",
+-                                        "/org/freedesktop/login1",
+-                                        NULL,
+-                                        G_DBUS_SIGNAL_FLAGS_NONE,
+-                                        prepare_for_sleep_cb,
+-                                        NULL,
+-                                        NULL);
++  priv->logind_proxy = get_logind_proxy (priv->cancellable, &error);
++
++  if (!priv->logind_proxy)
++    g_warning ("Failed to get logind proxy: %s", error->message);
++
++  g_signal_connect_object (priv->logind_proxy,
++                           "prepare-for-sleep",
++                           G_CALLBACK (prepare_for_sleep_cb),
++                           user_data,
++                           G_CONNECT_SWAPPED);
+ }
+ 
+ static gboolean
+diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml
+index 765475132..1ecfd976f 100644
+--- a/src/org.freedesktop.login1.xml
++++ b/src/org.freedesktop.login1.xml
+@@ -43,4 +43,17 @@
+       <arg name="vt" type="u"/>
+     </method>
+   </interface>
++
++  <interface name="org.freedesktop.login1.Manager">
++    <method name="Inhibit">
++      <arg name="what" type="s" direction="in"/>
++      <arg name="who" type="s" direction="in"/>
++      <arg name="why" type="s" direction="in"/>
++      <arg name="mode" type="s" direction="in"/>
++      <arg name="fd" type="h" direction="out"/>
++    </method>
++    <signal name="PrepareForSleep">
++      <arg name="active" type="b"/>
++    </signal>
++  </interface>
+ </node>
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch
new file mode 100644
index 0000000..510b926
--- /dev/null
+++ b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch
@@ -0,0 +1,42 @@
+From 801da0dab1d2928578e9b191ee1684bcc7154081 Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Tue, 30 Apr 2019 17:01:04 +0300
+Subject: [PATCH 02/12] cogl: Fix doc for _cogl_blit_framebuffer
+
+Commit 38921701e533b7fda38a236cc45aec2ed3afef8a added explicit source and
+destination parameters. Fix the documentation to match.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit fc0ce11fcd997af12fc2253eeb37e03cebb5964f)
+---
+ cogl/cogl/cogl-framebuffer-private.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index 296788c2b..de886b64f 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -4,6 +4,7 @@
+  * A Low Level GPU Graphics and Utilities API
+  *
+  * Copyright (C) 2007,2008,2009 Intel Corporation.
++ * Copyright (C) 2019 DisplayLink (UK) Ltd.
+  *
+  * Permission is hereby granted, free of charge, to any person
+  * obtaining a copy of this software and associated documentation
+@@ -377,9 +378,8 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  * @width: Width of region to copy
+  * @height: Height of region to copy
+  *
+- * This blits a region of the color buffer of the current draw buffer
+- * to the current read buffer. The draw and read buffers can be set up
+- * using _cogl_push_framebuffers(). This function should only be
++ * This blits a region of the color buffer of the source buffer
++ * to the destination buffer. This function should only be
+  * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is
+  * advertised. The two buffers must both be offscreen and have the
+  * same format.
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch
new file mode 100644
index 0000000..93756e4
--- /dev/null
+++ b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch
@@ -0,0 +1,185 @@
+From 85484d8f5d75764ab74308da7b21411c3fe4a2da 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 2/2] 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            | 60 +++++++++++++++++++
+ .../x11/meta-monitor-manager-xrandr.c         | 22 ++++++-
+ .../x11/meta-monitor-manager-xrandr.h         |  4 ++
+ 3 files changed, 85 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
+index 1884278ca..22e7e70e0 100644
+--- a/src/backends/x11/meta-gpu-xrandr.c
++++ b/src/backends/x11/meta-gpu-xrandr.c
+@@ -115,6 +115,63 @@ 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);
++  MetaCrtcMode *mode;
++  MetaCrtc *crtc;
++  MetaOutput *output;
++
++  meta_monitor_manager_xrandr_update_dpms_state (monitor_manager_xrandr);
++  update_screen_size (gpu_xrandr);
++
++  mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
++  mode->mode_id = 0;
++  mode->width = monitor_manager->screen_width;
++  mode->height = monitor_manager->screen_height;
++  mode->refresh_rate = 60.0;
++  mode->name = g_strdup_printf ("%dx%d", mode->width, mode->height);
++
++  meta_gpu_take_modes (gpu, g_list_prepend (NULL, mode));
++
++  crtc = g_object_new (META_TYPE_CRTC, NULL);
++  crtc->gpu = gpu;
++  crtc->crtc_id = 0;
++  crtc->rect = (MetaRectangle) { .width = mode->width, .height = mode->height };
++  crtc->current_mode = mode;
++
++  meta_gpu_take_crtcs (gpu, g_list_prepend (NULL, crtc));
++
++  output = g_object_new (META_TYPE_OUTPUT, NULL);
++  output->gpu = gpu;
++  output->winsys_id = 0;
++  output->name = g_strdup ("X11 Screen");
++  output->vendor = g_strdup ("unknown");
++  output->product = g_strdup ("unknown");
++  output->serial = g_strdup ("unknown");
++  output->hotplug_mode_update = TRUE;
++  output->suggested_x = -1;
++  output->suggested_y = -1;
++  output->connector_type = META_CONNECTOR_TYPE_Unknown;
++  output->modes = g_new0 (MetaCrtcMode *, 1);
++  output->modes[0] = mode;
++  output->n_modes = 1;
++  output->preferred_mode = mode;
++  output->possible_crtcs = g_new0 (MetaCrtc *, 1);
++  output->possible_crtcs[0] = crtc;
++  output->n_possible_crtcs = 1;
++  meta_output_assign_crtc (output, crtc);
++  output->is_primary = TRUE;
++
++  meta_gpu_take_outputs (gpu, g_list_prepend (NULL, output));
++
++  return TRUE;
++}
++
+ static gboolean
+ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
+                               GError  **error)
+@@ -133,6 +190,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 7a0b43ac4..d6306faeb 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -75,6 +75,7 @@ struct _MetaMonitorManagerXrandr
+   guint logind_watch_id;
+   guint logind_signal_sub_id;
+ 
++  gboolean has_randr;
+   gboolean has_randr15;
+ 
+   /*
+@@ -114,6 +115,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)
+ {
+@@ -145,7 +152,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);
+@@ -637,9 +644,18 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager      *mana
+                                                    MetaMonitorsConfigMethod method,
+                                                    GError                 **error)
+ {
++  MetaMonitorManagerXrandr *manager_xrandr =
++    META_MONITOR_MANAGER_XRANDR (manager);
+   GPtrArray *crtc_infos;
+   GPtrArray *output_infos;
+ 
++  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)
+     {
+       meta_monitor_manager_xrandr_rebuild_derived (manager, NULL);
+@@ -1105,11 +1121,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 d55b3d2b8..dc75134a5 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.23.0
+
diff --git a/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch b/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch
new file mode 100644
index 0000000..fedf5ce
--- /dev/null
+++ b/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch
@@ -0,0 +1,42 @@
+From 9a8bb8a205656ca1089444a041c99c5591477642 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
+Date: Fri, 3 May 2019 18:10:47 +0000
+Subject: [PATCH 2/2] window: Emit an error and return when trying to activate
+ an unmanaged
+
+If something (i.e. gnome-shell or an extension) tries to activate an unmanaged
+window, we should warn about this and avoid to perform further actions as this
+could lead to a crash of mutter, since the window has not valid flags (like
+workspace) set anymore at this stage.
+
+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/580
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/564
+
+
+(cherry picked from commit a6fc656e917fd48b8708b8d9f4bf9f8b15581313)
+---
+ src/core/window.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/core/window.c b/src/core/window.c
+index d2c24506b..725cca7ce 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -3683,6 +3683,13 @@ meta_window_activate_full (MetaWindow     *window,
+ {
+   MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+   gboolean allow_workspace_switch;
++
++  if (window->unmanaging)
++    {
++      g_warning ("Trying to activate unmanaged window '%s'", window->desc);
++      return;
++    }
++
+   meta_topic (META_DEBUG_FOCUS,
+               "_NET_ACTIVE_WINDOW message sent for %s at time %u "
+               "by client type %u.\n",
+-- 
+2.21.0
+
diff --git a/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch b/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch
new file mode 100644
index 0000000..03adc3a
--- /dev/null
+++ b/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch
@@ -0,0 +1,181 @@
+From c5020c3d303ab211a970d88638e7d723034688db Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Thu, 10 Jan 2019 10:47:19 -0500
+Subject: [PATCH 3/9] backend: add signals for reporting suspend and resume
+
+This commit adds "suspending" and "resuming" signals
+to MetaBackend.
+
+It's preliminary work needed for tracking when to purge
+and recreate all textures (needed by nvidia).
+---
+ src/backends/meta-backend.c    | 98 ++++++++++++++++++++++++++++++----
+ src/org.freedesktop.login1.xml |  1 +
+ 2 files changed, 88 insertions(+), 11 deletions(-)
+
+diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
+index 5d71977c6..f59b899b7 100644
+--- a/src/backends/meta-backend.c
++++ b/src/backends/meta-backend.c
+@@ -53,6 +53,8 @@
+ 
+ #include <stdlib.h>
+ 
++#include <gio/gunixfdlist.h>
++
+ #include "backends/meta-cursor-tracker-private.h"
+ #include "backends/meta-idle-monitor-private.h"
+ #include "backends/meta-input-settings-private.h"
+@@ -87,6 +89,8 @@ enum
+   LAST_DEVICE_CHANGED,
+   LID_IS_CLOSED_CHANGED,
+ 
++  SUSPENDING,
++  RESUMING,
+   N_SIGNALS
+ };
+ 
+@@ -745,6 +749,20 @@ meta_backend_class_init (MetaBackendClass *klass)
+                   0,
+                   NULL, NULL, NULL,
+                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
++  signals[SUSPENDING] =
++    g_signal_new ("suspending",
++                  G_TYPE_FROM_CLASS (object_class),
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  NULL, NULL, NULL,
++                  G_TYPE_NONE, 0);
++  signals[RESUMING] =
++    g_signal_new ("resuming",
++                  G_TYPE_FROM_CLASS (object_class),
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  NULL, NULL, NULL,
++                  G_TYPE_NONE, 0);
+ 
+   mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS");
+   stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0;
+@@ -768,15 +786,66 @@ meta_backend_create_renderer (MetaBackend *backend,
+   return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
+ }
+ 
++static void
++inhibit_sleep (MetaBackend *backend)
++{
++  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
++  g_autoptr (GVariant) fd_variant = NULL;
++  g_autoptr (GUnixFDList) fd_list = NULL;
++  g_autoptr (GError) error = NULL;
++  int handle, fd;
++
++  if (priv->inhibit_sleep_fd >= 0)
++    return;
++
++  if (!login1_manager_call_inhibit_sync (priv->logind_proxy,
++                                         "sleep",
++                                         "Display Server",
++                                         "Prepare for suspend",
++                                         "delay",
++                                         NULL,
++                                         &fd_variant,
++                                         &fd_list,
++                                         priv->cancellable,
++                                         &error))
++    {
++      g_warning ("Failed to inhibit sleep: %s", error->message);
++      return;
++    }
++
++  handle = g_variant_get_handle (fd_variant);
++  fd = g_unix_fd_list_get (fd_list, handle, &error);
++
++  if (fd < 0)
++    {
++      g_warning ("Failed to fetch sleep inhibitor fd: %s", error->message);
++      return;
++    }
++
++  priv->inhibit_sleep_fd = fd;
++}
++
++static void
++uninhibit_sleep (MetaBackend *backend)
++{
++  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
++
++  close (priv->inhibit_sleep_fd);
++  priv->inhibit_sleep_fd = -1;
++}
++
+ static void
+ prepare_for_sleep_cb (MetaBackend *backend,
+                       gboolean     suspending)
+ {
+-  gboolean suspending;
+-
+-  g_variant_get (parameters, "(b)", &suspending);
+-  if (suspending)
++  if (suspending) {
++    g_signal_emit (backend, signals[SUSPENDING], 0);
++    uninhibit_sleep (backend);
+     return;
++  }
++
++  inhibit_sleep (backend);
++  g_signal_emit (backend, signals[RESUMING], 0);
+   meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
+ }
+ 
+@@ -803,6 +872,7 @@ system_bus_gotten_cb (GObject      *object,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+ {
++  MetaBackend *backend = META_BACKEND (user_data);
+   MetaBackendPrivate *priv;
+   g_autoptr (GError) error = NULL;
+   GDBusConnection *bus;
+@@ -814,15 +884,21 @@ system_bus_gotten_cb (GObject      *object,
+   priv = meta_backend_get_instance_private (user_data);
+   priv->system_bus = bus;
+   priv->logind_proxy = get_logind_proxy (priv->cancellable, &error);
++  priv->inhibit_sleep_fd = -1;
+ 
+   if (!priv->logind_proxy)
+-    g_warning ("Failed to get logind proxy: %s", error->message);
+-
+-  g_signal_connect_object (priv->logind_proxy,
+-                           "prepare-for-sleep",
+-                           G_CALLBACK (prepare_for_sleep_cb),
+-                           user_data,
+-                           G_CONNECT_SWAPPED);
++    {
++      g_warning ("Failed to get logind proxy: %s", error->message);
++    }
++  else
++    {
++      inhibit_sleep (backend);
++      g_signal_connect_object (priv->logind_proxy,
++                               "prepare-for-sleep",
++                               G_CALLBACK (prepare_for_sleep_cb),
++                               user_data,
++                               G_CONNECT_SWAPPED);
++    }
+ }
+ 
+ static gboolean
+diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml
+index 1ecfd976f..7db8f373c 100644
+--- a/src/org.freedesktop.login1.xml
++++ b/src/org.freedesktop.login1.xml
+@@ -46,6 +46,7 @@
+ 
+   <interface name="org.freedesktop.login1.Manager">
+     <method name="Inhibit">
++      <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
+       <arg name="what" type="s" direction="in"/>
+       <arg name="who" type="s" direction="in"/>
+       <arg name="why" type="s" direction="in"/>
+-- 
+2.21.0
+
diff --git a/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch
new file mode 100644
index 0000000..b41fa93
--- /dev/null
+++ b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch
@@ -0,0 +1,77 @@
+From 04d921c2c1da571c8c61a4ca12a380bc3b9623fe Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Mon, 6 May 2019 13:40:31 +0300
+Subject: [PATCH 03/12] cogl: Replace ANGLE with GLES3 and NV framebuffer_blit
+
+ANGLE extensions are only provided by Google's Almost Native Graphics Layer
+Engine (ANGLE) implementation. Therefore they do not seem too useful for
+Mutter.
+
+The reason to drop GL_ANGLE_framebuffer_blit support is that it has more
+limitations compared to the glBlitFramebuffer in GL_EXT_framebuffer_blit,
+GL_NV_framebuffer_bit, OpenGL 3.0 and OpenGL ES 3.0. Most importantly, the
+ANGLE version cannot flip the image while copying, which limits
+_cogl_blit_framebuffer to only off-screen <-> off-screen copies. Follow-up work
+will need off-screen <-> on-screen copies.
+
+Instead of adding yet more capability flags to Cogl, dropping ANGLE support
+seems appropriate.
+
+The NV extension is added to the list of glBlitFramebuffer providers because it
+provides the same support as ANGLE and more.
+
+Likewise OpenGL ES 3.0 is added to the list of glBlitFramebuffer providers
+because e.g. Mesa GLES implementation usually provides it and that makes it
+widely available, again surpassing the ANGLE supported features.
+
+Follow-up patches will lift some of the Cogl assumptions of what
+glBlitFramebuffer cannot do.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit 3e68c9e8faa78298039fa3583898f18550740812)
+---
+ cogl/cogl/cogl-framebuffer-private.h         | 3 +--
+ cogl/cogl/gl-prototypes/cogl-all-functions.h | 5 +++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index de886b64f..3aab852c4 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -387,8 +387,7 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  * Note that this function differs a lot from the glBlitFramebuffer
+  * function provided by the GL_EXT_framebuffer_blit extension. Notably
+  * it doesn't support having different sizes for the source and
+- * destination rectangle. This isn't supported by the corresponding
+- * GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem
++ * destination rectangle. This doesn't seem
+  * like a particularly useful feature. If the application wanted to
+  * scale the results it may make more sense to draw a primitive
+  * instead.
+diff --git a/cogl/cogl/gl-prototypes/cogl-all-functions.h b/cogl/cogl/gl-prototypes/cogl-all-functions.h
+index 924ee349d..0af126059 100644
+--- a/cogl/cogl/gl-prototypes/cogl-all-functions.h
++++ b/cogl/cogl/gl-prototypes/cogl-all-functions.h
+@@ -4,6 +4,7 @@
+  * A Low Level GPU Graphics and Utilities API
+  *
+  * Copyright (C) 2009, 2011 Intel Corporation.
++ * Copyright (C) 2019 DisplayLink (UK) Ltd.
+  *
+  * Permission is hereby granted, free of charge, to any person
+  * obtaining a copy of this software and associated documentation
+@@ -132,8 +133,8 @@ COGL_EXT_END ()
+ 
+ 
+ COGL_EXT_BEGIN (offscreen_blit, 3, 0,
+-                0, /* not in either GLES */
+-                "EXT\0ANGLE\0",
++                COGL_EXT_IN_GLES3,
++                "EXT\0NV\0",
+                 "framebuffer_blit\0")
+ COGL_EXT_FUNCTION (void, glBlitFramebuffer,
+                    (GLint                 srcX0,
+-- 
+2.21.0
+
diff --git a/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch
new file mode 100644
index 0000000..751e0cb
--- /dev/null
+++ b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch
@@ -0,0 +1,100 @@
+From 6c6c6ad5412f5bb13592630d7cb3b7aed25d159b Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Mon, 6 May 2019 14:09:16 +0300
+Subject: [PATCH 04/12] cogl: Relax formats on glBlitFramebuffer
+
+Depends on: "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit"
+
+As a possible ANGLE implementation is not longer limiting the pixel format
+matching, lift the requirement of having the same pixel format.
+
+We still cannot do a premult <-> non-premult conversion during a blit, so guard
+against that.
+
+This will be useful in follow-up work to copy from onscreen primary GPU
+framebuffer to an offscreen secondary GPU framebuffer if the formats do not
+match exactly.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit 6df34eb4b7c65210f4066f7eb9bd462278b7279b)
+---
+ cogl/cogl/cogl-blit.c                | 10 ++++++----
+ cogl/cogl/cogl-framebuffer-private.h |  8 ++++++--
+ cogl/cogl/cogl-framebuffer.c         |  6 ++++--
+ 3 files changed, 16 insertions(+), 8 deletions(-)
+
+diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c
+index 74f404f3d..a61eb66d2 100644
+--- a/cogl/cogl/cogl-blit.c
++++ b/cogl/cogl/cogl-blit.c
+@@ -4,6 +4,7 @@
+  * A Low Level GPU Graphics and Utilities API
+  *
+  * Copyright (C) 2011 Intel Corporation.
++ * Copyright (C) 2019 DisplayLink (UK) Ltd.
+  *
+  * Permission is hereby granted, free of charge, to any person
+  * obtaining a copy of this software and associated documentation
+@@ -152,10 +153,11 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
+   CoglFramebuffer *dst_fb, *src_fb;
+   CoglError *ignore_error = NULL;
+ 
+-  /* We can only blit between FBOs if both textures are the same
+-     format and the blit framebuffer extension is supported */
+-  if ((_cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) !=
+-      (_cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) ||
++  /* We can only blit between FBOs if both textures have the same
++     premult convention and the blit framebuffer extension is
++     supported. */
++  if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) !=
++      (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) ||
+       !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT))
+     return FALSE;
+ 
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index 3aab852c4..b06fbaee1 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -381,8 +381,12 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  * This blits a region of the color buffer of the source buffer
+  * to the destination buffer. This function should only be
+  * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is
+- * advertised. The two buffers must both be offscreen and have the
+- * same format.
++ * advertised. The two buffers must both be offscreen.
++ *
++ * The two buffers must have the same value types (e.g. floating-point,
++ * unsigned int, signed int, or fixed-point), but color formats do not
++ * need to match. This limitation comes from OpenGL ES 3.0 definition
++ * of glBlitFramebuffer.
+  *
+  * Note that this function differs a lot from the glBlitFramebuffer
+  * function provided by the GL_EXT_framebuffer_blit extension. Notably
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index bd8a7fa42..0bc225945 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -4,6 +4,7 @@
+  * A Low Level GPU Graphics and Utilities API
+  *
+  * Copyright (C) 2007,2008,2009,2012 Intel Corporation.
++ * Copyright (C) 2019 DisplayLink (UK) Ltd.
+  *
+  * Permission is hereby granted, free of charge, to any person
+  * obtaining a copy of this software and associated documentation
+@@ -1468,8 +1469,9 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
+      support this */
+   _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src));
+   _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest));
+-  /* The buffers must be the same format */
+-  _COGL_RETURN_IF_FAIL (src->internal_format == dest->internal_format);
++  /* The buffers must use the same premult convention */
++  _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) ==
++                        (dest->internal_format & COGL_PREMULT_BIT));
+ 
+   /* Make sure the current framebuffers are bound. We explicitly avoid
+      flushing the clip state so we can bind our own empty state */
+-- 
+2.21.0
+
diff --git a/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch b/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch
new file mode 100644
index 0000000..d5a0e9f
--- /dev/null
+++ b/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch
@@ -0,0 +1,118 @@
+From a4a703c75e208badf78c81558994a249797dbb0a Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Sat, 12 Jan 2019 12:38:01 -0500
+Subject: [PATCH 4/9] wayland: force X clients to redraw on resume
+
+On nvidia, the textures backing Xwayland client window contents get
+corrupted on suspend.  Xwayland currently doesn't handle this situation
+itself.
+
+For now, in order to work around this issue, send an empty output
+change event to Xwayland.  This will cause it to force Expose events
+to get sent to all clients and get them to redraw.
+---
+ .../native/meta-monitor-manager-kms.c         |  7 +++
+ src/wayland/meta-wayland-outputs.c            | 47 +++++++++++++++++++
+ src/wayland/meta-wayland-outputs.h            |  1 +
+ 3 files changed, 55 insertions(+)
+
+diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
+index 9a0364441..7bcceee97 100644
+--- a/src/backends/native/meta-monitor-manager-kms.c
++++ b/src/backends/native/meta-monitor-manager-kms.c
+@@ -60,6 +60,7 @@
+ #include "clutter/clutter.h"
+ #include "meta/main.h"
+ #include "meta/meta-x11-errors.h"
++#include "wayland/meta-wayland-outputs.h"
+ 
+ #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor"
+ 
+@@ -505,9 +506,15 @@ void
+ meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
+ {
+   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
++  ClutterBackend *clutter_backend = clutter_get_default_backend ();
++  CoglContext *cogl_context =
++    clutter_backend_get_cogl_context (clutter_backend);
+ 
+   meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
+   handle_hotplug_event (manager);
++
++  if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
++    meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ());
+ }
+ 
+ static gboolean
+diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c
+index 099e87ab9..bc69d699d 100644
+--- a/src/wayland/meta-wayland-outputs.c
++++ b/src/wayland/meta-wayland-outputs.c
+@@ -496,6 +496,53 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
+   return new_table;
+ }
+ 
++void
++meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor)
++{
++  MetaMonitorManager *monitor_manager;
++  GList *logical_monitors, *l;
++
++  monitor_manager = meta_monitor_manager_get ();
++
++  logical_monitors =
++    meta_monitor_manager_get_logical_monitors (monitor_manager);
++
++  for (l = logical_monitors; l; l = l->next)
++    {
++      MetaLogicalMonitor *logical_monitor = l->data;
++      MetaWaylandOutput *wayland_output;
++      GList *iter;
++
++      if (logical_monitor->winsys_id == 0)
++        continue;
++
++      wayland_output =
++        g_hash_table_lookup (compositor->outputs,
++                             GSIZE_TO_POINTER (logical_monitor->winsys_id));
++
++      if (wayland_output == NULL)
++        continue;
++
++      /* Just output a "changes done" event for one of the outputs, with no actual changes.
++       * xwayland takes this as a cue to send expose events to all X clients.
++       */
++      for (iter = wayland_output->resources; iter; iter = iter->next)
++        {
++          struct wl_resource *resource = iter->data;
++          if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
++            wl_output_send_done (resource);
++        }
++
++      for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
++        {
++          struct wl_resource *xdg_output = iter->data;
++          zxdg_output_v1_send_done (xdg_output);
++        }
++
++      break;
++    }
++}
++
+ static void
+ on_monitors_changed (MetaMonitorManager    *monitors,
+                      MetaWaylandCompositor *compositor)
+diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h
+index ff15a81bd..d649e0fa1 100644
+--- a/src/wayland/meta-wayland-outputs.h
++++ b/src/wayland/meta-wayland-outputs.h
+@@ -49,5 +49,6 @@ struct _MetaWaylandOutput
+ };
+ 
+ void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);
++void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor);
+ 
+ #endif /* META_WAYLAND_OUTPUTS_H */
+-- 
+2.21.0
+
diff --git a/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch b/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch
new file mode 100644
index 0000000..0567862
--- /dev/null
+++ b/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch
@@ -0,0 +1,40 @@
+From 122d7726e450712b8b2fc85db41e3c8ab7b6ad56 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 15 Jan 2019 10:29:55 -0500
+Subject: [PATCH 5/9] backends/native: emit gl-video-memory-purged when
+ becoming active
+
+The proprietary NVIDIA driver garbles memory on suspend.  In order
+to work around that limitation, mutter needs to refresh all its
+textures on resuem.
+
+This commit lays the way toward doing that by emitting the
+"gl-video-memory-purged" signal when the compositor becomes active
+by logind (which happens on VT switch and on resume).
+---
+ src/backends/native/meta-backend-native.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
+index c473681cb..f593197e7 100644
+--- a/src/backends/native/meta-backend-native.c
++++ b/src/backends/native/meta-backend-native.c
+@@ -653,8 +653,15 @@ void meta_backend_native_resume (MetaBackendNative *native)
+     meta_backend_get_monitor_manager (backend);
+   MetaMonitorManagerKms *monitor_manager_kms =
+     META_MONITOR_MANAGER_KMS (monitor_manager);
++  MetaDisplay *display = meta_get_display ();
++  ClutterBackend *clutter_backend = clutter_get_default_backend ();
++  CoglContext *cogl_context =
++    clutter_backend_get_cogl_context (clutter_backend);
+   MetaIdleMonitor *idle_monitor;
+ 
++  if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
++    g_signal_emit_by_name (display, "gl-video-memory-purged");
++
+   meta_monitor_manager_kms_resume (monitor_manager_kms);
+ 
+   clutter_evdev_reclaim_devices ();
+-- 
+2.21.0
+
diff --git a/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch
new file mode 100644
index 0000000..81d49d6
--- /dev/null
+++ b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch
@@ -0,0 +1,145 @@
+From e4b2234d9918e9d3357ac3c7ca3898599725d3da Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Mon, 6 May 2019 15:08:29 +0300
+Subject: [PATCH 05/12] cogl: Allow glBlitFramebuffer between
+ onscreen/offscreen
+
+Depends on "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit"
+
+Allow blitting between onscreen and offscreen framebuffers by doing the y-flip
+as necessary. This was not possible with ANGLE, but now with ANGLE gone,
+glBlitFramebuffer supports flipping the copied image.
+
+This will be useful in follow-up work to copy from onscreen primary GPU
+framebuffer to an offscreen secondary GPU framebuffer.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit 45289b3d65e308117f1bc8fe6a4c88c1baaacca7)
+---
+ cogl/cogl/cogl-framebuffer-private.h      | 14 +++----
+ cogl/cogl/cogl-framebuffer.c              | 46 ++++++++++++++++++-----
+ cogl/cogl/driver/gl/cogl-framebuffer-gl.c |  5 +--
+ 3 files changed, 43 insertions(+), 22 deletions(-)
+
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index b06fbaee1..f68153d8b 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -381,7 +381,11 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  * This blits a region of the color buffer of the source buffer
+  * to the destination buffer. This function should only be
+  * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is
+- * advertised. The two buffers must both be offscreen.
++ * advertised.
++ *
++ * The source and destination rectangles are defined in offscreen
++ * framebuffer orientation. When copying between an offscreen and
++ * onscreen framebuffers, the image is y-flipped accordingly.
+  *
+  * The two buffers must have the same value types (e.g. floating-point,
+  * unsigned int, signed int, or fixed-point), but color formats do not
+@@ -396,14 +400,6 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  * scale the results it may make more sense to draw a primitive
+  * instead.
+  *
+- * We can only really support blitting between two offscreen buffers
+- * for this function on GLES2.0. This is because we effectively render
+- * upside down to offscreen buffers to maintain Cogl's representation
+- * of the texture coordinate system where 0,0 is the top left of the
+- * texture. If we were to blit from an offscreen to an onscreen buffer
+- * then we would need to mirror the blit along the x-axis but the GLES
+- * extension does not support this.
+- *
+  * The GL function is documented to be affected by the scissor. This
+  * function therefore ensure that an empty clip stack is flushed
+  * before performing the blit which means the scissor is effectively
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index 0bc225945..90976a611 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -1460,15 +1460,12 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
+                         int height)
+ {
+   CoglContext *ctx = src->context;
++  int src_x1, src_y1, src_x2, src_y2;
++  int dst_x1, dst_y1, dst_x2, dst_y2;
+ 
+   _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
+                         (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
+ 
+-  /* We can only support blitting between offscreen buffers because
+-     otherwise we would need to mirror the image and GLES2.0 doesn't
+-     support this */
+-  _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src));
+-  _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest));
+   /* The buffers must use the same premult convention */
+   _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) ==
+                         (dest->internal_format & COGL_PREMULT_BIT));
+@@ -1492,10 +1489,41 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
+    * as changed */
+   ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP;
+ 
+-  ctx->glBlitFramebuffer (src_x, src_y,
+-                          src_x + width, src_y + height,
+-                          dst_x, dst_y,
+-                          dst_x + width, dst_y + height,
++  /* Offscreens we do the normal way, onscreens need an y-flip. Even if
++   * we consider offscreens to be rendered upside-down, the offscreen
++   * orientation is in this function's API. */
++  if (cogl_is_offscreen (src))
++    {
++      src_x1 = src_x;
++      src_y1 = src_y;
++      src_x2 = src_x + width;
++      src_y2 = src_y + height;
++    }
++  else
++    {
++      src_x1 = src_x;
++      src_y1 = cogl_framebuffer_get_height (src) - src_y;
++      src_x2 = src_x + width;
++      src_y2 = src_y1 - height;
++    }
++
++  if (cogl_is_offscreen (dest))
++    {
++      dst_x1 = dst_x;
++      dst_y1 = dst_y;
++      dst_x2 = dst_x + width;
++      dst_y2 = dst_y + height;
++    }
++  else
++    {
++      dst_x1 = dst_x;
++      dst_y1 = cogl_framebuffer_get_height (dest) - dst_y;
++      dst_x2 = dst_x + width;
++      dst_y2 = dst_y1 - height;
++    }
++
++  ctx->glBlitFramebuffer (src_x1, src_y1, src_x2, src_y2,
++                          dst_x1, dst_y1, dst_x2, dst_y2,
+                           GL_COLOR_BUFFER_BIT,
+                           GL_NEAREST);
+ }
+diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+index 5402a7075..83e1d263a 100644
+--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+@@ -400,12 +400,9 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
+       else
+         {
+           /* NB: Currently we only take advantage of binding separate
+-           * read/write buffers for offscreen framebuffer blit
+-           * purposes.  */
++           * read/write buffers for framebuffer blit purposes. */
+           _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
+                                 (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
+-          _COGL_RETURN_IF_FAIL (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
+-          _COGL_RETURN_IF_FAIL (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
+ 
+           _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
+           _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
+-- 
+2.21.0
+
diff --git a/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch b/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch
new file mode 100644
index 0000000..3f4193b
--- /dev/null
+++ b/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch
@@ -0,0 +1,35 @@
+From 762ffddfa6157fe50bfa394ecbe4ba707d15f368 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 15 Jan 2019 10:29:55 -0500
+Subject: [PATCH 6/9] backends/native: update glyph cache on resume
+
+As mentioned in a previous commit, the proprietary NVIDIA
+driver garbles memory on suspend. That behavior, means that
+clutter's glyph cache (which is stored in GPU memory) gets
+corrupted on suspend.
+
+This commit ensures the glyph cache is blown away when
+the logind session becomes active (on VT switch and resume).
+---
+ src/backends/native/meta-backend-native.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
+index f593197e7..db9b63ac4 100644
+--- a/src/backends/native/meta-backend-native.c
++++ b/src/backends/native/meta-backend-native.c
+@@ -660,7 +660,10 @@ void meta_backend_native_resume (MetaBackendNative *native)
+   MetaIdleMonitor *idle_monitor;
+ 
+   if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
+-    g_signal_emit_by_name (display, "gl-video-memory-purged");
++    {
++      clutter_clear_glyph_cache ();
++      g_signal_emit_by_name (display, "gl-video-memory-purged");
++    }
+ 
+   meta_monitor_manager_kms_resume (monitor_manager_kms);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch
new file mode 100644
index 0000000..6bc5e2c
--- /dev/null
+++ b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch
@@ -0,0 +1,115 @@
+From 579c85d17b17fc7ad3d6c88af39932ce8faeaabe Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Mon, 6 May 2019 15:58:33 +0300
+Subject: [PATCH 06/12] cogl: Rename feature OFFSCREEN_BLIT to BLIT_FRAMEBUFFER
+
+The feature is not limited to offscreen framebuffer blits anymore since
+"cogl: Allow glBlitFramebuffer between onscreen/offscreen".
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+
+(cherry picked from commit 55c084e6e1059d8f94c699b01c408523ed504196)
+---
+ cogl/cogl/cogl-blit.c                       | 2 +-
+ cogl/cogl/cogl-framebuffer-private.h        | 2 +-
+ cogl/cogl/cogl-framebuffer.c                | 2 +-
+ cogl/cogl/cogl-private.h                    | 2 +-
+ cogl/cogl/driver/gl/cogl-framebuffer-gl.c   | 2 +-
+ cogl/cogl/driver/gl/gl/cogl-driver-gl.c     | 2 +-
+ cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 2 +-
+ 7 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c
+index a61eb66d2..c561b2e45 100644
+--- a/cogl/cogl/cogl-blit.c
++++ b/cogl/cogl/cogl-blit.c
+@@ -158,7 +158,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
+      supported. */
+   if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) !=
+       (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) ||
+-      !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT))
++      !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
+     return FALSE;
+ 
+   dst_offscreen = _cogl_offscreen_new_with_texture_full
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index f68153d8b..cb1f87354 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -380,7 +380,7 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+  *
+  * This blits a region of the color buffer of the source buffer
+  * to the destination buffer. This function should only be
+- * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is
++ * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is
+  * advertised.
+  *
+  * The source and destination rectangles are defined in offscreen
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index 90976a611..5cc4eada4 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -1464,7 +1464,7 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
+   int dst_x1, dst_y1, dst_x2, dst_y2;
+ 
+   _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
+-                        (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
++                        (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER));
+ 
+   /* The buffers must use the same premult convention */
+   _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) ==
+diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h
+index 9f918b851..d9fbe68c7 100644
+--- a/cogl/cogl/cogl-private.h
++++ b/cogl/cogl/cogl-private.h
+@@ -42,7 +42,7 @@ typedef enum
+ {
+   COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE,
+   COGL_PRIVATE_FEATURE_MESA_PACK_INVERT,
+-  COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT,
++  COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER,
+   COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES,
+   COGL_PRIVATE_FEATURE_PBOS,
+   COGL_PRIVATE_FEATURE_VBOS,
+diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+index 83e1d263a..90d08954d 100644
+--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+@@ -402,7 +402,7 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
+           /* NB: Currently we only take advantage of binding separate
+            * read/write buffers for framebuffer blit purposes. */
+           _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
+-                                (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
++                                (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER));
+ 
+           _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
+           _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
+diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+index 4d46844d5..e06e27961 100644
+--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
++++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+@@ -467,7 +467,7 @@ _cogl_driver_update_features (CoglContext *ctx,
+ 
+   if (ctx->glBlitFramebuffer)
+     COGL_FLAGS_SET (private_features,
+-                    COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE);
++                    COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
+ 
+   if (ctx->glRenderbufferStorageMultisampleIMG)
+     {
+diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
+index 23158d5c7..bcb0bdf07 100644
+--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
++++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
+@@ -326,7 +326,7 @@ _cogl_driver_update_features (CoglContext *context,
+ 
+   if (context->glBlitFramebuffer)
+     COGL_FLAGS_SET (private_features,
+-                    COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE);
++                    COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
+ 
+   if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions))
+     {
+-- 
+2.21.0
+
diff --git a/SOURCES/0007-backends-native-update-cursor-on-resume.patch b/SOURCES/0007-backends-native-update-cursor-on-resume.patch
new file mode 100644
index 0000000..721996f
--- /dev/null
+++ b/SOURCES/0007-backends-native-update-cursor-on-resume.patch
@@ -0,0 +1,38 @@
+From 59ba24c09e5d2a3210ca3d259789f7ba5ae6266a Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Tue, 15 Jan 2019 10:29:55 -0500
+Subject: [PATCH 7/9] backends/native: update cursor on resume
+
+As mentioned in a previous commit, the proprietary NVIDIA
+driver garbles memory on suspend. That behavior, means that
+the cursor gets corrupted on suspend.
+
+This commit forces the cursor to redraw itself when the
+logind session becomes active (on VT switch and resume).
+---
+ src/backends/native/meta-backend-native.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
+index db9b63ac4..479e9326b 100644
+--- a/src/backends/native/meta-backend-native.c
++++ b/src/backends/native/meta-backend-native.c
+@@ -54,6 +54,7 @@
+ #include "backends/native/meta-renderer-native.h"
+ #include "backends/native/meta-stage-native.h"
+ #include "clutter/evdev/clutter-evdev.h"
++#include "core/display-private.h"
+ #include "core/meta-border.h"
+ #include "meta/main.h"
+ 
+@@ -662,6 +663,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
+   if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
+     {
+       clutter_clear_glyph_cache ();
++      meta_display_update_cursor (display);
+       g_signal_emit_by_name (display, "gl-video-memory-purged");
+     }
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch
new file mode 100644
index 0000000..a5c9686
--- /dev/null
+++ b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch
@@ -0,0 +1,261 @@
+From be13d3c844a6623563ae4e74dbb3409baf16fc9c Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.com>
+Date: Mon, 3 Dec 2018 14:34:41 +0200
+Subject: [PATCH 07/12] cogl: Expose cogl_blit_framebuffer
+
+The function will be used in copying from a primary GPU framebuffer to a
+secondary GPU framebuffer using the primary GPU specifically when the
+secondary GPU is not render-capable.
+
+To allow falling back in case glBlitFramebuffer cannot be used, add boolean
+return value, and GError argument for debugging purposes.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
+(cherry picked from commit 6061abbf90cd1d62e262ebf3636470d2219e04a7)
+---
+ cogl/cogl/cogl-blit.c                | 11 ++---
+ cogl/cogl/cogl-framebuffer-private.h | 55 -----------------------
+ cogl/cogl/cogl-framebuffer.c         | 40 +++++++++++------
+ cogl/cogl/cogl-framebuffer.h         | 66 +++++++++++++++++++++++++++-
+ 4 files changed, 98 insertions(+), 74 deletions(-)
+
+diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c
+index c561b2e45..ae5a8a345 100644
+--- a/cogl/cogl/cogl-blit.c
++++ b/cogl/cogl/cogl-blit.c
+@@ -207,11 +207,12 @@ _cogl_blit_framebuffer_blit (CoglBlitData *data,
+                              int width,
+                              int height)
+ {
+-  _cogl_blit_framebuffer (data->src_fb,
+-                          data->dest_fb,
+-                          src_x, src_y,
+-                          dst_x, dst_y,
+-                          width, height);
++  cogl_blit_framebuffer (data->src_fb,
++                         data->dest_fb,
++                         src_x, src_y,
++                         dst_x, dst_y,
++                         width, height,
++                         NULL);
+ }
+ 
+ static void
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index cb1f87354..7d71fb1dc 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -367,61 +367,6 @@ void
+ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
+                          CoglFramebuffer *read_buffer);
+ 
+-/*
+- * _cogl_blit_framebuffer:
+- * @src: The source #CoglFramebuffer
+- * @dest: The destination #CoglFramebuffer
+- * @src_x: Source x position
+- * @src_y: Source y position
+- * @dst_x: Destination x position
+- * @dst_y: Destination y position
+- * @width: Width of region to copy
+- * @height: Height of region to copy
+- *
+- * This blits a region of the color buffer of the source buffer
+- * to the destination buffer. This function should only be
+- * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is
+- * advertised.
+- *
+- * The source and destination rectangles are defined in offscreen
+- * framebuffer orientation. When copying between an offscreen and
+- * onscreen framebuffers, the image is y-flipped accordingly.
+- *
+- * The two buffers must have the same value types (e.g. floating-point,
+- * unsigned int, signed int, or fixed-point), but color formats do not
+- * need to match. This limitation comes from OpenGL ES 3.0 definition
+- * of glBlitFramebuffer.
+- *
+- * Note that this function differs a lot from the glBlitFramebuffer
+- * function provided by the GL_EXT_framebuffer_blit extension. Notably
+- * it doesn't support having different sizes for the source and
+- * destination rectangle. This doesn't seem
+- * like a particularly useful feature. If the application wanted to
+- * scale the results it may make more sense to draw a primitive
+- * instead.
+- *
+- * The GL function is documented to be affected by the scissor. This
+- * function therefore ensure that an empty clip stack is flushed
+- * before performing the blit which means the scissor is effectively
+- * ignored.
+- *
+- * The function also doesn't support specifying the buffers to copy
+- * and instead only the color buffer is copied. When copying the depth
+- * or stencil buffers the extension on GLES2.0 only supports copying
+- * the full buffer which would be awkward to document with this
+- * API. If we wanted to support that feature it may be better to have
+- * a separate function to copy the entire buffer for a given mask.
+- */
+-void
+-_cogl_blit_framebuffer (CoglFramebuffer *src,
+-                        CoglFramebuffer *dest,
+-                        int src_x,
+-                        int src_y,
+-                        int dst_x,
+-                        int dst_y,
+-                        int width,
+-                        int height);
+-
+ void
+ _cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer);
+ 
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index 5cc4eada4..6d35c6b13 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -1449,26 +1449,38 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer,
+   return ret;
+ }
+ 
+-void
+-_cogl_blit_framebuffer (CoglFramebuffer *src,
+-                        CoglFramebuffer *dest,
+-                        int src_x,
+-                        int src_y,
+-                        int dst_x,
+-                        int dst_y,
+-                        int width,
+-                        int height)
++gboolean
++cogl_blit_framebuffer (CoglFramebuffer *src,
++                       CoglFramebuffer *dest,
++                       int src_x,
++                       int src_y,
++                       int dst_x,
++                       int dst_y,
++                       int width,
++                       int height,
++                       GError **error)
+ {
+   CoglContext *ctx = src->context;
+   int src_x1, src_y1, src_x2, src_y2;
+   int dst_x1, dst_y1, dst_x2, dst_y2;
+ 
+-  _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
+-                        (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER));
++  if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
++    {
++      g_set_error_literal (error, COGL_SYSTEM_ERROR,
++                           COGL_SYSTEM_ERROR_UNSUPPORTED,
++                           "Cogl BLIT_FRAMEBUFFER is not supported by the system.");
++      return FALSE;
++    }
+ 
+   /* The buffers must use the same premult convention */
+-  _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) ==
+-                        (dest->internal_format & COGL_PREMULT_BIT));
++  if ((src->internal_format & COGL_PREMULT_BIT) !=
++      (dest->internal_format & COGL_PREMULT_BIT))
++    {
++      g_set_error_literal (error, COGL_SYSTEM_ERROR,
++                           COGL_SYSTEM_ERROR_UNSUPPORTED,
++                           "cogl_blit_framebuffer premult mismatch.");
++      return FALSE;
++    }
+ 
+   /* Make sure the current framebuffers are bound. We explicitly avoid
+      flushing the clip state so we can bind our own empty state */
+@@ -1526,6 +1538,8 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
+                           dst_x1, dst_y1, dst_x2, dst_y2,
+                           GL_COLOR_BUFFER_BIT,
+                           GL_NEAREST);
++
++  return TRUE;
+ }
+ 
+ void
+diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h
+index 48a77e1ed..230a78627 100644
+--- a/cogl/cogl/cogl-framebuffer.h
++++ b/cogl/cogl/cogl-framebuffer.h
+@@ -3,7 +3,8 @@
+  *
+  * A Low Level GPU Graphics and Utilities API
+  *
+- * Copyright (C) 2011 Intel Corporation.
++ * Copyright (C) 2007,2008,2009,2011 Intel Corporation.
++ * Copyright (C) 2019 DisplayLink (UK) Ltd.
+  *
+  * Permission is hereby granted, free of charge, to any person
+  * obtaining a copy of this software and associated documentation
+@@ -1846,6 +1847,69 @@ typedef enum /*< prefix=COGL_FRAMEBUFFER_ERROR >*/
+ gboolean
+ cogl_is_framebuffer (void *object);
+ 
++/**
++ * cogl_blit_framebuffer:
++ * @src: The source #CoglFramebuffer
++ * @dest: The destination #CoglFramebuffer
++ * @src_x: Source x position
++ * @src_y: Source y position
++ * @dst_x: Destination x position
++ * @dst_y: Destination y position
++ * @width: Width of region to copy
++ * @height: Height of region to copy
++ * @error: optional error object
++ *
++ * @return FALSE for an immediately detected error, TRUE otherwise.
++ *
++ * This blits a region of the color buffer of the source buffer
++ * to the destination buffer. This function should only be
++ * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is
++ * advertised.
++ *
++ * The source and destination rectangles are defined in offscreen
++ * framebuffer orientation. When copying between an offscreen and
++ * onscreen framebuffers, the image is y-flipped accordingly.
++ *
++ * The two buffers must have the same value types (e.g. floating-point,
++ * unsigned int, signed int, or fixed-point), but color formats do not
++ * need to match. This limitation comes from OpenGL ES 3.0 definition
++ * of glBlitFramebuffer.
++ *
++ * Note that this function differs a lot from the glBlitFramebuffer
++ * function provided by the GL_EXT_framebuffer_blit extension. Notably
++ * it doesn't support having different sizes for the source and
++ * destination rectangle. This doesn't seem
++ * like a particularly useful feature. If the application wanted to
++ * scale the results it may make more sense to draw a primitive
++ * instead.
++ *
++ * The GL function is documented to be affected by the scissor. This
++ * function therefore ensure that an empty clip stack is flushed
++ * before performing the blit which means the scissor is effectively
++ * ignored.
++ *
++ * The function also doesn't support specifying the buffers to copy
++ * and instead only the color buffer is copied. When copying the depth
++ * or stencil buffers the extension on GLES2.0 only supports copying
++ * the full buffer which would be awkward to document with this
++ * API. If we wanted to support that feature it may be better to have
++ * a separate function to copy the entire buffer for a given mask.
++ *
++ * The @c error argument is optional, it can be NULL. If it is not NULL
++ * and this function returns FALSE, an error object with a code from
++ * COGL_SYSTEM_ERROR will be created.
++ */
++gboolean
++cogl_blit_framebuffer (CoglFramebuffer *src,
++                       CoglFramebuffer *dest,
++                       int src_x,
++                       int src_y,
++                       int dst_x,
++                       int dst_y,
++                       int width,
++                       int height,
++                       GError **error);
++
+ G_END_DECLS
+ 
+ #endif /* __COGL_FRAMEBUFFER_H */
+-- 
+2.21.0
+
diff --git a/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch b/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch
new file mode 100644
index 0000000..1034111
--- /dev/null
+++ b/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch
@@ -0,0 +1,110 @@
+From c78a614b0d45a4bc8101a93c7138c9fb6102d13c Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Wed, 9 Jan 2019 16:57:05 -0500
+Subject: [PATCH 8/9] background: purge all background textures on suspend
+
+This commit makes sure all background textures get purged
+on suspend, which is important for nvidia.
+---
+ src/compositor/meta-background-image.c | 28 ++++++++++++++++++++++++++
+ src/compositor/meta-background.c       | 17 +++++++++++++++-
+ src/meta/meta-background-image.h       |  2 ++
+ 3 files changed, 46 insertions(+), 1 deletion(-)
+
+diff --git a/src/compositor/meta-background-image.c b/src/compositor/meta-background-image.c
+index 14d3baf57..98909cb53 100644
+--- a/src/compositor/meta-background-image.c
++++ b/src/compositor/meta-background-image.c
+@@ -283,6 +283,34 @@ meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
+   image->in_cache = FALSE;
+ }
+ 
++/**
++ * meta_background_image_cache_unload_all:
++ * @cache: a #MetaBackgroundImageCache
++ *
++ * Remove all entries from the cache and unloads them; this would be used
++ * if textures in video memory have been invalidated.
++ */
++void
++meta_background_image_cache_unload_all (MetaBackgroundImageCache *cache)
++{
++  GHashTableIter iter;
++  gpointer key, value;
++
++  g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
++
++  g_hash_table_iter_init (&iter, cache->images);
++  while (g_hash_table_iter_next (&iter, &key, &value))
++    {
++      MetaBackgroundImage *image = value;
++
++      g_clear_pointer (&image->texture, cogl_object_unref);
++      image->in_cache = FALSE;
++      image->loaded = FALSE;
++    }
++
++  g_hash_table_remove_all (cache->images);
++}
++
+ G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT);
+ 
+ static void
+diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c
+index c033395fe..abdfcc7df 100644
+--- a/src/compositor/meta-background.c
++++ b/src/compositor/meta-background.c
+@@ -303,6 +303,18 @@ meta_background_finalize (GObject *object)
+   G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
+ }
+ 
++static void
++free_textures (MetaBackground *self)
++{
++  free_color_texture (self);
++  free_wallpaper_texture (self);
++
++  set_file (self, &self->file1, &self->background_image1, NULL);
++  set_file (self, &self->file2, &self->background_image2, NULL);
++
++  mark_changed (self);
++}
++
+ static void
+ meta_background_constructed (GObject *object)
+ {
+@@ -312,7 +324,7 @@ meta_background_constructed (GObject *object)
+   G_OBJECT_CLASS (meta_background_parent_class)->constructed (object);
+ 
+   g_signal_connect_object (self->display, "gl-video-memory-purged",
+-                           G_CALLBACK (mark_changed), object, G_CONNECT_SWAPPED);
++                           G_CALLBACK (free_textures), object, G_CONNECT_SWAPPED);
+ 
+   g_signal_connect_object (monitor_manager, "monitors-changed",
+                            G_CALLBACK (on_monitors_changed), self,
+@@ -950,8 +962,11 @@ meta_background_set_blend (MetaBackground          *self,
+ void
+ meta_background_refresh_all (void)
+ {
++  MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
+   GSList *l;
+ 
++  meta_background_image_cache_unload_all (cache);
++
+   for (l = all_backgrounds; l; l = l->next)
+     mark_changed (l->data);
+ }
+diff --git a/src/meta/meta-background-image.h b/src/meta/meta-background-image.h
+index 137a6ff8e..87e40d251 100644
+--- a/src/meta/meta-background-image.h
++++ b/src/meta/meta-background-image.h
+@@ -66,4 +66,6 @@ META_EXPORT
+ void                 meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
+                                                         GFile                    *file);
+ 
++void                 meta_background_image_cache_unload_all (MetaBackgroundImageCache *cache);
++
+ #endif /* __META_BACKGROUND_IMAGE_H__ */
+-- 
+2.21.0
+
diff --git a/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch
new file mode 100644
index 0000000..09e8db9
--- /dev/null
+++ b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch
@@ -0,0 +1,42 @@
+From bbeb161e8ab31bbef3c7d378e9a8d4ecc786c25d Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Thu, 26 Sep 2019 10:20:36 +0200
+Subject: [PATCH 08/12] clutter/stage-view: Use cogl_blit_framebuffer() for
+ shadow FB
+
+If there is no transformation, use `cogl_blit_framebuffer()` as a
+shortcut in `clutter_stage_view_blit_offscreen()`, that dramatically
+improves performance when using a shadow framebuffer.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/809
+(cherry picked from commit 3400c555a032832a689c208486891352a6cb92de)
+---
+ clutter/clutter/clutter-stage-view.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
+index cd6cd35cb..00cbfd1ce 100644
+--- a/clutter/clutter/clutter-stage-view.c
++++ b/clutter/clutter/clutter-stage-view.c
+@@ -126,6 +126,18 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
+     clutter_stage_view_get_instance_private (view);
+   CoglMatrix matrix;
+ 
++  clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
++  if (cogl_matrix_is_identity (&matrix))
++    {
++      if (cogl_blit_framebuffer (priv->offscreen,
++                                 priv->framebuffer,
++                                 rect->x, rect->y,
++                                 rect->x, rect->y,
++                                 rect->width, rect->height,
++                                 NULL))
++        return;
++    }
++
+   clutter_stage_view_ensure_offscreen_blit_pipeline (view);
+   cogl_framebuffer_push_matrix (priv->framebuffer);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch b/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch
new file mode 100644
index 0000000..4b38154
--- /dev/null
+++ b/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch
@@ -0,0 +1,712 @@
+From d8cc418899276b45cb1a787493e0998e3b008fe5 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Thu, 10 Jan 2019 10:48:02 -0500
+Subject: [PATCH 9/9] MetaShapedTexture: save and restore textures on suspend
+
+The proprietary nvidia driver garbles GPU memory on suspend.
+
+In order to workaround that limitation, this commit copies all
+textures to host memory on suspend and restores them on resume.
+
+One complication comes from external textures (such as those
+given to us by Xwayland for X clients).  We can't just restore
+those textures, since they aren't writable.
+
+This commit addresses that complication by keeping a local texture
+around for those external textures, and using it instead for parts
+of the window that haven't been redrawn since resume.
+---
+ src/compositor/meta-shaped-texture.c | 487 +++++++++++++++++++++++++--
+ src/meta/meta-shaped-texture.h       |   2 +
+ 2 files changed, 468 insertions(+), 21 deletions(-)
+
+diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
+index d64e214e5..ea8daa03d 100644
+--- a/src/compositor/meta-shaped-texture.c
++++ b/src/compositor/meta-shaped-texture.c
+@@ -40,7 +40,9 @@
+ #include "compositor/meta-texture-tower.h"
+ #include "compositor/region-utils.h"
+ #include "core/boxes-private.h"
++#include <meta/meta-backend.h>
+ #include "meta/meta-shaped-texture.h"
++#include "meta-texture-rectangle.h"
+ 
+ /* MAX_MIPMAPPING_FPS needs to be as small as possible for the best GPU
+  * performance, but higher than the refresh rate of commonly slow updating
+@@ -72,8 +74,12 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
+ 
+ static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
+ 
++static void disable_backing_store (MetaShapedTexture *stex);
++
+ static void cullable_iface_init (MetaCullableInterface *iface);
+ 
++static gboolean meta_debug_show_backing_store = FALSE;
++
+ enum
+ {
+   SIZE_CHANGED,
+@@ -83,6 +89,14 @@ enum
+ 
+ static guint signals[LAST_SIGNAL];
+ 
++typedef struct
++{
++  CoglTexture *texture;
++  CoglTexture *mask_texture;
++  cairo_surface_t *mask_surface;
++  cairo_region_t *region;
++} MetaTextureBackingStore;
++
+ struct _MetaShapedTexture
+ {
+   ClutterActor parent;
+@@ -114,6 +128,16 @@ struct _MetaShapedTexture
+   int viewport_dst_width;
+   int viewport_dst_height;
+ 
++  /* textures get corrupted on suspend, so save them */
++  cairo_surface_t *saved_base_surface;
++  cairo_surface_t *saved_mask_surface;
++
++  /* We can't just restore external textures, so we need to track
++   * which parts of the external texture are freshly drawn from
++   * the client after corruption, and fill in the rest from our
++   * saved snapshot */
++  MetaTextureBackingStore *backing_store;
++
+   int tex_width, tex_height;
+   int fallback_width, fallback_height;
+   int dst_width, dst_height;
+@@ -148,6 +172,9 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
+                                         0,
+                                         NULL, NULL, NULL,
+                                         G_TYPE_NONE, 0);
++
++  if (g_getenv ("MUTTER_DEBUG_BACKING_STORE"))
++    meta_debug_show_backing_store = TRUE;
+ }
+ 
+ static void
+@@ -159,6 +186,11 @@ invalidate_size (MetaShapedTexture *stex)
+ static void
+ meta_shaped_texture_init (MetaShapedTexture *stex)
+ {
++  MetaBackend *backend = meta_get_backend ();
++  ClutterBackend *clutter_backend = clutter_get_default_backend ();
++  CoglContext *cogl_context =
++    clutter_backend_get_cogl_context (clutter_backend);
++
+   stex->paint_tower = meta_texture_tower_new ();
+ 
+   stex->texture = NULL;
+@@ -171,6 +203,12 @@ meta_shaped_texture_init (MetaShapedTexture *stex)
+                     "notify::scale-x",
+                     G_CALLBACK (invalidate_size),
+                     stex);
++
++  if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
++    {
++      g_signal_connect_object (backend, "suspending", G_CALLBACK (meta_shaped_texture_save), stex, G_CONNECT_SWAPPED);
++      g_signal_connect_object (backend, "resuming", G_CALLBACK (meta_shaped_texture_restore), stex, G_CONNECT_SWAPPED);
++    }
+ }
+ 
+ static void
+@@ -311,24 +349,72 @@ meta_shaped_texture_dispose (GObject *object)
+   G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
+ }
+ 
++static int
++get_layer_indices (MetaShapedTexture *stex,
++                   int               *main_layer_index,
++                   int               *backing_mask_layer_index,
++                   int               *backing_layer_index,
++                   int               *mask_layer_index)
++{
++  int next_layer_index = 0;
++
++  if (main_layer_index)
++    *main_layer_index = next_layer_index;
++
++  next_layer_index++;
++
++  if (stex->backing_store)
++    {
++      if (backing_mask_layer_index)
++        *backing_mask_layer_index = next_layer_index;
++      next_layer_index++;
++      if (backing_layer_index)
++        *backing_layer_index = next_layer_index;
++      next_layer_index++;
++    }
++  else
++    {
++      if (backing_mask_layer_index)
++        *backing_mask_layer_index = -1;
++      if (backing_layer_index)
++        *backing_layer_index = -1;
++    }
++
++  if (mask_layer_index)
++    *mask_layer_index = next_layer_index;
++
++  return next_layer_index;
++}
++
+ static CoglPipeline *
+ get_base_pipeline (MetaShapedTexture *stex,
+                    CoglContext       *ctx)
+ {
+   CoglPipeline *pipeline;
++  int main_layer_index;
++  int backing_layer_index;
++  int backing_mask_layer_index;
++  int i, number_of_layers;
+ 
+   if (stex->base_pipeline)
+     return stex->base_pipeline;
+ 
+   pipeline = cogl_pipeline_new (ctx);
+-  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
+-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+-  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
+-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+-  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
+-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+-  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
+-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
++
++  number_of_layers = get_layer_indices (stex,
++                                        &main_layer_index,
++                                        &backing_mask_layer_index,
++                                        &backing_layer_index,
++                                        NULL);
++
++  for (i = 0; i < number_of_layers; i++)
++    {
++      cogl_pipeline_set_layer_wrap_mode_s (pipeline, i,
++                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
++      cogl_pipeline_set_layer_wrap_mode_t (pipeline, i,
++                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
++    }
++
+   if (!stex->is_y_inverted)
+     {
+       CoglMatrix matrix;
+@@ -336,7 +422,22 @@ get_base_pipeline (MetaShapedTexture *stex,
+       cogl_matrix_init_identity (&matrix);
+       cogl_matrix_scale (&matrix, 1, -1, 1);
+       cogl_matrix_translate (&matrix, 0, -1, 0);
+-      cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
++      cogl_pipeline_set_layer_matrix (pipeline, main_layer_index, &matrix);
++    }
++
++  if (stex->backing_store)
++    {
++      g_autofree char *backing_description = NULL;
++      cogl_pipeline_set_layer_combine (pipeline, backing_mask_layer_index,
++                                       "RGBA = REPLACE(PREVIOUS)",
++                                       NULL);
++      backing_description = g_strdup_printf ("RGBA = INTERPOLATE(PREVIOUS, TEXTURE_%d, TEXTURE_%d[A])",
++                                             backing_layer_index,
++                                             backing_mask_layer_index);
++      cogl_pipeline_set_layer_combine (pipeline,
++                                       backing_layer_index,
++                                       backing_description,
++                                       NULL);
+     }
+ 
+   if (stex->transform != META_MONITOR_TRANSFORM_NORMAL)
+@@ -379,7 +480,7 @@ get_base_pipeline (MetaShapedTexture *stex,
+     }
+ 
+   if (stex->snippet)
+-    cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet);
++    cogl_pipeline_add_layer_snippet (pipeline, main_layer_index, stex->snippet);
+ 
+   stex->base_pipeline = pipeline;
+ 
+@@ -398,12 +499,15 @@ get_masked_pipeline (MetaShapedTexture *stex,
+                      CoglContext       *ctx)
+ {
+   CoglPipeline *pipeline;
++  int mask_layer_index;
+ 
+   if (stex->masked_pipeline)
+     return stex->masked_pipeline;
+ 
++  get_layer_indices (stex, NULL, NULL, NULL, &mask_layer_index);
++
+   pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
+-  cogl_pipeline_set_layer_combine (pipeline, 1,
++  cogl_pipeline_set_layer_combine (pipeline, mask_layer_index,
+                                    "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
+                                    NULL);
+ 
+@@ -517,6 +621,8 @@ set_cogl_texture (MetaShapedTexture *stex,
+   if (stex->texture)
+     cogl_object_unref (stex->texture);
+ 
++  g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy);
++
+   stex->texture = cogl_tex;
+ 
+   if (cogl_tex != NULL)
+@@ -579,6 +685,10 @@ do_paint (MetaShapedTexture *stex,
+   CoglContext *ctx;
+   ClutterActorBox alloc;
+   CoglPipelineFilter filter;
++  int main_layer_index;
++  int backing_mask_layer_index;
++  int backing_layer_index;
++  int mask_layer_index;
+ 
+   clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
+   ensure_size_valid (stex);
+@@ -665,6 +775,12 @@ do_paint (MetaShapedTexture *stex,
+         }
+     }
+ 
++  get_layer_indices (stex,
++                     &main_layer_index,
++                     &backing_mask_layer_index,
++                     &backing_layer_index,
++                     &mask_layer_index);
++
+   /* First, paint the unblended parts, which are part of the opaque region. */
+   if (use_opaque_region)
+     {
+@@ -686,8 +802,24 @@ do_paint (MetaShapedTexture *stex,
+       if (!cairo_region_is_empty (region))
+         {
+           opaque_pipeline = get_unblended_pipeline (stex, ctx);
+-          cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
+-          cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
++          cogl_pipeline_set_layer_texture (opaque_pipeline, main_layer_index, paint_tex);
++          cogl_pipeline_set_layer_filters (opaque_pipeline, main_layer_index, filter, filter);
++
++          if (stex->backing_store)
++            {
++              cogl_pipeline_set_layer_texture (opaque_pipeline,
++                                               backing_mask_layer_index,
++                                               stex->backing_store->mask_texture);
++              cogl_pipeline_set_layer_filters (opaque_pipeline,
++                                               backing_mask_layer_index,
++                                               filter, filter);
++              cogl_pipeline_set_layer_texture (opaque_pipeline,
++                                               backing_layer_index,
++                                               stex->backing_store->texture);
++              cogl_pipeline_set_layer_filters (opaque_pipeline,
++                                               backing_layer_index,
++                                               filter, filter);
++            }
+ 
+           n_rects = cairo_region_num_rectangles (region);
+           for (i = 0; i < n_rects; i++)
+@@ -726,12 +858,28 @@ do_paint (MetaShapedTexture *stex,
+       else
+         {
+           blended_pipeline = get_masked_pipeline (stex, ctx);
+-          cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture);
+-          cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
++          cogl_pipeline_set_layer_texture (blended_pipeline, mask_layer_index, stex->mask_texture);
++          cogl_pipeline_set_layer_filters (blended_pipeline, mask_layer_index, filter, filter);
+         }
+ 
+-      cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
+-      cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
++      cogl_pipeline_set_layer_texture (blended_pipeline, main_layer_index, paint_tex);
++      cogl_pipeline_set_layer_filters (blended_pipeline, main_layer_index, filter, filter);
++
++      if (stex->backing_store)
++        {
++          cogl_pipeline_set_layer_texture (blended_pipeline,
++                                           backing_mask_layer_index,
++                                           stex->backing_store->mask_texture);
++          cogl_pipeline_set_layer_filters (blended_pipeline,
++                                           backing_mask_layer_index,
++                                           filter, filter);
++          cogl_pipeline_set_layer_texture (blended_pipeline,
++                                           backing_layer_index,
++                                           stex->backing_store->texture);
++          cogl_pipeline_set_layer_filters (blended_pipeline,
++                                           backing_layer_index,
++                                           filter, filter);
++        }
+ 
+       CoglColor color;
+       cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
+@@ -925,6 +1073,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
+   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
+ 
+   g_clear_pointer (&stex->mask_texture, cogl_object_unref);
++  g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy);
+ 
+   if (mask_texture != NULL)
+     {
+@@ -946,6 +1095,65 @@ meta_shaped_texture_is_obscured (MetaShapedTexture *stex)
+     return FALSE;
+ }
+ 
++static void
++meta_texture_backing_store_redraw_mask (MetaTextureBackingStore *backing_store)
++{
++  CoglError *error = NULL;
++
++  if (!cogl_texture_set_data (backing_store->mask_texture, COGL_PIXEL_FORMAT_A_8,
++                              cairo_image_surface_get_stride (backing_store->mask_surface),
++                              cairo_image_surface_get_data (backing_store->mask_surface), 0,
++                              &error))
++    {
++
++      g_warning ("Failed to update backing mask texture");
++      g_clear_pointer (&error, cogl_error_free);
++    }
++}
++
++static gboolean
++meta_texture_backing_store_shrink (MetaTextureBackingStore     *backing_store,
++                                   const cairo_rectangle_int_t *area)
++{
++  cairo_t *cr;
++
++  cairo_region_subtract_rectangle (backing_store->region, area);
++
++  /* If the client has finally redrawn the entire surface, we can
++   * ditch our snapshot
++   */
++  if (cairo_region_is_empty (backing_store->region))
++    return FALSE;
++
++  cr = cairo_create (backing_store->mask_surface);
++  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
++  cairo_paint (cr);
++  gdk_cairo_region (cr, backing_store->region);
++  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
++  cairo_fill (cr);
++  cairo_destroy (cr);
++
++  meta_texture_backing_store_redraw_mask (backing_store);
++
++  return TRUE;
++}
++
++static void
++shrink_backing_region (MetaShapedTexture           *stex,
++                       const cairo_rectangle_int_t *area)
++{
++  gboolean still_backing_texture;
++
++  if (!stex->backing_store)
++    return;
++
++  still_backing_texture =
++      meta_texture_backing_store_shrink (stex->backing_store, area);
++
++  if (!still_backing_texture)
++    disable_backing_store (stex);
++}
++
+ /**
+  * meta_shaped_texture_update_area:
+  * @stex: #MetaShapedTexture
+@@ -1041,6 +1249,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
+                                      &clip);
+     }
+ 
++  shrink_backing_region (stex, &clip);
++
+   meta_texture_tower_update_area (stex->paint_tower,
+                                   clip.x,
+                                   clip.y,
+@@ -1268,8 +1478,9 @@ should_get_via_offscreen (MetaShapedTexture *stex)
+ }
+ 
+ static cairo_surface_t *
+-get_image_via_offscreen (MetaShapedTexture     *stex,
+-                         cairo_rectangle_int_t *clip)
++get_image_via_offscreen (MetaShapedTexture      *stex,
++                         cairo_rectangle_int_t  *clip,
++                         CoglTexture           **texture)
+ {
+   ClutterBackend *clutter_backend = clutter_get_default_backend ();
+   CoglContext *cogl_context =
+@@ -1340,9 +1551,29 @@ get_image_via_offscreen (MetaShapedTexture     *stex,
+                                 clip->width, clip->height,
+                                 CLUTTER_CAIRO_FORMAT_ARGB32,
+                                 cairo_image_surface_get_data (surface));
++  cairo_surface_mark_dirty (surface);
++
++  if (texture)
++    {
++      *texture = cogl_object_ref (image_texture);
++
++      if (G_UNLIKELY (meta_debug_show_backing_store))
++        {
++          cairo_t *cr;
++
++          cr = cairo_create (surface);
++          cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.75);
++          cairo_paint (cr);
++          cairo_destroy (cr);
++        }
++
++      cogl_texture_set_data (*texture, CLUTTER_CAIRO_FORMAT_ARGB32,
++                             cairo_image_surface_get_stride (surface),
++                             cairo_image_surface_get_data (surface), 0, NULL);
++    }
++
+   cogl_object_unref (fb);
+ 
+-  cairo_surface_mark_dirty (surface);
+ 
+   return surface;
+ }
+@@ -1404,7 +1635,7 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
+     }
+ 
+   if (should_get_via_offscreen (stex))
+-    return get_image_via_offscreen (stex, transformed_clip);
++    return get_image_via_offscreen (stex, transformed_clip, NULL);
+ 
+   if (transformed_clip)
+     texture = cogl_texture_new_from_sub_texture (texture,
+@@ -1465,6 +1696,220 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
+   return surface;
+ }
+ 
++static void
++meta_texture_backing_store_free (MetaTextureBackingStore *backing_store)
++{
++  g_clear_pointer (&backing_store->texture, cogl_object_unref);
++  g_clear_pointer (&backing_store->mask_texture, cogl_object_unref);
++  g_clear_pointer (&backing_store->mask_surface, cairo_surface_destroy);
++  g_clear_pointer (&backing_store->region, cairo_region_destroy);
++
++  g_slice_free (MetaTextureBackingStore, backing_store);
++}
++
++static MetaTextureBackingStore *
++meta_texture_backing_store_new (CoglTexture *texture)
++{
++  MetaTextureBackingStore *backing_store = NULL;
++  ClutterBackend *backend = clutter_get_default_backend ();
++  CoglContext *context = clutter_backend_get_cogl_context (backend);
++  CoglTexture *mask_texture = NULL;
++  guchar *mask_data;
++  int width, height, stride;
++  cairo_surface_t *surface;
++  cairo_region_t *region;
++  cairo_rectangle_int_t backing_rectangle;
++
++  width = cogl_texture_get_width (texture);
++  height = cogl_texture_get_height (texture);
++  stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, width);
++
++  /* we start off by only letting the backing texture through, and none of the real texture */
++  backing_rectangle.x = 0;
++  backing_rectangle.y = 0;
++  backing_rectangle.width = width;
++  backing_rectangle.height = height;
++
++  region = cairo_region_create_rectangle (&backing_rectangle);
++
++  /* initialize mask to transparent, so the entire backing store shows through
++   * up front
++   */
++  mask_data = g_malloc0 (stride * height);
++  surface = cairo_image_surface_create_for_data (mask_data,
++                                                 CAIRO_FORMAT_A8,
++                                                 width,
++                                                 height,
++                                                 stride);
++
++  if (meta_texture_rectangle_check (texture))
++    {
++      mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (context,
++                                                                         width,
++                                                                         height));
++      cogl_texture_set_components (mask_texture, COGL_TEXTURE_COMPONENTS_A);
++      cogl_texture_set_region (mask_texture,
++                               0, 0,
++                               0, 0,
++                               width, height,
++                               width, height,
++                               COGL_PIXEL_FORMAT_A_8,
++                               stride, mask_data);
++    }
++  else
++    {
++      CoglError *error = NULL;
++
++      mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (context, width, height,
++                                                                  COGL_PIXEL_FORMAT_A_8,
++                                                                  stride, mask_data, &error));
++
++      if (error)
++        {
++          g_warning ("Failed to allocate mask texture: %s", error->message);
++          cogl_error_free (error);
++        }
++    }
++
++  if (mask_texture)
++    {
++      backing_store = g_slice_new0 (MetaTextureBackingStore);
++      backing_store->texture = cogl_object_ref (texture);
++      backing_store->mask_texture = mask_texture;
++      backing_store->mask_surface = surface;
++      backing_store->region = region;
++    }
++
++  return backing_store;
++}
++
++static void
++enable_backing_store (MetaShapedTexture *stex,
++                      CoglTexture       *texture)
++{
++  g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free);
++
++  stex->backing_store = meta_texture_backing_store_new (texture);
++
++  meta_shaped_texture_reset_pipelines (stex);
++}
++
++static void
++disable_backing_store (MetaShapedTexture *stex)
++{
++  g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free);
++
++  meta_shaped_texture_reset_pipelines (stex);
++}
++
++void
++meta_shaped_texture_save (MetaShapedTexture *stex)
++{
++
++  CoglTexture *texture, *mask_texture;
++  cairo_surface_t *surface;
++
++  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
++
++  texture = COGL_TEXTURE (stex->texture);
++
++  if (texture == NULL)
++    return;
++
++  g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy);
++  g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy);
++  g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free);
++
++  if (should_get_via_offscreen (stex))
++    {
++      CoglTexture *backing_texture;
++
++      meta_shaped_texture_reset_pipelines (stex);
++
++      surface = get_image_via_offscreen (stex, NULL, &backing_texture);
++
++      enable_backing_store (stex, backing_texture);
++      cogl_object_unref (backing_texture);
++    }
++  else
++    {
++      surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
++                                            cogl_texture_get_width (texture),
++                                            cogl_texture_get_height (texture));
++
++      cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32,
++                             cairo_image_surface_get_stride (surface),
++                             cairo_image_surface_get_data (surface));
++    }
++
++  stex->saved_base_surface = surface;
++
++  mask_texture = stex->mask_texture;
++  if (mask_texture != NULL)
++    {
++      cairo_surface_t *mask_surface;
++
++      mask_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
++                                                 cogl_texture_get_width (mask_texture),
++                                                 cogl_texture_get_height (mask_texture));
++
++      cogl_texture_get_data (mask_texture, CLUTTER_CAIRO_FORMAT_ARGB32,
++                             cairo_image_surface_get_stride (mask_surface),
++                             cairo_image_surface_get_data (mask_surface));
++
++      cairo_surface_mark_dirty (mask_surface);
++
++      stex->saved_mask_surface = mask_surface;
++    }
++}
++
++void
++meta_shaped_texture_restore (MetaShapedTexture *stex)
++{
++  CoglTexture *texture;
++  CoglError *error = NULL;
++
++  texture = meta_shaped_texture_get_texture (stex);
++
++  if (texture == NULL)
++    return;
++
++  if (stex->mask_texture)
++    {
++      if (!cogl_texture_set_data (stex->mask_texture, CLUTTER_CAIRO_FORMAT_ARGB32,
++                                  cairo_image_surface_get_stride (stex->saved_mask_surface),
++                                  cairo_image_surface_get_data (stex->saved_mask_surface), 0,
++                                  &error))
++        {
++          g_warning ("Failed to restore mask texture");
++          g_clear_pointer (&error, cogl_error_free);
++        }
++      g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy);
++    }
++
++  /* if the main texture doesn't support direct writes, then
++   * write to the local backing texture instead, and blend old
++   * versus new at paint time.
++   */
++  if (stex->backing_store)
++    {
++      meta_texture_backing_store_redraw_mask (stex->backing_store);
++      texture = stex->backing_store->texture;
++    }
++
++  if (!cogl_texture_set_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32,
++                              cairo_image_surface_get_stride (stex->saved_base_surface),
++                              cairo_image_surface_get_data (stex->saved_base_surface), 0,
++                              &error))
++    {
++      g_warning ("Failed to restore texture");
++      g_clear_pointer (&error, cogl_error_free);
++    }
++  g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy);
++
++  clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
++}
++
+ void
+ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
+                                        int                fallback_width,
+diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
+index c36b8547f..22b4fbd53 100644
+--- a/src/meta/meta-shaped-texture.h
++++ b/src/meta/meta-shaped-texture.h
+@@ -66,6 +66,8 @@ META_EXPORT
+ cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture     *stex,
+                                                  cairo_rectangle_int_t *clip);
+ 
++void meta_shaped_texture_save (MetaShapedTexture *self);
++void meta_shaped_texture_restore (MetaShapedTexture *self);
+ G_END_DECLS
+ 
+ #endif /* __META_SHAPED_TEXTURE_H__ */
+-- 
+2.21.0
+
diff --git a/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch
new file mode 100644
index 0000000..ea67449
--- /dev/null
+++ b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch
@@ -0,0 +1,49 @@
+From 46bb54bcd9c90f90dd170355209f8c379680d5c1 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 1 Oct 2019 14:16:25 +0200
+Subject: [PATCH 09/12] clutter/stage-view: Ignore clipping rectangle for
+ offscreen blit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In `clutter_stage_view_blit_offscreen()`, the given clipping rectangle
+is in “view” coordinates whereas we intend to copy the whole actual
+framebuffer, meaning that we cannot use the clipping rectangle.
+
+Use the actual framebuffer size, starting at (0, 0) instead.
+
+That fixes the issue with partial repainting with shadow framebuffer
+when fractional scaling is enabled.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/820
+(cherry picked from commit 0a3f25c3039b586f5b5721e91136c5d2fccecca1)
+---
+ clutter/clutter/clutter-stage-view.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
+index 00cbfd1ce..503c31e78 100644
+--- a/clutter/clutter/clutter-stage-view.c
++++ b/clutter/clutter/clutter-stage-view.c
+@@ -129,11 +129,14 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
+   clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
+   if (cogl_matrix_is_identity (&matrix))
+     {
++      int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
++      int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
++
+       if (cogl_blit_framebuffer (priv->offscreen,
+                                  priv->framebuffer,
+-                                 rect->x, rect->y,
+-                                 rect->x, rect->y,
+-                                 rect->width, rect->height,
++                                 0, 0,
++                                 0, 0,
++                                 fb_width, fb_height,
+                                  NULL))
+         return;
+     }
+-- 
+2.21.0
+
diff --git a/SOURCES/0010-cogl-Flush-journal-before-blitting.patch b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch
new file mode 100644
index 0000000..f3935eb
--- /dev/null
+++ b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch
@@ -0,0 +1,34 @@
+From 4c7fe200e05f9a028d440ed2032961d1b798c83b Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 1 Oct 2019 15:54:47 +0200
+Subject: [PATCH 10/12] cogl: Flush journal before blitting
+
+Make sure to submit all pending primitives before blitting, otherwise
+rendering from the shell may be incomplete leaving partial drawing of
+the shell widgets.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/820
+(cherry picked from commit 0cdf13ac12c570d38737fddb68946157c0b7a4d2)
+---
+ cogl/cogl/cogl-framebuffer.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index 6d35c6b13..948cd112d 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -1482,6 +1482,11 @@ cogl_blit_framebuffer (CoglFramebuffer *src,
+       return FALSE;
+     }
+ 
++  /* Make sure any batched primitives get submitted to the driver
++   * before blitting
++   */
++  _cogl_framebuffer_flush_journal (src);
++
+   /* Make sure the current framebuffers are bound. We explicitly avoid
+      flushing the clip state so we can bind our own empty state */
+   _cogl_framebuffer_flush_state (dest,
+-- 
+2.21.0
+
diff --git a/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch
new file mode 100644
index 0000000..9dd46a0
--- /dev/null
+++ b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch
@@ -0,0 +1,304 @@
+From cf8f1fb8478e4b76c91e825d1537396b014689a0 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 22 Oct 2019 17:03:03 +0200
+Subject: [PATCH 11/12] clutter/stage-view: Separate offscreen and shadowfb
+
+Previously, we would use a single offscreen framebuffer for both
+transformations and when a shadow framebuffer should be used, but that
+can be dreadfully slow when using software rendering with a discrete GPU
+due to bandwidth limitations.
+
+Keep the offscreen framebuffer for transformations only and add another
+intermediate shadow framebuffer used as a copy of the onscreen
+framebuffer.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/917
+
+(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89)
+---
+ clutter/clutter/clutter-stage-view.c      | 162 +++++++++++++++++-----
+ clutter/clutter/cogl/clutter-stage-cogl.c |   6 +-
+ 2 files changed, 128 insertions(+), 40 deletions(-)
+
+diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
+index 503c31e78..c536ac720 100644
+--- a/clutter/clutter/clutter-stage-view.c
++++ b/clutter/clutter/clutter-stage-view.c
+@@ -29,6 +29,7 @@ enum
+   PROP_LAYOUT,
+   PROP_FRAMEBUFFER,
+   PROP_OFFSCREEN,
++  PROP_SHADOWFB,
+   PROP_SCALE,
+ 
+   PROP_LAST
+@@ -43,7 +44,10 @@ typedef struct _ClutterStageViewPrivate
+   CoglFramebuffer *framebuffer;
+ 
+   CoglOffscreen *offscreen;
+-  CoglPipeline *pipeline;
++  CoglPipeline *offscreen_pipeline;
++
++  CoglOffscreen *shadowfb;
++  CoglPipeline *shadowfb_pipeline;
+ 
+   guint dirty_viewport   : 1;
+   guint dirty_projection : 1;
+@@ -69,6 +73,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
+ 
+   if (priv->offscreen)
+     return priv->offscreen;
++  else if (priv->shadowfb)
++    return priv->shadowfb;
+   else
+     return priv->framebuffer;
+ }
+@@ -82,6 +88,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
+   return priv->framebuffer;
+ }
+ 
++static CoglPipeline *
++clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
++{
++  CoglPipeline *pipeline;
++
++  pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
++
++  cogl_pipeline_set_layer_filters (pipeline, 0,
++                                   COGL_PIPELINE_FILTER_NEAREST,
++                                   COGL_PIPELINE_FILTER_NEAREST);
++  cogl_pipeline_set_layer_texture (pipeline, 0,
++                                   cogl_offscreen_get_texture (framebuffer));
++  cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
++                                     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
++
++  return pipeline;
++}
++
+ static void
+ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
+ {
+@@ -92,71 +116,122 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
+ 
+   g_assert (priv->offscreen != NULL);
+ 
+-  if (priv->pipeline)
++  if (priv->offscreen_pipeline)
+     return;
+ 
+-  priv->pipeline =
+-    cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
+-  cogl_pipeline_set_layer_filters (priv->pipeline, 0,
+-                                   COGL_PIPELINE_FILTER_NEAREST,
+-                                   COGL_PIPELINE_FILTER_NEAREST);
+-  cogl_pipeline_set_layer_texture (priv->pipeline, 0,
+-                                   cogl_offscreen_get_texture (priv->offscreen));
+-  cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
+-                                     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
++  priv->offscreen_pipeline =
++    clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
+ 
+   if (view_class->setup_offscreen_blit_pipeline)
+-    view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
++    view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
+ }
+ 
+-void
+-clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
++static void
++clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
+ {
+   ClutterStageViewPrivate *priv =
+     clutter_stage_view_get_instance_private (view);
+ 
+-  g_clear_pointer (&priv->pipeline, cogl_object_unref);
++  if (priv->shadowfb_pipeline)
++    return;
++
++  priv->shadowfb_pipeline =
++    clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
+ }
+ 
+ void
+-clutter_stage_view_blit_offscreen (ClutterStageView            *view,
+-                                   const cairo_rectangle_int_t *rect)
++clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
+ {
+   ClutterStageViewPrivate *priv =
+     clutter_stage_view_get_instance_private (view);
++
++  g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
++}
++
++static void
++clutter_stage_view_copy_to_framebuffer (ClutterStageView            *view,
++                                        const cairo_rectangle_int_t *rect,
++                                        CoglPipeline                *pipeline,
++                                        CoglFramebuffer             *src_framebuffer,
++                                        CoglFramebuffer             *dst_framebuffer,
++                                        gboolean                     can_blit)
++{
+   CoglMatrix matrix;
+ 
+-  clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
+-  if (cogl_matrix_is_identity (&matrix))
++  /* First, try with blit */
++  if (can_blit)
+     {
+-      int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
+-      int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
+-
+-      if (cogl_blit_framebuffer (priv->offscreen,
+-                                 priv->framebuffer,
++      if (cogl_blit_framebuffer (src_framebuffer,
++                                 dst_framebuffer,
+                                  0, 0,
+                                  0, 0,
+-                                 fb_width, fb_height,
++                                 cogl_framebuffer_get_width (dst_framebuffer),
++                                 cogl_framebuffer_get_height (dst_framebuffer),
+                                  NULL))
+         return;
+     }
+ 
+-  clutter_stage_view_ensure_offscreen_blit_pipeline (view);
+-  cogl_framebuffer_push_matrix (priv->framebuffer);
++  /* If blit fails, fallback to the slower painting method */
++  cogl_framebuffer_push_matrix (dst_framebuffer);
+ 
+-  /* Set transform so 0,0 is on the top left corner and 1,1 on
+-   * the bottom right corner.
+-   */
+   cogl_matrix_init_identity (&matrix);
+   cogl_matrix_translate (&matrix, -1, 1, 0);
+   cogl_matrix_scale (&matrix, 2, -2, 0);
+-  cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
++  cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
+ 
+-  cogl_framebuffer_draw_rectangle (priv->framebuffer,
+-                                   priv->pipeline,
++  cogl_framebuffer_draw_rectangle (dst_framebuffer,
++                                   pipeline,
+                                    0, 0, 1, 1);
+ 
+-  cogl_framebuffer_pop_matrix (priv->framebuffer);
++  cogl_framebuffer_pop_matrix (dst_framebuffer);
++}
++
++void
++clutter_stage_view_blit_offscreen (ClutterStageView            *view,
++                                   const cairo_rectangle_int_t *rect)
++{
++  ClutterStageViewPrivate *priv =
++    clutter_stage_view_get_instance_private (view);
++
++  if (priv->offscreen)
++    {
++      gboolean can_blit;
++      CoglMatrix matrix;
++
++      clutter_stage_view_ensure_offscreen_blit_pipeline (view);
++      clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
++      can_blit = cogl_matrix_is_identity (&matrix);
++
++      if (priv->shadowfb)
++        {
++          clutter_stage_view_copy_to_framebuffer (view,
++                                                  rect,
++                                                  priv->offscreen_pipeline,
++                                                  priv->offscreen,
++                                                  priv->shadowfb,
++                                                  can_blit);
++        }
++      else
++        {
++          clutter_stage_view_copy_to_framebuffer (view,
++                                                  rect,
++                                                  priv->offscreen_pipeline,
++                                                  priv->offscreen,
++                                                  priv->framebuffer,
++                                                  can_blit);
++        }
++    }
++
++  if (priv->shadowfb)
++    {
++      clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
++      clutter_stage_view_copy_to_framebuffer (view,
++                                              rect,
++                                              priv->shadowfb_pipeline,
++                                              priv->shadowfb,
++                                              priv->framebuffer,
++                                              TRUE);
++    }
+ }
+ 
+ float
+@@ -256,6 +331,9 @@ clutter_stage_view_get_property (GObject    *object,
+     case PROP_OFFSCREEN:
+       g_value_set_boxed (value, priv->offscreen);
+       break;
++    case PROP_SHADOWFB:
++      g_value_set_boxed (value, priv->shadowfb);
++      break;
+     case PROP_SCALE:
+       g_value_set_float (value, priv->scale);
+       break;
+@@ -301,6 +379,9 @@ clutter_stage_view_set_property (GObject      *object,
+     case PROP_OFFSCREEN:
+       priv->offscreen = g_value_dup_boxed (value);
+       break;
++    case PROP_SHADOWFB:
++      priv->shadowfb = g_value_dup_boxed (value);
++      break;
+     case PROP_SCALE:
+       priv->scale = g_value_get_float (value);
+       break;
+@@ -317,8 +398,10 @@ clutter_stage_view_dispose (GObject *object)
+     clutter_stage_view_get_instance_private (view);
+ 
+   g_clear_pointer (&priv->framebuffer, cogl_object_unref);
++  g_clear_pointer (&priv->shadowfb, cogl_object_unref);
+   g_clear_pointer (&priv->offscreen, cogl_object_unref);
+-  g_clear_pointer (&priv->pipeline, cogl_object_unref);
++  g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
++  g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
+ 
+   G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
+ }
+@@ -373,6 +456,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+ 
++  obj_props[PROP_SHADOWFB] =
++    g_param_spec_boxed ("shadowfb",
++                        "Shadow framebuffer",
++                        "Framebuffer used as intermediate shadow buffer",
++                        COGL_TYPE_HANDLE,
++                        G_PARAM_READWRITE |
++                        G_PARAM_CONSTRUCT_ONLY |
++                        G_PARAM_STATIC_STRINGS);
++
+   obj_props[PROP_SCALE] =
+     g_param_spec_float ("scale",
+                         "View scale",
+diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
+index e0c39185b..eab76e52f 100644
+--- a/clutter/clutter/cogl/clutter-stage-cogl.c
++++ b/clutter/clutter/cogl/clutter-stage-cogl.c
+@@ -477,11 +477,7 @@ paint_stage (ClutterStageCogl            *stage_cogl,
+   _clutter_stage_maybe_setup_viewport (stage, view);
+   _clutter_stage_paint_view (stage, view, clip);
+ 
+-  if (clutter_stage_view_get_onscreen (view) !=
+-      clutter_stage_view_get_framebuffer (view))
+-    {
+-      clutter_stage_view_blit_offscreen (view, clip);
+-    }
++  clutter_stage_view_blit_offscreen (view, clip);
+ }
+ 
+ static void
+-- 
+2.21.0
+
diff --git a/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch
new file mode 100644
index 0000000..cd748a9
--- /dev/null
+++ b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch
@@ -0,0 +1,98 @@
+From ca3e9e3b3b84fe95affbe5485212c6ecfa1a4b51 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 22 Oct 2019 17:05:46 +0200
+Subject: [PATCH 12/12] renderer-native: Separate offscreen and shadowfb
+
+Create the intermediate shadow framebuffer for use exclusively when a
+shadowfb is required.
+
+Keep the previous offscreen framebuffer is as an intermediate
+framebuffer for transformations only.
+
+This way, we can apply transformations between in-memory framebuffers
+prior to blit the result to screen, and achieve acceptable performance
+even with software rendering on discrete GPU.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/917
+
+(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2)
+---
+ src/backends/native/meta-renderer-native.c | 29 ++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index 3cd01bcb7..ffb64a6bd 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -3287,7 +3287,6 @@ meta_renderer_native_create_onscreen (MetaRendererNative   *renderer_native,
+ static CoglOffscreen *
+ meta_renderer_native_create_offscreen (MetaRendererNative    *renderer,
+                                        CoglContext           *context,
+-                                       MetaMonitorTransform   transform,
+                                        gint                   view_width,
+                                        gint                   view_height,
+                                        GError               **error)
+@@ -3489,6 +3488,7 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
+   MetaMonitorTransform view_transform;
+   CoglOnscreen *onscreen = NULL;
+   CoglOffscreen *offscreen = NULL;
++  CoglOffscreen *shadowfb = NULL;
+   float scale;
+   int width, height;
+   MetaRendererView *view;
+@@ -3515,18 +3515,35 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
+   if (!onscreen)
+     g_error ("Failed to allocate onscreen framebuffer: %s", error->message);
+ 
+-  if (view_transform != META_MONITOR_TRANSFORM_NORMAL ||
+-      should_force_shadow_fb (renderer_native,
+-                              renderer_native->primary_gpu_kms))
++ if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
+     {
+       offscreen = meta_renderer_native_create_offscreen (renderer_native,
+                                                          cogl_context,
+-                                                         view_transform,
+                                                          width,
+                                                          height,
+                                                          &error);
+       if (!offscreen)
+         g_error ("Failed to allocate back buffer texture: %s", error->message);
++
++    }
++
++  if (should_force_shadow_fb (renderer_native,
++                              renderer_native->primary_gpu_kms))
++    {
++      int shadow_width;
++      int shadow_height;
++
++      /* The shadowfb must be the same size as the on-screen framebuffer */
++      shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen));
++      shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen));
++
++      shadowfb = meta_renderer_native_create_offscreen (renderer_native,
++                                                        cogl_context,
++                                                        shadow_width,
++                                                        shadow_height,
++                                                        &error);
++      if (!shadowfb)
++        g_error ("Failed to allocate shadow buffer texture: %s", error->message);
+     }
+ 
+   view = g_object_new (META_TYPE_RENDERER_VIEW,
+@@ -3534,10 +3551,12 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
+                        "scale", scale,
+                        "framebuffer", onscreen,
+                        "offscreen", offscreen,
++                       "shadowfb", shadowfb,
+                        "logical-monitor", logical_monitor,
+                        "transform", view_transform,
+                        NULL);
+   g_clear_pointer (&offscreen, cogl_object_unref);
++  g_clear_pointer (&shadowfb, cogl_object_unref);
+ 
+   meta_onscreen_native_set_view (onscreen, view);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/add-support-for-plain-old-x-device-configuration.patch b/SOURCES/add-support-for-plain-old-x-device-configuration.patch
new file mode 100644
index 0000000..beefaf2
--- /dev/null
+++ b/SOURCES/add-support-for-plain-old-x-device-configuration.patch
@@ -0,0 +1,378 @@
+From 3f7ba6739773f43a3ad2a5d26cb8c3365f77cc00 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 9 Oct 2017 18:39:52 +0200
+Subject: [PATCH 1/3] 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 051a1c605..887bc8b42 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -630,6 +630,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.21.0
+
+
+From 717561b28f35e05d40fb941baba781436a0abf68 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Mon, 9 Oct 2017 18:55:56 +0200
+Subject: [PATCH 2/3] 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 887bc8b42..12a592c75 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/meta-logical-monitor.h"
+ #include "backends/x11/meta-backend-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,
+@@ -337,6 +342,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,
+@@ -461,6 +567,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.21.0
+
+
+From 0afa6d0940ca4f5ffafd24effd2c414963a44277 Mon Sep 17 00:00:00 2001
+From: Rui Matos <tiagomatos@gmail.com>
+Date: Tue, 10 Oct 2017 19:07:27 +0200
+Subject: [PATCH 3/3] 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 | 97 +++++++++++++++++-----
+ 1 file changed, 74 insertions(+), 23 deletions(-)
+
+diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
+index 12a592c75..80e5ed10e 100644
+--- a/src/backends/x11/meta-input-settings-x11.c
++++ b/src/backends/x11/meta-input-settings-x11.c
+@@ -182,36 +182,36 @@ 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;
+   MetaBackend *backend = meta_get_backend ();
+   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+   XDevice *xdevice;
+-  guchar *tap_action, *buttons;
++  guchar *buttons;
+   guint buttons_capacity = 16, n_buttons;
+ 
+   xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (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);
+@@ -235,17 +235,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;
+@@ -342,6 +364,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
+@@ -510,9 +549,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;
+     }
+ 
+@@ -554,6 +594,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);
+@@ -767,6 +812,12 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings,
+                                            ClutterInputDevice *device,
+                                            guint               button)
+ {
++  if (!is_device_libinput (device))
++    {
++      change_x_device_scroll_button (device, button);
++      return;
++    }
++
+   change_property (device, "libinput Button Scrolling Button",
+                    XA_INTEGER, 32, &button, 1);
+ }
+-- 
+2.21.0
+
diff --git a/SOURCES/covscan-fixes.patch b/SOURCES/covscan-fixes.patch
new file mode 100644
index 0000000..25bfe3c
--- /dev/null
+++ b/SOURCES/covscan-fixes.patch
@@ -0,0 +1,246 @@
+From 55417eea4294210495eceebd6dd4b832f371f054 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
+Date: Sun, 14 Apr 2019 17:15:06 +0200
+Subject: [PATCH 1/5] display: Fix a possible bug in
+ meta_display_sync_wayland_focus
+
+The check for the focus xwindow is called, but not used. Fix that by
+renaming the variable to reflect better what it does and actually using
+the return value of the check.
+
+This was the original intention of the author in commit
+05899596d10918df5359d89baa82e6fedd0ae208 and got broken in commit
+8e7e1eeef59c4f74046e6783b6334c1432255c5a.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/535
+---
+ src/core/display.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/core/display.c b/src/core/display.c
+index 0de99edb2..4c8907f40 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -1208,15 +1208,15 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
+   MetaWindow *focus_window = NULL;
+   MetaBackend *backend = meta_get_backend ();
+   MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
+-  gboolean is_focus_xwindow = FALSE;
++  gboolean is_no_focus_xwindow = FALSE;
+ 
+   if (display->x11_display)
+-    meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display,
+-                                                   display->x11_display->focus_xwindow);
++    is_no_focus_xwindow = meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display,
++                                                                         display->x11_display->focus_xwindow);
+ 
+   if (!meta_display_windows_are_interactable (display))
+     focus_window = NULL;
+-  else if (is_focus_xwindow)
++  else if (is_no_focus_xwindow)
+     focus_window = NULL;
+   else if (display->focus_window && display->focus_window->surface)
+     focus_window = display->focus_window;
+-- 
+2.21.0
+
+
+From 17cc0a2a21c504b8631bf2ce0f508f611f9b1d3e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 20:03:25 +0000
+Subject: [PATCH 2/5] renderer-x11-nested: Fix copy-and-paste error
+
+The rounding added in commit c5471e5b8b1 mixed up some variables,
+whoops.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
+---
+ src/backends/x11/nested/meta-renderer-x11-nested.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c
+index 71a85a8c2..5000bf357 100644
+--- a/src/backends/x11/nested/meta-renderer-x11-nested.c
++++ b/src/backends/x11/nested/meta-renderer-x11-nested.c
+@@ -203,7 +203,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
+       height = logical_monitor->rect.height;
+     }
+   width = roundf (width * view_scale);
+-  height = roundf (width * view_scale);
++  height = roundf (height * view_scale);
+ 
+   fake_onscreen = create_offscreen (cogl_context, width, height);
+ 
+-- 
+2.21.0
+
+
+From a58fabbb0e3173359d3374b931815c21ce65032d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 19:59:53 +0000
+Subject: [PATCH 3/5] input-mapper: Remove unnecessary return value
+
+Since commit ae6d9e35bd, there is a fallback to META_MATCH_IS_BUILTIN,
+so the condition for returning FALSE is never met.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
+---
+ src/backends/meta-input-mapper.c | 15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/src/backends/meta-input-mapper.c b/src/backends/meta-input-mapper.c
+index acc9b1618..fc4f3bd59 100644
+--- a/src/backends/meta-input-mapper.c
++++ b/src/backends/meta-input-mapper.c
+@@ -353,7 +353,7 @@ find_builtin_output (MetaInputMapper  *mapper,
+   return panel != NULL;
+ }
+ 
+-static gboolean
++static void
+ guess_candidates (MetaInputMapper     *mapper,
+                   MetaMapperInputInfo *input,
+                   DeviceCandidates    *info)
+@@ -387,15 +387,7 @@ guess_candidates (MetaInputMapper     *mapper,
+       find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
+     }
+ 
+-  if (best < N_OUTPUT_MATCHES)
+-    {
+-      info->best = best;
+-      return TRUE;
+-    }
+-  else
+-    {
+-      return FALSE;
+-    }
++  info->best = best;
+ }
+ 
+ static void
+@@ -408,8 +400,7 @@ mapping_helper_add (MappingHelper       *helper,
+ 
+   info.input = input;
+ 
+-  if (!guess_candidates (mapper, input, &info))
+-    return;
++  guess_candidates (mapper, input, &info);
+ 
+   for (i = 0; i < helper->device_maps->len; i++)
+     {
+-- 
+2.21.0
+
+
+From 4eb025cf36a9118cc496ae9143ee2eb510b6228c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 20:22:50 +0000
+Subject: [PATCH 4/5] workspace-manager: Remove unnecessary assignment
+
+The initialization to -1 is never used, instead the variables are
+re-initialized to 0 before the loop that uses them.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
+---
+ src/core/meta-workspace-manager.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c
+index af7344709..8e1f03fe8 100644
+--- a/src/core/meta-workspace-manager.c
++++ b/src/core/meta-workspace-manager.c
+@@ -600,8 +600,6 @@ meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_ma
+ 
+   grid = g_new (int, grid_area);
+ 
+-  current_row = -1;
+-  current_col = -1;
+   i = 0;
+ 
+   switch (workspace_manager->starting_corner)
+-- 
+2.21.0
+
+
+From a854a337ac8807f310ac2c474f9be290089f79f3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 20:43:21 +0000
+Subject: [PATCH 5/5] x11-display: Simplify bell handling
+
+Since commit 956ab4bd made libcanberra mandatory, we never use
+the system bell for handling the `audible-bell` setting. So
+instead of reacting to settings changes with the exact same call
+to XkbChangeEnabledControls(), just call it once when initializing.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
+---
+ src/x11/meta-x11-display.c | 39 +++++++-------------------------------
+ 1 file changed, 7 insertions(+), 32 deletions(-)
+
+diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
+index 8ce12b994..065ffcdda 100644
+--- a/src/x11/meta-x11-display.c
++++ b/src/x11/meta-x11-display.c
+@@ -463,6 +463,13 @@ init_x11_bell (MetaX11Display *x11_display)
+                                    &mask);
+         }
+     }
++
++  /* We are playing sounds using libcanberra support, we handle the
++   * bell whether its an audible bell or a visible bell */
++  XkbChangeEnabledControls (x11_display->xdisplay,
++                            XkbUseCoreKbd,
++                            XkbAudibleBellMask,
++                            0);
+ }
+ 
+ /*
+@@ -480,32 +487,6 @@ shutdown_x11_bell (MetaX11Display *x11_display)
+                             XkbAudibleBellMask);
+ }
+ 
+-/*
+- * Turns the bell to audible or visual. This tells X what to do, but
+- * not Mutter; you will need to set the "visual bell" pref for that.
+- */
+-static void
+-set_x11_bell_is_audible (MetaX11Display *x11_display,
+-                         gboolean is_audible)
+-{
+-  /* When we are playing sounds using libcanberra support, we handle the
+-   * bell whether its an audible bell or a visible bell */
+-  gboolean enable_system_bell = FALSE;
+-
+-  XkbChangeEnabledControls (x11_display->xdisplay,
+-                            XkbUseCoreKbd,
+-                            XkbAudibleBellMask,
+-                            enable_system_bell ? XkbAudibleBellMask : 0);
+-}
+-
+-static void
+-on_is_audible_changed (MetaBell       *bell,
+-                       gboolean        is_audible,
+-                       MetaX11Display *x11_display)
+-{
+-  set_x11_bell_is_audible (x11_display, is_audible);
+-}
+-
+ static void
+ set_desktop_geometry_hint (MetaX11Display *x11_display)
+ {
+@@ -1320,12 +1301,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
+ 
+   init_x11_bell (x11_display);
+ 
+-  g_signal_connect_object (display->bell, "is-audible-changed",
+-                           G_CALLBACK (on_is_audible_changed),
+-                           x11_display, 0);
+-
+-  set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ());
+-
+   meta_x11_startup_notification_init (x11_display);
+ 
+   return x11_display;
+-- 
+2.21.0
+
diff --git a/SOURCES/deal-more-gracefully-with-oversized-windows.patch b/SOURCES/deal-more-gracefully-with-oversized-windows.patch
new file mode 100644
index 0000000..9a7a36d
--- /dev/null
+++ b/SOURCES/deal-more-gracefully-with-oversized-windows.patch
@@ -0,0 +1,85 @@
+From 575490895047e0709bc84826fe6d6a73028d7bbc 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 117131b15..379372245 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;
+ 
+@@ -201,6 +202,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,
+@@ -236,6 +241,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}
+ };
+ 
+@@ -1780,3 +1786,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.21.0
+
diff --git a/SOURCES/fix-text-selection-drawing.patch b/SOURCES/fix-text-selection-drawing.patch
new file mode 100644
index 0000000..11554aa
--- /dev/null
+++ b/SOURCES/fix-text-selection-drawing.patch
@@ -0,0 +1,138 @@
+From 30d6e3abe2a0251b11513d66d15a59cd0705a828 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 17:48:41 +0000
+Subject: [PATCH 1/2] clutter-text: Fix selection color drawing
+
+Commit cabcad185 removed the call to cogl_set_source_color4ub() before
+cogl_fill_path(), so instead of the previously assigned selection color,
+the background is drawn with the last set source.
+
+In order to honour the newly added framebuffer parameter and still apply
+the correct color, switch from cogl_fill_path() to the (deprecated!)
+cogl_framebuffer_fill_path() method.
+
+https://gitlab.gnome.org/GNOME/mutter/issues/494
+---
+ clutter/clutter/clutter-text.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/clutter/clutter/clutter-text.c b/clutter/clutter/clutter-text.c
+index fb9d926df..000bbbbd4 100644
+--- a/clutter/clutter/clutter-text.c
++++ b/clutter/clutter/clutter-text.c
+@@ -1975,6 +1975,7 @@ selection_paint (ClutterText     *self,
+   else
+     {
+       /* Paint selection background first */
++      CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
+       PangoLayout *layout = clutter_text_get_layout (self);
+       CoglPath *selection_path = cogl_path_new ();
+       CoglColor cogl_color = { 0, };
+@@ -1987,11 +1988,19 @@ selection_paint (ClutterText     *self,
+       else
+         color = &priv->text_color;
+ 
++      cogl_color_init_from_4ub (&cogl_color,
++                                color->red,
++                                color->green,
++                                color->blue,
++                                paint_opacity * color->alpha / 255);
++      cogl_color_premultiply (&cogl_color);
++      cogl_pipeline_set_color (color_pipeline, &cogl_color);
++
+       clutter_text_foreach_selection_rectangle_prescaled (self,
+                                                           add_selection_rectangle_to_path,
+                                                           selection_path);
+ 
+-      cogl_path_fill (selection_path);
++      cogl_framebuffer_fill_path (fb, color_pipeline, selection_path);
+ 
+       /* Paint selected text */
+       cogl_framebuffer_push_path_clip (fb, selection_path);
+-- 
+2.21.0
+
+
+From 13a1624c1050c91cd4d8a298f7a10fafe56fe9e5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Mon, 27 May 2019 22:40:47 +0000
+Subject: [PATCH 2/2] cogl-path: Undeprecate framebuffer functions
+
+It looks like deprecating the functions with explicit framebuffer/pipeline
+arguments made it to (cogl) master by mistake:
+
+https://mail.gnome.org/archives/clutter-list/2016-April/msg00008.html
+
+We now use one of them, so this is a good time to undeprecate the lot.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/597
+---
+ cogl/cogl-path/cogl-path-functions.h | 6 ------
+ cogl/cogl-path/cogl-path.c           | 3 ---
+ 2 files changed, 9 deletions(-)
+
+diff --git a/cogl/cogl-path/cogl-path-functions.h b/cogl/cogl-path/cogl-path-functions.h
+index d4ef328d2..318fed028 100644
+--- a/cogl/cogl-path/cogl-path-functions.h
++++ b/cogl/cogl-path/cogl-path-functions.h
+@@ -460,9 +460,7 @@ cogl_path_fill (CoglPath *path);
+  * use while filling a path.</note>
+  *
+  * Stability: unstable
+- * Deprecated: 1.16: Use cogl_path_fill() instead
+  */
+-COGL_DEPRECATED_FOR (cogl_path_fill)
+ void
+ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
+                             CoglPipeline *pipeline,
+@@ -492,9 +490,7 @@ cogl_path_stroke (CoglPath *path);
+  * regardless of the current transformation matrix.
+  *
+  * Stability: unstable
+- * Deprecated: 1.16: Use cogl_path_stroke() instead
+  */
+-COGL_DEPRECATED_FOR (cogl_path_stroke)
+ void
+ cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
+                               CoglPipeline *pipeline,
+@@ -529,9 +525,7 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
+  *
+  * Since: 1.8
+  * Stability: Unstable
+- * Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead
+  */
+-COGL_DEPRECATED_FOR (cogl_framebuffer_push_path_clip)
+ void
+ cogl_clip_push_from_path (CoglPath *path);
+ 
+diff --git a/cogl/cogl-path/cogl-path.c b/cogl/cogl-path/cogl-path.c
+index 4d86c6fb5..8774406f8 100644
+--- a/cogl/cogl-path/cogl-path.c
++++ b/cogl/cogl-path/cogl-path.c
+@@ -1504,7 +1504,6 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
+       COGL_FRAMEBUFFER_STATE_CLIP;
+ }
+ 
+-/* XXX: deprecated */
+ void
+ cogl_clip_push_from_path (CoglPath *path)
+ {
+@@ -1575,7 +1574,6 @@ _cogl_path_build_stroke_attribute_buffer (CoglPath *path)
+   data->stroke_n_attributes = n_attributes;
+ }
+ 
+-/* XXX: deprecated */
+ void
+ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
+                             CoglPipeline *pipeline,
+@@ -1588,7 +1586,6 @@ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
+   _cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
+ }
+ 
+-/* XXX: deprecated */
+ void
+ cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
+                               CoglPipeline *pipeline,
+-- 
+2.21.0
+
diff --git a/SOURCES/handle-hotplug-better.patch b/SOURCES/handle-hotplug-better.patch
new file mode 100644
index 0000000..57668d9
--- /dev/null
+++ b/SOURCES/handle-hotplug-better.patch
@@ -0,0 +1,614 @@
+From d442ef48412e3dc1b24a9f97b02ee3383404d501 Mon Sep 17 00:00:00 2001
+From: Emil Velikov <emil.velikov@collabora.com>
+Date: Wed, 12 Jun 2019 16:58:54 +0000
+Subject: [PATCH 1/8] renderer/native: add missing eglTerminate in EGLDevice
+ error path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently the EGLDevice code gets the display and calls eglInitialize.
+As a follow-up it checks the required EGL extensions - technically it
+could check the EGL device extensions earlier.
+
+In either case, eglTerminate is missing. Thus the connection to the
+display was still bound.
+
+This was highlighted with Mesa commit d6edccee8da ("egl: add
+EGL_platform_device support") + amdgpu.
+
+In that case, since the eglTerminate is missing, we end up reusing the
+underlying amdgpu_device due to some caching in libdrm_amdgpu. The
+latter in itself being a good solution since it allows buffer sharing
+across primary and render node of the same device.
+
+Note: we should really get this in branches all the way back to 3.30.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/619
+
+Fixes: 934184e23 ("MetaRendererNative: Add EGLDevice based rendering support")
+Cc: Jonas Ådahl <jadahl@gmail.com>
+Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
+
+
+(cherry picked from commit 9213574870faee7fe40609791fc48f4b44f861c0)
+---
+ src/backends/native/meta-renderer-native.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index dbfc97aae..207b654fa 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -4038,6 +4038,7 @@ create_renderer_gpu_data_egl_device (MetaRendererNative  *renderer_native,
+                    G_IO_ERROR_FAILED,
+                    "Missing EGL extensions required for EGLDevice renderer: %s",
+                    missing_extensions_str);
++      meta_egl_terminate (egl, egl_display, NULL);
+       g_free (missing_extensions_str);
+       g_free (missing_extensions);
+       return NULL;
+-- 
+2.24.1
+
+
+From e18dfc888343585d21b3f64568571009c4967a95 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 17 Jun 2019 18:18:12 +0200
+Subject: [PATCH 2/8] renderer/native: Use g_set_error() instead of
+ _cogl_set_error()
+
+It's even a GError, so lets use the proper API.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/622
+(cherry picked from commit 1efb32d3000ca06ee3cfcc146dc812866d243619)
+---
+ src/backends/native/meta-renderer-native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index 207b654fa..e7aa6f389 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -1277,7 +1277,7 @@ meta_renderer_native_egl_context_created (CoglDisplay *cogl_display,
+                                       cogl_display_egl->dummy_surface,
+                                       cogl_display_egl->egl_context))
+     {
+-      _cogl_set_error (error, COGL_WINSYS_ERROR,
++      g_set_error (error, COGL_WINSYS_ERROR,
+                    COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                    "Failed to make context current");
+       return FALSE;
+-- 
+2.24.1
+
+
+From 1947a81db93624d57471ce1edf5548c7774c3569 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 17 Jun 2019 18:18:42 +0200
+Subject: [PATCH 3/8] renderer/native: Make sure we're not destroying an active
+ EGLSurface
+
+When making a new surface/context pair current, mesa may want to flush
+the old context. Make sure we don't try to flush any freed memory by
+unmaking a surface/context pair current before freeing it.
+
+Not doing this results in the following valgrind warnings:
+
+==15986== Invalid read of size 8
+==15986==    at 0x69A6D80: dri_flush_front_buffer (gbm_dri.c:92)
+==15986==    by 0x1750D458: intel_flush_front (brw_context.c:251)
+==15986==    by 0x1750D4BB: intel_glFlush (brw_context.c:296)
+==15986==    by 0x1739D8DD: dri2_make_current (egl_dri2.c:1461)
+==15986==    by 0x17393A3A: eglMakeCurrent (eglapi.c:869)
+==15986==    by 0x54381FB: InternalMakeCurrentVendor (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
+==15986==    by 0x5438515: eglMakeCurrent (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
+==15986==    by 0x522A782: _cogl_winsys_egl_make_current (cogl-winsys-egl.c:303)
+==15986==    by 0x49B64C8: meta_renderer_native_create_view (meta-renderer-native.c:3076)
+==15986==    by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78)
+==15986==    by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111)
+==15986==    by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142)
+==15986==  Address 0x1b076600 is 0 bytes inside a block of size 48 free'd
+==15986==    at 0x4839A0C: free (vg_replace_malloc.c:540)
+==15986==    by 0x49B59F3: meta_renderer_native_release_onscreen (meta-renderer-native.c:2651)
+==15986==    by 0x5211441: _cogl_onscreen_free (cogl-onscreen.c:167)
+==15986==    by 0x5210D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
+==15986==    by 0x51D0066: _cogl_object_default_unref (cogl-object.c:103)
+==15986==    by 0x520F989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
+==15986==    by 0x51D00B1: cogl_object_unref (cogl-object.c:115)
+==15986==    by 0x536F3C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
+==15986==    by 0x4B7DAF2: g_object_unref (gobject.c:3309)
+==15986==    by 0x4A9596C: g_list_foreach (glist.c:1013)
+==15986==    by 0x4A9599A: g_list_free_full (glist.c:223)
+==15986==    by 0x48D2737: meta_renderer_rebuild_views (meta-renderer.c:100)
+==15986==  Block was alloc'd at
+==15986==    at 0x483AB1A: calloc (vg_replace_malloc.c:762)
+==15986==    by 0x69A76B2: gbm_dri_surface_create (gbm_dri.c:1252)
+==15986==    by 0x69A6BFE: gbm_surface_create (gbm.c:600)
+==15986==    by 0x49B4E29: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2221)
+==15986==    by 0x49B57DB: meta_onscreen_native_allocate (meta-renderer-native.c:2569)
+==15986==    by 0x49B6423: meta_renderer_native_create_view (meta-renderer-native.c:3062)
+==15986==    by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78)
+==15986==    by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111)
+==15986==    by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142)
+==15986==    by 0x49A75B5: meta_backend_native_update_screen_size (meta-backend-native.c:520)
+==15986==    by 0x48B01BB: meta_backend_sync_screen_size (meta-backend.c:224)
+==15986==    by 0x48B09B7: meta_backend_real_post_init (meta-backend.c:501)
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/622
+(cherry picked from commit 56ddaaa3809240a357b5e19b5789d1aa49aaecc3)
+---
+ src/backends/native/meta-renderer-native.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index e7aa6f389..b7bc3121a 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -3040,6 +3040,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+ {
+   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+   CoglContext *cogl_context = framebuffer->context;
++  CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
++  CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
+   CoglRenderer *cogl_renderer = cogl_context->display->renderer;
+   CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
+   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+@@ -3052,6 +3054,17 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+ 
+   onscreen_native = onscreen_egl->platform;
+ 
++  if (onscreen_egl->egl_surface != EGL_NO_SURFACE &&
++      (cogl_display_egl->current_draw_surface == onscreen_egl->egl_surface ||
++       cogl_display_egl->current_read_surface == onscreen_egl->egl_surface))
++    {
++      if (!_cogl_winsys_egl_make_current (cogl_display,
++                                          cogl_display_egl->dummy_surface,
++                                          cogl_display_egl->dummy_surface,
++                                          cogl_display_egl->egl_context))
++        g_warning ("Failed to clear current context");
++    }
++
+   g_list_free_full (onscreen_native->pending_page_flip_retries,
+                     (GDestroyNotify) retry_page_flip_data_free);
+   if (onscreen_native->retry_page_flips_source)
+-- 
+2.24.1
+
+
+From 60551e5e6f984a7ed3ba3339f027ed7b37f802c4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 17 Jun 2019 19:16:12 +0200
+Subject: [PATCH 4/8] renderer/native: Fix EGLSurface destruction order
+
+Make sure to destroy the EGL surface after releasing held buffers,
+otherwise we'll get the following valgrind warnings:
+
+==24016== Invalid read of size 8
+==24016==    at 0x1739943F: release_buffer (platform_drm.c:73)
+==24016==    by 0x49AC355: meta_drm_buffer_gbm_finalize (meta-drm-buffer-gbm.c:213)
+==24016==    by 0x4B75B61: g_object_unref (gobject.c:3346)
+==24016==    by 0x49B4B41: free_current_bo (meta-renderer-native.c:991)
+==24016==    by 0x49B816F: meta_renderer_native_release_onscreen (meta-renderer-native.c:2971)
+==24016==    by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167)
+==24016==    by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
+==24016==    by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103)
+==24016==    by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
+==24016==    by 0x51C80B1: cogl_object_unref (cogl-object.c:115)
+==24016==    by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
+==24016==    by 0x4B75AF2: g_object_unref (gobject.c:3309)
+==24016==  Address 0x18e742a8 is 536 bytes inside a block of size 784 free'd
+==24016==    at 0x4839A0C: free (vg_replace_malloc.c:540)
+==24016==    by 0x17399764: dri2_drm_destroy_surface (platform_drm.c:231)
+==24016==    by 0x1738550A: eglDestroySurface (eglapi.c:1145)
+==24016==    by 0x5440286: eglDestroySurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
+==24016==    by 0x49613A5: meta_egl_destroy_surface (meta-egl.c:432)
+==24016==    by 0x49B80F9: meta_renderer_native_release_onscreen (meta-renderer-native.c:2954)
+==24016==    by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167)
+==24016==    by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
+==24016==    by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103)
+==24016==    by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
+==24016==    by 0x51C80B1: cogl_object_unref (cogl-object.c:115)
+==24016==    by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
+==24016==  Block was alloc'd at
+==24016==    at 0x483AB1A: calloc (vg_replace_malloc.c:762)
+==24016==    by 0x173997AE: dri2_drm_create_window_surface (platform_drm.c:145)
+==24016==    by 0x17388906: _eglCreateWindowSurfaceCommon (eglapi.c:929)
+==24016==    by 0x5440197: eglCreateWindowSurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
+==24016==    by 0x49612FF: meta_egl_create_window_surface (meta-egl.c:396)
+==24016==    by 0x49B752E: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2538)
+==24016==    by 0x49B7E6C: meta_onscreen_native_allocate (meta-renderer-native.c:2870)
+==24016==    by 0x49B8BCF: meta_renderer_native_create_view (meta-renderer-native.c:3387)
+==24016==    by 0x48D274B: meta_renderer_create_view (meta-renderer.c:78)
+==24016==    by 0x48D27DE: meta_renderer_rebuild_views (meta-renderer.c:111)
+==24016==    by 0x49BB4FB: meta_stage_native_rebuild_views (meta-stage-native.c:142)
+==24016==    by 0x49A733C: meta_backend_native_update_screen_size (meta-backend-native.c:517)
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/622
+(cherry picked from commit d9fb11b04319c00fd89715dd9207fe54e1d18c2d)
+---
+ src/backends/native/meta-renderer-native.c | 38 +++++++++++++++-------
+ 1 file changed, 27 insertions(+), 11 deletions(-)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index b7bc3121a..62c27c191 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -3035,6 +3035,28 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
+   return TRUE;
+ }
+ 
++static void
++destroy_egl_surface (CoglOnscreen *onscreen)
++{
++  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
++
++  if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
++    {
++      MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
++      MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
++      CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
++      CoglContext *cogl_context = framebuffer->context;
++      CoglRenderer *cogl_renderer = cogl_context->display->renderer;
++      CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
++
++      meta_egl_destroy_surface (egl,
++                                cogl_renderer_egl->edpy,
++                                onscreen_egl->egl_surface,
++                                NULL);
++      onscreen_egl->egl_surface = EGL_NO_SURFACE;
++    }
++}
++
+ static void
+ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+ {
+@@ -3077,17 +3099,6 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+                        g_source_destroy);
+     }
+ 
+-  if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
+-    {
+-      MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
+-
+-      meta_egl_destroy_surface (egl,
+-                                cogl_renderer_egl->edpy,
+-                                onscreen_egl->egl_surface,
+-                                NULL);
+-      onscreen_egl->egl_surface = EGL_NO_SURFACE;
+-    }
+-
+   renderer_gpu_data =
+     meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
+                                        onscreen_native->render_gpu);
+@@ -3100,6 +3111,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+ 
+       free_current_bo (onscreen);
+ 
++      destroy_egl_surface (onscreen);
++
+       if (onscreen_native->gbm.surface)
+         {
+           gbm_surface_destroy (onscreen_native->gbm.surface);
+@@ -3110,6 +3123,9 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+     case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
+       release_dumb_fb (&onscreen_native->egl.dumb_fb,
+                        onscreen_native->render_gpu);
++
++      destroy_egl_surface (onscreen);
++
+       if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR)
+         {
+           MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
+-- 
+2.24.1
+
+
+From c447010a23edc03c7a1103b477972ad666c2600f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 19 Jun 2019 20:55:48 +0200
+Subject: [PATCH 5/8] renderer/native: Remove left-over function declarations
+
+There are no callers and no definitions of these.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/655
+---
+ src/backends/native/meta-renderer-native.h | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h
+index a006dcbe7..8468208e1 100644
+--- a/src/backends/native/meta-renderer-native.h
++++ b/src/backends/native/meta-renderer-native.h
+@@ -55,18 +55,6 @@ gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_n
+ 
+ void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
+ 
+-gboolean meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
+-                                                    MetaRendererView   *view,
+-                                                    int                 width,
+-                                                    int                 height,
+-                                                    GError            **error);
+-
+-void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
+-                                           uint32_t            id,
+-                                           gboolean            ignore);
+-
+-MetaRendererView * meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native);
+-
+ void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
+ 
+ int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
+-- 
+2.24.1
+
+
+From 7f97403d12df19cf936a341cc218743ec339aa0a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 19 Jun 2019 20:57:14 +0200
+Subject: [PATCH 6/8] renderer/native: Queue mode reset from new rebuild_views
+ vfunc
+
+Simplify the call site a bit and make the native renderer know it should
+queue mode reset itself when views have been rebuilt. This is done
+partly due to more things needing to be dealt with after views have been
+rebuilt.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/655
+---
+ src/backends/meta-renderer.c               |  8 ++++++++
+ src/backends/meta-renderer.h               |  1 +
+ src/backends/native/meta-renderer-native.c | 17 ++++++++++++++++-
+ src/backends/native/meta-renderer-native.h |  2 --
+ src/backends/native/meta-stage-native.c    |  1 -
+ 5 files changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c
+index 28637437b..87ba9f9f0 100644
+--- a/src/backends/meta-renderer.c
++++ b/src/backends/meta-renderer.c
+@@ -90,6 +90,12 @@ meta_renderer_create_view (MetaRenderer       *renderer,
+  */
+ void
+ meta_renderer_rebuild_views (MetaRenderer *renderer)
++{
++  return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer);
++}
++
++static void
++meta_renderer_real_rebuild_views (MetaRenderer *renderer)
+ {
+   MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
+   MetaBackend *backend = meta_get_backend ();
+@@ -181,4 +187,6 @@ meta_renderer_class_init (MetaRendererClass *klass)
+   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ 
+   object_class->finalize = meta_renderer_finalize;
++
++  klass->rebuild_views = meta_renderer_real_rebuild_views;
+ }
+diff --git a/src/backends/meta-renderer.h b/src/backends/meta-renderer.h
+index dae52cb9a..478baee91 100644
+--- a/src/backends/meta-renderer.h
++++ b/src/backends/meta-renderer.h
+@@ -43,6 +43,7 @@ struct _MetaRendererClass
+   CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer);
+   MetaRendererView * (* create_view) (MetaRenderer       *renderer,
+                                       MetaLogicalMonitor *logical_monitor);
++  void (* rebuild_views) (MetaRenderer *renderer);
+ };
+ 
+ CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index 62c27c191..70e1c4f9d 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -258,6 +258,9 @@ cogl_pixel_format_from_drm_format (uint32_t               drm_format,
+                                    CoglPixelFormat       *out_format,
+                                    CoglTextureComponents *out_components);
+ 
++static void
++meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
++
+ static MetaBackend *
+ backend_from_renderer_native (MetaRendererNative *renderer_native)
+ {
+@@ -3186,7 +3189,7 @@ meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native)
+   return TRUE;
+ }
+ 
+-void
++static void
+ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
+ {
+   MetaRenderer *renderer = META_RENDERER (renderer_native);
+@@ -3552,6 +3555,17 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
+   return view;
+ }
+ 
++static void
++meta_renderer_native_rebuild_views (MetaRenderer *renderer)
++{
++  MetaRendererClass *parent_renderer_class =
++    META_RENDERER_CLASS (meta_renderer_native_parent_class);
++
++  parent_renderer_class->rebuild_views (renderer);
++
++  meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
++}
++
+ void
+ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
+ {
+@@ -4350,6 +4364,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass)
+ 
+   renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
+   renderer_class->create_view = meta_renderer_native_create_view;
++  renderer_class->rebuild_views = meta_renderer_native_rebuild_views;
+ 
+   obj_props[PROP_MONITOR_MANAGER] =
+     g_param_spec_object ("monitor-manager",
+diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h
+index 8468208e1..9eecdead1 100644
+--- a/src/backends/native/meta-renderer-native.h
++++ b/src/backends/native/meta-renderer-native.h
+@@ -53,8 +53,6 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms);
+ 
+ gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native);
+ 
+-void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
+-
+ void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
+ 
+ int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
+diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c
+index add3e81fd..9b9c45ef3 100644
+--- a/src/backends/native/meta-stage-native.c
++++ b/src/backends/native/meta-stage-native.c
+@@ -140,7 +140,6 @@ meta_stage_native_rebuild_views (MetaStageNative *stage_native)
+   ClutterActor *stage = meta_backend_get_stage (backend);
+ 
+   meta_renderer_rebuild_views (renderer);
+-  meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
+   clutter_stage_update_resource_scales (CLUTTER_STAGE (stage));
+   ensure_frame_callbacks (stage_native);
+ }
+-- 
+2.24.1
+
+
+From 025054c93e43e8359c9ecafb6edea1eb4b7ad681 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 19 Jun 2019 21:14:05 +0200
+Subject: [PATCH 7/8] renderer/native: Discard page flip retries when
+ rebuilding views
+
+Rebuilding views means we don't care to retry page flip attempts for
+previous views, especially since connectors may have been disconnected,
+making a page flip retry hit an assert a flipped CRTC has connectors
+associated with it.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/655
+---
+ src/backends/native/meta-renderer-native.c | 50 +++++++++++++++++-----
+ 1 file changed, 39 insertions(+), 11 deletions(-)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index 70e1c4f9d..3cd01bcb7 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -3060,6 +3060,24 @@ destroy_egl_surface (CoglOnscreen *onscreen)
+     }
+ }
+ 
++static void
++discard_onscreen_page_flip_retries (MetaOnscreenNative *onscreen_native)
++{
++  g_list_free_full (onscreen_native->pending_page_flip_retries,
++                    (GDestroyNotify) retry_page_flip_data_free);
++  onscreen_native->pending_page_flip_retries = NULL;
++
++  if (onscreen_native->retry_page_flips_source)
++    {
++      MetaBackend *backend =
++        backend_from_renderer_native (onscreen_native->renderer_native);
++
++      meta_backend_thaw_updates (backend);
++      g_clear_pointer (&onscreen_native->retry_page_flips_source,
++                       g_source_destroy);
++    }
++}
++
+ static void
+ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+ {
+@@ -3090,17 +3108,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
+         g_warning ("Failed to clear current context");
+     }
+ 
+-  g_list_free_full (onscreen_native->pending_page_flip_retries,
+-                    (GDestroyNotify) retry_page_flip_data_free);
+-  if (onscreen_native->retry_page_flips_source)
+-    {
+-      MetaBackend *backend =
+-        backend_from_renderer_native (onscreen_native->renderer_native);
+-
+-      meta_backend_thaw_updates (backend);
+-      g_clear_pointer (&onscreen_native->retry_page_flips_source,
+-                       g_source_destroy);
+-    }
++  discard_onscreen_page_flip_retries (onscreen_native);
+ 
+   renderer_gpu_data =
+     meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
+@@ -3555,12 +3563,32 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
+   return view;
+ }
+ 
++static void
++discard_page_flip_retries (MetaRenderer *renderer)
++{
++  GList *l;
++
++  for (l = meta_renderer_get_views (renderer); l; l = l->next)
++    {
++      ClutterStageView *stage_view = l->data;
++      CoglFramebuffer *framebuffer =
++        clutter_stage_view_get_onscreen (stage_view);
++      CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
++      CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
++      MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
++
++      discard_onscreen_page_flip_retries (onscreen_native);
++    }
++}
++
+ static void
+ meta_renderer_native_rebuild_views (MetaRenderer *renderer)
+ {
+   MetaRendererClass *parent_renderer_class =
+     META_RENDERER_CLASS (meta_renderer_native_parent_class);
+ 
++  discard_page_flip_retries (renderer);
++
+   parent_renderer_class->rebuild_views (renderer);
+ 
+   meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
+-- 
+2.24.1
+
+
+From f4fdec6003e2cf9fa4b1882e92faf1da64e6052e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 27 Nov 2019 17:34:35 +0100
+Subject: [PATCH 8/8] =?UTF-8?q?crtc-kms:=20Ignore=2090=C2=B0=20rotations?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+They tend to require special modifiers or won't work at all; ignore
+them.
+---
+ src/backends/native/meta-crtc-kms.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
+index 8c2fbfe3c..8374376d5 100644
+--- a/src/backends/native/meta-crtc-kms.c
++++ b/src/backends/native/meta-crtc-kms.c
+@@ -368,12 +368,8 @@ parse_transforms (MetaCrtc          *crtc,
+ 
+       if (strcmp (prop->enums[i].name, "rotate-0") == 0)
+         transform = META_MONITOR_TRANSFORM_NORMAL;
+-      else if (strcmp (prop->enums[i].name, "rotate-90") == 0)
+-        transform = META_MONITOR_TRANSFORM_90;
+       else if (strcmp (prop->enums[i].name, "rotate-180") == 0)
+         transform = META_MONITOR_TRANSFORM_180;
+-      else if (strcmp (prop->enums[i].name, "rotate-270") == 0)
+-        transform = META_MONITOR_TRANSFORM_270;
+ 
+       if (transform != -1)
+         {
+-- 
+2.24.1
+
diff --git a/SOURCES/idle-monitor-reset-fix.patch b/SOURCES/idle-monitor-reset-fix.patch
new file mode 100644
index 0000000..b67e015
--- /dev/null
+++ b/SOURCES/idle-monitor-reset-fix.patch
@@ -0,0 +1,128 @@
+From 35333114a991440d671e3642170aa080df45a171 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 16 Sep 2019 16:17:48 +0200
+Subject: [PATCH 1/3] idle-monitor: Make helper function static
+
+It wasn't used outside the file, so no reason to not have it static.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/799
+---
+ src/backends/meta-idle-monitor-private.h | 1 -
+ src/backends/meta-idle-monitor.c         | 8 ++++----
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/src/backends/meta-idle-monitor-private.h b/src/backends/meta-idle-monitor-private.h
+index 93948b14b..cc08f8c8e 100644
+--- a/src/backends/meta-idle-monitor-private.h
++++ b/src/backends/meta-idle-monitor-private.h
+@@ -54,7 +54,6 @@ struct _MetaIdleMonitorClass
+   GObjectClass parent_class;
+ };
+ 
+-void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
+ void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
+ 
+ #endif /* META_IDLE_MONITOR_PRIVATE_H */
+diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c
+index e83d6c778..de1c7e0ba 100644
+--- a/src/backends/meta-idle-monitor.c
++++ b/src/backends/meta-idle-monitor.c
+@@ -54,8 +54,8 @@ static GParamSpec *obj_props[PROP_LAST];
+ 
+ G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
+ 
+-void
+-_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
++static void
++meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
+ {
+   MetaIdleMonitor *monitor;
+   guint id;
+@@ -324,7 +324,7 @@ idle_monitor_dispatch_timeout (GSource     *source,
+   if (ready_time > now)
+     return G_SOURCE_CONTINUE;
+ 
+-  _meta_idle_monitor_watch_fire (watch);
++  meta_idle_monitor_watch_fire (watch);
+   g_source_set_ready_time (watch->timeout_source, -1);
+ 
+   return G_SOURCE_CONTINUE;
+@@ -511,7 +511,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
+ 
+       if (watch->timeout_msec == 0)
+         {
+-          _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
++          meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
+         }
+       else
+         {
+-- 
+2.23.0
+
+
+From 07276cf94d84489d450c17b7dec5a8075c60440a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 16 Sep 2019 16:36:05 +0200
+Subject: [PATCH 2/3] idle-monitor: Remove redundant type cast
+
+No need to type cast a `MetaIdleMonitorWatch *` to a
+`MetaIdleMonitorWatch *`.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/799
+---
+ src/backends/meta-idle-monitor.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c
+index de1c7e0ba..e5124abc1 100644
+--- a/src/backends/meta-idle-monitor.c
++++ b/src/backends/meta-idle-monitor.c
+@@ -511,7 +511,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
+ 
+       if (watch->timeout_msec == 0)
+         {
+-          meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
++          meta_idle_monitor_watch_fire (watch);
+         }
+       else
+         {
+-- 
+2.23.0
+
+
+From 73c1f387765ef528c7323e6e7ca3c05899cfcc4a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Mon, 16 Sep 2019 16:36:51 +0200
+Subject: [PATCH 3/3] idle-monitor: Reset timeout before firing watch
+
+The watch might be removed during firing, meaning the source is
+destroyed after returning. Avoid use-after-free by unsetting the timeout
+before firing. Returning G_SOURCE_CONTINUE in that case is harmless, as
+source is destroyed.
+
+Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/796
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/799
+---
+ src/backends/meta-idle-monitor.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c
+index e5124abc1..9fa481742 100644
+--- a/src/backends/meta-idle-monitor.c
++++ b/src/backends/meta-idle-monitor.c
+@@ -324,9 +324,10 @@ idle_monitor_dispatch_timeout (GSource     *source,
+   if (ready_time > now)
+     return G_SOURCE_CONTINUE;
+ 
+-  meta_idle_monitor_watch_fire (watch);
+   g_source_set_ready_time (watch->timeout_source, -1);
+ 
++  meta_idle_monitor_watch_fire (watch);
++
+   return G_SOURCE_CONTINUE;
+ }
+ 
+-- 
+2.23.0
+
diff --git a/SOURCES/inherit-xrandr-metamodes.patch b/SOURCES/inherit-xrandr-metamodes.patch
new file mode 100644
index 0000000..9f3f6c9
--- /dev/null
+++ b/SOURCES/inherit-xrandr-metamodes.patch
@@ -0,0 +1,365 @@
+From 2fd3910c29d2af2a7c64b82f075cd3647d7e4bee 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 1/2] 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 | 77 +++++++++++++---------
+ 1 file changed, 47 insertions(+), 30 deletions(-)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index c09edbe00..a3387aa0f 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -592,20 +592,19 @@ create_monitor_config (MetaMonitor     *monitor,
+ }
+ 
+ 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;
+   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) &
+@@ -645,22 +644,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;
++  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);
+-    return create_preferred_logical_monitor_config (monitor_manager,
+-                                                    monitor,
+-                                                    crtc->rect.x,
+-                                                    crtc->rect.y,
+-                                                    primary_logical_monitor_config,
+-                                                    layout_mode);
++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_logical_monitor_config (monitor_manager,
++                                        monitor,
++                                        mode,
++                                        monitor_layout.x,
++                                        monitor_layout.y,
++                                        primary_logical_monitor_config,
++                                        layout_mode);
+ }
+ 
+ MetaMonitorsConfig *
+@@ -688,10 +705,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);
+ 
+   primary_logical_monitor_config->is_primary = TRUE;
+   logical_monitor_configs = g_list_append (NULL,
+@@ -710,10 +727,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);
+ 
+       logical_monitor_configs = g_list_append (logical_monitor_configs,
+                                                logical_monitor_config);
+-- 
+2.21.0
+
+
+From d8c34e4cd7e500567e72e0f219295d7c2162dcf3 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 2/2] 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 a3387aa0f..bc1a39db8 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;
+ };
+ 
+@@ -680,11 +680,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;
+@@ -692,12 +691,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;
+@@ -736,14 +729,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 *
+@@ -1282,7 +1287,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 409611bb0..bb847b96e 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 cdb8f4209..223b5dfbd 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_MIRRORING = (1 << 0),
+   META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 1),
+-  META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2)
++  META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2),
++  META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT = (1 << 3),
+ } MetaMonitorManagerCapability;
+ 
+ /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
+@@ -133,6 +134,7 @@ struct _MetaMonitorManager
+   int persistent_timeout_id;
+ 
+   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 bb4b44188..076dca8cb 100644
+--- a/src/backends/meta-monitor-manager.c
++++ b/src/backends/meta-monitor-manager.c
+@@ -531,14 +531,21 @@ should_use_stored_config (MetaMonitorManager *manager)
+           !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;
+@@ -549,17 +556,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)
+     {
+@@ -628,9 +626,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 d60f00325..b8d6342b6 100644
+--- a/src/backends/x11/meta-monitor-manager-xrandr.c
++++ b/src/backends/x11/meta-monitor-manager-xrandr.c
+@@ -999,7 +999,8 @@ static MetaMonitorManagerCapability
+ meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager)
+ {
+   return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING |
+-          META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED);
++          META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED |
++          META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT);
+ }
+ 
+ static gboolean
+-- 
+2.21.0
+
diff --git a/SOURCES/input-after-long-idle-fix.patch b/SOURCES/input-after-long-idle-fix.patch
new file mode 100644
index 0000000..9c4c2a6
--- /dev/null
+++ b/SOURCES/input-after-long-idle-fix.patch
@@ -0,0 +1,374 @@
+From 05bca153bb92c5daa5b961214ff7f80af88cb7cf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Thu, 24 Oct 2019 21:19:36 +0200
+Subject: [PATCH 1/2] display: Move finishing of touch sequence to the backend
+
+We need to manipulate an X11 grab when a touch sequence ends; move that
+logic to where it belongs - in the X11 backend.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
+---
+ src/backends/meta-backend-private.h     | 16 ++++++++++++
+ src/backends/meta-backend.c             | 14 +++++++++++
+ src/backends/x11/meta-backend-x11.c     | 23 +++++++++++++++++
+ src/core/display.c                      | 33 +++++++++++--------------
+ src/core/meta-gesture-tracker-private.h |  9 +------
+ 5 files changed, 69 insertions(+), 26 deletions(-)
+
+diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
+index 7eba1806b..81ec81e5f 100644
+--- a/src/backends/meta-backend-private.h
++++ b/src/backends/meta-backend-private.h
+@@ -49,6 +49,14 @@
+ #define DEFAULT_XKB_RULES_FILE "evdev"
+ #define DEFAULT_XKB_MODEL "pc105+inet"
+ 
++typedef enum
++{
++  META_SEQUENCE_NONE,
++  META_SEQUENCE_ACCEPTED,
++  META_SEQUENCE_REJECTED,
++  META_SEQUENCE_PENDING_END
++} MetaSequenceState;
++
+ struct _MetaBackendClass
+ {
+   GObjectClass parent_class;
+@@ -71,6 +79,10 @@ struct _MetaBackendClass
+                               int          device_id,
+                               uint32_t     timestamp);
+ 
++  void (* finish_touch_sequence) (MetaBackend          *backend,
++                                  ClutterEventSequence *sequence,
++                                  MetaSequenceState     state);
++
+   void (* warp_pointer) (MetaBackend *backend,
+                          int          x,
+                          int          y);
+@@ -135,6 +147,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
+                                      int          device_id,
+                                      uint32_t     timestamp);
+ 
++void meta_backend_finish_touch_sequence (MetaBackend          *backend,
++                                         ClutterEventSequence *sequence,
++                                         MetaSequenceState     state);
++
+ void meta_backend_warp_pointer (MetaBackend *backend,
+                                 int          x,
+                                 int          y);
+diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
+index c980cf150..bb7d66f2a 100644
+--- a/src/backends/meta-backend.c
++++ b/src/backends/meta-backend.c
+@@ -1086,6 +1086,20 @@ meta_backend_ungrab_device (MetaBackend *backend,
+   return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
+ }
+ 
++/**
++ * meta_backend_finish_touch_sequence: (skip)
++ */
++void
++meta_backend_finish_touch_sequence (MetaBackend          *backend,
++                                    ClutterEventSequence *sequence,
++                                    MetaSequenceState     state)
++{
++  if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
++    META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
++                                                             sequence,
++                                                             state);
++}
++
+ /**
+  * meta_backend_warp_pointer: (skip)
+  */
+diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
+index c10365f9d..cdefa50a9 100644
+--- a/src/backends/x11/meta-backend-x11.c
++++ b/src/backends/x11/meta-backend-x11.c
+@@ -591,6 +591,28 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
+   return (ret == Success);
+ }
+ 
++static void
++meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
++                                        ClutterEventSequence *sequence,
++                                        MetaSequenceState     state)
++{
++  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
++  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
++  int event_mode;
++
++  if (state == META_SEQUENCE_ACCEPTED)
++    event_mode = XIAcceptTouch;
++  else if (state == META_SEQUENCE_REJECTED)
++    event_mode = XIRejectTouch;
++  else
++    g_return_if_reached ();
++
++  XIAllowTouchEvents (priv->xdisplay,
++                      META_VIRTUAL_CORE_POINTER_ID,
++                      clutter_x11_event_sequence_get_touch_detail (sequence),
++                      DefaultRootWindow (priv->xdisplay), event_mode);
++}
++
+ static void
+ meta_backend_x11_warp_pointer (MetaBackend *backend,
+                                int          x,
+@@ -776,6 +798,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
+   backend_class->post_init = meta_backend_x11_post_init;
+   backend_class->grab_device = meta_backend_x11_grab_device;
+   backend_class->ungrab_device = meta_backend_x11_ungrab_device;
++  backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence;
+   backend_class->warp_pointer = meta_backend_x11_warp_pointer;
+   backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
+   backend_class->get_keymap = meta_backend_x11_get_keymap;
+diff --git a/src/core/display.c b/src/core/display.c
+index 4c8907f40..eb7dc43b6 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -42,6 +42,7 @@
+ #include <X11/extensions/Xdamage.h>
+ #include <X11/extensions/Xfixes.h>
+ 
++#include "backends/meta-backend-private.h"
+ #include "backends/meta-cursor-sprite-xcursor.h"
+ #include "backends/meta-cursor-tracker-private.h"
+ #include "backends/meta-idle-monitor-dbus.h"
+@@ -598,27 +599,23 @@ gesture_tracker_state_changed (MetaGestureTracker   *tracker,
+                                MetaSequenceState     state,
+                                MetaDisplay          *display)
+ {
+-  if (meta_is_wayland_compositor ())
++  switch (state)
+     {
+-      if (state == META_SEQUENCE_ACCEPTED)
+-        meta_display_cancel_touch (display);
+-    }
+-  else
+-    {
+-      MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
+-      int event_mode;
++    case META_SEQUENCE_NONE:
++    case META_SEQUENCE_PENDING_END:
++      return;
++    case META_SEQUENCE_ACCEPTED:
++      meta_display_cancel_touch (display);
+ 
+-      if (state == META_SEQUENCE_ACCEPTED)
+-        event_mode = XIAcceptTouch;
+-      else if (state == META_SEQUENCE_REJECTED)
+-        event_mode = XIRejectTouch;
+-      else
+-        return;
++      /* Intentional fall-through */
++    case META_SEQUENCE_REJECTED:
++      {
++        MetaBackend *backend;
+ 
+-      XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
+-                          META_VIRTUAL_CORE_POINTER_ID,
+-                          clutter_x11_event_sequence_get_touch_detail (sequence),
+-                          DefaultRootWindow (display->x11_display->xdisplay), event_mode);
++        backend = meta_get_backend ();
++        meta_backend_finish_touch_sequence (backend, sequence, state);
++        break;
++      }
+     }
+ }
+ 
+diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h
+index a9db35ebc..e7bfc5472 100644
+--- a/src/core/meta-gesture-tracker-private.h
++++ b/src/core/meta-gesture-tracker-private.h
+@@ -26,6 +26,7 @@
+ 
+ #include <glib-object.h>
+ 
++#include "backends/meta-backend-private.h"
+ #include "clutter/clutter.h"
+ #include "meta/window.h"
+ 
+@@ -39,14 +40,6 @@
+ typedef struct _MetaGestureTracker MetaGestureTracker;
+ typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
+ 
+-typedef enum
+-{
+-  META_SEQUENCE_NONE,
+-  META_SEQUENCE_ACCEPTED,
+-  META_SEQUENCE_REJECTED,
+-  META_SEQUENCE_PENDING_END
+-} MetaSequenceState;
+-
+ struct _MetaGestureTracker
+ {
+   GObject parent_instance;
+-- 
+2.23.0
+
+
+From 8cf4f500defb421d5c96f2c1f9fcf7bb5545d70d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Fri, 25 Oct 2019 10:06:55 +0200
+Subject: [PATCH 2/2] x11: Limit touch replay pointer events to when replaying
+
+When a touch sequence was rejected, the emulated pointer events would be
+replayed with old timestamps. This caused issues with grabs as they
+would be ignored due to being too old. This was mitigated by making sure
+device event timestamps never travelled back in time by tampering with
+any event that had a timestamp seemingly in the past.
+
+This failed when the most recent timestamp that had been received were
+much older than the timestamp of the new event. This could for example
+happen when a session was left not interacted with for 40+ days or so;
+when interacted with again, as any new timestamp would according to
+XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most
+recent" one. The effect is that we'd always use the `latest_evtime` for
+all new device events without ever updating it.
+
+The end result of this was that passive grabs would become active when
+interacted with, but would then newer be released, as the timestamps to
+XIAllowEvents() would out of date, resulting in the desktop effectively
+freezing, as the Shell would have an active pointer grab.
+
+To avoid the situation where we get stuck with an old `latest_evtime`
+timestamp, limit the tampering with device event timestamp to 1) only
+pointer events, and 2) only during the replay sequence. The second part
+is implemented by sending an asynchronous message via the X server after
+rejecting a touch sequence, only potentially tampering with the device
+event timestamps until the reply. This should avoid the stuck timestamp
+as in those situations, we'll always have a relatively up to date
+`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
+---
+ src/backends/x11/meta-backend-x11.c | 71 +++++++++++++++++++++++------
+ 1 file changed, 58 insertions(+), 13 deletions(-)
+
+diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
+index cdefa50a9..821b30f5b 100644
+--- a/src/backends/x11/meta-backend-x11.c
++++ b/src/backends/x11/meta-backend-x11.c
+@@ -66,6 +66,10 @@ struct _MetaBackendX11Private
+   XSyncAlarm user_active_alarm;
+   XSyncCounter counter;
+ 
++  int current_touch_replay_sync_serial;
++  int pending_touch_replay_sync_serial;
++  Atom touch_replay_sync_atom;
++
+   int xinput_opcode;
+   int xinput_event_base;
+   int xinput_error_base;
+@@ -174,6 +178,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
+   backend_x11_class->translate_device_event (x11, device_event);
+ }
+ 
++static void
++maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11,
++                                            XIDeviceEvent  *device_event)
++{
++  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
++
++  if (!device_event->send_event &&
++      device_event->time != META_CURRENT_TIME &&
++      priv->current_touch_replay_sync_serial !=
++      priv->pending_touch_replay_sync_serial &&
++      XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
++    {
++      /* Emulated pointer events received after XIRejectTouch is received
++       * on a passive touch grab will contain older timestamps, update those
++       * so we dont get InvalidTime at grabs.
++       */
++      device_event->time = priv->latest_evtime;
++    }
++}
++
+ static void
+ translate_device_event (MetaBackendX11 *x11,
+                         XIDeviceEvent  *device_event)
+@@ -183,19 +207,7 @@ translate_device_event (MetaBackendX11 *x11,
+   meta_backend_x11_translate_device_event (x11, device_event);
+ 
+   if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
+-    {
+-      if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
+-        {
+-          /* Emulated pointer events received after XIRejectTouch is received
+-           * on a passive touch grab will contain older timestamps, update those
+-           * so we dont get InvalidTime at grabs.
+-           */
+-          device_event->time = priv->latest_evtime;
+-        }
+-
+-      /* Update the internal latest evtime, for any possible later use */
+-      priv->latest_evtime = device_event->time;
+-    }
++    priv->latest_evtime = device_event->time;
+ }
+ 
+ static void
+@@ -260,6 +272,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
+     case XI_Motion:
+     case XI_ButtonPress:
+     case XI_ButtonRelease:
++      maybe_translate_touch_replay_pointer_event (x11,
++                                                  (XIDeviceEvent *) input_event);
++      /* Intentional fall-through */
+     case XI_KeyPress:
+     case XI_KeyRelease:
+     case XI_TouchBegin:
+@@ -327,6 +342,17 @@ handle_host_xevent (MetaBackend *backend,
+   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
+   gboolean bypass_clutter = FALSE;
+ 
++  switch (event->type)
++    {
++    case ClientMessage:
++      if (event->xclient.window == meta_backend_x11_get_xwindow (x11) &&
++          event->xclient.message_type == priv->touch_replay_sync_atom)
++        priv->current_touch_replay_sync_serial = event->xclient.data.l[0];
++      break;
++    default:
++      break;
++    }
++
+   XGetEventData (priv->xdisplay, &event->xcookie);
+ 
+   {
+@@ -534,6 +560,10 @@ meta_backend_x11_post_init (MetaBackend *backend)
+   monitor_manager = meta_backend_get_monitor_manager (backend);
+   g_signal_connect (monitor_manager, "monitors-changed-internal",
+                     G_CALLBACK (on_monitors_changed), backend);
++
++  priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
++                                              "_MUTTER_TOUCH_SEQUENCE_SYNC",
++                                              False);
+ }
+ 
+ static ClutterBackend *
+@@ -611,6 +641,21 @@ meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
+                       META_VIRTUAL_CORE_POINTER_ID,
+                       clutter_x11_event_sequence_get_touch_detail (sequence),
+                       DefaultRootWindow (priv->xdisplay), event_mode);
++
++  if (state == META_SEQUENCE_REJECTED)
++    {
++      XClientMessageEvent ev;
++
++      ev = (XClientMessageEvent) {
++        .type = ClientMessage,
++        .window = meta_backend_x11_get_xwindow (x11),
++        .message_type = priv->touch_replay_sync_atom,
++        .format = 32,
++        .data.l[0] = ++priv->pending_touch_replay_sync_serial,
++      };
++      XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11),
++                  False, 0, (XEvent *) &ev);
++    }
+ }
+ 
+ static void
+-- 
+2.23.0
+
diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec
new file mode 100644
index 0000000..9e14457
--- /dev/null
+++ b/SPECS/mutter.spec
@@ -0,0 +1,1301 @@
+%global gtk3_version 3.19.8
+%global glib_version 2.53.2
+%global gsettings_desktop_schemas_version 3.21.4
+%global json_glib_version 0.12.0
+%global libinput_version 1.4
+%global pipewire_version 0.2.2
+%global mutter_api_version 4
+
+Name:          mutter
+Version:       3.32.2
+Release:       34%{?dist}
+Summary:       Window and compositing manager based on Clutter
+
+License:       GPLv2+
+#VCS:          git:git://git.gnome.org/mutter
+URL:           http://www.gnome.org
+Source0:       http://download.gnome.org/sources/%{name}/3.32/%{name}-%{version}.tar.xz
+
+# Work-around for OpenJDK's compliance test
+Patch0:        0001-window-actor-Special-case-shaped-Java-windows.patch
+
+# Allow Xwayland grabs by default, on a selected set of X11 apps
+# https://bugzilla.redhat.com/1500399
+Patch1: 0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch
+
+Patch2: fix-text-selection-drawing.patch
+Patch3: covscan-fixes.patch
+Patch4: 0001-enum-types-Use-basename-in-header-comment.patch
+Patch5: 0001-workspace-manager-Expose-layout-properties.patch
+
+# Fix corruption on suspend and resume with nvidia (rhbz#1663440)
+Patch10001: 0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch
+Patch10002: 0002-backend-switch-to-using-generated-logind-proxy.patch
+Patch10003: 0003-backend-add-signals-for-reporting-suspend-and-resume.patch
+Patch10004: 0004-wayland-force-X-clients-to-redraw-on-resume.patch
+Patch10005: 0005-backends-native-emit-gl-video-memory-purged-when-bec.patch
+Patch10006: 0006-backends-native-update-glyph-cache-on-resume.patch
+Patch10007: 0007-backends-native-update-cursor-on-resume.patch
+Patch10008: 0008-background-purge-all-background-textures-on-suspend.patch
+Patch10009: 0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch
+
+# RHEL 7 downstream patches
+Patch100: deal-more-gracefully-with-oversized-windows.patch
+# Work-around for Xvnc resizing (rhbz#1265511)
+Patch101: 0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch
+Patch102: 0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch
+Patch103: 0001-monitor-manager-Consider-external-layout-before-defa.patch
+Patch104: 0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch
+Patch105: 0001-backends-x11-Support-synaptics-configuration.patch
+Patch107: 0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch
+# http://bugzilla.gnome.org/show_bug.cgi?id=733277
+Patch109: 0001-Add-support-for-quad-buffer-stereo.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=1618632
+# https://bugzilla.redhat.com/show_bug.cgi?id=1497303
+Patch110: 0001-monitor-manager-only-reuse-initial-config-if-monitor.patch
+Patch112: add-support-for-plain-old-x-device-configuration.patch
+Patch113: 0001-main-be-more-aggressive-in-assuming-X11-backend.patch
+Patch114: 0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch
+
+# Inherit xorg.conf (rhbz#1690506)
+Patch115: inherit-xrandr-metamodes.patch
+
+# Fix test blocker when running on cirrus (rhbz#1735382)
+Patch116: 0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch
+
+# Don't focus or activate unmanaging windows (rhbz#1741547)
+Patch117: 0001-workspace-Focus-only-ancestors-that-are-focusable.patch
+Patch118: 0002-window-Emit-an-error-and-return-when-trying-to-activ.patch
+
+# Don't freeze on rapid input (rhbz#1759525)
+Patch119: 0001-events-Sync-pending-pointer-events-without-a-window.patch
+
+# Don't freeze if input happens after many days of inactivity (rhbz#1766649)
+Patch120: input-after-long-idle-fix.patch
+
+# Fix invalid read in idle monitor (rhbz#1766695)
+Patch121: idle-monitor-reset-fix.patch
+
+# Improve shadow-fb performance on llvmpipe
+# https://bugzilla.redhat.com/1737553
+Patch201: 0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch
+Patch202: 0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch
+Patch203: 0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch
+Patch204: 0004-cogl-Relax-formats-on-glBlitFramebuffer.patch
+Patch205: 0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch
+Patch206: 0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch
+Patch207: 0007-cogl-Expose-cogl_blit_framebuffer.patch
+Patch208: 0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch
+Patch209: 0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch
+Patch210: 0010-cogl-Flush-journal-before-blitting.patch
+Patch211: 0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch
+Patch212: 0012-renderer-native-Separate-offscreen-and-shadowfb.patch
+
+# Handle lack of RANDR (#1776530)
+Patch250: 0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch
+Patch251: 0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch
+
+# Fix build due to egl.pc provider change
+Patch260: 0001-EGL-Include-EGL-eglmesaext.h.patch
+
+# Fix popups with styli
+Patch261: 0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch
+
+# Fix led-less pad mode switch buttons
+Patch262: 0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch
+
+# Wacom fixes
+Patch263: 0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch
+Patch264: 0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch
+Patch265: 0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch
+Patch266: 0001-backends-Check-both-input-settings-and-mapper-for-ta.patch
+Patch267: 0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch
+Patch268: 0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch
+Patch269: 0001-Skip-wacom-touchpads-when-updating-setting.patch
+
+# Revert stored-config behavior for VMs (#1365717)
+Patch280: 0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch
+
+# Respect xrandr --panning (#1690170)
+Patch281: 0001-crtc-xrandr-Respect-configured-RANDR-panning.patch
+
+# gnome-shell core dump after connection to docking station (#1809079)
+Patch282: handle-hotplug-better.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: pam-devel
+BuildRequires: pipewire-devel >= %{pipewire_version}
+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: xorg-x11-server-Xwayland
+
+Obsoletes: mutter-wayland < 3.13.0
+Obsoletes: mutter-wayland-devel < 3.13.0
+
+# Make sure yum updates gnome-shell as well; otherwise we might end up with
+# broken gnome-shell installations due to mutter ABI changes.
+Conflicts: gnome-shell < 3.21.1
+
+Requires: control-center-filesystem
+Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version}
+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}
+
+%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
+
+%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*
+
+%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
+* Thu Mar 05 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-34
+- gnome-shell core dump after connection to docking station
+  Resolves: #1809079
+
+* Mon Feb 24 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-33
+- Respect xrandr --panning
+  Resolves: #1690170
+
+* Mon Feb 24 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-32
+- Revert stored-config behavior for VMs
+  Resolves: #1365717
+
+* Mon Feb 24 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-31
+- Fixup detection of multiple mode switch buttons
+  Resolves: #1687979
+
+* Fri Feb 21 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-30
+- Avoid toggling wacom touchpads on tap-to-click/drag setting updates
+  Resolves: #1716754
+
+* Thu Feb 13 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-29
+- Fixup Wacom pad OSD so it appears on the right monitor
+  Resolves: #1777556
+
+* Thu Feb 13 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-28
+- Fixup automatic enabling of wacom touchpad tapping
+  Resolves: #1716754
+
+* Thu Feb 13 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-27
+- Fixup handling of multiple mode switch buttons in pads
+  Resolves: #1687979
+
+* Mon Dec 16 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-26
+- Let pad OSD update on mode switching
+  Resolves: #1716774
+
+* Fri Dec 13 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-25
+- Fix Wacom OSDs so they appear on the right monitor
+  Resolves: #1777556
+
+* Fri Dec 13 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-24
+- Handle multiple mode switch buttons in Cintiq 27QHD
+  Resolves: #1687979
+
+* Fri Dec 13 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-23
+- Enable tapping features by default on standalone Wacom tablets
+  Resolves: #1716754
+
+* Fri Dec 13 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-22
+- Fix detection of Wacom tablet features on X11
+  Resolves: #1759619
+
+* Wed Dec 04 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-21
+- Fix mode switch pad buttons without LEDs
+  Resolves: #1666070
+
+* Mon Dec 01 2019 Tomas Pelka <tpelka@redhat.com> - 3.32.2-20
+- Need rebuild in correct build target
+  Resolves: #1730891
+
+* Fri Nov 29 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-19
+- Fix pop ups with stylus input
+  Resolves: #1730891
+
+* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-18
+- Revert memory leak fix
+  Resolves: #1777911
+
+* Wed Nov 27 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.2-17
+- Fix some memory leaks
+  Resolves: #1719819
+
+* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-16
+- Fix build due to egl.pc provider change
+  Related: #1776530
+
+* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-15
+- Handle lack of RANDR
+  Resolves: #1776530
+
+* Mon Nov  4 2019 Olivier Fourdan <ofourdan@redhat.com> - 3.32.2-14
+- Backports shadow FB improvements on llvmpipe
+  Resolves: #1737553
+
+* Wed Oct 30 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-13
+- Fix invalid read in idle monitor
+  Resolves: #1766695
+
+* Wed Oct 30 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-12
+- Don't freeze if input happens after many days of inactivity
+  Resolves: #1766649
+
+* Fri Oct 25 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-11
+- Don't freeze on rapid input
+  Resolves: #1759525
+
+* Fri Aug 16 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-10
+- Don't focus or activate unmanaging windows
+  Resolves: #1741547
+
+* Mon Aug 05 2019 Ray Strode <rstrode@redhat.com> - 3.32.2-9
+- Another 16bpp graphics card crash
+  Related: #1735382
+  Resolves: #1737326
+
+* Fri Aug 02 2019 Ray Strode <rstrode@redhat.com> - 3.32.2-8
+- Fix crash in window icon handling on 16bpp graphics cards
+  Resolves: #1735382
+
+* Tue Jul 23 2019 Ray Strode <rstrode@redhat.com> - 3.32.2-7
+- Fix bug leading to 100% cpu usage on suspend/resume
+  Resolves: #1724551
+
+* Mon Jul 15 2019 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-6
+- Don't ignore current mode when deriving current config
+  Resolves: #1690506
+
+* Thu Jun 20 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-5
+- Ensure pad XDevices do not get buttons remapped
+  Resolves: #1687949
+
+* Wed Jun 12 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.2-4
+- Expose workspace layout as properties
+  Related: #1704360
+
+* Thu May 30 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.2-3
+- Avoid arch-specific bits in header comments
+  Related: #1698884
+* Tue May 28 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.2-2
+- Fix a couple of issues pointed out by covscan
+  Resolves: #1698884
+
+* Thu May 23 2019 Florian Müllner <fmuellner@redhat.com> - 3.32.2-1
+- Update to 3.32.2
+  Resolves: #1698884
+
+* Tue Apr 02 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.28.3-19
+- Fix synaptics/evdev driver support forward port to not break tablet pads
+  Resolves: #1687949
+
+* Thu Feb 21 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-18
+- Remove patch enabling monitor framebuffer scaling
+  Related: #1668883
+
+* Mon Feb 11 2019 Ray Strode <rstrode@redhat.com> - 3.28.3-17
+- Fix bug in suspend/resume corruption patch leading to inhibit fd
+  not getting fetched
+  Related: #1663440
+
+* Mon Feb 11 2019 Florian Müllner <fmuellner@redhat.com> - 3.28.3-16
+- Backport forward_key() method
+  Related: #1668979
+
+* Mon Feb 11 2019 Florian Müllner <fmuellner@redhat.com> - 3.28.3-15
+- Re-add dropped downstream patches (rhbz#1668883)
+
+* Tue Feb 05 2019 Olivier Fourdan <jadahl@redhat.com> - 3.28.3-14
+- Restore update monitor fix (rhbz#1635123)
+
+* Fri Feb 01 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-13
+- Fix screen recording on HiDPI monitor (rhbz#1670287)
+
+* Thu Jan 31 2019 Ray Strode <rstrode@redhat.com> - 3.28.3-12
+- Drop "Always update monitor for non user op" patch. It's already
+  in tree and getting misapplied
+  Related: #1663440
+- Fix suspend and resume corruption on NVidia
+  Resolves: #1663440
+
+* Tue Jan 22 2019 Olivier Fourdan <ofourdan@redhat.com> - 3.28.3-11
+- Fix a new crash in recordwindow related to behavior changes in
+  recent backport additions (rhbz#1657661)
+
+* Fri Jan 11 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-10
+- Backport screen cast cursor side channel patches (rhbz#1658971)
+
+* Fri Jan 11 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-9
+- Avoid EGLStream backend deadlock (rhbz#1656905)
+
+* Fri Jan 11 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-8
+- Get texture pixels via offscreen for EGLStreams (rhbz#1656926)
+
+* Mon Jan 07 2019 Olivier Fourdan <ofourdan@redhat.com> - 3.28.3-7
+- Backport the RecordWindow screencast mode (rhbz#1657661)
+
+* Fri Jan 04 2019 Ray Strode <rstrode@redhat.com> - 3.28.3-6
+- Add shadow framebuffer for server cards to fix blending
+  performance
+  Resolves: #1591250
+
+* Fri Oct 26 2018 Olivier Fourdan <ofourdan@redhat.com> - 3.28.3-5
+- Allow Xwayland grabs on a selected set of X11 applications.
+  (rhbz#1500399)
+
+* Tue Oct 23 2018 Olivier Fourdan <ofourdan@redhat.com> - 3.28.3-4
+- More backport fixes from upstream "gnome-3-28" branch
+- enable eglstream support (rhbz#1639782)
+
+* Mon Oct 15 2018 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-3
+- Fix garbled window titles (rhbz#1639194)
+
+* Thu Oct 04 2018 Olivier Fourdan <ofourdan@redhat.com> - 3.28.3-2
+- Backport fixes from upstream "gnome-3-28" branch:
+- [wayland] laptop with lid closed and external monitor can't log in to
+  wayland session (rhbz#1635106)
+- [Wayland] Crash with Xwayland grabs enabled in mutter (rhbz#1635110)
+- [Wayland] Crash on monitor hotplug (rhbz#1635123)
+- [wayland] mutter crashes if drmModeSetCrtc() failed (rhbz#1635155)
+- mutter crashes if a modal window closes whilst being dragged (rhbz#1635159)
+- gnome-shell crashed with SIGSEGV in meta_monitor_mode_get_resolution()
+  (rhbz#1635164)
+- [wayland] crash when drmModeGetResources() fails (rhbz#1635167)
+- [wayland] Can't create new back buffer on Intel i915 (rhbz#1635170)
+- [wayland] keyboard: Create a separate keymap shm file per resource
+  (rhbz#1635235)
+- Crash in gnome-shell/mutter after a window is destroyed (rhbz#1635237)
+- [x11] Using a cursor theme missing cursors can crash mutter (rhbz#1635241)
+- [wayland] Warning messages when starting mutter (rhbz#1635248)
+- [wayland] mutter/gnome-shell crash after failed DnD in nautilus
+  (rhbz#1635718)
+
+* Thu Aug 09 2018 Kalev Lember <klember@redhat.com> - 3.28.3-1
+- Update to 3.28.3
+- Apply HW cursor on-demand patches
+- Apply monitor transform regression patch
+
+* Wed Aug 08 2018 Jonas Ådahl <jadahl@redhat.com> - 3.28.1-4
+- Backport remote-access controller API patch
+
+* Tue Aug 07 2018 Jonas Ådahl <jadahl@redhat.com> - 3.28.1-3
+- Backport remote desktop related patches
+
+* Wed Aug 01 2018 Jan Grulich <jgrulich@redhat.com> - 3.28.1-2
+- Support PipeWire 0.2.2+
+
+* 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