Marco Trevisan (Treviño) has proposed merging 
~3v1n0/ubuntu/+source/mutter:ubuntu/bionic into 
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic.

Requested reviews:
  Ubuntu Desktop (ubuntu-desktop)
Related bugs:
  Bug #1791574 in gnome-shell (Ubuntu): "gnome-shell crashed with SIGABRT: 
assertion failed "window->display->focus_window != window" in 
meta_window_unmanage"
  https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
  Bug #1832869 in gnome-shell (Ubuntu): "gnome-shell crashed with SIGSEGV in 
g_hash_table_iter_next → meta_display_list_windows → 
meta_workspace_list_windows → ffi_call_SYSV → ffi_call()"
  https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1832869

For more details, see:
https://code.launchpad.net/~3v1n0/ubuntu/+source/mutter/+git/mutter/+merge/369334

Upstream cherry-picks and crash fix
-- 
Your team Ubuntu Desktop is requested to review the proposed merge of 
~3v1n0/ubuntu/+source/mutter:ubuntu/bionic into 
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic.
diff --git a/debian/changelog b/debian/changelog
index 62c0624..8ab7c4c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,28 @@
+mutter (3.28.4-0ubuntu18.04.2) UNRELEASED; urgency=medium
+
+  * d/p/cogl-pipeline-Don-t-try-to-access-to-free-d-pointer-data.patch,
+    d/p/cursor-renderer-native-Free-MetaCursorNativePrivate-struc.patch:
+    - Fix memory errors causing tests to fail
+  * d/p/debian/skip-failing-tests-325.patch,
+    d/p/debian/skip-failing-tests.patch:
+    - Refreshed and enabled 'actor-pick' test as it doesn't fail anymore as
+      the errors are fixed by the patches above
+  * d/p/test-runner-Add-assert_focused-command.patch,
+    d/p/test-runner-Add-dispatch-command.patch,
+    d/p/test-runner-Add-sleep-command.patch,
+    d/p/tests-Add-accept_focus-command-to-runner-and-client.patch,
+    d/p/tests-Add-can_take_focus-command-to-runner-and-client.patch,
+    d/p/tests-Verify-focused-window-in-closed-transient-tests.patch,
+    d/p/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch,
+    d/p/window-x11-Focus-the-default-window-with-delay-while-wait.patch,
+    d/p/workspace-Focus-only-ancestors-that-are-focusable.patch:
+    - Don't crash when try to focus unfocusable windows (LP: #1791574)
+  *  d/p/screen-Destroy-window-actors-after-windows-while-unmanagi.patch,
+     d/p/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch:
+     - Unmanage window actors before destroying screen (LP: #1832869)
+
+ -- Marco Trevisan (Treviño) <ma...@ubuntu.com>  Wed, 26 Jun 2019 13:24:18 +0200
+
 mutter (3.28.4-0ubuntu18.04.1) bionic; urgency=medium
 
   * New upstream release:
diff --git a/debian/patches/cogl-pipeline-Don-t-try-to-access-to-free-d-pointer-data.patch b/debian/patches/cogl-pipeline-Don-t-try-to-access-to-free-d-pointer-data.patch
new file mode 100644
index 0000000..9dca63c
--- /dev/null
+++ b/debian/patches/cogl-pipeline-Don-t-try-to-access-to-free-d-pointer-data.patch
@@ -0,0 +1,46 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Fri, 17 May 2019 21:35:46 +0200
+Subject: cogl/pipeline: Don't try to access to free'd pointer data
+
+When free'ing a pipeline we destroy the BigState first and then the fragment and
+vertex snippets lists using the big state pointer which is now invalid.
+This causes a crash  when G_SLICE=always-malloc is set and using MALLOC_CHECK_.
+
+So, invert the operations by free'ing the snippet lists first, and the big state
+afterwards.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+
+(cherry picked from commit 7e0d185120ea116c91a8db60276971d3fecece80)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/8d936a41
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+Applied-Upstream: 3.28.5
+---
+ cogl/cogl/cogl-pipeline.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/cogl/cogl/cogl-pipeline.c b/cogl/cogl/cogl-pipeline.c
+index da2d2ce..6a77cda 100644
+--- a/cogl/cogl/cogl-pipeline.c
++++ b/cogl/cogl/cogl-pipeline.c
+@@ -492,9 +492,6 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
+       _cogl_bitmask_destroy (&uniforms_state->changed_mask);
+     }
+ 
+-  if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
+-    g_slice_free (CoglPipelineBigState, pipeline->big_state);
+-
+   if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
+     {
+       g_list_foreach (pipeline->layer_differences,
+@@ -508,6 +505,9 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
+   if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS)
+     _cogl_pipeline_snippet_list_free (&pipeline->big_state->fragment_snippets);
+ 
++  if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
++    g_slice_free (CoglPipelineBigState, pipeline->big_state);
++
+   g_list_free (pipeline->deprecated_get_layers_list);
+ 
+   recursively_free_layer_caches (pipeline);
diff --git a/debian/patches/cursor-renderer-native-Free-MetaCursorNativePrivate-struc.patch b/debian/patches/cursor-renderer-native-Free-MetaCursorNativePrivate-struc.patch
new file mode 100644
index 0000000..47abac4
--- /dev/null
+++ b/debian/patches/cursor-renderer-native-Free-MetaCursorNativePrivate-struc.patch
@@ -0,0 +1,29 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Fri, 17 May 2019 21:46:33 +0200
+Subject: cursor-renderer-native: Free MetaCursorNativePrivate struct
+
+Fix a small leak in native renderer.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+
+(cherry picked from commit b016ff29f638b04d1a756b82c461563207083391)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/9b8a3fba
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+Applied-Upstream: 3.28.5
+---
+ src/backends/native/meta-cursor-renderer-native.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
+index c7326af..0967ddb 100644
+--- a/src/backends/native/meta-cursor-renderer-native.c
++++ b/src/backends/native/meta-cursor-renderer-native.c
+@@ -710,6 +710,7 @@ static void
+ cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
+ {
+   g_hash_table_destroy (cursor_priv->gpu_states);
++  g_free (cursor_priv);
+ }
+ 
+ static MetaCursorNativePrivate *
diff --git a/debian/patches/debian/skip-failing-tests-325.patch b/debian/patches/debian/skip-failing-tests-325.patch
index 54d8f62..4bdaf1e 100644
--- a/debian/patches/debian/skip-failing-tests-325.patch
+++ b/debian/patches/debian/skip-failing-tests-325.patch
@@ -1,5 +1,5 @@
 From: Jeremy Bicha <jbi...@ubuntu.com>
-Date: Thu, 31 Aug 2017 07:11:39 -0400
+Date: Thu, 31 Aug 2017 13:11:39 +0200
 Subject: Skip test that started failing with 3.25
 
 That way we can still benefit by running all the other tests.
@@ -11,7 +11,7 @@ Applied-upstream: no
  1 file changed, 1 deletion(-)
 
 diff --git a/clutter/tests/conform/Makefile.am b/clutter/tests/conform/Makefile.am
-index 840e120..2bd7f4d 100644
+index cf59b96..6d7a6ba 100644
 --- a/clutter/tests/conform/Makefile.am
 +++ b/clutter/tests/conform/Makefile.am
 @@ -25,7 +25,6 @@ actor_tests = \
@@ -20,5 +20,5 @@ index 840e120..2bd7f4d 100644
  	actor-meta \
 -	actor-offscreen-redirect \
  	actor-paint-opacity \
+ 	actor-pick \
  	actor-size \
- 	$(NULL)
diff --git a/debian/patches/debian/skip-failing-tests.patch b/debian/patches/debian/skip-failing-tests.patch
index 205962c..a75fb55 100644
--- a/debian/patches/debian/skip-failing-tests.patch
+++ b/debian/patches/debian/skip-failing-tests.patch
@@ -1,25 +1,23 @@
 From: Jeremy Bicha <jbi...@ubuntu.com>
-Date: Fri, 5 May 2017 08:26:36 -0500
+Date: Fri, 5 May 2017 15:26:36 +0200
 Subject: Don't run failing tests
 
 That way we can still benefit by running all the other tests.
 
 Bug: https://bugzilla.gnome.org/782215
-Bug: https://bugzilla.gnome.org/753836
 Applied-upstream: no
 ---
- clutter/tests/conform/Makefile.am | 2 --
- 1 file changed, 2 deletions(-)
+ clutter/tests/conform/Makefile.am | 1 -
+ 1 file changed, 1 deletion(-)
 
 diff --git a/clutter/tests/conform/Makefile.am b/clutter/tests/conform/Makefile.am
-index afa9dad..840e120 100644
+index afa9dad..cf59b96 100644
 --- a/clutter/tests/conform/Makefile.am
 +++ b/clutter/tests/conform/Makefile.am
-@@ -27,8 +27,6 @@ actor_tests = \
- 	actor-meta \
+@@ -28,7 +28,6 @@ actor_tests = \
  	actor-offscreen-redirect \
  	actor-paint-opacity \
--	actor-pick \
+ 	actor-pick \
 -	actor-shader-effect \
  	actor-size \
  	$(NULL)
diff --git a/debian/patches/screen-Destroy-window-actors-after-windows-while-unmanagi.patch b/debian/patches/screen-Destroy-window-actors-after-windows-while-unmanagi.patch
new file mode 100644
index 0000000..df77116
--- /dev/null
+++ b/debian/patches/screen-Destroy-window-actors-after-windows-while-unmanagi.patch
@@ -0,0 +1,105 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 25 Jun 2019 20:22:23 +0200
+Subject: screen: Destroy window actors after windows while unmanaging
+ compositor
+
+After commit 2e64457f4 we destroy window actors as part of compositor
+destruction, however this might emit 'actor-removed' signals on window groups
+that the shell could use to access to resources that are already free'd at this
+point (like the destroyed screen, in gnome-shell's Panel._updateSolidStyle()).
+
+So, move the actor destructions under in a new function and destroy the window
+actors as part of compositor unmanage step, just after that all the windows are
+unmanaged (as they need to have an actor around).
+
+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/652
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/653
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/652
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1832869
+---
+ src/compositor/compositor-private.h |  2 ++
+ src/compositor/compositor.c         | 30 +++++++++++++++++-------------
+ src/core/screen.c                   |  3 +++
+ 3 files changed, 22 insertions(+), 13 deletions(-)
+
+diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
+index 4669bc5..d07d54f 100644
+--- a/src/compositor/compositor-private.h
++++ b/src/compositor/compositor-private.h
+@@ -73,4 +73,6 @@ MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *composito
+ MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
+                                                                               MetaWindow     *window);
+ 
++void _meta_compositor_unmanage_window_actors (MetaCompositor *compositor);
++
+ #endif /* META_COMPOSITOR_PRIVATE_H */
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 2545d2c..158acb5 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -145,19 +145,6 @@ meta_compositor_destroy (MetaCompositor *compositor)
+   clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
+   clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
+ 
+-  if (compositor->top_window_actor)
+-    {
+-      g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
+-                                            on_top_window_actor_destroyed,
+-                                            compositor);
+-      compositor->top_window_actor = NULL;
+-    }
+-
+-  g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
+-  g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
+-  g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
+-  g_clear_pointer (&compositor->windows, g_list_free);
+-
+   if (compositor->have_x11_sync_object)
+     meta_sync_ring_destroy ();
+ }
+@@ -610,6 +597,23 @@ meta_compositor_unmanage (MetaCompositor *compositor)
+     }
+ }
+ 
++void
++_meta_compositor_unmanage_window_actors (MetaCompositor *compositor)
++{
++  if (compositor->top_window_actor)
++    {
++      g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
++                                            on_top_window_actor_destroyed,
++                                            compositor);
++      compositor->top_window_actor = NULL;
++    }
++
++  g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
++  g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
++  g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
++  g_clear_pointer (&compositor->windows, g_list_free);
++}
++
+ /**
+  * meta_shape_cow_for_window:
+  * @compositor: A #MetaCompositor
+diff --git a/src/core/screen.c b/src/core/screen.c
+index d7623f3..d0daf97 100644
+--- a/src/core/screen.c
++++ b/src/core/screen.c
+@@ -41,6 +41,7 @@
+ #include "stack.h"
+ #include <meta/compositor.h>
+ #include <meta/meta-enum-types.h>
++#include "compositor-private.h"
+ #include "core.h"
+ #include "meta-cursor-tracker-private.h"
+ #include "boxes-private.h"
+@@ -844,6 +845,8 @@ meta_screen_free (MetaScreen *screen,
+ 
+   meta_display_unmanage_windows_for_screen (display, screen, timestamp);
+ 
++  _meta_compositor_unmanage_window_actors (display->compositor);
++
+   meta_prefs_remove_listener (prefs_changed_callback, screen);
+ 
+   meta_screen_ungrab_keys (screen);
diff --git a/debian/patches/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch b/debian/patches/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch
new file mode 100644
index 0000000..77cbb84
--- /dev/null
+++ b/debian/patches/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch
@@ -0,0 +1,42 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 25 Jun 2019 20:22:54 +0200
+Subject: screen: Unset the active workspace and remove workspaces on free
+
+Related to https://gitlab.gnome.org/GNOME/mutter/issues/652
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/653
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/652
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1832869
+---
+ src/core/screen.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/src/core/screen.c b/src/core/screen.c
+index d0daf97..6ebc863 100644
+--- a/src/core/screen.c
++++ b/src/core/screen.c
+@@ -836,6 +836,7 @@ meta_screen_free (MetaScreen *screen,
+                   guint32     timestamp)
+ {
+   MetaDisplay *display;
++  GList *l;
+ 
+   display = screen->display;
+ 
+@@ -877,6 +878,16 @@ meta_screen_free (MetaScreen *screen,
+ 
+   g_free (screen->screen_name);
+ 
++  screen->active_workspace = NULL;
++
++  for (l = screen->workspaces; l;)
++    {
++      MetaWorkspace *workspace = l->data;
++      l = l->next;
++
++      meta_workspace_remove (workspace);
++    }
++
+   g_object_unref (screen);
+ }
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 5bf1aa6..5727177 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,15 @@
+cursor-renderer-native-Free-MetaCursorNativePrivate-struc.patch
+wayland-seat-Use-g_free-to-cleanup-MetaWaylandSeat.patch
+cogl-pipeline-Don-t-try-to-access-to-free-d-pointer-data.patch
+workspace-Focus-only-ancestors-that-are-focusable.patch
+tests-Add-accept_focus-command-to-runner-and-client.patch
+tests-Add-can_take_focus-command-to-runner-and-client.patch
+tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch
+test-runner-Add-assert_focused-command.patch
+tests-Verify-focused-window-in-closed-transient-tests.patch
+test-runner-Add-sleep-command.patch
+test-runner-Add-dispatch-command.patch
+window-x11-Focus-the-default-window-with-delay-while-wait.patch
 theme-use-gtk_render_icon_suface-to-paint-button-icon.patch
 theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch
 clutter-Fix-offscreen-effect-painting-of-clones.patch
@@ -9,3 +21,5 @@ lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
 debian/synaptics-support.patch
 debian/skip-failing-tests.patch
 debian/skip-failing-tests-325.patch
+screen-Destroy-window-actors-after-windows-while-unmanagi.patch
+screen-Unset-the-active-workspace-and-remove-workspaces-o.patch
diff --git a/debian/patches/test-runner-Add-assert_focused-command.patch b/debian/patches/test-runner-Add-assert_focused-command.patch
new file mode 100644
index 0000000..55ddb44
--- /dev/null
+++ b/debian/patches/test-runner-Add-assert_focused-command.patch
@@ -0,0 +1,75 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 08:37:14 +0100
+Subject: test-runner: Add 'assert_focused' command
+
+This allows to verify which window should have the focus, which might not
+be the same as the top of the stack.
+
+It's possible to assert the case where there's no focused window using
+"NONE" as parameter.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit 51f9e04ef1fa8cd7298044ac8c82e83bea425770)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/1dd0799c
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/tests/test-runner.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
+index 37befb4..9056d9a 100644
+--- a/src/tests/test-runner.c
++++ b/src/tests/test-runner.c
+@@ -273,6 +273,37 @@ test_case_assert_stacking (TestCase *test,
+   return *error == NULL;
+ }
+ 
++static gboolean
++test_case_assert_focused (TestCase    *test,
++                          const char  *expected_window,
++                          GError     **error)
++{
++  MetaDisplay *display = meta_get_display ();
++
++  if (!display->focus_window)
++    {
++      if (g_strcmp0 (expected_window, "none") != 0)
++        {
++          g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
++                       "focus: expected='%s', actual='none'", expected_window);
++        }
++    }
++  else
++    {
++      const char *focused = display->focus_window->title;
++
++      if (g_str_has_prefix (focused, "test/"))
++        focused += 5;
++
++      if (g_strcmp0 (focused, expected_window) != 0)
++        g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
++                     "focus: expected='%s', actual='%s'",
++                     expected_window, focused);
++    }
++
++  return *error == NULL;
++}
++
+ static gboolean
+ test_case_check_xserver_stacking (TestCase *test,
+                                   GError  **error)
+@@ -496,6 +527,11 @@ test_case_do (TestCase *test,
+       if (!test_case_check_xserver_stacking (test, error))
+         return FALSE;
+     }
++  else if (strcmp (argv[0], "assert_focused") == 0)
++    {
++      if (!test_case_assert_focused (test, argv[1], error))
++        return FALSE;
++    }
+   else
+     {
+       BAD_COMMAND("Unknown command %s", argv[0]);
diff --git a/debian/patches/test-runner-Add-dispatch-command.patch b/debian/patches/test-runner-Add-dispatch-command.patch
new file mode 100644
index 0000000..12cd309
--- /dev/null
+++ b/debian/patches/test-runner-Add-dispatch-command.patch
@@ -0,0 +1,83 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Fri, 21 Jun 2019 13:15:48 +0200
+Subject: test-runner: Add 'dispatch' command
+
+This will only wait for events to be dispatched and processed by the server
+without waiting for client processing.
+
+Reuse the code for the wait command too.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit 6022b23923fa6192c630920e9f895f185977beee)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/0060ddc5
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/tests/test-runner.c | 38 ++++++++++++++++++++++++++++----------
+ 1 file changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
+index 75732c6..cdeaba2 100644
+--- a/src/tests/test-runner.c
++++ b/src/tests/test-runner.c
+@@ -122,6 +122,24 @@ test_case_loop_quit (gpointer data)
+   return FALSE;
+ }
+ 
++static gboolean
++test_case_dispatch (TestCase *test,
++                    GError  **error)
++{
++  /* Wait until we've done any outstanding queued up work.
++   * Though we add this as BEFORE_REDRAW, the iteration that runs the
++   * BEFORE_REDRAW idles will proceed on and do the redraw, so we're
++   * waiting until after *all* frame processing.
++   */
++  meta_later_add (META_LATER_BEFORE_REDRAW,
++                  test_case_loop_quit,
++                  test,
++                  NULL);
++  g_main_loop_run (test->loop);
++
++  return TRUE;
++}
++
+ static gboolean
+ test_case_wait (TestCase *test,
+                 GError  **error)
+@@ -138,16 +156,8 @@ test_case_wait (TestCase *test,
+     if (!test_client_wait (value, error))
+       return FALSE;
+ 
+-  /* Then wait until we've done any outstanding queued up work.
+-   * Though we add this as BEFORE_REDRAW, the iteration that runs the
+-   * BEFORE_REDRAW idles will proceed on and do the redraw, so we're
+-   * waiting until after *all* frame processing.
+-   */
+-  meta_later_add (META_LATER_BEFORE_REDRAW,
+-                  test_case_loop_quit,
+-                  test,
+-                  NULL);
+-  g_main_loop_run (test->loop);
++  /* Then wait until we've done any outstanding queued up work. */
++  test_case_dispatch (test, error);
+ 
+   /* Then set an XSync counter ourselves and and wait until
+    * we receive the resulting event - this makes sure that we've
+@@ -530,6 +540,14 @@ test_case_do (TestCase *test,
+       if (!test_case_wait (test, error))
+         return FALSE;
+     }
++  else if (strcmp (argv[0], "dispatch") == 0)
++    {
++      if (argc != 1)
++        BAD_COMMAND("usage: %s", argv[0]);
++
++      if (!test_case_dispatch (test, error))
++        return FALSE;
++    }
+   else if (strcmp (argv[0], "sleep") == 0)
+     {
+       guint64 interval;
diff --git a/debian/patches/test-runner-Add-sleep-command.patch b/debian/patches/test-runner-Add-sleep-command.patch
new file mode 100644
index 0000000..19aee93
--- /dev/null
+++ b/debian/patches/test-runner-Add-sleep-command.patch
@@ -0,0 +1,81 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 18 Jun 2019 19:33:10 +0200
+Subject: test-runner: Add 'sleep' command
+
+This allows to sleep for a given timeout in milliseconds.
+
+Rename test_case_before_redraw to test_case_loop_quit since it's a generic
+function and use it for the timeout too.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit d08763c18cb25fe250b27bf296e1607e63e86400)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/8dd564ad
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/tests/test-runner.c | 29 +++++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
+index 9056d9a..75732c6 100644
+--- a/src/tests/test-runner.c
++++ b/src/tests/test-runner.c
+@@ -113,7 +113,7 @@ test_case_new (void)
+ }
+ 
+ static gboolean
+-test_case_before_redraw (gpointer data)
++test_case_loop_quit (gpointer data)
+ {
+   TestCase *test = data;
+ 
+@@ -144,7 +144,7 @@ test_case_wait (TestCase *test,
+    * waiting until after *all* frame processing.
+    */
+   meta_later_add (META_LATER_BEFORE_REDRAW,
+-                  test_case_before_redraw,
++                  test_case_loop_quit,
+                   test,
+                   NULL);
+   g_main_loop_run (test->loop);
+@@ -157,6 +157,17 @@ test_case_wait (TestCase *test,
+   return TRUE;
+ }
+ 
++static gboolean
++test_case_sleep (TestCase  *test,
++                 guint32    interval,
++                 GError   **error)
++{
++  g_timeout_add_full (G_PRIORITY_LOW, interval, test_case_loop_quit, test, NULL);
++  g_main_loop_run (test->loop);
++
++  return TRUE;
++}
++
+ #define BAD_COMMAND(...)                                                \
+   G_STMT_START {                                                        \
+       g_set_error (error,                                               \
+@@ -519,6 +530,20 @@ test_case_do (TestCase *test,
+       if (!test_case_wait (test, error))
+         return FALSE;
+     }
++  else if (strcmp (argv[0], "sleep") == 0)
++    {
++      guint64 interval;
++
++      if (argc != 2)
++        BAD_COMMAND("usage: %s <milliseconds>", argv[0]);
++
++      if (!g_ascii_string_to_unsigned (argv[1], 10, 0, G_MAXUINT32,
++                                       &interval, error))
++        return FALSE;
++
++      if (!test_case_sleep (test, (guint32) interval, error))
++        return FALSE;
++    }
+   else if (strcmp (argv[0], "assert_stacking") == 0)
+     {
+       if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
diff --git a/debian/patches/tests-Add-accept_focus-command-to-runner-and-client.patch b/debian/patches/tests-Add-accept_focus-command-to-runner-and-client.patch
new file mode 100644
index 0000000..5e82d7a
--- /dev/null
+++ b/debian/patches/tests-Add-accept_focus-command-to-runner-and-client.patch
@@ -0,0 +1,77 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 03:43:57 +0100
+Subject: tests: Add 'accept_focus' command to runner and client
+
+Under the hood, calls gtk_window_set_accept_focus in the client
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit e1f839f48f8e49c826ba558fbc9d6842a156b28b)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/93f268a4
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/tests/test-client.c | 18 ++++++++++++++++++
+ src/tests/test-runner.c | 19 +++++++++++++++++++
+ 2 files changed, 37 insertions(+)
+
+diff --git a/src/tests/test-client.c b/src/tests/test-client.c
+index 5836083..1870fd2 100644
+--- a/src/tests/test-client.c
++++ b/src/tests/test-client.c
+@@ -161,6 +161,24 @@ process_line (const char *line)
+       gtk_window_set_transient_for (GTK_WINDOW (window),
+                                     GTK_WINDOW (parent_window));
+     }
++  else if (strcmp (argv[0], "accept_focus") == 0)
++    {
++      if (argc != 3)
++        {
++          g_print ("usage: %s <window-id> [true|false]", argv[0]);
++          goto out;
++        }
++
++      GtkWidget *window = lookup_window (argv[1]);
++      if (!window)
++        {
++          g_print ("unknown window %s", argv[1]);
++          goto out;
++        }
++
++      gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
++      gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
++    }
+   else if (strcmp (argv[0], "show") == 0)
+     {
+       if (argc != 2)
+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
+index 8867945..613c0bb 100644
+--- a/src/tests/test-runner.c
++++ b/src/tests/test-runner.c
+@@ -406,6 +406,25 @@ test_case_do (TestCase *test,
+                            NULL))
+         return FALSE;
+     }
++  else if (strcmp (argv[0], "accept_focus") == 0)
++    {
++      if (argc != 3 ||
++          (g_ascii_strcasecmp (argv[2], "true") != 0 &&
++           g_ascii_strcasecmp (argv[2], "false") != 0))
++        BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
++                    argv[0]);
++
++      TestClient *client;
++      const char *window_id;
++      if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
++        return FALSE;
++
++      if (!test_client_do (client, error,
++                           argv[0], window_id,
++                           argv[2],
++                           NULL))
++        return FALSE;
++    }
+   else if (strcmp (argv[0], "show") == 0 ||
+            strcmp (argv[0], "hide") == 0 ||
+            strcmp (argv[0], "activate") == 0 ||
diff --git a/debian/patches/tests-Add-can_take_focus-command-to-runner-and-client.patch b/debian/patches/tests-Add-can_take_focus-command-to-runner-and-client.patch
new file mode 100644
index 0000000..ebcae9d
--- /dev/null
+++ b/debian/patches/tests-Add-can_take_focus-command-to-runner-and-client.patch
@@ -0,0 +1,115 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 04:04:22 +0100
+Subject: tests: Add 'can_take_focus' command to runner and client
+
+Allow to set/unset WM_TAKE_FOCUS from client window.
+This is added by default by gtk, but this might not happen in other toolkits,
+so add an ability to (un)set this.
+
+So fetch the protocols with XGetWMProtocols and unset the atom.
+
+test-client now needs to depend on Xlib directly in meson build.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit f2d2d473b71dbdb339c80f068c5cb3e529af2478)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/ac1503a5
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/tests/test-client.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/tests/test-runner.c | 19 +++++++++++++++++++
+ 2 files changed, 69 insertions(+)
+
+diff --git a/src/tests/test-client.c b/src/tests/test-client.c
+index 1870fd2..aa763d5 100644
+--- a/src/tests/test-client.c
++++ b/src/tests/test-client.c
+@@ -179,6 +179,56 @@ process_line (const char *line)
+       gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
+       gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
+     }
++  else if (strcmp (argv[0], "can_take_focus") == 0)
++    {
++      if (argc != 3)
++        {
++          g_print ("usage: %s <window-id> [true|false]", argv[0]);
++          goto out;
++        }
++
++      GtkWidget *window = lookup_window (argv[1]);
++      if (!window)
++        {
++          g_print ("unknown window %s", argv[1]);
++          goto out;
++        }
++
++      if (wayland)
++        {
++          g_print ("%s not supported under wayland", argv[0]);
++          goto out;
++        }
++
++      GdkDisplay *display = gdk_display_get_default ();
++      GdkWindow *gdkwindow = gtk_widget_get_window (window);
++      Display *xdisplay = gdk_x11_display_get_xdisplay (display);
++      Window xwindow = GDK_WINDOW_XID (gdkwindow);
++      Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
++      gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0;
++      Atom *protocols = NULL;
++      Atom *new_protocols;
++      int n_protocols = 0;
++      int i, n = 0;
++
++      gdk_display_sync (display);
++      XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols);
++      new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0));
++
++      for (i = 0; i < n_protocols; ++i)
++        {
++          if (protocols[i] != wm_take_focus)
++            new_protocols[n++] = protocols[i];
++        }
++
++      if (add)
++        new_protocols[n++] = wm_take_focus;
++
++      XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
++
++      XFree (new_protocols);
++      XFree (protocols);
++    }
+   else if (strcmp (argv[0], "show") == 0)
+     {
+       if (argc != 2)
+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
+index 613c0bb..37befb4 100644
+--- a/src/tests/test-runner.c
++++ b/src/tests/test-runner.c
+@@ -425,6 +425,25 @@ test_case_do (TestCase *test,
+                            NULL))
+         return FALSE;
+     }
++  else if (strcmp (argv[0], "can_take_focus") == 0)
++    {
++      if (argc != 3 ||
++          (g_ascii_strcasecmp (argv[2], "true") != 0 &&
++           g_ascii_strcasecmp (argv[2], "false") != 0))
++        BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
++                    argv[0]);
++
++      TestClient *client;
++      const char *window_id;
++      if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
++        return FALSE;
++
++      if (!test_client_do (client, error,
++                           argv[0], window_id,
++                           argv[2],
++                           NULL))
++        return FALSE;
++    }
+   else if (strcmp (argv[0], "show") == 0 ||
+            strcmp (argv[0], "hide") == 0 ||
+            strcmp (argv[0], "activate") == 0 ||
diff --git a/debian/patches/tests-Verify-focused-window-in-closed-transient-tests.patch b/debian/patches/tests-Verify-focused-window-in-closed-transient-tests.patch
new file mode 100644
index 0000000..9dee9fc
--- /dev/null
+++ b/debian/patches/tests-Verify-focused-window-in-closed-transient-tests.patch
@@ -0,0 +1,63 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 08:45:56 +0100
+Subject: tests: Verify focused window in closed-transient tests
+
+Ensure that we have a focused window when closing transient windows with
+no-focus or no-take-focus atoms
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit fcb408ad5d8d7fec3e6a7bdaa92e5ef06b55c2c6)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/556d36ba
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ .../closed-transient-no-input-no-take-focus-parent.metatest |  2 ++
+ ...closed-transient-no-input-no-take-focus-parents.metatest | 13 ++++++++++---
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
+index 4249c32..0c0649c 100644
+--- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
+@@ -13,9 +13,11 @@ set_parent 1/3 2
+ show 1/3
+ 
+ wait
++assert_focused 1/3
+ assert_stacking 1/1 1/2 1/3
+ 
+ destroy 1/3
+ 
+ wait
++assert_focused 1/1
+ assert_stacking 1/1 1/2
+diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
+index a61c640..6556803 100644
+--- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
+@@ -1,3 +1,8 @@
++new_client 2 x11
++create 2/1
++show 2/1
++wait
++
+ new_client 1 x11
+ create 1/1
+ accept_focus 1/1 false
+@@ -15,9 +20,11 @@ set_parent 1/3 2
+ show 1/3
+ 
+ wait
+-assert_stacking 1/1 1/2 1/3
++assert_focused 1/3
++assert_stacking 2/1 1/1 1/2 1/3
+ 
+ destroy 1/3
+-wait
+ 
+-assert_stacking 1/1 1/2
++wait
++assert_stacking 1/1 1/2 2/1
++assert_focused 2/1
diff --git a/debian/patches/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch b/debian/patches/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch
new file mode 100644
index 0000000..58f86ae
--- /dev/null
+++ b/debian/patches/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch
@@ -0,0 +1,124 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 07:48:53 +0100
+Subject: tests, stacking: Add tests with no-input and no-take-focus windows
+
+When a window with no frame, that doesn't accept focus and that has no
+take-focus atom set is destroyed, we ended up in not changing the current_focus
+window, causing a crash.
+
+Added test cases that verify this situation.
+
+Related to https://gitlab.gnome.org/GNOME/mutter/issues/308
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit 2fc7760ceed6f948d4f3c1dd74d4e57c7df05eea)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/1ebf3218
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/Makefile-tests.am                              |  3 +++
+ ...ransient-no-input-no-take-focus-parent.metatest | 21 ++++++++++++++++++++
+ ...ansient-no-input-no-take-focus-parents.metatest | 23 ++++++++++++++++++++++
+ .../closed-transient-no-input-parent.metatest      | 20 +++++++++++++++++++
+ 4 files changed, 67 insertions(+)
+ create mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
+ create mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
+ create mode 100644 src/tests/stacking/closed-transient-no-input-parent.metatest
+
+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
+index 4be832c..3764917 100644
+--- a/src/Makefile-tests.am
++++ b/src/Makefile-tests.am
+@@ -15,6 +15,9 @@ dist_stacking_DATA =				\
+ 	tests/stacking/basic-x11.metatest	\
+ 	tests/stacking/basic-wayland.metatest	\
+ 	tests/stacking/closed-transient.metatest	\
++	tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest	\
++	tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest	\
++	tests/stacking/closed-transient-no-input-parent.metatest	\
+ 	tests/stacking/minimized.metatest   	\
+ 	tests/stacking/mixed-windows.metatest   \
+ 	tests/stacking/set-parent.metatest	\
+diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
+new file mode 100644
+index 0000000..4249c32
+--- /dev/null
++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
+@@ -0,0 +1,21 @@
++new_client 1 x11
++create 1/1
++show 1/1
++
++create 1/2 csd
++set_parent 1/2 1
++can_take_focus 1/2 false
++accept_focus 1/2 false
++show 1/2
++
++create 1/3 csd
++set_parent 1/3 2
++show 1/3
++
++wait
++assert_stacking 1/1 1/2 1/3
++
++destroy 1/3
++
++wait
++assert_stacking 1/1 1/2
+diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
+new file mode 100644
+index 0000000..a61c640
+--- /dev/null
++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
+@@ -0,0 +1,23 @@
++new_client 1 x11
++create 1/1
++accept_focus 1/1 false
++can_take_focus 1/1 false
++show 1/1
++
++create 1/2 csd
++set_parent 1/2 1
++can_take_focus 1/2 false
++accept_focus 1/2 false
++show 1/2
++
++create 1/3 csd
++set_parent 1/3 2
++show 1/3
++
++wait
++assert_stacking 1/1 1/2 1/3
++
++destroy 1/3
++wait
++
++assert_stacking 1/1 1/2
+diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest
+new file mode 100644
+index 0000000..4cadb23
+--- /dev/null
++++ b/src/tests/stacking/closed-transient-no-input-parent.metatest
+@@ -0,0 +1,20 @@
++new_client 1 x11
++create 1/1
++show 1/1
++
++create 1/2 csd
++set_parent 1/2 1
++accept_focus 1/2 false
++show 1/2
++
++create 1/3 csd
++set_parent 1/3 2
++show 1/3
++
++wait
++assert_stacking 1/1 1/2 1/3
++
++destroy 1/3
++
++wait
++assert_stacking 1/1 1/2
diff --git a/debian/patches/wayland-seat-Use-g_free-to-cleanup-MetaWaylandSeat.patch b/debian/patches/wayland-seat-Use-g_free-to-cleanup-MetaWaylandSeat.patch
new file mode 100644
index 0000000..7977827
--- /dev/null
+++ b/debian/patches/wayland-seat-Use-g_free-to-cleanup-MetaWaylandSeat.patch
@@ -0,0 +1,31 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Fri, 17 May 2019 21:56:31 +0200
+Subject: wayland-seat: Use g_free to cleanup MetaWaylandSeat
+
+MetaWaylandSeat is allocated using g_new0(), and thus we should use g_free() to
+destroy it.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+
+(cherry picked from commit 040578657309a515df4c73b51a068140ad477f03)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/fc74c7de
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
+Applied-Upstream: 3.28.5
+---
+ src/wayland/meta-wayland-seat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
+index 7c86739..445f4c6 100644
+--- a/src/wayland/meta-wayland-seat.c
++++ b/src/wayland/meta-wayland-seat.c
+@@ -264,7 +264,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
+   g_object_unref (seat->touch);
+   meta_wayland_text_input_destroy (seat->text_input);
+ 
+-  g_slice_free (MetaWaylandSeat, seat);
++  g_free (seat);
+ }
+ 
+ static gboolean
diff --git a/debian/patches/window-x11-Focus-the-default-window-with-delay-while-wait.patch b/debian/patches/window-x11-Focus-the-default-window-with-delay-while-wait.patch
new file mode 100644
index 0000000..91da5b1
--- /dev/null
+++ b/debian/patches/window-x11-Focus-the-default-window-with-delay-while-wait.patch
@@ -0,0 +1,246 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Wed, 14 Nov 2018 00:08:34 +0100
+Subject: window-x11: Focus the default window with delay while waiting for
+ take-focus
+
+When requesting to a take-focus window to acquire the input, the client may or
+may not respond with a SetInputFocus (this doesn't happen for no-input gtk
+windows in fact [to be fixed there too]), in such case we were unsetting the
+focus while waiting the reply.
+
+In case the client won't respond, we wait for a small delay (set to 250 ms) for
+the take-focus window to grab the input focus before setting it to the default
+window.
+
+Added a test for this behavior and for the case in which a window takes the
+focus meanwhile we're waiting to focus the default window.
+
+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
+(cherry picked from commit f71151a5dd990d935f3fbb39451f9b41f640b625)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/b462e519
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ src/Makefile-tests.am                              |   1 +
+ ...parent-delayed-focus-default-cancelled.metatest |  36 ++++++++
+ .../closed-transient-no-input-parent.metatest      |  16 +++-
+ src/x11/window-x11.c                               | 101 ++++++++++++++++++++-
+ 4 files changed, 146 insertions(+), 8 deletions(-)
+ create mode 100644 src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest
+
+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
+index 3764917..eca6a7b 100644
+--- a/src/Makefile-tests.am
++++ b/src/Makefile-tests.am
+@@ -18,6 +18,7 @@ dist_stacking_DATA =				\
+ 	tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest	\
+ 	tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest	\
+ 	tests/stacking/closed-transient-no-input-parent.metatest	\
++	tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest	\
+ 	tests/stacking/minimized.metatest   	\
+ 	tests/stacking/mixed-windows.metatest   \
+ 	tests/stacking/set-parent.metatest	\
+diff --git a/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest b/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest
+new file mode 100644
+index 0000000..38897e3
+--- /dev/null
++++ b/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest
+@@ -0,0 +1,36 @@
++new_client 2 x11
++create 2/1
++show 2/1
++
++new_client 1 x11
++create 1/1
++show 1/1
++
++create 1/2 csd
++set_parent 1/2 1
++accept_focus 1/2 false
++show 1/2
++
++create 1/3 csd
++set_parent 1/3 2
++show 1/3
++
++wait
++assert_focused 1/3
++assert_stacking 2/1 1/1 1/2 1/3
++
++destroy 1/3
++sleep 10
++
++assert_focused none
++assert_stacking 2/1 1/1 1/2
++
++activate 2/1
++wait
++
++assert_focused 2/1
++assert_stacking 1/1 1/2 2/1
++
++sleep 250
++assert_focused 2/1
++assert_stacking 1/1 1/2 2/1
+diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest
+index 4cadb23..e0f1dc1 100644
+--- a/src/tests/stacking/closed-transient-no-input-parent.metatest
++++ b/src/tests/stacking/closed-transient-no-input-parent.metatest
+@@ -1,3 +1,7 @@
++new_client 2 x11
++create 2/1
++show 2/1
++
+ new_client 1 x11
+ create 1/1
+ show 1/1
+@@ -12,9 +16,15 @@ set_parent 1/3 2
+ show 1/3
+ 
+ wait
+-assert_stacking 1/1 1/2 1/3
++assert_focused 1/3
++assert_stacking 2/1 1/1 1/2 1/3
+ 
+ destroy 1/3
++dispatch
+ 
+-wait
+-assert_stacking 1/1 1/2
++assert_focused none
++assert_stacking 2/1 1/1 1/2
++
++sleep 250
++assert_focused 1/1
++assert_stacking 2/1 1/1 1/2
+diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
+index e1c3441..29ea3a6 100644
+--- a/src/x11/window-x11.c
++++ b/src/x11/window-x11.c
+@@ -53,6 +53,8 @@
+ #include "backends/meta-logical-monitor.h"
+ #include "backends/x11/meta-backend-x11.h"
+ 
++#define TAKE_FOCUS_FALLBACK_DELAY_MS 250
++
+ G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
+ 
+ static void
+@@ -722,6 +724,66 @@ request_take_focus (MetaWindow *window,
+   send_icccm_message (window, display->atom_WM_TAKE_FOCUS, timestamp);
+ }
+ 
++typedef struct
++{
++  MetaWindow *window;
++  guint32 timestamp;
++  guint timeout_id;
++  gulong unmanaged_id;
++  gulong focused_changed_id;
++} MetaWindowX11DelayedFocusData;
++
++static void
++meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data)
++{
++  g_signal_handler_disconnect (data->window, data->unmanaged_id);
++  g_signal_handler_disconnect (data->window->display, data->focused_changed_id);
++
++  if (data->timeout_id)
++    g_source_remove (data->timeout_id);
++
++  g_free (data);
++}
++
++static gboolean
++focus_window_delayed_timeout (gpointer user_data)
++{
++  MetaWindowX11DelayedFocusData *data = user_data;
++  MetaWindow *window = data->window;
++  guint32 timestamp = data->timestamp;
++
++  data->timeout_id = 0;
++  meta_window_x11_delayed_focus_data_free (data);
++
++  meta_window_focus (window, timestamp);
++
++  return G_SOURCE_REMOVE;
++}
++
++static void
++meta_window_x11_maybe_focus_delayed (MetaWindow *window,
++                                     guint32     timestamp)
++{
++  MetaWindowX11DelayedFocusData *data;
++
++  data = g_new0 (MetaWindowX11DelayedFocusData, 1);
++  data->window = window;
++  data->timestamp = timestamp;
++
++  data->unmanaged_id =
++    g_signal_connect_swapped (window, "unmanaged",
++                              G_CALLBACK (meta_window_x11_delayed_focus_data_free),
++                              data);
++
++  data->focused_changed_id =
++    g_signal_connect_swapped (window->display, "notify::focus-window",
++                              G_CALLBACK (meta_window_x11_delayed_focus_data_free),
++                              data);
++
++  data->timeout_id = g_timeout_add (TAKE_FOCUS_FALLBACK_DELAY_MS,
++                                    focus_window_delayed_timeout, data);
++}
++
+ static void
+ meta_window_x11_focus (MetaWindow *window,
+                        guint32     timestamp)
+@@ -771,14 +833,43 @@ meta_window_x11_focus (MetaWindow *window,
+                * Normally, we want to just leave the focus undisturbed until
+                * the window responds to WM_TAKE_FOCUS, but if we're unmanaging
+                * the current focus window we *need* to move the focus away, so
+-               * we focus the no_focus_window now (and set
+-               * display->focus_window to that) before sending WM_TAKE_FOCUS.
++               * we focus the no focus window before sending WM_TAKE_FOCUS,
++               * and eventually the default focus windwo excluding this one,
++               * if meanwhile we don't get any focus request.
+                */
+               if (window->display->focus_window != NULL &&
+                   window->display->focus_window->unmanaging)
+-                meta_display_focus_the_no_focus_window (window->display,
+-                                                        window->screen,
+-                                                        timestamp);
++                {
++                  MetaWindow *focus_window = window;
++                  MetaWorkspace *workspace = window->workspace;
++                  MetaStack *stack = window->screen->stack;
++
++                  while (TRUE)
++                    {
++                      focus_window = meta_stack_get_default_focus_window (stack,
++                                                                          workspace,
++                                                                          focus_window);
++                      if (!focus_window)
++                        break;
++
++                      if (focus_window->unmanaging)
++                        continue;
++
++                      if (focus_window->input)
++                        break;
++
++                      if (focus_window->shaded && focus_window->frame)
++                        break;
++                    }
++
++                  meta_display_focus_the_no_focus_window (window->display,
++                                                          window->screen,
++                                                          timestamp);
++
++                  if (focus_window)
++                    meta_window_x11_maybe_focus_delayed (focus_window,
++                                                         timestamp);
++                }
+             }
+ 
+           request_take_focus (window, timestamp);
diff --git a/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch b/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch
new file mode 100644
index 0000000..486d904
--- /dev/null
+++ b/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch
@@ -0,0 +1,84 @@
+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net>
+Date: Tue, 13 Nov 2018 08:31:52 +0100
+Subject: 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)
+
+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/68691cb1
+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/308
+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1791574
+Applied-Upstream: 3.28.5
+---
+ 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 a964e66..d194943 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)
+@@ -1319,13 +1325,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 && (window->input || window->take_focus) &&
++      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 */
+@@ -1347,11 +1360,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",
-- 
ubuntu-desktop mailing list
ubuntu-desktop@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop

Reply via email to