diff --git a/SOURCES/0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch b/SOURCES/0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch
new file mode 100644
index 0000000..5f6473c
--- /dev/null
+++ b/SOURCES/0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch
@@ -0,0 +1,27 @@
+From 2a45b7de7cf5955b81cc1778dbb5085bfabb1c56 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Corentin=20No=C3=ABl?= <corentin@elementary.io>
+Date: Sat, 2 Jun 2018 19:16:32 +0100
+Subject: [PATCH] clutter-input-device-xi2: Check for null group_modes before
+ unref
+
+---
+ clutter/clutter/x11/clutter-input-device-xi2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c
+index f62ba85dcb..1254aca3ae 100644
+--- a/clutter/clutter/x11/clutter-input-device-xi2.c
++++ b/clutter/clutter/x11/clutter-input-device-xi2.c
+@@ -110,7 +110,8 @@ clutter_input_device_xi2_finalize (GObject *object)
+   if (device_xi2->wacom_device)
+     libwacom_destroy (device_xi2->wacom_device);
+ 
+-  g_array_unref (device_xi2->group_modes);
++  if (device_xi2->group_modes)
++    g_array_unref (device_xi2->group_modes);
+ #endif
+ 
+   G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object);
+-- 
+2.23.0.rc1
+
diff --git a/SOURCES/0001-compositor-Don-t-emit-size-changed-when-only-positio.patch b/SOURCES/0001-compositor-Don-t-emit-size-changed-when-only-positio.patch
new file mode 100644
index 0000000..0e04185
--- /dev/null
+++ b/SOURCES/0001-compositor-Don-t-emit-size-changed-when-only-positio.patch
@@ -0,0 +1,140 @@
+From a8d0870c6e9c9d2269c2b856cd2d83949fef4154 Mon Sep 17 00:00:00 2001
+From: Daniel van Vugt <daniel.van.vugt@canonical.com>
+Date: Tue, 7 May 2019 18:08:13 +0800
+Subject: [PATCH 1/2] compositor: Don't emit size-changed when only position
+ changes
+
+Waking up gnome-shell and triggering JavaScript listeners of
+`size-changed` every time a window was only moved was wasting a lot
+of CPU.
+
+This cuts the CPU requirement for dragging windows by around 22%.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/568
+---
+ src/compositor/compositor.c                |  8 +++-
+ src/compositor/meta-window-actor-private.h | 12 +++++-
+ src/compositor/meta-window-actor.c         | 43 ++++++++++++++++++----
+ 3 files changed, 52 insertions(+), 11 deletions(-)
+
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 8c924d256..abf7de57d 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -1070,8 +1070,12 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
+                                       gboolean did_placement)
+ {
+   MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
+-  meta_window_actor_sync_actor_geometry (window_actor, did_placement);
+-  meta_plugin_manager_event_size_changed (compositor->plugin_mgr, window_actor);
++  MetaWindowActorChanges changes;
++
++  changes = meta_window_actor_sync_actor_geometry (window_actor, did_placement);
++
++  if (changes & META_WINDOW_ACTOR_CHANGE_SIZE)
++    meta_plugin_manager_event_size_changed (compositor->plugin_mgr, window_actor);
+ }
+ 
+ static void
+diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
+index ce5e7eadc..acd649d07 100644
+--- a/src/compositor/meta-window-actor-private.h
++++ b/src/compositor/meta-window-actor-private.h
+@@ -12,6 +12,12 @@
+ 
+ MetaWindowActor *meta_window_actor_new (MetaWindow *window);
+ 
++typedef enum
++{
++  META_WINDOW_ACTOR_CHANGE_SIZE     = 1 << 0,
++  META_WINDOW_ACTOR_CHANGE_POSITION = 1 << 1
++} MetaWindowActorChanges;
++
+ void meta_window_actor_queue_destroy   (MetaWindowActor *self);
+ 
+ void meta_window_actor_show (MetaWindowActor *self,
+@@ -43,8 +49,10 @@ void     meta_window_actor_set_unredirected    (MetaWindowActor *self,
+                                                 gboolean         unredirected);
+ 
+ gboolean meta_window_actor_effect_in_progress  (MetaWindowActor *self);
+-void     meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
+-                                                gboolean         did_placement);
++
++MetaWindowActorChanges meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
++                                                              gboolean         did_placement);
++
+ void     meta_window_actor_update_shape        (MetaWindowActor *self);
+ void     meta_window_actor_update_opacity      (MetaWindowActor *self);
+ void     meta_window_actor_mapped              (MetaWindowActor *self);
+diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
+index 120b0432c..afe2bab6e 100644
+--- a/src/compositor/meta-window-actor.c
++++ b/src/compositor/meta-window-actor.c
+@@ -1299,12 +1299,14 @@ meta_window_actor_queue_destroy (MetaWindowActor *self)
+     clutter_actor_destroy (CLUTTER_ACTOR (self));
+ }
+ 
+-void
++MetaWindowActorChanges
+ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
+                                        gboolean         did_placement)
+ {
+   MetaWindowActorPrivate *priv = self->priv;
+   MetaRectangle window_rect;
++  ClutterActor *actor = CLUTTER_ACTOR (self);
++  MetaWindowActorChanges changes = 0;
+ 
+   meta_window_get_buffer_rect (priv->window, &window_rect);
+ 
+@@ -1322,15 +1324,42 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
+    * updates.
+    */
+   if (is_frozen (self) && !did_placement)
+-    return;
++    return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE;
+ 
+   if (meta_window_actor_effect_in_progress (self))
+-    return;
++    return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE;
++
++  if (clutter_actor_has_allocation (actor))
++    {
++      ClutterActorBox box;
++      float old_x, old_y;
++      float old_width, old_height;
++
++      clutter_actor_get_allocation_box (actor, &box);
++
++      old_x = box.x1;
++      old_y = box.y1;
++      old_width = box.x2 - box.x1;
++      old_height = box.y2 - box.y1;
++
++      if (old_x != window_rect.x || old_y != window_rect.y)
++        changes |= META_WINDOW_ACTOR_CHANGE_POSITION;
++
++      if (old_width != window_rect.width || old_height != window_rect.height)
++        changes |= META_WINDOW_ACTOR_CHANGE_SIZE;
++    }
++  else
++    {
++      changes = META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE;
++    }
++
++  if (changes & META_WINDOW_ACTOR_CHANGE_POSITION)
++    clutter_actor_set_position (actor, window_rect.x, window_rect.y);
++
++  if (changes & META_WINDOW_ACTOR_CHANGE_SIZE)
++    clutter_actor_set_size (actor, window_rect.width, window_rect.height);
+ 
+-  clutter_actor_set_position (CLUTTER_ACTOR (self),
+-                              window_rect.x, window_rect.y);
+-  clutter_actor_set_size (CLUTTER_ACTOR (self),
+-                          window_rect.width, window_rect.height);
++  return changes;
+ }
+ 
+ void
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-screen-Expose-workspace-layout-properties.patch b/SOURCES/0001-screen-Expose-workspace-layout-properties.patch
new file mode 100644
index 0000000..bc7ed96
--- /dev/null
+++ b/SOURCES/0001-screen-Expose-workspace-layout-properties.patch
@@ -0,0 +1,80 @@
+From 6b8e2636911c79d77d95aaac62336dd4f4063f63 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] screen: Expose workspace 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/screen.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/src/core/screen.c b/src/core/screen.c
+index c14bba0cf..4fac02cdb 100644
+--- a/src/core/screen.c
++++ b/src/core/screen.c
+@@ -81,6 +81,9 @@ static void on_monitors_changed          (MetaMonitorManager *manager,
+ enum
+ {
+   PROP_N_WORKSPACES = 1,
++
++  PROP_LAYOUT_COLUMNS,
++  PROP_LAYOUT_ROWS,
+ };
+ 
+ enum
+@@ -138,6 +141,12 @@ meta_screen_get_property (GObject      *object,
+ 
+   switch (prop_id)
+     {
++    case PROP_LAYOUT_COLUMNS:
++      g_value_set_int (value, screen->columns_of_workspaces);
++      break;
++    case PROP_LAYOUT_ROWS:
++      g_value_set_int (value, screen->rows_of_workspaces);
++      break;
+     case PROP_N_WORKSPACES:
+       g_value_set_int (value, meta_screen_get_n_workspaces (screen));
+       break;
+@@ -261,6 +270,22 @@ meta_screen_class_init (MetaScreenClass *klass)
+                   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_PARAM_STATIC_STRINGS));
++
++  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_PARAM_STATIC_STRINGS));
++
+   g_object_class_install_property (object_class,
+                                    PROP_N_WORKSPACES,
+                                    pspec);
+@@ -1753,6 +1778,8 @@ meta_screen_update_workspace_layout (MetaScreen *screen)
+                 screen->columns_of_workspaces,
+                 screen->vertical_workspaces,
+                 screen->starting_corner);
++  g_object_notify (G_OBJECT (screen), "layout-columns");
++  g_object_notify (G_OBJECT (screen), "layout-rows");
+ }
+ 
+ /**
+-- 
+2.21.0
+
diff --git a/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch b/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch
new file mode 100644
index 0000000..f7ce445
--- /dev/null
+++ b/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch
@@ -0,0 +1,38 @@
+From ad1a395707f7c37b26ce446f0fd73ac7fbb9d0fd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Tue, 9 Oct 2018 00:40:33 +0200
+Subject: [PATCH 1/2] x11/window-props: Do not convert WM_NAME
+
+The WM_NAME property is of type TEXT_PROPERTY, which is supposed to be
+returned as UTF-8. Commit 840378ae68 broke that assumption, resulting
+in crashes with non-UTF8 locales; however the "fix" of converting from
+LATIN1 to UTF8 is wrong as well, as the conversion will spit out garbage
+when the input encoding isn't actually LATIN1.
+
+Now that the original issue in text_property_to_utf8() has been fixed,
+we can simply revert the relevant bits of commit d62491f46eba748e.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/227
+---
+ src/x11/window-props.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/src/x11/window-props.c b/src/x11/window-props.c
+index 2f4dfeb31..7c6b25fdb 100644
+--- a/src/x11/window-props.c
++++ b/src/x11/window-props.c
+@@ -645,10 +645,7 @@ reload_wm_name (MetaWindow    *window,
+ 
+   if (value->type != META_PROP_VALUE_INVALID)
+     {
+-      g_autofree gchar *title = g_convert (value->v.str, -1,
+-                                           "UTF-8", "LATIN1",
+-                                           NULL, NULL, NULL);
+-      set_window_title (window, title);
++      set_window_title (window, value->v.str);
+ 
+       meta_verbose ("Using WM_NAME for new title of %s: \"%s\"\n",
+                     window->desc, window->title);
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch b/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch
new file mode 100644
index 0000000..3bdd6e8
--- /dev/null
+++ b/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch
@@ -0,0 +1,60 @@
+From dcf0717d7d90ff525c4f87cf633353caabf0eeeb Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 10 Aug 2018 21:30:58 +0200
+Subject: [PATCH 2/2] clutter: Avoid relayouts when raising/lowering children
+
+These calls don't actually affect the layout, but the paint order.
+It seems safe to skip the full relayout/repaint of the parent actor,
+and redraw only the area occupied by the affected child.
+---
+ clutter/clutter/clutter-actor.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
+index 6954f0396..7a9da7257 100644
+--- a/clutter/clutter/clutter-actor.c
++++ b/clutter/clutter/clutter-actor.c
+@@ -1713,6 +1713,22 @@ set_show_on_set_parent (ClutterActor *self,
+     }
+ }
+ 
++static void
++clutter_actor_queue_redraw_on_parent (ClutterActor *self)
++{
++  const ClutterPaintVolume *pv;
++
++  if (!self->priv->parent)
++    return;
++
++  /* A relayout/redraw is underway */
++  if (self->priv->needs_allocation)
++    return;
++
++  pv = clutter_actor_get_transformed_paint_volume (self, self->priv->parent);
++  _clutter_actor_queue_redraw_with_clip (self->priv->parent, 0, pv);
++}
++
+ /**
+  * clutter_actor_show:
+  * @self: A #ClutterActor
+@@ -13618,7 +13634,7 @@ clutter_actor_set_child_above_sibling (ClutterActor *self,
+                                     sibling);
+   g_object_unref(child);
+ 
+-  clutter_actor_queue_relayout (self);
++  clutter_actor_queue_redraw_on_parent (child);
+ }
+ 
+ /**
+@@ -13665,7 +13681,7 @@ clutter_actor_set_child_below_sibling (ClutterActor *self,
+                                     sibling);
+   g_object_unref(child);
+ 
+-  clutter_actor_queue_relayout (self);
++  clutter_actor_queue_redraw_on_parent (child);
+ }
+ 
+ /**
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch b/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch
new file mode 100644
index 0000000..6178049
--- /dev/null
+++ b/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch
@@ -0,0 +1,44 @@
+From 5881b87be4432ca1c50ee0652634883110b487de Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Tue, 9 Oct 2018 00:29:01 +0200
+Subject: [PATCH 2/2] xprops: Make sure text_property_to_utf8() returns UTF8
+
+Commit 840378ae682 changed the code to use XmbTextPropertyToTextList()
+instead of gdk_text_property_to_utf8_list_for_display(), but didn't
+take into account that the replacement returns text in the current
+locale's encoding, while any callers (rightfully) expect UTF8.
+
+Fix this by converting the text if necessary.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/227
+---
+ src/x11/xprops.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/x11/xprops.c b/src/x11/xprops.c
+index cffa5958a..ca686b2fa 100644
+--- a/src/x11/xprops.c
++++ b/src/x11/xprops.c
+@@ -637,6 +637,7 @@ text_property_to_utf8 (Display *xdisplay,
+ {
+   char *ret = NULL;
+   char **local_list = NULL;
++  const char *charset = NULL;
+   int count = 0;
+   int res;
+ 
+@@ -647,7 +648,10 @@ text_property_to_utf8 (Display *xdisplay,
+   if (count == 0)
+     goto out;
+ 
+-  ret = g_strdup (local_list[0]);
++  if (g_get_charset (&charset))
++    ret = g_strdup (local_list[0]);
++  else
++    ret = g_convert (local_list[0], -1, "UTF-8", charset, NULL, NULL, NULL);
+ 
+  out:
+   XFreeStringList (local_list);
+-- 
+2.21.0
+
diff --git a/SOURCES/idle-monitor-reset-fix.patch b/SOURCES/idle-monitor-reset-fix.patch
new file mode 100644
index 0000000..411b625
--- /dev/null
+++ b/SOURCES/idle-monitor-reset-fix.patch
@@ -0,0 +1,128 @@
+From 23c81629d775fd902e4bee7ec0a182a916f4252b 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 82f3f87b7..9ce7e743a 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 2c06ee73c..ce1b87bbb 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;
+@@ -319,7 +319,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;
+@@ -506,7 +506,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 0d43bbdae0a08c7618e789fa0d5270615c907a36 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 ce1b87bbb..3dbb89944 100644
+--- a/src/backends/meta-idle-monitor.c
++++ b/src/backends/meta-idle-monitor.c
+@@ -506,7 +506,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 f6c24dd45c14dd16d6878ebf170f8468ad3d47e1 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 3dbb89944..c6e814468 100644
+--- a/src/backends/meta-idle-monitor.c
++++ b/src/backends/meta-idle-monitor.c
+@@ -319,9 +319,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/input-after-long-idle-fix.patch b/SOURCES/input-after-long-idle-fix.patch
index 1f26abd..d211ff9 100644
--- a/SOURCES/input-after-long-idle-fix.patch
+++ b/SOURCES/input-after-long-idle-fix.patch
@@ -1,4 +1,4 @@
-From a86f1085d1f5056fb4b19f1d7f72a1905122cc24 Mon Sep 17 00:00:00 2001
+From 388ed4984586f96250934a025b1c78915c4cd856 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
@@ -211,7 +211,7 @@ index e3b702f56..1313aad6d 100644
 2.23.0
 
 
-From 651a45057bce8d1dd8d493d1f6a0486e04d6571b Mon Sep 17 00:00:00 2001
+From 75cf52ac533675ecf5d3542e9fba2937a56bfefd 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
@@ -246,11 +246,11 @@ as in those situations, we'll always have a relatively up to date
 
 https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
 ---
- src/backends/x11/meta-backend-x11.c | 67 +++++++++++++++++++++++------
- 1 file changed, 54 insertions(+), 13 deletions(-)
+ 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 2835d47d6..7b8ff1b94 100644
+index 2835d47d6..3f8645e93 100644
 --- a/src/backends/x11/meta-backend-x11.c
 +++ b/src/backends/x11/meta-backend-x11.c
 @@ -60,6 +60,10 @@ struct _MetaBackendX11Private
@@ -351,28 +351,25 @@ index 2835d47d6..7b8ff1b94 100644
  }
  
  static ClutterBackend *
-@@ -591,6 +621,7 @@ meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
-   MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-   int event_mode;
-+  XClientMessageEvent ev;
- 
-   if (state == META_SEQUENCE_ACCEPTED)
-     event_mode = XIAcceptTouch;
-@@ -603,6 +634,16 @@ meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
+@@ -603,6 +633,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);
 +
-+  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);
++  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
diff --git a/SOURCES/more-performance-backports.patch b/SOURCES/more-performance-backports.patch
new file mode 100644
index 0000000..17db38d
--- /dev/null
+++ b/SOURCES/more-performance-backports.patch
@@ -0,0 +1,186 @@
+From f86e33e1ea32c4208809e8de33bed05ddbce9a4c Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Sun, 7 May 2017 03:00:10 +0200
+Subject: [PATCH 1/3] compositor: Avoid changing pipeline/source if shadow is
+ not being painted
+
+Avoids some context invalidations in cogl.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=782344
+---
+ src/compositor/meta-shadow-factory.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/src/compositor/meta-shadow-factory.c b/src/compositor/meta-shadow-factory.c
+index cd006008b..19147ca9f 100644
+--- a/src/compositor/meta-shadow-factory.c
++++ b/src/compositor/meta-shadow-factory.c
+@@ -220,9 +220,7 @@ meta_shadow_paint (MetaShadow     *shadow,
+   int dest_x[4];
+   int dest_y[4];
+   int n_x, n_y;
+-
+-  cogl_pipeline_set_color4ub (shadow->pipeline,
+-                              opacity, opacity, opacity, opacity);
++  gboolean source_updated = FALSE;
+ 
+   cogl_set_source (shadow->pipeline);
+ 
+@@ -300,6 +298,17 @@ meta_shadow_paint (MetaShadow     *shadow,
+           else
+             overlap = CAIRO_REGION_OVERLAP_IN;
+ 
++          if (overlap == CAIRO_REGION_OVERLAP_OUT)
++            continue;
++
++          if (!source_updated)
++            {
++              cogl_pipeline_set_color4ub (shadow->pipeline,
++                                          opacity, opacity, opacity, opacity);
++              cogl_set_source (shadow->pipeline);
++              source_updated = TRUE;
++            }
++
+           /* There's quite a bit of overhead from allocating a new
+            * region in order to find an exact intersection and
+            * generating more geometry - we make the assumption that
+-- 
+2.23.0
+
+
+From f530bc4c3391cabe2b084cd59def00d81c13286c Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Fri, 5 May 2017 14:15:30 +0200
+Subject: [PATCH 2/3] clutter: Avoid rounding compensation when invalidating 2D
+ actors
+
+This allows the redraw clip to be more constrained, so MetaCullable doesn't
+end up rendering portions of window shadows, frame and background when a
+window invalidates (part of) its contents.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=782344
+---
+ clutter/clutter/clutter-paint-volume.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/clutter/clutter/clutter-paint-volume.c b/clutter/clutter/clutter-paint-volume.c
+index b48f7f9d6..f3405138b 100644
+--- a/clutter/clutter/clutter-paint-volume.c
++++ b/clutter/clutter/clutter-paint-volume.c
+@@ -1166,6 +1166,21 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
+ 
+   _clutter_paint_volume_get_bounding_box (&projected_pv, box);
+ 
++  if (pv->is_2d && pv->actor &&
++      clutter_actor_get_z_position (pv->actor) == 0)
++    {
++      /* If the volume/actor are perfectly 2D, take the bounding box as
++       * good. We won't need to add any extra room for sub-pixel positioning
++       * in this case.
++       */
++      clutter_paint_volume_free (&projected_pv);
++      box->x1 = CLUTTER_NEARBYINT (box->x1);
++      box->y1 = CLUTTER_NEARBYINT (box->y1);
++      box->x2 = CLUTTER_NEARBYINT (box->x2);
++      box->y2 = CLUTTER_NEARBYINT (box->y2);
++      return;
++    }
++
+   /* The aim here is that for a given rectangle defined with floating point
+    * coordinates we want to determine a stable quantized size in pixels
+    * that doesn't vary due to the original box's sub-pixel position.
+-- 
+2.23.0
+
+
+From 676369000658c6121d0c3b5e1286aa68dc79eb35 Mon Sep 17 00:00:00 2001
+From: Carlos Garnacho <carlosg@gnome.org>
+Date: Mon, 8 May 2017 15:10:58 +0200
+Subject: [PATCH 3/3] cogl: Ensure to only clear the depth buffer if depth
+ testing is enabled
+
+The depth buffer is marked as invalid when 1) the framebuffer is just created,
+and 2) whenever GL_DEPTH_TEST is enabled on it. This will ensure the
+framebuffers attached depth buffer (if any) is properly cleared before it's
+actually used, while saving needless clears while depth testing is disabled
+(the default).
+
+https://bugzilla.gnome.org/show_bug.cgi?id=782344
+---
+ cogl/cogl/cogl-framebuffer-private.h       |  5 +++++
+ cogl/cogl/cogl-framebuffer.c               | 11 +++++++++++
+ cogl/cogl/driver/gl/cogl-pipeline-opengl.c |  6 +++++-
+ 3 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
+index 99ac2fba9..756e34dfe 100644
+--- a/cogl/cogl/cogl-framebuffer-private.h
++++ b/cogl/cogl/cogl-framebuffer-private.h
+@@ -193,6 +193,11 @@ struct _CoglFramebuffer
+   CoglFramebufferBits bits;
+ 
+   int                 samples_per_pixel;
++
++  /* Whether the depth buffer was enabled for this framebuffer,
++   * usually means it needs to be cleared before being reused next.
++   */
++  CoglBool            depth_buffer_clear_needed;
+ };
+ 
+ typedef enum {
+diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
+index 55b9e3756..6b105087d 100644
+--- a/cogl/cogl/cogl-framebuffer.c
++++ b/cogl/cogl/cogl-framebuffer.c
+@@ -117,6 +117,7 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
+   framebuffer->viewport_age_for_scissor_workaround = -1;
+   framebuffer->dither_enabled = TRUE;
+   framebuffer->depth_writing_enabled = TRUE;
++  framebuffer->depth_buffer_clear_needed = TRUE;
+ 
+   framebuffer->modelview_stack = cogl_matrix_stack_new (ctx);
+   framebuffer->projection_stack = cogl_matrix_stack_new (ctx);
+@@ -268,6 +269,13 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
+   int scissor_y1;
+   CoglBool saved_viewport_scissor_workaround;
+ 
++  if (!framebuffer->depth_buffer_clear_needed &&
++      (buffers & COGL_BUFFER_BIT_DEPTH))
++    buffers &= ~(COGL_BUFFER_BIT_DEPTH);
++
++  if (buffers == 0)
++    return;
++
+   _cogl_clip_stack_get_bounds (clip_stack,
+                                &scissor_x0, &scissor_y0,
+                                &scissor_x1, &scissor_y1);
+@@ -415,6 +423,9 @@ cleared:
+   _cogl_framebuffer_mark_mid_scene (framebuffer);
+   _cogl_framebuffer_mark_clear_clip_dirty (framebuffer);
+ 
++  if (buffers & COGL_BUFFER_BIT_DEPTH)
++    framebuffer->depth_buffer_clear_needed = FALSE;
++
+   if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
+     {
+       /* For our fast-path for reading back a single pixel of simple
+diff --git a/cogl/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c
+index 178269646..4f1f69f96 100644
+--- a/cogl/cogl/driver/gl/cogl-pipeline-opengl.c
++++ b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c
+@@ -418,7 +418,11 @@ flush_depth_state (CoglContext *ctx,
+   if (ctx->depth_test_enabled_cache != depth_state->test_enabled)
+     {
+       if (depth_state->test_enabled == TRUE)
+-        GE (ctx, glEnable (GL_DEPTH_TEST));
++        {
++          GE (ctx, glEnable (GL_DEPTH_TEST));
++          if (ctx->current_draw_buffer)
++            ctx->current_draw_buffer->depth_buffer_clear_needed = TRUE;
++        }
+       else
+         GE (ctx, glDisable (GL_DEPTH_TEST));
+       ctx->depth_test_enabled_cache = depth_state->test_enabled;
+-- 
+2.23.0
+
diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec
index 5b356ee..efaedff 100644
--- a/SPECS/mutter.spec
+++ b/SPECS/mutter.spec
@@ -10,7 +10,7 @@
 
 Name:          mutter
 Version:       3.28.3
-Release:       14%{?dist}
+Release:       20%{?dist}
 Summary:       Window and compositing manager based on Clutter
 
 License:       GPLv2+
@@ -49,6 +49,9 @@ Patch32: 0001-clutter-Do-not-latch-modifiers-on-modifier-keys.patch
 # Prevent titlebar from going off-screen (rhbz#1664407)
 Patch33: 0001-constraints-Fix-titlebars-going-off-the-bottom.patch
 
+# Classic classic mode support
+Patch34: 0001-screen-Expose-workspace-layout-properties.patch
+
 # el7 patches
 Patch100: 0001-Revert-build-Require-libgudev-232.patch
 Patch101: 0001-rhel7-Fix-build-for-el7.patch
@@ -78,15 +81,32 @@ Patch262: 0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch
 Patch270: 0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch
 Patch271: 0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch
 
-# Don't loose pointer button grabs (#1756263)
-Patch272: 0001-events-Sync-pending-pointer-events-without-a-window.patch
+# Fix crash in meta_monitor_mode_get_resolution() (#1638727)
+Patch272: 0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch
+Patch273: 0002-window-Return-1-if-meta_window_get_monitor-is-called.patch
+
+# Fix crash on device removal (#1578186)
+Patch274: 0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch
+
+# Backport two performance improvement patches (#1737515)
+Patch275: 0001-compositor-Don-t-emit-size-changed-when-only-positio.patch
+Patch276: 0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch
+
+# Backport window title encoding bug fixes (#1630686)
+Patch277: 0001-x11-window-props-Do-not-convert-WM_NAME.patch
+Patch278: 0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch
 
-# Fix crash in meta_monitor_mode_get_resolution() (#1760738)
-Patch273: 0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch
-Patch274: 0002-window-Return-1-if-meta_window_get_monitor-is-called.patch
+# Don't loose pointer button grabs (#1657887)
+Patch279: 0001-events-Sync-pending-pointer-events-without-a-window.patch
 
-# Don't freeze if input happens after many days of inactivity (#1778212)
-Patch275: input-after-long-idle-fix.patch
+# Don't freeze if input happens after many days of inactivity (#1728761)
+Patch280: input-after-long-idle-fix.patch
+
+# More performance backports (#1766501)
+Patch281: more-performance-backports.patch
+
+#  Fix invalid read in idle monitor (#1752378)
+Patch282: idle-monitor-reset-fix.patch
 
 # Prevent orphaned animation actors getting stuck on screen (#1753799)
 Patch 283: 0001-window-free-close-dialog-before-unmanaging-window-fr.patch
@@ -246,21 +266,45 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
 %{_libdir}/pkgconfig/*
 
 %changelog
-* Thu Dec 12 2019 Florian Müllner <fmuellner@redhat.com> - 3.28.3-14
+* Tue Dec 03 2019 Florian Müllner <fmuellner@redhat.com> - 3.28.3-20
 - Free close dialog before unmanaging parent
-  Related: #1780030
+  Related: #1753799
 
-* Tue Dec 03 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-13
-- Don't freeze if input happens after many days of inactivity
-  Resolves: #1778212
+* Tue Oct 29 2019 Jonas Ådahl <jadahl@redhat.com>) - 3.28.3-19
+- Fix invalid read in idle monitor
+  Resolves: #1752378
 
-* Fri Oct 11 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-12
-- Fix crash in meta_monitor_mode_get_resolution()
-  Resolves #1760738
+* Tue Oct 29 2019  Jonas Ådahl <jadahl@redhat.com>) - 3.28.3-18
+- More performance backports
+  Resolves: #1766501
 
-* Wed Oct 02 2019 Jonas Ådahl <jadahl@redhat.com>) - 3.28.3-11
+* Tue Oct 29 2019  Jonas Ådahl <jadahl@redhat.com>) - 3.28.3-17
+- Don't freeze if input happens after many days of inactivity
+  Resolves: #1728761
+
+* Wed Oct 02 2019 Jonas Ådahl <jadahl@redhat.com>) - 3.28.3-16
 - Don't loose pointer button grabs
-  Resolves: #1756263
+  Resolves: #1657887
+
+* Sun Aug 25 2019 Florian MÜllner <fmuellner@redhat.com> - 3.28.3-15
+- Expose workspace layout as properties
+  Related: #1720286
+
+* Thu Aug 15 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-14
+- Backport window title encoding bug fixes
+  Resolves: #1630686
+
+* Mon Aug 12 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-13
+- Backport two performance improvement patches.
+  Resolves #1737515
+
+* Wed Aug 07 2019 Carlos garnacho <cgarnach@redhat.com> - 3.28.3-12
+- Fix crash on input device removal
+  Resolves: #1578186
+
+* Mon Aug 05 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-11
+- Fix crash in meta_monitor_mode_get_resolution()
+  Resolves #1638727
 
 * Wed Apr 17 2019 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-10
 - Fix idle monitor race condition