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