Merge ~3v1n0/ubuntu/+source/mutter:ubuntu/bionic into ~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: ed7085fc0db5b8af44c792b36354da20f3bc45a3
Proposed branch: ~3v1n0/ubuntu/+source/mutter:ubuntu/bionic
Merge into: ~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic
Diff against target: 1948 lines (+1815/-0)
19 files modified
debian/changelog (+27/-0)
debian/libmutter-2-0.symbols (+2/-0)
debian/patches/screen-Destroy-window-actors-after-windows-while-unmanagi.patch (+106/-0)
debian/patches/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch (+43/-0)
debian/patches/series (+16/-0)
debian/patches/stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch (+134/-0)
debian/patches/test-runner-Add-assert_focused-command.patch (+76/-0)
debian/patches/test-runner-Add-dispatch-command.patch (+84/-0)
debian/patches/test-runner-Add-sleep-command.patch (+82/-0)
debian/patches/tests-Add-accept_focus-command-to-runner-and-client.patch (+78/-0)
debian/patches/tests-Add-can_take_focus-command-to-runner-and-client.patch (+116/-0)
debian/patches/tests-Verify-focused-window-in-closed-transient-tests.patch (+64/-0)
debian/patches/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch (+125/-0)
debian/patches/window-Emit-an-error-and-return-when-trying-to-activate-a.patch (+43/-0)
debian/patches/window-x11-Accept-any-focusable-window-as-fallback-focus.patch (+109/-0)
debian/patches/window-x11-Don-t-double-check-for-unmanaging-windows.patch (+39/-0)
debian/patches/window-x11-Focus-the-default-window-with-delay-while-wait.patch (+247/-0)
debian/patches/window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch (+339/-0)
debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch (+85/-0)
Reviewer Review Type Date Requested Status
Ubuntu Desktop Pending
Review via email: mp+369334@code.launchpad.net

Description of the change

Upstream cherry-picks and crash fix

To post a comment you must log in.
Revision history for this message
Iain Lane (laney) wrote :

Done, thanks! I think we should probably think about doing a snapshot next time, this is a lot of cherry-picks already.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 62c0624..9a06342 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,30 @@
6+mutter (3.28.4-0ubuntu18.04.2) UNRELEASED; urgency=medium
7+
8+ * d/p/screen-Destroy-window-actors-after-windows-while-unmanagi.patch,
9+ d/p/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch:
10+ - Destroy window actors after windows while unmanaging compositor
11+ (LP: #1832869)
12+ * d/p/window-Emit-an-error-and-return-when-trying-to-activate-a.patch:
13+ - window: Emit an error and return when trying to activate an unmanaged
14+ (LP: #1827401)
15+ * d/p/stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch,
16+ d/p/test-runner-Add-assert_focused-command.patch,
17+ d/p/test-runner-Add-dispatch-command.patch,
18+ d/p/test-runner-Add-sleep-command.patch,
19+ d/p/tests-Add-accept_focus-command-to-runner-and-client.patch,
20+ d/p/tests-Add-can_take_focus-command-to-runner-and-client.patch,
21+ d/p/tests-Verify-focused-window-in-closed-transient-tests.patch,
22+ d/p/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch,
23+ d/p/window-x11-Accept-any-focusable-window-as-fallback-focus.patch,
24+ d/p/window-x11-Don-t-double-check-for-unmanaging-windows.patch,
25+ d/p/window-x11-Focus-the-default-window-with-delay-while-wait.patch,
26+ d/p/window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch,
27+ d/p/workspace-Focus-only-ancestors-that-are-focusable.patch:
28+ - Workspace: Take-Input windows focus fixes (LP: #1791574)
29+ * debian/libmutter-2-0.symbols: Update with new symbols
30+
31+ -- Marco Trevisan (Treviño) <marco@ubuntu.com> Mon, 08 Jul 2019 20:00:56 +0200
32+
33 mutter (3.28.4-0ubuntu18.04.1) bionic; urgency=medium
34
35 * New upstream release:
36diff --git a/debian/libmutter-2-0.symbols b/debian/libmutter-2-0.symbols
37index 951e8e4..70b61dc 100644
38--- a/debian/libmutter-2-0.symbols
39+++ b/debian/libmutter-2-0.symbols
40@@ -139,6 +139,7 @@ libmutter-2.so.0 libmutter-2-0 #MINVER#
41 meta_compositor_sync_updates_frozen@Base 3.28.2
42 meta_compositor_sync_window_geometry@Base 3.28.2
43 meta_compositor_unmanage@Base 3.28.2
44+ meta_compositor_unmanage_window_actors@Base 3.28.4-0ubuntu18.04.2
45 meta_compositor_window_opacity_changed@Base 3.28.2
46 meta_compositor_window_shape_changed@Base 3.28.2
47 meta_compositor_window_surface_changed@Base 3.28.2
48@@ -1112,6 +1113,7 @@ libmutter-2.so.0 libmutter-2-0 #MINVER#
49 meta_stack_get_above@Base 3.28.2
50 meta_stack_get_below@Base 3.28.2
51 meta_stack_get_bottom@Base 3.28.2
52+ meta_stack_get_default_focus_candidates@Base 3.28.4-0ubuntu18.04.2
53 meta_stack_get_default_focus_window@Base 3.28.2
54 meta_stack_get_default_focus_window_at_point@Base 3.28.2
55 meta_stack_get_positions@Base 3.28.2
56diff --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
57new file mode 100644
58index 0000000..3bf085a
59--- /dev/null
60+++ b/debian/patches/screen-Destroy-window-actors-after-windows-while-unmanagi.patch
61@@ -0,0 +1,106 @@
62+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
63+Date: Tue, 25 Jun 2019 20:22:23 +0200
64+Subject: screen: Destroy window actors after windows while unmanaging
65+ compositor
66+
67+After commit 2e64457f4 we destroy window actors as part of compositor
68+destruction, however this might emit 'actor-removed' signals on window groups
69+that the shell could use to access to resources that are already free'd at this
70+point (like the destroyed screen, in gnome-shell's Panel._updateSolidStyle()).
71+
72+So, move the actor destructions under in a new function and destroy the window
73+actors as part of compositor unmanage step, just after that all the windows are
74+unmanaged (as they need to have an actor around).
75+
76+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/652
77+
78+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/653
79+Bug-Ubuntu: https://launchpad.net/bugs/1832869
80+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/652
81+Applied-Upstream: 3.28.5
82+---
83+ src/compositor/compositor-private.h | 2 ++
84+ src/compositor/compositor.c | 30 +++++++++++++++++-------------
85+ src/core/screen.c | 3 +++
86+ 3 files changed, 22 insertions(+), 13 deletions(-)
87+
88+diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
89+index 4669bc5..4582792 100644
90+--- a/src/compositor/compositor-private.h
91++++ b/src/compositor/compositor-private.h
92+@@ -73,4 +73,6 @@ MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *composito
93+ MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
94+ MetaWindow *window);
95+
96++void meta_compositor_unmanage_window_actors (MetaCompositor *compositor);
97++
98+ #endif /* META_COMPOSITOR_PRIVATE_H */
99+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
100+index 2545d2c..6d04533 100644
101+--- a/src/compositor/compositor.c
102++++ b/src/compositor/compositor.c
103+@@ -145,19 +145,6 @@ meta_compositor_destroy (MetaCompositor *compositor)
104+ clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
105+ clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
106+
107+- if (compositor->top_window_actor)
108+- {
109+- g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
110+- on_top_window_actor_destroyed,
111+- compositor);
112+- compositor->top_window_actor = NULL;
113+- }
114+-
115+- g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
116+- g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
117+- g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
118+- g_clear_pointer (&compositor->windows, g_list_free);
119+-
120+ if (compositor->have_x11_sync_object)
121+ meta_sync_ring_destroy ();
122+ }
123+@@ -610,6 +597,23 @@ meta_compositor_unmanage (MetaCompositor *compositor)
124+ }
125+ }
126+
127++void
128++meta_compositor_unmanage_window_actors (MetaCompositor *compositor)
129++{
130++ if (compositor->top_window_actor)
131++ {
132++ g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
133++ on_top_window_actor_destroyed,
134++ compositor);
135++ compositor->top_window_actor = NULL;
136++ }
137++
138++ g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
139++ g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
140++ g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
141++ g_clear_pointer (&compositor->windows, g_list_free);
142++}
143++
144+ /**
145+ * meta_shape_cow_for_window:
146+ * @compositor: A #MetaCompositor
147+diff --git a/src/core/screen.c b/src/core/screen.c
148+index d7623f3..2e59754 100644
149+--- a/src/core/screen.c
150++++ b/src/core/screen.c
151+@@ -41,6 +41,7 @@
152+ #include "stack.h"
153+ #include <meta/compositor.h>
154+ #include <meta/meta-enum-types.h>
155++#include "compositor-private.h"
156+ #include "core.h"
157+ #include "meta-cursor-tracker-private.h"
158+ #include "boxes-private.h"
159+@@ -844,6 +845,8 @@ meta_screen_free (MetaScreen *screen,
160+
161+ meta_display_unmanage_windows_for_screen (display, screen, timestamp);
162+
163++ meta_compositor_unmanage_window_actors (display->compositor);
164++
165+ meta_prefs_remove_listener (prefs_changed_callback, screen);
166+
167+ meta_screen_ungrab_keys (screen);
168diff --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
169new file mode 100644
170index 0000000..7c67b0c
171--- /dev/null
172+++ b/debian/patches/screen-Unset-the-active-workspace-and-remove-workspaces-o.patch
173@@ -0,0 +1,43 @@
174+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
175+Date: Tue, 25 Jun 2019 20:22:54 +0200
176+Subject: screen: Unset the active workspace and remove workspaces on free
177+
178+Related to https://gitlab.gnome.org/GNOME/mutter/issues/652
179+
180+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/653
181+Bug-Ubuntu: https://launchpad.net/bugs/1832869
182+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/652
183+Applied-Upstream: 3.28.5
184+---
185+ src/core/screen.c | 11 +++++++++++
186+ 1 file changed, 11 insertions(+)
187+
188+diff --git a/src/core/screen.c b/src/core/screen.c
189+index 2e59754..11f3bad 100644
190+--- a/src/core/screen.c
191++++ b/src/core/screen.c
192+@@ -836,6 +836,7 @@ meta_screen_free (MetaScreen *screen,
193+ guint32 timestamp)
194+ {
195+ MetaDisplay *display;
196++ GList *l;
197+
198+ display = screen->display;
199+
200+@@ -877,6 +878,16 @@ meta_screen_free (MetaScreen *screen,
201+
202+ g_free (screen->screen_name);
203+
204++ screen->active_workspace = NULL;
205++
206++ for (l = screen->workspaces; l;)
207++ {
208++ MetaWorkspace *workspace = l->data;
209++ l = l->next;
210++
211++ meta_workspace_remove (workspace);
212++ }
213++
214+ g_object_unref (screen);
215+ }
216+
217diff --git a/debian/patches/series b/debian/patches/series
218index 5bf1aa6..8165334 100644
219--- a/debian/patches/series
220+++ b/debian/patches/series
221@@ -4,6 +4,22 @@ clutter-Fix-offscreen-effect-painting-of-clones.patch
222 bgo768531_workaround-startup-notifications.patch
223 monitor-manager-use-MonitorsConfig-to-track-switch_config.patch
224 monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch
225+screen-Destroy-window-actors-after-windows-while-unmanagi.patch
226+screen-Unset-the-active-workspace-and-remove-workspaces-o.patch
227+workspace-Focus-only-ancestors-that-are-focusable.patch
228+tests-Add-accept_focus-command-to-runner-and-client.patch
229+tests-Add-can_take_focus-command-to-runner-and-client.patch
230+tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch
231+test-runner-Add-assert_focused-command.patch
232+tests-Verify-focused-window-in-closed-transient-tests.patch
233+test-runner-Add-sleep-command.patch
234+test-runner-Add-dispatch-command.patch
235+window-x11-Focus-the-default-window-with-delay-while-wait.patch
236+window-Emit-an-error-and-return-when-trying-to-activate-a.patch
237+window-x11-Don-t-double-check-for-unmanaging-windows.patch
238+window-x11-Accept-any-focusable-window-as-fallback-focus.patch
239+stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch
240+window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch
241 lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
242 lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
243 debian/synaptics-support.patch
244diff --git a/debian/patches/stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch b/debian/patches/stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch
245new file mode 100644
246index 0000000..f3452b8
247--- /dev/null
248+++ b/debian/patches/stack-Add-a-function-to-get-a-sorted-list-of-focus-candid.patch
249@@ -0,0 +1,134 @@
250+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
251+Date: Wed, 3 Jul 2019 18:48:07 +0200
252+Subject: stack: Add a function to get a sorted list of focus candidates
253+
254+Use a static function if a window can be the default focus window, and use such
255+function to return a filtered list of the stack.
256+
257+https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
258+
259+(cherry picked from commit 2439255f32b4e775d4427c92a6797b8bd33e7d5a)
260+
261+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
262+Bug-Ubuntu: https://launchpad.net/bugs/1791574
263+Bug-Ubuntu: https://launchpad.net/bugs/1834583
264+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
265+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/660
266+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
267+Applied-Upstream: 3.28.5
268+---
269+ src/core/stack.c | 55 ++++++++++++++++++++++++++++++++++++++++++-------------
270+ src/core/stack.h | 15 +++++++++++++++
271+ 2 files changed, 57 insertions(+), 13 deletions(-)
272+
273+diff --git a/src/core/stack.c b/src/core/stack.c
274+index fc51aa1..3a0130f 100644
275+--- a/src/core/stack.c
276++++ b/src/core/stack.c
277+@@ -1176,6 +1176,27 @@ window_contains_point (MetaWindow *window,
278+ return POINT_IN_RECT (root_x, root_y, rect);
279+ }
280+
281++static gboolean
282++window_can_get_default_focus (MetaWindow *window)
283++{
284++ if (window->unmaps_pending > 0)
285++ return FALSE;
286++
287++ if (window->unmanaging)
288++ return FALSE;
289++
290++ if (!(window->input || window->take_focus))
291++ return FALSE;
292++
293++ if (!meta_window_should_be_showing (window))
294++ return FALSE;
295++
296++ if (window->type == META_WINDOW_DOCK)
297++ return FALSE;
298++
299++ return TRUE;
300++}
301++
302+ static MetaWindow*
303+ get_default_focus_window (MetaStack *stack,
304+ MetaWorkspace *workspace,
305+@@ -1203,24 +1224,12 @@ get_default_focus_window (MetaStack *stack,
306+ if (window == not_this_one)
307+ continue;
308+
309+- if (window->unmaps_pending > 0)
310+- continue;
311+-
312+- if (window->unmanaging)
313+- continue;
314+-
315+- if (!(window->input || window->take_focus))
316+- continue;
317+-
318+- if (!meta_window_should_be_showing (window))
319++ if (!window_can_get_default_focus (window))
320+ continue;
321+
322+ if (must_be_at_point && !window_contains_point (window, root_x, root_y))
323+ continue;
324+
325+- if (window->type == META_WINDOW_DOCK)
326+- continue;
327+-
328+ return window;
329+ }
330+
331+@@ -1275,6 +1284,26 @@ meta_stack_list_windows (MetaStack *stack,
332+ return workspace_windows;
333+ }
334+
335++GList *
336++meta_stack_get_default_focus_candidates (MetaStack *stack,
337++ MetaWorkspace *workspace)
338++{
339++ GList *windows = meta_stack_list_windows (stack, workspace);
340++ GList *l;
341++
342++ for (l = windows; l;)
343++ {
344++ GList *next = l->next;
345++
346++ if (!window_can_get_default_focus (l->data))
347++ windows = g_list_delete_link (windows, l);
348++
349++ l = next;
350++ }
351++
352++ return windows;
353++}
354++
355+ int
356+ meta_stack_windows_cmp (MetaStack *stack,
357+ MetaWindow *window_a,
358+diff --git a/src/core/stack.h b/src/core/stack.h
359+index e82be0a..8cd7c68 100644
360+--- a/src/core/stack.h
361++++ b/src/core/stack.h
362+@@ -337,6 +337,21 @@ MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack,
363+ int root_x,
364+ int root_y);
365+
366++/**
367++ * meta_stack_get_default_focus_candidates:
368++ * @stack: The stack to examine.
369++ * @workspace: If not %NULL, only windows on this workspace will be
370++ * returned; otherwise all windows in the stack will be
371++ * returned.
372++ *
373++ * Returns all the focus candidate windows in the stack, in order.
374++ *
375++ * Returns: (transfer container) (element-type Meta.Window):
376++ * A #GList of #MetaWindow, in stacking order, honouring layers.
377++ */
378++GList * meta_stack_get_default_focus_candidates (MetaStack *stack,
379++ MetaWorkspace *workspace);
380++
381+ /**
382+ * meta_stack_list_windows:
383+ * @stack: The stack to examine.
384diff --git a/debian/patches/test-runner-Add-assert_focused-command.patch b/debian/patches/test-runner-Add-assert_focused-command.patch
385new file mode 100644
386index 0000000..94d47fc
387--- /dev/null
388+++ b/debian/patches/test-runner-Add-assert_focused-command.patch
389@@ -0,0 +1,76 @@
390+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
391+Date: Tue, 13 Nov 2018 08:37:14 +0100
392+Subject: test-runner: Add 'assert_focused' command
393+
394+This allows to verify which window should have the focus, which might not
395+be the same as the top of the stack.
396+
397+It's possible to assert the case where there's no focused window using
398+"NONE" as parameter.
399+
400+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
401+(cherry picked from commit 51f9e04ef1fa8cd7298044ac8c82e83bea425770)
402+
403+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
404+Bug-Ubuntu: https://launchpad.net/bugs/1791574
405+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
406+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
407+Applied-Upstream: 3.28.5
408+---
409+ src/tests/test-runner.c | 36 ++++++++++++++++++++++++++++++++++++
410+ 1 file changed, 36 insertions(+)
411+
412+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
413+index 37befb4..9056d9a 100644
414+--- a/src/tests/test-runner.c
415++++ b/src/tests/test-runner.c
416+@@ -273,6 +273,37 @@ test_case_assert_stacking (TestCase *test,
417+ return *error == NULL;
418+ }
419+
420++static gboolean
421++test_case_assert_focused (TestCase *test,
422++ const char *expected_window,
423++ GError **error)
424++{
425++ MetaDisplay *display = meta_get_display ();
426++
427++ if (!display->focus_window)
428++ {
429++ if (g_strcmp0 (expected_window, "none") != 0)
430++ {
431++ g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
432++ "focus: expected='%s', actual='none'", expected_window);
433++ }
434++ }
435++ else
436++ {
437++ const char *focused = display->focus_window->title;
438++
439++ if (g_str_has_prefix (focused, "test/"))
440++ focused += 5;
441++
442++ if (g_strcmp0 (focused, expected_window) != 0)
443++ g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
444++ "focus: expected='%s', actual='%s'",
445++ expected_window, focused);
446++ }
447++
448++ return *error == NULL;
449++}
450++
451+ static gboolean
452+ test_case_check_xserver_stacking (TestCase *test,
453+ GError **error)
454+@@ -496,6 +527,11 @@ test_case_do (TestCase *test,
455+ if (!test_case_check_xserver_stacking (test, error))
456+ return FALSE;
457+ }
458++ else if (strcmp (argv[0], "assert_focused") == 0)
459++ {
460++ if (!test_case_assert_focused (test, argv[1], error))
461++ return FALSE;
462++ }
463+ else
464+ {
465+ BAD_COMMAND("Unknown command %s", argv[0]);
466diff --git a/debian/patches/test-runner-Add-dispatch-command.patch b/debian/patches/test-runner-Add-dispatch-command.patch
467new file mode 100644
468index 0000000..0fcbbd7
469--- /dev/null
470+++ b/debian/patches/test-runner-Add-dispatch-command.patch
471@@ -0,0 +1,84 @@
472+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
473+Date: Fri, 21 Jun 2019 13:15:48 +0200
474+Subject: test-runner: Add 'dispatch' command
475+
476+This will only wait for events to be dispatched and processed by the server
477+without waiting for client processing.
478+
479+Reuse the code for the wait command too.
480+
481+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
482+(cherry picked from commit 6022b23923fa6192c630920e9f895f185977beee)
483+
484+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
485+Bug-Ubuntu: https://launchpad.net/bugs/1791574
486+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
487+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
488+Applied-Upstream: 3.28.5
489+---
490+ src/tests/test-runner.c | 38 ++++++++++++++++++++++++++++----------
491+ 1 file changed, 28 insertions(+), 10 deletions(-)
492+
493+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
494+index 75732c6..cdeaba2 100644
495+--- a/src/tests/test-runner.c
496++++ b/src/tests/test-runner.c
497+@@ -122,6 +122,24 @@ test_case_loop_quit (gpointer data)
498+ return FALSE;
499+ }
500+
501++static gboolean
502++test_case_dispatch (TestCase *test,
503++ GError **error)
504++{
505++ /* Wait until we've done any outstanding queued up work.
506++ * Though we add this as BEFORE_REDRAW, the iteration that runs the
507++ * BEFORE_REDRAW idles will proceed on and do the redraw, so we're
508++ * waiting until after *all* frame processing.
509++ */
510++ meta_later_add (META_LATER_BEFORE_REDRAW,
511++ test_case_loop_quit,
512++ test,
513++ NULL);
514++ g_main_loop_run (test->loop);
515++
516++ return TRUE;
517++}
518++
519+ static gboolean
520+ test_case_wait (TestCase *test,
521+ GError **error)
522+@@ -138,16 +156,8 @@ test_case_wait (TestCase *test,
523+ if (!test_client_wait (value, error))
524+ return FALSE;
525+
526+- /* Then wait until we've done any outstanding queued up work.
527+- * Though we add this as BEFORE_REDRAW, the iteration that runs the
528+- * BEFORE_REDRAW idles will proceed on and do the redraw, so we're
529+- * waiting until after *all* frame processing.
530+- */
531+- meta_later_add (META_LATER_BEFORE_REDRAW,
532+- test_case_loop_quit,
533+- test,
534+- NULL);
535+- g_main_loop_run (test->loop);
536++ /* Then wait until we've done any outstanding queued up work. */
537++ test_case_dispatch (test, error);
538+
539+ /* Then set an XSync counter ourselves and and wait until
540+ * we receive the resulting event - this makes sure that we've
541+@@ -530,6 +540,14 @@ test_case_do (TestCase *test,
542+ if (!test_case_wait (test, error))
543+ return FALSE;
544+ }
545++ else if (strcmp (argv[0], "dispatch") == 0)
546++ {
547++ if (argc != 1)
548++ BAD_COMMAND("usage: %s", argv[0]);
549++
550++ if (!test_case_dispatch (test, error))
551++ return FALSE;
552++ }
553+ else if (strcmp (argv[0], "sleep") == 0)
554+ {
555+ guint64 interval;
556diff --git a/debian/patches/test-runner-Add-sleep-command.patch b/debian/patches/test-runner-Add-sleep-command.patch
557new file mode 100644
558index 0000000..914c9c2
559--- /dev/null
560+++ b/debian/patches/test-runner-Add-sleep-command.patch
561@@ -0,0 +1,82 @@
562+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
563+Date: Tue, 18 Jun 2019 19:33:10 +0200
564+Subject: test-runner: Add 'sleep' command
565+
566+This allows to sleep for a given timeout in milliseconds.
567+
568+Rename test_case_before_redraw to test_case_loop_quit since it's a generic
569+function and use it for the timeout too.
570+
571+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
572+(cherry picked from commit d08763c18cb25fe250b27bf296e1607e63e86400)
573+
574+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
575+Bug-Ubuntu: https://launchpad.net/bugs/1791574
576+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
577+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
578+Applied-Upstream: 3.28.5
579+---
580+ src/tests/test-runner.c | 29 +++++++++++++++++++++++++++--
581+ 1 file changed, 27 insertions(+), 2 deletions(-)
582+
583+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
584+index 9056d9a..75732c6 100644
585+--- a/src/tests/test-runner.c
586++++ b/src/tests/test-runner.c
587+@@ -113,7 +113,7 @@ test_case_new (void)
588+ }
589+
590+ static gboolean
591+-test_case_before_redraw (gpointer data)
592++test_case_loop_quit (gpointer data)
593+ {
594+ TestCase *test = data;
595+
596+@@ -144,7 +144,7 @@ test_case_wait (TestCase *test,
597+ * waiting until after *all* frame processing.
598+ */
599+ meta_later_add (META_LATER_BEFORE_REDRAW,
600+- test_case_before_redraw,
601++ test_case_loop_quit,
602+ test,
603+ NULL);
604+ g_main_loop_run (test->loop);
605+@@ -157,6 +157,17 @@ test_case_wait (TestCase *test,
606+ return TRUE;
607+ }
608+
609++static gboolean
610++test_case_sleep (TestCase *test,
611++ guint32 interval,
612++ GError **error)
613++{
614++ g_timeout_add_full (G_PRIORITY_LOW, interval, test_case_loop_quit, test, NULL);
615++ g_main_loop_run (test->loop);
616++
617++ return TRUE;
618++}
619++
620+ #define BAD_COMMAND(...) \
621+ G_STMT_START { \
622+ g_set_error (error, \
623+@@ -519,6 +530,20 @@ test_case_do (TestCase *test,
624+ if (!test_case_wait (test, error))
625+ return FALSE;
626+ }
627++ else if (strcmp (argv[0], "sleep") == 0)
628++ {
629++ guint64 interval;
630++
631++ if (argc != 2)
632++ BAD_COMMAND("usage: %s <milliseconds>", argv[0]);
633++
634++ if (!g_ascii_string_to_unsigned (argv[1], 10, 0, G_MAXUINT32,
635++ &interval, error))
636++ return FALSE;
637++
638++ if (!test_case_sleep (test, (guint32) interval, error))
639++ return FALSE;
640++ }
641+ else if (strcmp (argv[0], "assert_stacking") == 0)
642+ {
643+ if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
644diff --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
645new file mode 100644
646index 0000000..82dc33b
647--- /dev/null
648+++ b/debian/patches/tests-Add-accept_focus-command-to-runner-and-client.patch
649@@ -0,0 +1,78 @@
650+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
651+Date: Tue, 13 Nov 2018 03:43:57 +0100
652+Subject: tests: Add 'accept_focus' command to runner and client
653+
654+Under the hood, calls gtk_window_set_accept_focus in the client
655+
656+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
657+(cherry picked from commit e1f839f48f8e49c826ba558fbc9d6842a156b28b)
658+
659+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
660+Bug-Ubuntu: https://launchpad.net/bugs/1791574
661+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
662+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
663+Applied-Upstream: 3.28.5
664+---
665+ src/tests/test-client.c | 18 ++++++++++++++++++
666+ src/tests/test-runner.c | 19 +++++++++++++++++++
667+ 2 files changed, 37 insertions(+)
668+
669+diff --git a/src/tests/test-client.c b/src/tests/test-client.c
670+index 5836083..1870fd2 100644
671+--- a/src/tests/test-client.c
672++++ b/src/tests/test-client.c
673+@@ -161,6 +161,24 @@ process_line (const char *line)
674+ gtk_window_set_transient_for (GTK_WINDOW (window),
675+ GTK_WINDOW (parent_window));
676+ }
677++ else if (strcmp (argv[0], "accept_focus") == 0)
678++ {
679++ if (argc != 3)
680++ {
681++ g_print ("usage: %s <window-id> [true|false]", argv[0]);
682++ goto out;
683++ }
684++
685++ GtkWidget *window = lookup_window (argv[1]);
686++ if (!window)
687++ {
688++ g_print ("unknown window %s", argv[1]);
689++ goto out;
690++ }
691++
692++ gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
693++ gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
694++ }
695+ else if (strcmp (argv[0], "show") == 0)
696+ {
697+ if (argc != 2)
698+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
699+index 8867945..613c0bb 100644
700+--- a/src/tests/test-runner.c
701++++ b/src/tests/test-runner.c
702+@@ -406,6 +406,25 @@ test_case_do (TestCase *test,
703+ NULL))
704+ return FALSE;
705+ }
706++ else if (strcmp (argv[0], "accept_focus") == 0)
707++ {
708++ if (argc != 3 ||
709++ (g_ascii_strcasecmp (argv[2], "true") != 0 &&
710++ g_ascii_strcasecmp (argv[2], "false") != 0))
711++ BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
712++ argv[0]);
713++
714++ TestClient *client;
715++ const char *window_id;
716++ if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
717++ return FALSE;
718++
719++ if (!test_client_do (client, error,
720++ argv[0], window_id,
721++ argv[2],
722++ NULL))
723++ return FALSE;
724++ }
725+ else if (strcmp (argv[0], "show") == 0 ||
726+ strcmp (argv[0], "hide") == 0 ||
727+ strcmp (argv[0], "activate") == 0 ||
728diff --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
729new file mode 100644
730index 0000000..03357df
731--- /dev/null
732+++ b/debian/patches/tests-Add-can_take_focus-command-to-runner-and-client.patch
733@@ -0,0 +1,116 @@
734+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
735+Date: Tue, 13 Nov 2018 04:04:22 +0100
736+Subject: tests: Add 'can_take_focus' command to runner and client
737+
738+Allow to set/unset WM_TAKE_FOCUS from client window.
739+This is added by default by gtk, but this might not happen in other toolkits,
740+so add an ability to (un)set this.
741+
742+So fetch the protocols with XGetWMProtocols and unset the atom.
743+
744+test-client now needs to depend on Xlib directly in meson build.
745+
746+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
747+(cherry picked from commit f2d2d473b71dbdb339c80f068c5cb3e529af2478)
748+
749+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
750+Bug-Ubuntu: https://launchpad.net/bugs/1791574
751+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
752+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
753+Applied-Upstream: 3.28.5
754+---
755+ src/tests/test-client.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
756+ src/tests/test-runner.c | 19 +++++++++++++++++++
757+ 2 files changed, 69 insertions(+)
758+
759+diff --git a/src/tests/test-client.c b/src/tests/test-client.c
760+index 1870fd2..aa763d5 100644
761+--- a/src/tests/test-client.c
762++++ b/src/tests/test-client.c
763+@@ -179,6 +179,56 @@ process_line (const char *line)
764+ gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
765+ gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
766+ }
767++ else if (strcmp (argv[0], "can_take_focus") == 0)
768++ {
769++ if (argc != 3)
770++ {
771++ g_print ("usage: %s <window-id> [true|false]", argv[0]);
772++ goto out;
773++ }
774++
775++ GtkWidget *window = lookup_window (argv[1]);
776++ if (!window)
777++ {
778++ g_print ("unknown window %s", argv[1]);
779++ goto out;
780++ }
781++
782++ if (wayland)
783++ {
784++ g_print ("%s not supported under wayland", argv[0]);
785++ goto out;
786++ }
787++
788++ GdkDisplay *display = gdk_display_get_default ();
789++ GdkWindow *gdkwindow = gtk_widget_get_window (window);
790++ Display *xdisplay = gdk_x11_display_get_xdisplay (display);
791++ Window xwindow = GDK_WINDOW_XID (gdkwindow);
792++ Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
793++ gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0;
794++ Atom *protocols = NULL;
795++ Atom *new_protocols;
796++ int n_protocols = 0;
797++ int i, n = 0;
798++
799++ gdk_display_sync (display);
800++ XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols);
801++ new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0));
802++
803++ for (i = 0; i < n_protocols; ++i)
804++ {
805++ if (protocols[i] != wm_take_focus)
806++ new_protocols[n++] = protocols[i];
807++ }
808++
809++ if (add)
810++ new_protocols[n++] = wm_take_focus;
811++
812++ XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
813++
814++ XFree (new_protocols);
815++ XFree (protocols);
816++ }
817+ else if (strcmp (argv[0], "show") == 0)
818+ {
819+ if (argc != 2)
820+diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
821+index 613c0bb..37befb4 100644
822+--- a/src/tests/test-runner.c
823++++ b/src/tests/test-runner.c
824+@@ -425,6 +425,25 @@ test_case_do (TestCase *test,
825+ NULL))
826+ return FALSE;
827+ }
828++ else if (strcmp (argv[0], "can_take_focus") == 0)
829++ {
830++ if (argc != 3 ||
831++ (g_ascii_strcasecmp (argv[2], "true") != 0 &&
832++ g_ascii_strcasecmp (argv[2], "false") != 0))
833++ BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
834++ argv[0]);
835++
836++ TestClient *client;
837++ const char *window_id;
838++ if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
839++ return FALSE;
840++
841++ if (!test_client_do (client, error,
842++ argv[0], window_id,
843++ argv[2],
844++ NULL))
845++ return FALSE;
846++ }
847+ else if (strcmp (argv[0], "show") == 0 ||
848+ strcmp (argv[0], "hide") == 0 ||
849+ strcmp (argv[0], "activate") == 0 ||
850diff --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
851new file mode 100644
852index 0000000..f65d295
853--- /dev/null
854+++ b/debian/patches/tests-Verify-focused-window-in-closed-transient-tests.patch
855@@ -0,0 +1,64 @@
856+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
857+Date: Tue, 13 Nov 2018 08:45:56 +0100
858+Subject: tests: Verify focused window in closed-transient tests
859+
860+Ensure that we have a focused window when closing transient windows with
861+no-focus or no-take-focus atoms
862+
863+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
864+(cherry picked from commit fcb408ad5d8d7fec3e6a7bdaa92e5ef06b55c2c6)
865+
866+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
867+Bug-Ubuntu: https://launchpad.net/bugs/1791574
868+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
869+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
870+Applied-Upstream: 3.28.5
871+---
872+ .../closed-transient-no-input-no-take-focus-parent.metatest | 2 ++
873+ ...closed-transient-no-input-no-take-focus-parents.metatest | 13 ++++++++++---
874+ 2 files changed, 12 insertions(+), 3 deletions(-)
875+
876+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
877+index 4249c32..0c0649c 100644
878+--- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
879++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
880+@@ -13,9 +13,11 @@ set_parent 1/3 2
881+ show 1/3
882+
883+ wait
884++assert_focused 1/3
885+ assert_stacking 1/1 1/2 1/3
886+
887+ destroy 1/3
888+
889+ wait
890++assert_focused 1/1
891+ assert_stacking 1/1 1/2
892+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
893+index a61c640..6556803 100644
894+--- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
895++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
896+@@ -1,3 +1,8 @@
897++new_client 2 x11
898++create 2/1
899++show 2/1
900++wait
901++
902+ new_client 1 x11
903+ create 1/1
904+ accept_focus 1/1 false
905+@@ -15,9 +20,11 @@ set_parent 1/3 2
906+ show 1/3
907+
908+ wait
909+-assert_stacking 1/1 1/2 1/3
910++assert_focused 1/3
911++assert_stacking 2/1 1/1 1/2 1/3
912+
913+ destroy 1/3
914+-wait
915+
916+-assert_stacking 1/1 1/2
917++wait
918++assert_stacking 1/1 1/2 2/1
919++assert_focused 2/1
920diff --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
921new file mode 100644
922index 0000000..77cc7d3
923--- /dev/null
924+++ b/debian/patches/tests-stacking-Add-tests-with-no-input-and-no-take-focus-.patch
925@@ -0,0 +1,125 @@
926+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
927+Date: Tue, 13 Nov 2018 07:48:53 +0100
928+Subject: tests, stacking: Add tests with no-input and no-take-focus windows
929+
930+When a window with no frame, that doesn't accept focus and that has no
931+take-focus atom set is destroyed, we ended up in not changing the current_focus
932+window, causing a crash.
933+
934+Added test cases that verify this situation.
935+
936+Related to https://gitlab.gnome.org/GNOME/mutter/issues/308
937+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
938+(cherry picked from commit 2fc7760ceed6f948d4f3c1dd74d4e57c7df05eea)
939+
940+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
941+Bug-Ubuntu: https://launchpad.net/bugs/1791574
942+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
943+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
944+Applied-Upstream: 3.28.5
945+---
946+ src/Makefile-tests.am | 3 +++
947+ ...ransient-no-input-no-take-focus-parent.metatest | 21 ++++++++++++++++++++
948+ ...ansient-no-input-no-take-focus-parents.metatest | 23 ++++++++++++++++++++++
949+ .../closed-transient-no-input-parent.metatest | 20 +++++++++++++++++++
950+ 4 files changed, 67 insertions(+)
951+ create mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
952+ create mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
953+ create mode 100644 src/tests/stacking/closed-transient-no-input-parent.metatest
954+
955+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
956+index 4be832c..3764917 100644
957+--- a/src/Makefile-tests.am
958++++ b/src/Makefile-tests.am
959+@@ -15,6 +15,9 @@ dist_stacking_DATA = \
960+ tests/stacking/basic-x11.metatest \
961+ tests/stacking/basic-wayland.metatest \
962+ tests/stacking/closed-transient.metatest \
963++ tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest \
964++ tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest \
965++ tests/stacking/closed-transient-no-input-parent.metatest \
966+ tests/stacking/minimized.metatest \
967+ tests/stacking/mixed-windows.metatest \
968+ tests/stacking/set-parent.metatest \
969+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
970+new file mode 100644
971+index 0000000..4249c32
972+--- /dev/null
973++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest
974+@@ -0,0 +1,21 @@
975++new_client 1 x11
976++create 1/1
977++show 1/1
978++
979++create 1/2 csd
980++set_parent 1/2 1
981++can_take_focus 1/2 false
982++accept_focus 1/2 false
983++show 1/2
984++
985++create 1/3 csd
986++set_parent 1/3 2
987++show 1/3
988++
989++wait
990++assert_stacking 1/1 1/2 1/3
991++
992++destroy 1/3
993++
994++wait
995++assert_stacking 1/1 1/2
996+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
997+new file mode 100644
998+index 0000000..a61c640
999+--- /dev/null
1000++++ b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest
1001+@@ -0,0 +1,23 @@
1002++new_client 1 x11
1003++create 1/1
1004++accept_focus 1/1 false
1005++can_take_focus 1/1 false
1006++show 1/1
1007++
1008++create 1/2 csd
1009++set_parent 1/2 1
1010++can_take_focus 1/2 false
1011++accept_focus 1/2 false
1012++show 1/2
1013++
1014++create 1/3 csd
1015++set_parent 1/3 2
1016++show 1/3
1017++
1018++wait
1019++assert_stacking 1/1 1/2 1/3
1020++
1021++destroy 1/3
1022++wait
1023++
1024++assert_stacking 1/1 1/2
1025+diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest
1026+new file mode 100644
1027+index 0000000..4cadb23
1028+--- /dev/null
1029++++ b/src/tests/stacking/closed-transient-no-input-parent.metatest
1030+@@ -0,0 +1,20 @@
1031++new_client 1 x11
1032++create 1/1
1033++show 1/1
1034++
1035++create 1/2 csd
1036++set_parent 1/2 1
1037++accept_focus 1/2 false
1038++show 1/2
1039++
1040++create 1/3 csd
1041++set_parent 1/3 2
1042++show 1/3
1043++
1044++wait
1045++assert_stacking 1/1 1/2 1/3
1046++
1047++destroy 1/3
1048++
1049++wait
1050++assert_stacking 1/1 1/2
1051diff --git a/debian/patches/window-Emit-an-error-and-return-when-trying-to-activate-a.patch b/debian/patches/window-Emit-an-error-and-return-when-trying-to-activate-a.patch
1052new file mode 100644
1053index 0000000..0d9d7e1
1054--- /dev/null
1055+++ b/debian/patches/window-Emit-an-error-and-return-when-trying-to-activate-a.patch
1056@@ -0,0 +1,43 @@
1057+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1058+Date: Fri, 3 May 2019 20:10:47 +0200
1059+Subject: window: Emit an error and return when trying to activate an
1060+ unmanaged
1061+
1062+If something (i.e. gnome-shell or an extension) tries to activate an unmanaged
1063+window, we should warn about this and avoid to perform further actions as this
1064+could lead to a crash of mutter, since the window has not valid flags (like
1065+workspace) set anymore at this stage.
1066+
1067+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/580
1068+
1069+https://gitlab.gnome.org/GNOME/mutter/merge_requests/564
1070+
1071+(cherry picked from commit a6fc656e917fd48b8708b8d9f4bf9f8b15581313)
1072+
1073+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
1074+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1075+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1076+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1077+Applied-Upstream: 3.28.5
1078+---
1079+ src/core/window.c | 7 +++++++
1080+ 1 file changed, 7 insertions(+)
1081+
1082+diff --git a/src/core/window.c b/src/core/window.c
1083+index eaae5b0..32c9461 100644
1084+--- a/src/core/window.c
1085++++ b/src/core/window.c
1086+@@ -3622,6 +3622,13 @@ meta_window_activate_full (MetaWindow *window,
1087+ MetaWorkspace *workspace)
1088+ {
1089+ gboolean allow_workspace_switch;
1090++
1091++ if (window->unmanaging)
1092++ {
1093++ g_warning ("Trying to activate unmanaged window '%s'", window->desc);
1094++ return;
1095++ }
1096++
1097+ meta_topic (META_DEBUG_FOCUS,
1098+ "_NET_ACTIVE_WINDOW message sent for %s at time %u "
1099+ "by client type %u.\n",
1100diff --git a/debian/patches/window-x11-Accept-any-focusable-window-as-fallback-focus.patch b/debian/patches/window-x11-Accept-any-focusable-window-as-fallback-focus.patch
1101new file mode 100644
1102index 0000000..77c2843
1103--- /dev/null
1104+++ b/debian/patches/window-x11-Accept-any-focusable-window-as-fallback-focus.patch
1105@@ -0,0 +1,109 @@
1106+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1107+Date: Wed, 3 Jul 2019 11:15:36 +0200
1108+Subject: window-x11: Accept any focusable window as fallback focus
1109+
1110+As per commit f71151a5 we were ignoring WM_TAKE_FOCUS-only windows as focus
1111+targets, however this might end-up in an infinite loop if there are multiple
1112+non-input windows stacked.
1113+
1114+So, accept any focusable window as fallback focus target even if it's a
1115+take-focus one (that might not reply to the request).
1116+
1117+Added a stacking test to verify this.
1118+
1119+Closes: https://gitlab.gnome.org/GNOME/mutter/issues/660
1120+https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1121+
1122+(cherry picked from commit c327b2df95ff9979dd22bca2e0d285e1b3ba0add)
1123+
1124+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1125+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1126+Bug-Ubuntu: https://launchpad.net/bugs/1834583
1127+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1128+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/660
1129+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1130+Applied-Upstream: 3.28.5
1131+---
1132+ src/Makefile-tests.am | 1 +
1133+ .../closed-transient-no-input-parents.metatest | 46 ++++++++++++++++++++++
1134+ src/x11/window-x11.c | 2 +-
1135+ 3 files changed, 48 insertions(+), 1 deletion(-)
1136+ create mode 100644 src/tests/stacking/closed-transient-no-input-parents.metatest
1137+
1138+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
1139+index eca6a7b..21d0619 100644
1140+--- a/src/Makefile-tests.am
1141++++ b/src/Makefile-tests.am
1142+@@ -19,6 +19,7 @@ dist_stacking_DATA = \
1143+ tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest \
1144+ tests/stacking/closed-transient-no-input-parent.metatest \
1145+ tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest \
1146++ tests/stacking/closed-transient-no-input-parents.metatest \
1147+ tests/stacking/minimized.metatest \
1148+ tests/stacking/mixed-windows.metatest \
1149+ tests/stacking/set-parent.metatest \
1150+diff --git a/src/tests/stacking/closed-transient-no-input-parents.metatest b/src/tests/stacking/closed-transient-no-input-parents.metatest
1151+new file mode 100644
1152+index 0000000..e3ec2e8
1153+--- /dev/null
1154++++ b/src/tests/stacking/closed-transient-no-input-parents.metatest
1155+@@ -0,0 +1,46 @@
1156++new_client 0 x11
1157++create 0/1
1158++show 0/1
1159++
1160++new_client 1 x11
1161++create 1/1
1162++show 1/1
1163++
1164++create 1/2 csd
1165++set_parent 1/2 1
1166++accept_focus 1/2 false
1167++show 1/2
1168++
1169++create 1/3 csd
1170++set_parent 1/3 2
1171++accept_focus 1/3 false
1172++show 1/3
1173++
1174++create 1/4 csd
1175++set_parent 1/4 3
1176++accept_focus 1/4 false
1177++show 1/4
1178++
1179++create 1/5 csd
1180++set_parent 1/5 3
1181++show 1/5
1182++
1183++wait
1184++assert_focused 1/5
1185++assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
1186++
1187++destroy 1/5
1188++dispatch
1189++
1190++assert_focused none
1191++assert_stacking 0/1 1/1 1/2 1/3 1/4
1192++
1193++sleep 250
1194++assert_focused none
1195++assert_stacking 0/1 1/1 1/2 1/3 1/4
1196++
1197++destroy 1/3
1198++wait
1199++
1200++assert_focused none
1201++assert_stacking 0/1 1/1 1/2 1/4
1202+diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
1203+index c09ba3e..7dff35e 100644
1204+--- a/src/x11/window-x11.c
1205++++ b/src/x11/window-x11.c
1206+@@ -852,7 +852,7 @@ meta_window_x11_focus (MetaWindow *window,
1207+ if (!focus_window)
1208+ break;
1209+
1210+- if (focus_window->input)
1211++ if (focus_window->input || focus_window->take_focus)
1212+ break;
1213+
1214+ if (focus_window->shaded && focus_window->frame)
1215diff --git a/debian/patches/window-x11-Don-t-double-check-for-unmanaging-windows.patch b/debian/patches/window-x11-Don-t-double-check-for-unmanaging-windows.patch
1216new file mode 100644
1217index 0000000..8127f55
1218--- /dev/null
1219+++ b/debian/patches/window-x11-Don-t-double-check-for-unmanaging-windows.patch
1220@@ -0,0 +1,39 @@
1221+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1222+Date: Mon, 1 Jul 2019 10:38:02 +0200
1223+Subject: window-x11: Don't double-check for unmanaging windows
1224+
1225+When looking for the best fallback focus window, we ignore it if it is in the
1226+unmanaging state, but meta_stack_get_default_focus_window() does this is check
1227+for us already.
1228+
1229+So, ignore the redundant test.
1230+
1231+https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1232+
1233+(cherry picked from commit 9aee47daa984e5cc4a1ccefb3aacfbb2729cfbc1)
1234+
1235+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1236+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1237+Bug-Ubuntu: https://launchpad.net/bugs/1834583
1238+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1239+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/660
1240+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1241+Applied-Upstream: 3.28.5
1242+---
1243+ src/x11/window-x11.c | 3 ---
1244+ 1 file changed, 3 deletions(-)
1245+
1246+diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
1247+index 29ea3a6..c09ba3e 100644
1248+--- a/src/x11/window-x11.c
1249++++ b/src/x11/window-x11.c
1250+@@ -852,9 +852,6 @@ meta_window_x11_focus (MetaWindow *window,
1251+ if (!focus_window)
1252+ break;
1253+
1254+- if (focus_window->unmanaging)
1255+- continue;
1256+-
1257+ if (focus_window->input)
1258+ break;
1259+
1260diff --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
1261new file mode 100644
1262index 0000000..9e9af63
1263--- /dev/null
1264+++ b/debian/patches/window-x11-Focus-the-default-window-with-delay-while-wait.patch
1265@@ -0,0 +1,247 @@
1266+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1267+Date: Wed, 14 Nov 2018 00:08:34 +0100
1268+Subject: window-x11: Focus the default window with delay while waiting for
1269+ take-focus
1270+
1271+When requesting to a take-focus window to acquire the input, the client may or
1272+may not respond with a SetInputFocus (this doesn't happen for no-input gtk
1273+windows in fact [to be fixed there too]), in such case we were unsetting the
1274+focus while waiting the reply.
1275+
1276+In case the client won't respond, we wait for a small delay (set to 250 ms) for
1277+the take-focus window to grab the input focus before setting it to the default
1278+window.
1279+
1280+Added a test for this behavior and for the case in which a window takes the
1281+focus meanwhile we're waiting to focus the default window.
1282+
1283+https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
1284+(cherry picked from commit f71151a5dd990d935f3fbb39451f9b41f640b625)
1285+
1286+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
1287+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1288+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1289+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1290+Applied-Upstream: 3.28.5
1291+---
1292+ src/Makefile-tests.am | 1 +
1293+ ...parent-delayed-focus-default-cancelled.metatest | 36 ++++++++
1294+ .../closed-transient-no-input-parent.metatest | 16 +++-
1295+ src/x11/window-x11.c | 101 ++++++++++++++++++++-
1296+ 4 files changed, 146 insertions(+), 8 deletions(-)
1297+ create mode 100644 src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest
1298+
1299+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
1300+index 3764917..eca6a7b 100644
1301+--- a/src/Makefile-tests.am
1302++++ b/src/Makefile-tests.am
1303+@@ -18,6 +18,7 @@ dist_stacking_DATA = \
1304+ tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest \
1305+ tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest \
1306+ tests/stacking/closed-transient-no-input-parent.metatest \
1307++ tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest \
1308+ tests/stacking/minimized.metatest \
1309+ tests/stacking/mixed-windows.metatest \
1310+ tests/stacking/set-parent.metatest \
1311+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
1312+new file mode 100644
1313+index 0000000..38897e3
1314+--- /dev/null
1315++++ b/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest
1316+@@ -0,0 +1,36 @@
1317++new_client 2 x11
1318++create 2/1
1319++show 2/1
1320++
1321++new_client 1 x11
1322++create 1/1
1323++show 1/1
1324++
1325++create 1/2 csd
1326++set_parent 1/2 1
1327++accept_focus 1/2 false
1328++show 1/2
1329++
1330++create 1/3 csd
1331++set_parent 1/3 2
1332++show 1/3
1333++
1334++wait
1335++assert_focused 1/3
1336++assert_stacking 2/1 1/1 1/2 1/3
1337++
1338++destroy 1/3
1339++sleep 10
1340++
1341++assert_focused none
1342++assert_stacking 2/1 1/1 1/2
1343++
1344++activate 2/1
1345++wait
1346++
1347++assert_focused 2/1
1348++assert_stacking 1/1 1/2 2/1
1349++
1350++sleep 250
1351++assert_focused 2/1
1352++assert_stacking 1/1 1/2 2/1
1353+diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest
1354+index 4cadb23..e0f1dc1 100644
1355+--- a/src/tests/stacking/closed-transient-no-input-parent.metatest
1356++++ b/src/tests/stacking/closed-transient-no-input-parent.metatest
1357+@@ -1,3 +1,7 @@
1358++new_client 2 x11
1359++create 2/1
1360++show 2/1
1361++
1362+ new_client 1 x11
1363+ create 1/1
1364+ show 1/1
1365+@@ -12,9 +16,15 @@ set_parent 1/3 2
1366+ show 1/3
1367+
1368+ wait
1369+-assert_stacking 1/1 1/2 1/3
1370++assert_focused 1/3
1371++assert_stacking 2/1 1/1 1/2 1/3
1372+
1373+ destroy 1/3
1374++dispatch
1375+
1376+-wait
1377+-assert_stacking 1/1 1/2
1378++assert_focused none
1379++assert_stacking 2/1 1/1 1/2
1380++
1381++sleep 250
1382++assert_focused 1/1
1383++assert_stacking 2/1 1/1 1/2
1384+diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
1385+index e1c3441..29ea3a6 100644
1386+--- a/src/x11/window-x11.c
1387++++ b/src/x11/window-x11.c
1388+@@ -53,6 +53,8 @@
1389+ #include "backends/meta-logical-monitor.h"
1390+ #include "backends/x11/meta-backend-x11.h"
1391+
1392++#define TAKE_FOCUS_FALLBACK_DELAY_MS 250
1393++
1394+ G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
1395+
1396+ static void
1397+@@ -722,6 +724,66 @@ request_take_focus (MetaWindow *window,
1398+ send_icccm_message (window, display->atom_WM_TAKE_FOCUS, timestamp);
1399+ }
1400+
1401++typedef struct
1402++{
1403++ MetaWindow *window;
1404++ guint32 timestamp;
1405++ guint timeout_id;
1406++ gulong unmanaged_id;
1407++ gulong focused_changed_id;
1408++} MetaWindowX11DelayedFocusData;
1409++
1410++static void
1411++meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data)
1412++{
1413++ g_signal_handler_disconnect (data->window, data->unmanaged_id);
1414++ g_signal_handler_disconnect (data->window->display, data->focused_changed_id);
1415++
1416++ if (data->timeout_id)
1417++ g_source_remove (data->timeout_id);
1418++
1419++ g_free (data);
1420++}
1421++
1422++static gboolean
1423++focus_window_delayed_timeout (gpointer user_data)
1424++{
1425++ MetaWindowX11DelayedFocusData *data = user_data;
1426++ MetaWindow *window = data->window;
1427++ guint32 timestamp = data->timestamp;
1428++
1429++ data->timeout_id = 0;
1430++ meta_window_x11_delayed_focus_data_free (data);
1431++
1432++ meta_window_focus (window, timestamp);
1433++
1434++ return G_SOURCE_REMOVE;
1435++}
1436++
1437++static void
1438++meta_window_x11_maybe_focus_delayed (MetaWindow *window,
1439++ guint32 timestamp)
1440++{
1441++ MetaWindowX11DelayedFocusData *data;
1442++
1443++ data = g_new0 (MetaWindowX11DelayedFocusData, 1);
1444++ data->window = window;
1445++ data->timestamp = timestamp;
1446++
1447++ data->unmanaged_id =
1448++ g_signal_connect_swapped (window, "unmanaged",
1449++ G_CALLBACK (meta_window_x11_delayed_focus_data_free),
1450++ data);
1451++
1452++ data->focused_changed_id =
1453++ g_signal_connect_swapped (window->display, "notify::focus-window",
1454++ G_CALLBACK (meta_window_x11_delayed_focus_data_free),
1455++ data);
1456++
1457++ data->timeout_id = g_timeout_add (TAKE_FOCUS_FALLBACK_DELAY_MS,
1458++ focus_window_delayed_timeout, data);
1459++}
1460++
1461+ static void
1462+ meta_window_x11_focus (MetaWindow *window,
1463+ guint32 timestamp)
1464+@@ -771,14 +833,43 @@ meta_window_x11_focus (MetaWindow *window,
1465+ * Normally, we want to just leave the focus undisturbed until
1466+ * the window responds to WM_TAKE_FOCUS, but if we're unmanaging
1467+ * the current focus window we *need* to move the focus away, so
1468+- * we focus the no_focus_window now (and set
1469+- * display->focus_window to that) before sending WM_TAKE_FOCUS.
1470++ * we focus the no focus window before sending WM_TAKE_FOCUS,
1471++ * and eventually the default focus windwo excluding this one,
1472++ * if meanwhile we don't get any focus request.
1473+ */
1474+ if (window->display->focus_window != NULL &&
1475+ window->display->focus_window->unmanaging)
1476+- meta_display_focus_the_no_focus_window (window->display,
1477+- window->screen,
1478+- timestamp);
1479++ {
1480++ MetaWindow *focus_window = window;
1481++ MetaWorkspace *workspace = window->workspace;
1482++ MetaStack *stack = window->screen->stack;
1483++
1484++ while (TRUE)
1485++ {
1486++ focus_window = meta_stack_get_default_focus_window (stack,
1487++ workspace,
1488++ focus_window);
1489++ if (!focus_window)
1490++ break;
1491++
1492++ if (focus_window->unmanaging)
1493++ continue;
1494++
1495++ if (focus_window->input)
1496++ break;
1497++
1498++ if (focus_window->shaded && focus_window->frame)
1499++ break;
1500++ }
1501++
1502++ meta_display_focus_the_no_focus_window (window->display,
1503++ window->screen,
1504++ timestamp);
1505++
1506++ if (focus_window)
1507++ meta_window_x11_maybe_focus_delayed (focus_window,
1508++ timestamp);
1509++ }
1510+ }
1511+
1512+ request_take_focus (window, timestamp);
1513diff --git a/debian/patches/window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch b/debian/patches/window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch
1514new file mode 100644
1515index 0000000..a29f61e
1516--- /dev/null
1517+++ b/debian/patches/window-x11-Use-any-focusable-window-as-fallback-delayed-f.patch
1518@@ -0,0 +1,339 @@
1519+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1520+Date: Wed, 3 Jul 2019 12:04:08 +0200
1521+Subject: window-x11: Use any focusable window as fallback delayed focus
1522+ window
1523+
1524+As per commit f71151a5 we focus an input window if no take-focus-window accepts
1525+it. This might lead to an infinite loop if there are various focusable but
1526+non-input windows in the stack.
1527+
1528+When the current focus window is unmanaging and we're trying to focus a
1529+WM_TAKE_FOCUS window, we intent to give the focus to the first focusable input
1530+window in the stack.
1531+
1532+However, if an application (such as the Java ones) only uses non-input
1533+WM_TAKE_FOCUS windows, are not requesting these ones to get the focus. This
1534+might lead to a state where no window is focused, or a wrong one is.
1535+
1536+So, instead of only focus the first eventually input window available, try to
1537+request to all the take-focus windows that are in the stack between the
1538+destroyed one and the first input one to acquire the input focus.
1539+Use a queue to keep track of those windows, that is passed around stealing
1540+ownership, while we protect for unmanaged queued windows.
1541+
1542+Also, reduce the default timeout value, as the previous one might lead to an
1543+excessive long wait.
1544+
1545+Added metatests verifying these situations.
1546+
1547+Closes: https://gitlab.gnome.org/GNOME/mutter/issues/660
1548+https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1549+
1550+(cherry picked from commit 6d8293a422b08af97d3da985d49448db32d59248)
1551+
1552+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
1553+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1554+Bug-Ubuntu: https://launchpad.net/bugs/1834583
1555+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1556+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/660
1557+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1558+Applied-Upstream: 3.28.5
1559+---
1560+ src/Makefile-tests.am | 1 +
1561+ .../closed-transient-no-input-parent.metatest | 2 +-
1562+ ...parents-queued-default-focus-destroyed.metatest | 43 ++++++++
1563+ .../closed-transient-no-input-parents.metatest | 6 +-
1564+ src/x11/window-x11.c | 120 ++++++++++++++++-----
1565+ 5 files changed, 144 insertions(+), 28 deletions(-)
1566+ create mode 100644 src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest
1567+
1568+diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
1569+index 21d0619..359f398 100644
1570+--- a/src/Makefile-tests.am
1571++++ b/src/Makefile-tests.am
1572+@@ -20,6 +20,7 @@ dist_stacking_DATA = \
1573+ tests/stacking/closed-transient-no-input-parent.metatest \
1574+ tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest \
1575+ tests/stacking/closed-transient-no-input-parents.metatest \
1576++ tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest \
1577+ tests/stacking/minimized.metatest \
1578+ tests/stacking/mixed-windows.metatest \
1579+ tests/stacking/set-parent.metatest \
1580+diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest
1581+index e0f1dc1..d0f3228 100644
1582+--- a/src/tests/stacking/closed-transient-no-input-parent.metatest
1583++++ b/src/tests/stacking/closed-transient-no-input-parent.metatest
1584+@@ -25,6 +25,6 @@ dispatch
1585+ assert_focused none
1586+ assert_stacking 2/1 1/1 1/2
1587+
1588+-sleep 250
1589++sleep 150
1590+ assert_focused 1/1
1591+ assert_stacking 2/1 1/1 1/2
1592+diff --git a/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest b/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest
1593+new file mode 100644
1594+index 0000000..49ecc51
1595+--- /dev/null
1596++++ b/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest
1597+@@ -0,0 +1,43 @@
1598++new_client 0 x11
1599++create 0/1
1600++show 0/1
1601++
1602++new_client 1 x11
1603++create 1/1
1604++show 1/1
1605++
1606++create 1/2 csd
1607++set_parent 1/2 1
1608++accept_focus 1/2 false
1609++show 1/2
1610++
1611++create 1/3 csd
1612++set_parent 1/3 2
1613++accept_focus 1/3 false
1614++show 1/3
1615++
1616++create 1/4 csd
1617++set_parent 1/4 3
1618++accept_focus 1/4 false
1619++show 1/4
1620++
1621++create 1/5 csd
1622++set_parent 1/5 3
1623++show 1/5
1624++
1625++wait
1626++assert_focused 1/5
1627++assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
1628++
1629++destroy 1/5
1630++dispatch
1631++
1632++assert_focused none
1633++assert_stacking 0/1 1/1 1/2 1/3 1/4
1634++
1635++destroy 1/2
1636++dispatch
1637++
1638++sleep 450
1639++assert_focused 1/1
1640++assert_stacking 0/1 1/1 1/3 1/4
1641+diff --git a/src/tests/stacking/closed-transient-no-input-parents.metatest b/src/tests/stacking/closed-transient-no-input-parents.metatest
1642+index e3ec2e8..ee99841 100644
1643+--- a/src/tests/stacking/closed-transient-no-input-parents.metatest
1644++++ b/src/tests/stacking/closed-transient-no-input-parents.metatest
1645+@@ -35,12 +35,12 @@ dispatch
1646+ assert_focused none
1647+ assert_stacking 0/1 1/1 1/2 1/3 1/4
1648+
1649+-sleep 250
1650+-assert_focused none
1651++sleep 600
1652++assert_focused 1/1
1653+ assert_stacking 0/1 1/1 1/2 1/3 1/4
1654+
1655+ destroy 1/3
1656+ wait
1657+
1658+-assert_focused none
1659++assert_focused 1/1
1660+ assert_stacking 0/1 1/1 1/2 1/4
1661+diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
1662+index 7dff35e..60b121f 100644
1663+--- a/src/x11/window-x11.c
1664++++ b/src/x11/window-x11.c
1665+@@ -53,10 +53,15 @@
1666+ #include "backends/meta-logical-monitor.h"
1667+ #include "backends/x11/meta-backend-x11.h"
1668+
1669+-#define TAKE_FOCUS_FALLBACK_DELAY_MS 250
1670++#define TAKE_FOCUS_FALLBACK_DELAY_MS 150
1671+
1672+ G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
1673+
1674++static void
1675++meta_window_x11_maybe_focus_delayed (MetaWindow *window,
1676++ GQueue *other_focus_candidates,
1677++ guint32 timestamp);
1678++
1679+ static void
1680+ meta_window_x11_init (MetaWindowX11 *window_x11)
1681+ {
1682+@@ -727,24 +732,60 @@ request_take_focus (MetaWindow *window,
1683+ typedef struct
1684+ {
1685+ MetaWindow *window;
1686++ GQueue *pending_focus_candidates;
1687+ guint32 timestamp;
1688+ guint timeout_id;
1689+ gulong unmanaged_id;
1690+ gulong focused_changed_id;
1691+ } MetaWindowX11DelayedFocusData;
1692+
1693++static void
1694++disconnect_pending_focus_window_signals (MetaWindow *window,
1695++ GQueue *focus_candidates)
1696++{
1697++ g_signal_handlers_disconnect_by_func (window, g_queue_remove,
1698++ focus_candidates);
1699++}
1700++
1701+ static void
1702+ meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data)
1703+ {
1704+ g_signal_handler_disconnect (data->window, data->unmanaged_id);
1705+ g_signal_handler_disconnect (data->window->display, data->focused_changed_id);
1706+
1707++ if (data->pending_focus_candidates)
1708++ {
1709++ g_queue_foreach (data->pending_focus_candidates,
1710++ (GFunc) disconnect_pending_focus_window_signals,
1711++ data->pending_focus_candidates);
1712++ g_queue_free (data->pending_focus_candidates);
1713++ }
1714++
1715+ if (data->timeout_id)
1716+ g_source_remove (data->timeout_id);
1717+
1718+ g_free (data);
1719+ }
1720+
1721++static void
1722++focus_candidates_maybe_take_and_focus_next (GQueue **focus_candidates_ptr,
1723++ guint32 timestamp)
1724++{
1725++ MetaWindow *focus_window;
1726++ GQueue *focus_candidates;
1727++
1728++ g_assert (*focus_candidates_ptr);
1729++
1730++ if (g_queue_is_empty (*focus_candidates_ptr))
1731++ return;
1732++
1733++ focus_candidates = g_steal_pointer (focus_candidates_ptr);
1734++ focus_window = g_queue_pop_head (focus_candidates);
1735++
1736++ disconnect_pending_focus_window_signals (focus_window, focus_candidates);
1737++ meta_window_x11_maybe_focus_delayed (focus_window, focus_candidates, timestamp);
1738++}
1739++
1740+ static gboolean
1741+ focus_window_delayed_timeout (gpointer user_data)
1742+ {
1743+@@ -752,6 +793,9 @@ focus_window_delayed_timeout (gpointer user_data)
1744+ MetaWindow *window = data->window;
1745+ guint32 timestamp = data->timestamp;
1746+
1747++ focus_candidates_maybe_take_and_focus_next (&data->pending_focus_candidates,
1748++ timestamp);
1749++
1750+ data->timeout_id = 0;
1751+ meta_window_x11_delayed_focus_data_free (data);
1752+
1753+@@ -762,6 +806,7 @@ focus_window_delayed_timeout (gpointer user_data)
1754+
1755+ static void
1756+ meta_window_x11_maybe_focus_delayed (MetaWindow *window,
1757++ GQueue *other_focus_candidates,
1758+ guint32 timestamp)
1759+ {
1760+ MetaWindowX11DelayedFocusData *data;
1761+@@ -769,6 +814,10 @@ meta_window_x11_maybe_focus_delayed (MetaWindow *window,
1762+ data = g_new0 (MetaWindowX11DelayedFocusData, 1);
1763+ data->window = window;
1764+ data->timestamp = timestamp;
1765++ data->pending_focus_candidates = other_focus_candidates;
1766++
1767++ meta_topic (META_DEBUG_FOCUS,
1768++ "Requesting delayed focus to %s\n", window->desc);
1769+
1770+ data->unmanaged_id =
1771+ g_signal_connect_swapped (window, "unmanaged",
1772+@@ -784,6 +833,50 @@ meta_window_x11_maybe_focus_delayed (MetaWindow *window,
1773+ focus_window_delayed_timeout, data);
1774+ }
1775+
1776++static void
1777++maybe_focus_default_window (MetaWorkspace *workspace,
1778++ MetaWindow *not_this_one,
1779++ guint32 timestamp)
1780++{
1781++ MetaStack *stack = workspace->screen->stack;
1782++ g_autoptr (GList) focusable_windows = NULL;
1783++ g_autoptr (GQueue) focus_candidates = NULL;
1784++ GList *l;
1785++
1786++ /* Go through all the focusable windows and try to focus them
1787++ * in order, waiting for a delay. The first one that replies to
1788++ * the request (in case of take focus windows) changing the display
1789++ * focused window, will stop the chained requests.
1790++ */
1791++ focusable_windows =
1792++ meta_stack_get_default_focus_candidates (stack, workspace);
1793++ focus_candidates = g_queue_new ();
1794++
1795++ for (l = g_list_last (focusable_windows); l; l = l->prev)
1796++ {
1797++ MetaWindow *focus_window = l->data;
1798++
1799++ if (focus_window == not_this_one)
1800++ continue;
1801++
1802++ g_queue_push_tail (focus_candidates, focus_window);
1803++ g_signal_connect_swapped (focus_window, "unmanaged",
1804++ G_CALLBACK (g_queue_remove),
1805++ focus_candidates);
1806++
1807++ if (!META_IS_WINDOW_X11 (focus_window))
1808++ break;
1809++
1810++ if (focus_window->input)
1811++ break;
1812++
1813++ if (focus_window->shaded && focus_window->frame)
1814++ break;
1815++ }
1816++
1817++ focus_candidates_maybe_take_and_focus_next (&focus_candidates, timestamp);
1818++}
1819++
1820+ static void
1821+ meta_window_x11_focus (MetaWindow *window,
1822+ guint32 timestamp)
1823+@@ -840,32 +933,11 @@ meta_window_x11_focus (MetaWindow *window,
1824+ if (window->display->focus_window != NULL &&
1825+ window->display->focus_window->unmanaging)
1826+ {
1827+- MetaWindow *focus_window = window;
1828+- MetaWorkspace *workspace = window->workspace;
1829+- MetaStack *stack = window->screen->stack;
1830+-
1831+- while (TRUE)
1832+- {
1833+- focus_window = meta_stack_get_default_focus_window (stack,
1834+- workspace,
1835+- focus_window);
1836+- if (!focus_window)
1837+- break;
1838+-
1839+- if (focus_window->input || focus_window->take_focus)
1840+- break;
1841+-
1842+- if (focus_window->shaded && focus_window->frame)
1843+- break;
1844+- }
1845+-
1846+ meta_display_focus_the_no_focus_window (window->display,
1847+ window->screen,
1848+ timestamp);
1849+-
1850+- if (focus_window)
1851+- meta_window_x11_maybe_focus_delayed (focus_window,
1852+- timestamp);
1853++ maybe_focus_default_window (window->workspace, window,
1854++ timestamp);
1855+ }
1856+ }
1857+
1858diff --git a/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch b/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch
1859new file mode 100644
1860index 0000000..53d4ff0
1861--- /dev/null
1862+++ b/debian/patches/workspace-Focus-only-ancestors-that-are-focusable.patch
1863@@ -0,0 +1,85 @@
1864+From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
1865+Date: Tue, 13 Nov 2018 08:31:52 +0100
1866+Subject: workspace: Focus only ancestors that are focusable
1867+
1868+When destroying a window that has a parent, we initially try to focus one of
1869+its ancestors. However if no ancestor can be focused, then we should instead
1870+focus the default focus window instead of trying to request focus for a window
1871+that can't get focus anyways.
1872+
1873+Fixes https://gitlab.gnome.org/GNOME/mutter/issues/308
1874+(cherry picked from commit eccc791f3b3451216f957e67fec47a73b65ed2b2)
1875+
1876+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
1877+Bug-Ubuntu: https://launchpad.net/bugs/1791574
1878+Bug-JetBrains: https://youtrack.jetbrains.com/issue/IDEA-198187
1879+Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/issues/308
1880+Applied-Upstream: 3.28.5
1881+---
1882+ src/core/workspace.c | 37 +++++++++++++++++++++++++++----------
1883+ 1 file changed, 27 insertions(+), 10 deletions(-)
1884+
1885+diff --git a/src/core/workspace.c b/src/core/workspace.c
1886+index a964e66..d194943 100644
1887+--- a/src/core/workspace.c
1888++++ b/src/core/workspace.c
1889+@@ -85,6 +85,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData
1890+ MetaRectangle logical_monitor_work_area;
1891+ } MetaWorkspaceLogicalMonitorData;
1892+
1893++typedef struct _MetaWorkspaceFocusableAncestorData
1894++{
1895++ MetaWorkspace *workspace;
1896++ MetaWindow *out_window;
1897++} MetaWorkspaceFocusableAncestorData;
1898++
1899+ static MetaWorkspaceLogicalMonitorData *
1900+ meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace,
1901+ MetaLogicalMonitor *logical_monitor)
1902+@@ -1319,13 +1325,20 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
1903+ }
1904+
1905+ static gboolean
1906+-record_ancestor (MetaWindow *window,
1907+- void *data)
1908++find_focusable_ancestor (MetaWindow *window,
1909++ gpointer user_data)
1910+ {
1911+- MetaWindow **result = data;
1912++ MetaWorkspaceFocusableAncestorData *data = user_data;
1913++
1914++ if (!window->unmanaging && (window->input || window->take_focus) &&
1915++ meta_window_located_on_workspace (window, data->workspace) &&
1916++ meta_window_showing_on_its_workspace (window))
1917++ {
1918++ data->out_window = window;
1919++ return FALSE;
1920++ }
1921+
1922+- *result = window;
1923+- return FALSE; /* quit with the first ancestor we find */
1924++ return TRUE;
1925+ }
1926+
1927+ /* Focus ancestor of not_this_one if there is one */
1928+@@ -1347,11 +1360,15 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
1929+ if (not_this_one)
1930+ {
1931+ MetaWindow *ancestor;
1932+- ancestor = NULL;
1933+- meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
1934+- if (ancestor != NULL &&
1935+- meta_window_located_on_workspace (ancestor, workspace) &&
1936+- meta_window_showing_on_its_workspace (ancestor))
1937++ MetaWorkspaceFocusableAncestorData data;
1938++
1939++ data = (MetaWorkspaceFocusableAncestorData) {
1940++ .workspace = workspace,
1941++ };
1942++ meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data);
1943++ ancestor = data.out_window;
1944++
1945++ if (ancestor)
1946+ {
1947+ meta_topic (META_DEBUG_FOCUS,
1948+ "Focusing %s, ancestor of %s\n",

Subscribers

People subscribed via source and target branches