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: b154de179b5d063103bf958fb30e4544e2527d55
Proposed branch: ~3v1n0/ubuntu/+source/mutter:ubuntu/bionic
Merge into: ~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic
Diff against target: 1319 lines (+1031/-226)
9 files modified
debian/changelog (+18/-0)
debian/patches/clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch (+53/-0)
debian/patches/clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch (+294/-0)
debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch (+372/-0)
debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch (+53/-0)
debian/patches/monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch (+37/-0)
debian/patches/monitor-manager-use-MonitorsConfig-to-track-switch_config.patch (+198/-0)
debian/patches/series (+6/-1)
dev/null (+0/-225)
Reviewer Review Type Date Requested Status
Daniel van Vugt (community) Approve
Ubuntu Desktop Pending
Review via email: mp+366676@code.launchpad.net
To post a comment you must log in.
ce3f911... by Marco Trevisan (Treviño)

debian/patches: Ignore new symbols added in switch-config

No need to export new symbols for this one

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Looking good.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It looks like this has landed. Please close this MP.

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 99219d6..a1467bf 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,21 @@
6+mutter (3.28.3+git20190124-0ubuntu18.04.3) UNRELEASED; urgency=medium
7+
8+ * d/p/monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch,
9+ d/p/monitor-manager-use-MonitorsConfig-to-track-switch_config.patch:
10+ - Ensure switch display mode is cyclic (LP: #1772811)
11+ * d/p/clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch,
12+ d/p/clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch:
13+ - Implement keycode remap to keysyms on virtual key devices (LP: #1827029)
14+
15+ [ Daniel van Vugt ]
16+ * d/p/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch,
17+ d/p/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch:
18+ - Add support for high frame rate displays (LP: #1763892)
19+ * d/p/clutter-Smooth-out-master-clock-to-smooth-visuals.patch:
20+ - Dropped
21+
22+ -- Marco Trevisan (Treviño) <marco@ubuntu.com> Mon, 29 Apr 2019 23:29:24 -0500
23+
24 mutter (3.28.3+git20190124-0ubuntu18.04.2) bionic; urgency=medium
25
26 * control: Add Breaks on budgie-desktop verions broken by this upload.
27diff --git a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch b/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
28deleted file mode 100644
29index 2239837..0000000
30--- a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
31+++ /dev/null
32@@ -1,225 +0,0 @@
33-From: Daniel van Vugt <daniel.van.vugt@canonical.com>
34-Date: Fri, 16 Feb 2018 02:50:59 -0600
35-Subject: clutter: Smooth out master clock to smooth visuals
36-
37-Clutter's master clock was jittery because it included errors in cur_tick
38-such as dispatch delays due to other sources. Dispatch could also occur up
39-to 1ms early since GSource can only be timed to the millisecond. All of this
40-could impact the visual smoothness of animations as they are displayed on
41-the steady interval of the monitor, but spacially moving in less regular
42-steps derived from the dispatch times.
43-
44-The simple fix is to ignore any jitter in dispatch timing. Try a little
45-bit harder to use a precise interval that will better match the display
46-hardware, and smoother visuals will follow.
47-
48-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/25
49-Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/70
50----
51- clutter/clutter/clutter-master-clock-default.c | 134 +++++++++++++++++--------
52- 1 file changed, 93 insertions(+), 41 deletions(-)
53-
54-diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c
55-index 7b2df0d..97b6d13 100644
56---- a/clutter/clutter/clutter-master-clock-default.c
57-+++ b/clutter/clutter/clutter-master-clock-default.c
58-@@ -69,8 +69,10 @@ struct _ClutterMasterClockDefault
59- /* the previous state of the clock, in usecs, used to compute the delta */
60- gint64 prev_tick;
61-
62-+ /* the ideal frame interval in usecs (inverse of your max refresh rate) */
63-+ gint64 frame_interval;
64-+
65- #ifdef CLUTTER_ENABLE_DEBUG
66-- gint64 frame_budget;
67- gint64 remaining_budget;
68- #endif
69-
70-@@ -264,6 +266,41 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
71- }
72- }
73-
74-+static gint64
75-+estimate_next_presentation_time (ClutterMasterClockDefault *master_clock)
76-+{
77-+ gint64 frame_phase, now, now_phase, undershoot;
78-+
79-+ /* In future if this was updated from the backend's (maximum) refresh rate
80-+ * then that would fix: https://bugzilla.gnome.org/show_bug.cgi?id=781296
81-+ */
82-+ master_clock->frame_interval = G_USEC_PER_SEC /
83-+ clutter_get_default_frame_rate ();
84-+
85-+ now = g_source_get_time (master_clock->source);
86-+ now_phase = now % master_clock->frame_interval;
87-+
88-+ /* To be precise we would like to use:
89-+ * frame_phase = a_recent_hardware_presentation_time % frame_interval;
90-+ * where hardware_presentation_time must be using the same clock as
91-+ * g_source_get_time. Unfortunately they're different clocks right now
92-+ * so we can't.
93-+ * Alternatively, we could replace g_source_get_time in future with the
94-+ * current time in the clutter/cogl presentation clock, but that function
95-+ * also doesn't exist yet.
96-+ * Until we can get either of those, zero is fine. It just means latency
97-+ * will be suboptimal by half a frame on average. We still get maximum
98-+ * smoothness this way...
99-+ */
100-+ frame_phase = 0;
101-+
102-+ undershoot = frame_phase - now_phase;
103-+ if (undershoot < 0)
104-+ undershoot += master_clock->frame_interval;
105-+
106-+ return now + undershoot;
107-+}
108-+
109- /*
110- * master_clock_next_frame_delay:
111- * @master_clock: a #ClutterMasterClock
112-@@ -276,7 +313,8 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
113- static gint
114- master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
115- {
116-- gint64 now, next;
117-+ gint64 now, target_presentation_time, ideal_render_start; /* timestamps */
118-+ gint64 ideal_prerender_time, lateness; /* deltas */
119- gint swap_delay;
120-
121- if (!master_clock_is_running (master_clock))
122-@@ -307,46 +345,45 @@ master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
123- return 0;
124- }
125-
126-- if (master_clock->prev_tick == 0)
127-- {
128-- /* If we weren't previously running, then draw the next frame
129-- * immediately
130-- */
131-- CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
132-- return 0;
133-- }
134--
135-- /* Otherwise, wait at least 1/frame_rate seconds since we last
136-- * started a frame
137-- */
138- now = g_source_get_time (master_clock->source);
139-
140-- next = master_clock->prev_tick;
141--
142-- /* If time has gone backwards then there's no way of knowing how
143-- long we should wait so let's just dispatch immediately */
144-- if (now <= next)
145-+ /* As first preference, try to carry on smoothly from the previous frame,
146-+ * even if that means we start rendering frame 2 before frame 1 has been
147-+ * presented. This is why we ignore estimate_next_presentation_time here...
148-+ */
149-+ target_presentation_time = master_clock->prev_tick +
150-+ master_clock->frame_interval;
151-+ ideal_prerender_time = master_clock->frame_interval;
152-+ ideal_render_start = target_presentation_time - ideal_prerender_time;
153-+ lateness = now - ideal_render_start;
154-+
155-+ /* If we just woke from idle then try to improve the smoothness of the first
156-+ * two frames some more. Otherwise the first frame would appear too old
157-+ * relative to the second frame.
158-+ */
159-+ if (lateness >= master_clock->frame_interval)
160- {
161-- CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
162--
163-- return 0;
164-+ target_presentation_time = estimate_next_presentation_time (master_clock);
165-+ ideal_render_start = target_presentation_time - ideal_prerender_time;
166-+ lateness = now - ideal_render_start;
167- }
168-
169-- next += (1000000L / clutter_get_default_frame_rate ());
170--
171-- if (next <= now)
172-+ if (lateness > 0)
173- {
174-- CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
175-- 1000000L / (gulong) clutter_get_default_frame_rate ());
176--
177-+ CLUTTER_NOTE (SCHEDULER, "No wait required. We're already late.");
178- return 0;
179- }
180- else
181- {
182-- CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
183-- (next - now) / 1000);
184--
185-- return (next - now) / 1000;
186-+ /* We +1 here to avoid premature dispatches that would otherwise occur
187-+ * repeatedly during the 1ms before 'ideal_render_start'. We don't care
188-+ * if this makes the final dispatch 1ms late because the smoothing
189-+ * algorithm corrects that, and it's much better than attempting to
190-+ * render more frames than the hardware can physically display...
191-+ */
192-+ gint millisec_delay = -lateness / 1000 + 1;
193-+ CLUTTER_NOTE (SCHEDULER, "Waiting %dms", millisec_delay);
194-+ return millisec_delay;
195- }
196- }
197-
198-@@ -532,16 +569,34 @@ clutter_clock_dispatch (GSource *source,
199- ClutterMasterClockDefault *master_clock = clock_source->master_clock;
200- gboolean stages_updated = FALSE;
201- GSList *stages;
202--
203-- CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
204-+ gint64 smooth_tick;
205-
206- _clutter_threads_acquire_lock ();
207-
208- /* Get the time to use for this frame */
209-- master_clock->cur_tick = g_source_get_time (source);
210-+ smooth_tick = estimate_next_presentation_time (master_clock);
211-+ if (smooth_tick <= master_clock->prev_tick)
212-+ {
213-+ /* Ordinarily this will never happen. But after we fix bug 781296, it
214-+ * could happen in the rare case when the ideal frame_interval changes,
215-+ * such as video mode switching or hotplugging monitors. As such it is
216-+ * not considered a bug (unless it's happening without mode switching
217-+ * or hotplugging).
218-+ */
219-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] was premature (skipped)");
220-+ _clutter_threads_release_lock ();
221-+ return G_SOURCE_CONTINUE;
222-+ }
223-+
224-+ master_clock->cur_tick = smooth_tick;
225-+ if (master_clock->prev_tick)
226-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] %+ldus",
227-+ (long) (master_clock->cur_tick - master_clock->prev_tick));
228-+ else
229-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] startup");
230-
231- #ifdef CLUTTER_ENABLE_DEBUG
232-- master_clock->remaining_budget = master_clock->frame_budget;
233-+ master_clock->remaining_budget = master_clock->frame_interval;
234- #endif
235-
236- /* We need to protect ourselves against stages being destroyed during
237-@@ -580,7 +635,7 @@ clutter_clock_dispatch (GSource *source,
238-
239- _clutter_threads_release_lock ();
240-
241-- return TRUE;
242-+ return G_SOURCE_CONTINUE;
243- }
244-
245- static void
246-@@ -612,10 +667,7 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
247- self->idle = FALSE;
248- self->ensure_next_iteration = FALSE;
249- self->paused = FALSE;
250--
251--#ifdef CLUTTER_ENABLE_DEBUG
252-- self->frame_budget = G_USEC_PER_SEC / 60;
253--#endif
254-+ self->frame_interval = G_USEC_PER_SEC / 60; /* Will be refined at runtime */
255-
256- g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
257- g_source_set_can_recurse (source, FALSE);
258diff --git a/debian/patches/clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch b/debian/patches/clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch
259new file mode 100644
260index 0000000..e2d3140
261--- /dev/null
262+++ b/debian/patches/clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch
263@@ -0,0 +1,53 @@
264+From: Andrea Azzarone <andrea.azzarone@canonical.com>
265+Date: Tue, 22 Jan 2019 11:20:37 -0600
266+Subject: clutter/x11: Consider remapped keys when guessing the keycode from
267+ the keysym
268+
269+Since e3e933c4 a keyval can be temporarily remapped to an unused keycode. Due to
270+some limitations in XTestFakeKeyEvent, the remapping has to be done in the first
271+xkb group/layout. In case there are two or more keyboard layouts enabled and the
272+selected keyboard layout is not the first, clutter_keymap_x11_keycode_for_keyval
273+will fail to retrieve the correct keycode for a remapped keyval. Let's use the
274+reserved_keycodes map in order to retrieve the correct keycode if needed.
275+
276+Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/443
277+
278+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/443
279+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1827029
280+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/24b4c82
281+Applied-Upstream: 3.28.4
282+---
283+ clutter/clutter/x11/clutter-keymap-x11.c | 20 ++++++++++++++++++++
284+ 1 file changed, 20 insertions(+)
285+
286+diff --git a/clutter/clutter/x11/clutter-keymap-x11.c b/clutter/clutter/x11/clutter-keymap-x11.c
287+index 5dd40a9..f1bdf16 100644
288+--- a/clutter/clutter/x11/clutter-keymap-x11.c
289++++ b/clutter/clutter/x11/clutter-keymap-x11.c
290+@@ -1005,6 +1005,26 @@ clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
291+ }
292+ }
293+
294++ if (!found)
295++ {
296++ GHashTableIter iter;
297++ gpointer key, value;
298++
299++ g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes);
300++ while (!found && g_hash_table_iter_next (&iter, &key, &value))
301++ {
302++ guint reserved_keycode = GPOINTER_TO_UINT (key);
303++ guint reserved_keysym = GPOINTER_TO_UINT (value);
304++
305++ if (keyval == reserved_keysym)
306++ {
307++ *keycode_out = reserved_keycode;
308++ *level_out = 0;
309++ found = TRUE;
310++ }
311++ }
312++ }
313++
314+ g_free (keys);
315+ return found;
316+ }
317diff --git a/debian/patches/clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch b/debian/patches/clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch
318new file mode 100644
319index 0000000..944e1ea
320--- /dev/null
321+++ b/debian/patches/clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch
322@@ -0,0 +1,294 @@
323+From: Andrea Azzarone <azzaronea@gmail.com>
324+Date: Fri, 13 Jul 2018 07:49:38 -0500
325+Subject: clutter/x11: Implement keycode remap to keysyms on virtual key
326+ devices
327+
328+Keycode lookup can fail for serveral reasons, e.g. if there is no combination of
329+modifiers and keycodes that can produce the target keysym with the current
330+keyboard layout.
331+
332+In case the keycode lookup fails, remap temporarily the keysym to an unused
333+keycodes.
334+
335+Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/109
336+
337+GNOME-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/109
338+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1827029
339+Origin: https://gitlab.gnome.org/GNOME/mutter/commit/6198d389
340+Applied-Upstream: 3.28.4
341+---
342+ clutter/clutter/x11/clutter-keymap-x11.c | 167 +++++++++++++++++++++
343+ clutter/clutter/x11/clutter-keymap-x11.h | 6 +-
344+ .../clutter/x11/clutter-virtual-input-device-x11.c | 19 ++-
345+ 3 files changed, 186 insertions(+), 6 deletions(-)
346+
347+diff --git a/clutter/clutter/x11/clutter-keymap-x11.c b/clutter/clutter/x11/clutter-keymap-x11.c
348+index c34e676..5dd40a9 100644
349+--- a/clutter/clutter/x11/clutter-keymap-x11.c
350++++ b/clutter/clutter/x11/clutter-keymap-x11.c
351+@@ -79,6 +79,9 @@ struct _ClutterKeymapX11
352+ guint current_cache_serial;
353+ DirectionCacheEntry group_direction_cache[4];
354+ int current_group;
355++
356++ GHashTable *reserved_keycodes;
357++ GQueue *available_keycodes;
358+ #endif
359+
360+ guint caps_lock_state : 1;
361+@@ -441,16 +444,100 @@ clutter_keymap_x11_set_property (GObject *gobject,
362+ }
363+ }
364+
365++#ifdef HAVE_XKB
366++static void
367++clutter_keymap_x11_refresh_reserved_keycodes (ClutterKeymapX11 *keymap_x11)
368++{
369++ Display *dpy = clutter_x11_get_default_display ();
370++ GHashTableIter iter;
371++ gpointer key, value;
372++
373++ g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes);
374++ while (g_hash_table_iter_next (&iter, &key, &value))
375++ {
376++ guint reserved_keycode = GPOINTER_TO_UINT (key);
377++ guint reserved_keysym = GPOINTER_TO_UINT (value);
378++ guint actual_keysym = XkbKeycodeToKeysym (dpy, reserved_keycode, 0, 0);
379++
380++ /* If an available keycode is no longer mapped to the stored keysym, then
381++ * the keycode should not be considered available anymore and should be
382++ * removed both from the list of available and reserved keycodes.
383++ */
384++ if (reserved_keysym != actual_keysym)
385++ {
386++ g_hash_table_iter_remove (&iter);
387++ g_queue_remove (keymap_x11->available_keycodes, key);
388++ }
389++ }
390++}
391++
392++static gboolean
393++clutter_keymap_x11_replace_keycode (ClutterKeymapX11 *keymap_x11,
394++ KeyCode keycode,
395++ KeySym keysym)
396++{
397++ if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
398++ {
399++ Display *dpy = clutter_x11_get_default_display ();
400++ XkbDescPtr xkb = get_xkb (keymap_x11);
401++ XkbMapChangesRec changes;
402++
403++ XFlush (dpy);
404++
405++ xkb->device_spec = XkbUseCoreKbd;
406++ memset (&changes, 0, sizeof(changes));
407++
408++ if (keysym != NoSymbol)
409++ {
410++ int types[XkbNumKbdGroups] = { XkbOneLevelIndex };
411++ XkbChangeTypesOfKey (xkb, keycode, 1, XkbGroup1Mask, types, &changes);
412++ XkbKeySymEntry (xkb, keycode, 0, 0) = keysym;
413++ }
414++ else
415++ {
416++ /* Reset to NoSymbol */
417++ XkbChangeTypesOfKey (xkb, keycode, 0, XkbGroup1Mask, NULL, &changes);
418++ }
419++
420++ changes.changed = XkbKeySymsMask | XkbKeyTypesMask;
421++ changes.first_key_sym = keycode;
422++ changes.num_key_syms = 1;
423++ changes.first_type = 0;
424++ changes.num_types = xkb->map->num_types;
425++ XkbChangeMap (dpy, xkb, &changes);
426++
427++ XFlush (dpy);
428++
429++ return TRUE;
430++ }
431++
432++ return FALSE;
433++}
434++#endif
435++
436+ static void
437+ clutter_keymap_x11_finalize (GObject *gobject)
438+ {
439+ ClutterKeymapX11 *keymap;
440+ ClutterEventTranslator *translator;
441++ GHashTableIter iter;
442++ gpointer key, value;
443+
444+ keymap = CLUTTER_KEYMAP_X11 (gobject);
445+ translator = CLUTTER_EVENT_TRANSLATOR (keymap);
446+
447+ #ifdef HAVE_XKB
448++ clutter_keymap_x11_refresh_reserved_keycodes (keymap);
449++ g_hash_table_iter_init (&iter, keymap->reserved_keycodes);
450++ while (g_hash_table_iter_next (&iter, &key, &value))
451++ {
452++ guint keycode = GPOINTER_TO_UINT (key);
453++ clutter_keymap_x11_replace_keycode (keymap, keycode, NoSymbol);
454++ }
455++
456++ g_hash_table_destroy (keymap->reserved_keycodes);
457++ g_queue_free (keymap->available_keycodes);
458++
459+ _clutter_backend_remove_event_translator (keymap->backend, translator);
460+
461+ if (keymap->xkb_desc != NULL)
462+@@ -460,6 +547,7 @@ clutter_keymap_x11_finalize (GObject *gobject)
463+ G_OBJECT_CLASS (clutter_keymap_x11_parent_class)->finalize (gobject);
464+ }
465+
466++
467+ static void
468+ clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
469+ {
470+@@ -483,6 +571,11 @@ clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
471+ {
472+ keymap->current_direction = PANGO_DIRECTION_NEUTRAL;
473+ keymap->current_group = -1;
474++
475++#ifdef HAVE_XKB
476++ keymap->reserved_keycodes = g_hash_table_new (NULL, NULL);
477++ keymap->available_keycodes = g_queue_new ();
478++#endif
479+ }
480+
481+ static ClutterTranslateReturn
482+@@ -766,6 +859,80 @@ clutter_keymap_x11_get_entries_for_keyval (ClutterKeymapX11 *keymap_x11,
483+ }
484+ }
485+
486++#ifdef HAVE_XKB
487++static guint
488++clutter_keymap_x11_get_available_keycode (ClutterKeymapX11 *keymap_x11)
489++{
490++ if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
491++ {
492++ clutter_keymap_x11_refresh_reserved_keycodes (keymap_x11);
493++
494++ if (g_hash_table_size (keymap_x11->reserved_keycodes) < 5)
495++ {
496++ Display *dpy = clutter_x11_get_default_display ();
497++ XkbDescPtr xkb = get_xkb (keymap_x11);
498++ guint i;
499++
500++ for (i = xkb->max_key_code; i >= xkb->min_key_code; --i)
501++ {
502++ if (XkbKeycodeToKeysym (dpy, i, 0, 0) == NoSymbol)
503++ return i;
504++ }
505++ }
506++
507++ return GPOINTER_TO_UINT (g_queue_pop_head (keymap_x11->available_keycodes));
508++ }
509++
510++ return 0;
511++}
512++#endif
513++
514++gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
515++ guint keyval,
516++ guint *keycode_out)
517++{
518++ g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11), FALSE);
519++ g_return_val_if_fail (keyval != 0, FALSE);
520++ g_return_val_if_fail (keycode_out != NULL, FALSE);
521++
522++#ifdef HAVE_XKB
523++ *keycode_out = clutter_keymap_x11_get_available_keycode (keymap_x11);
524++
525++ if (*keycode_out == NoSymbol)
526++ {
527++ g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval);
528++ return FALSE;
529++ }
530++
531++ if (!clutter_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval))
532++ {
533++ g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval);
534++ return FALSE;
535++ }
536++
537++ g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval));
538++ g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out));
539++
540++ return TRUE;
541++#else
542++ return FALSE;
543++#endif
544++}
545++
546++void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
547++ guint keycode)
548++{
549++ g_return_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11));
550++
551++#ifdef HAVE_XKB
552++ if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) ||
553++ g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1)
554++ return;
555++
556++ g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode));
557++#endif
558++}
559++
560+ void
561+ clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
562+ uint32_t level,
563+diff --git a/clutter/clutter/x11/clutter-keymap-x11.h b/clutter/clutter/x11/clutter-keymap-x11.h
564+index 4b5b403..4decb44 100644
565+--- a/clutter/clutter/x11/clutter-keymap-x11.h
566++++ b/clutter/clutter/x11/clutter-keymap-x11.h
567+@@ -58,7 +58,11 @@ gboolean clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
568+ void clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
569+ uint32_t level,
570+ gboolean enable);
571+-
572++gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
573++ guint keyval,
574++ guint *keycode_out);
575++void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
576++ guint keycode);
577+ G_END_DECLS
578+
579+ #endif /* __CLUTTER_KEYMAP_X11_H__ */
580+diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.c b/clutter/clutter/x11/clutter-virtual-input-device-x11.c
581+index e16ba3f..cab26c3 100644
582+--- a/clutter/clutter/x11/clutter-virtual-input-device-x11.c
583++++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.c
584+@@ -143,8 +143,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
585+
586+ if (!clutter_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level))
587+ {
588+- g_warning ("No keycode found for keyval %x in current group", keyval);
589+- return;
590++ level = 0;
591++
592++ if (!clutter_keymap_x11_reserve_keycode (keymap, keyval, &keycode))
593++ {
594++ g_warning ("No keycode found for keyval %x in current group", keyval);
595++ return;
596++ }
597+ }
598+
599+ if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
600+@@ -155,9 +160,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
601+ (KeyCode) keycode,
602+ key_state == CLUTTER_KEY_STATE_PRESSED, 0);
603+
604+- if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
605+- key_state == CLUTTER_KEY_STATE_RELEASED)
606+- clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
607++
608++ if (key_state == CLUTTER_KEY_STATE_RELEASED)
609++ {
610++ if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode))
611++ clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
612++ clutter_keymap_x11_release_keycode_if_needed (keymap, keycode);
613++ }
614+ }
615+
616+ static void
617diff --git a/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch b/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
618new file mode 100644
619index 0000000..1e5958e
620--- /dev/null
621+++ b/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
622@@ -0,0 +1,372 @@
623+From: Daniel van Vugt <daniel.van.vugt@canonical.com>
624+Date: Fri, 3 May 2019 11:31:08 -0500
625+Subject: renderer-native: Add hardware presentation timing
626+
627+Add support for getting hardware presentation times from KMS (Wayland
628+sessions). Also implement cogl_get_clock_time which is required to compare
629+and judge the age of presentation timestamps.
630+
631+For single monitor systems this is straightforward. For multi-monitor
632+systems though we have to choose a display to sync to. The compositor
633+already partially solves this for us in the case of only one display
634+updating because it will only use the subset of monitors that are
635+changing. In the case of multiple monitors consuming the same frame
636+concurrently however, we choose the fastest one (in use at the time).
637+
638+Patch 1 of 2
639+
640+Origin: https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
641+Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=781296
642+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
643+Applied-Upstream: https://gitlab.gnome.org/vanvugt/mutter/commit/e9e4b2b7
644+Forwarded: yes
645+Last-Update: 2019-03-13
646+---
647+ src/Makefile.am | 25 ++++++++++-
648+ src/backends/native/meta-gpu-kms.c | 69 +++++++++++++++++++++++++++---
649+ src/backends/native/meta-gpu-kms.h | 3 ++
650+ src/backends/native/meta-renderer-native.c | 38 +++++++++++++++-
651+ src/meta-marshal.list | 1 +
652+ 5 files changed, 128 insertions(+), 8 deletions(-)
653+ create mode 100644 src/meta-marshal.list
654+
655+diff --git a/src/Makefile.am b/src/Makefile.am
656+index bcb3505..13862e9 100644
657+--- a/src/Makefile.am
658++++ b/src/Makefile.am
659+@@ -51,6 +51,8 @@ mutter_built_sources = \
660+ $(dbus_login1_built_sources) \
661+ meta/meta-enum-types.h \
662+ meta-enum-types.c \
663++ meta-marshal.c \
664++ meta-marshal.h \
665+ $(NULL)
666+
667+ if HAVE_REMOTE_DESKTOP
668+@@ -653,6 +655,7 @@ EXTRA_DIST += \
669+ libmutter.pc.in \
670+ meta-enum-types.h.in \
671+ meta-enum-types.c.in \
672++ meta-marshal.list \
673+ org.freedesktop.login1.xml \
674+ org.gnome.Mutter.DisplayConfig.xml \
675+ org.gnome.Mutter.IdleMonitor.xml \
676+@@ -666,7 +669,10 @@ BUILT_SOURCES = \
677+ $(libmutterinclude_built_headers)
678+
679+ MUTTER_STAMP_FILES = stamp-meta-enum-types.h
680+-CLEANFILES += $(MUTTER_STAMP_FILES)
681++CLEANFILES += \
682++ $(MUTTER_STAMP_FILES) \
683++ meta-marshal.c \
684++ meta-marshal.h
685+
686+ meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
687+ @true
688+@@ -760,3 +766,20 @@ endef
689+ $(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
690+ %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
691+ $(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
692++
693++meta_marshal_opts = --prefix=meta_marshal --internal
694++
695++meta-marshal.h: meta-marshal.list
696++ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
697++ --header \
698++ $(meta_marshal_opts) \
699++ --output=$@ \
700++ $<
701++
702++meta-marshal.c: meta-marshal.list meta-marshal.h
703++ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
704++ --include-header=meta-marshal.h \
705++ $(meta_marshal_opts) \
706++ --body \
707++ --output=$@ \
708++ $<
709+diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
710+index 815caf5..02649c5 100644
711+--- a/src/backends/native/meta-gpu-kms.c
712++++ b/src/backends/native/meta-gpu-kms.c
713+@@ -27,6 +27,7 @@
714+ #include <errno.h>
715+ #include <poll.h>
716+ #include <string.h>
717++#include <time.h>
718+ #include <xf86drm.h>
719+ #include <xf86drmMode.h>
720+
721+@@ -51,6 +52,7 @@ typedef struct _MetaGpuKmsFlipClosureContainer
722+ {
723+ GClosure *flip_closure;
724+ MetaGpuKms *gpu_kms;
725++ MetaCrtc *crtc;
726+ } MetaGpuKmsFlipClosureContainer;
727+
728+ struct _MetaGpuKms
729+@@ -61,6 +63,8 @@ struct _MetaGpuKms
730+ char *file_path;
731+ GSource *source;
732+
733++ clockid_t clock_id;
734++
735+ drmModeConnector **connectors;
736+ unsigned int n_connectors;
737+
738+@@ -166,18 +170,26 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
739+
740+ static void
741+ invoke_flip_closure (GClosure *flip_closure,
742+- MetaGpuKms *gpu_kms)
743++ MetaGpuKms *gpu_kms,
744++ MetaCrtc *crtc,
745++ int64_t page_flip_time_ns)
746+ {
747+ GValue params[] = {
748+ G_VALUE_INIT,
749+- G_VALUE_INIT
750++ G_VALUE_INIT,
751++ G_VALUE_INIT,
752++ G_VALUE_INIT,
753+ };
754+
755+ g_value_init (&params[0], G_TYPE_POINTER);
756+ g_value_set_pointer (&params[0], flip_closure);
757+ g_value_init (&params[1], G_TYPE_OBJECT);
758+ g_value_set_object (&params[1], gpu_kms);
759+- g_closure_invoke (flip_closure, NULL, 2, params, NULL);
760++ g_value_init (&params[2], G_TYPE_OBJECT);
761++ g_value_set_object (&params[2], crtc);
762++ g_value_init (&params[3], G_TYPE_INT64);
763++ g_value_set_int64 (&params[3], page_flip_time_ns);
764++ g_closure_invoke (flip_closure, NULL, 4, params, NULL);
765+ g_closure_unref (flip_closure);
766+ }
767+
768+@@ -217,6 +229,7 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
769+
770+ MetaGpuKmsFlipClosureContainer *
771+ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
772++ MetaCrtc *crtc,
773+ GClosure *flip_closure)
774+ {
775+ MetaGpuKmsFlipClosureContainer *closure_container;
776+@@ -224,7 +237,8 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
777+ closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
778+ *closure_container = (MetaGpuKmsFlipClosureContainer) {
779+ .flip_closure = flip_closure,
780+- .gpu_kms = gpu_kms
781++ .gpu_kms = gpu_kms,
782++ .crtc = crtc
783+ };
784+
785+ return closure_container;
786+@@ -264,6 +278,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
787+ int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
788+
789+ closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
790++ crtc,
791+ flip_closure);
792+
793+ ret = drmModePageFlip (kms_fd,
794+@@ -297,6 +312,23 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
795+ return TRUE;
796+ }
797+
798++static int64_t
799++timespec_to_nanoseconds (const struct timespec *ts)
800++{
801++ const int64_t one_billion = 1000000000;
802++
803++ return ((int64_t) ts->tv_sec) * one_billion + ts->tv_nsec;
804++}
805++
806++static int64_t
807++timeval_to_nanoseconds (const struct timeval *tv)
808++{
809++ int64_t usec = ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec;
810++ int64_t nsec = usec * 1000;
811++
812++ return nsec;
813++}
814++
815+ static void
816+ page_flip_handler (int fd,
817+ unsigned int frame,
818+@@ -307,8 +339,12 @@ page_flip_handler (int fd,
819+ MetaGpuKmsFlipClosureContainer *closure_container = user_data;
820+ GClosure *flip_closure = closure_container->flip_closure;
821+ MetaGpuKms *gpu_kms = closure_container->gpu_kms;
822++ struct timeval page_flip_time = {sec, usec};
823+
824+- invoke_flip_closure (flip_closure, gpu_kms);
825++ invoke_flip_closure (flip_closure,
826++ gpu_kms,
827++ closure_container->crtc,
828++ timeval_to_nanoseconds (&page_flip_time));
829+ meta_gpu_kms_flip_closure_container_free (closure_container);
830+ }
831+
832+@@ -381,6 +417,17 @@ meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
833+ return gpu_kms->file_path;
834+ }
835+
836++int64_t
837++_meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
838++{
839++ struct timespec ts;
840++
841++ if (clock_gettime (gpu_kms->clock_id, &ts))
842++ return 0;
843++
844++ return timespec_to_nanoseconds (&ts);
845++}
846++
847+ void
848+ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
849+ uint64_t state)
850+@@ -680,6 +727,17 @@ init_crtcs (MetaGpuKms *gpu_kms,
851+ meta_gpu_take_crtcs (gpu, crtcs);
852+ }
853+
854++static void
855++init_frame_clock (MetaGpuKms *gpu_kms)
856++{
857++ uint64_t uses_monotonic;
858++
859++ if (drmGetCap (gpu_kms->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic) != 0)
860++ uses_monotonic = 0;
861++
862++ gpu_kms->clock_id = uses_monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME;
863++}
864++
865+ static void
866+ init_outputs (MetaGpuKms *gpu_kms,
867+ MetaKmsResources *resources)
868+@@ -809,6 +867,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
869+ init_modes (gpu_kms, resources.resources);
870+ init_crtcs (gpu_kms, &resources);
871+ init_outputs (gpu_kms, &resources);
872++ init_frame_clock (gpu_kms);
873+
874+ meta_kms_resources_release (&resources);
875+
876+diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
877+index 01c3f2c..c12246c 100644
878+--- a/src/backends/native/meta-gpu-kms.h
879++++ b/src/backends/native/meta-gpu-kms.h
880+@@ -81,6 +81,8 @@ int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
881+
882+ const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms);
883+
884++int64_t _meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms);
885++
886+ void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms,
887+ int *max_width,
888+ int *max_height);
889+@@ -97,6 +99,7 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
890+ float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
891+
892+ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
893++ MetaCrtc *crtc,
894+ GClosure *flip_closure);
895+
896+ void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
897+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
898+index 470da88..0fd104b 100644
899+--- a/src/backends/native/meta-renderer-native.c
900++++ b/src/backends/native/meta-renderer-native.c
901+@@ -61,6 +61,7 @@
902+ #include "backends/native/meta-monitor-manager-kms.h"
903+ #include "backends/native/meta-renderer-native.h"
904+ #include "backends/native/meta-renderer-native-gles3.h"
905++#include "meta-marshal.h"
906+ #include "cogl/cogl.h"
907+ #include "core/boxes-private.h"
908+
909+@@ -1157,6 +1158,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
910+ static void
911+ on_crtc_flipped (GClosure *closure,
912+ MetaGpuKms *gpu_kms,
913++ MetaCrtc *crtc,
914++ int64_t page_flip_time_ns,
915+ MetaRendererView *view)
916+ {
917+ ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
918+@@ -1167,6 +1170,24 @@ on_crtc_flipped (GClosure *closure,
919+ MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
920+ MetaRendererNative *renderer_native = onscreen_native->renderer_native;
921+ MetaGpuKms *render_gpu = onscreen_native->render_gpu;
922++ CoglFrameInfo *frame_info;
923++ float refresh_rate;
924++
925++ frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
926++ refresh_rate = crtc && crtc->current_mode ?
927++ crtc->current_mode->refresh_rate :
928++ 0.0f;
929++
930++ /* Only keep the frame info for the fastest CRTC in use, which may not be
931++ * the first one to complete a flip. By only telling the compositor about the
932++ * fastest monitor(s) we direct it to produce new frames fast enough to
933++ * satisfy all monitors.
934++ */
935++ if (refresh_rate >= frame_info->refresh_rate)
936++ {
937++ frame_info->presentation_time = page_flip_time_ns;
938++ frame_info->refresh_rate = refresh_rate;
939++ }
940+
941+ if (gpu_kms != render_gpu)
942+ {
943+@@ -1297,7 +1318,9 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
944+ return FALSE;
945+
946+ closure_container =
947+- meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
948++ meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu,
949++ NULL,
950++ flip_closure);
951+
952+ acquire_attribs = (EGLAttrib[]) {
953+ EGL_DRM_FLIP_EVENT_DATA_NV,
954+@@ -1540,7 +1563,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
955+ flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
956+ g_object_ref (view),
957+ (GClosureNotify) flip_closure_destroyed);
958+- g_closure_set_marshal (flip_closure, g_cclosure_marshal_VOID__OBJECT);
959++ g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
960+
961+ /* Either flip the CRTC's of the monitor info, if we are drawing just part
962+ * of the stage, or all of the CRTC's if we are drawing the whole stage.
963+@@ -2673,6 +2696,15 @@ meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
964+ return fb;
965+ }
966+
967++static int64_t
968++meta_renderer_native_get_clock_time (CoglContext *context)
969++{
970++ CoglRenderer *cogl_renderer = cogl_context_get_renderer (context);
971++ MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data;
972++
973++ return _meta_gpu_kms_get_current_time_ns (gpu_kms);
974++}
975++
976+ static const CoglWinsysVtable *
977+ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
978+ {
979+@@ -2701,6 +2733,8 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
980+ vtable.onscreen_swap_buffers_with_damage =
981+ meta_onscreen_native_swap_buffers_with_damage;
982+
983++ vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
984++
985+ vtable_inited = TRUE;
986+ }
987+
988+diff --git a/src/meta-marshal.list b/src/meta-marshal.list
989+new file mode 100644
990+index 0000000..c1f4781
991+--- /dev/null
992++++ b/src/meta-marshal.list
993+@@ -0,0 +1 @@
994++VOID:OBJECT,OBJECT,INT64
995diff --git a/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch b/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
996new file mode 100644
997index 0000000..9a6a64d
998--- /dev/null
999+++ b/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
1000@@ -0,0 +1,53 @@
1001+From: Daniel van Vugt <daniel.van.vugt@canonical.com>
1002+Date: Fri, 3 May 2019 11:31:08 -0500
1003+Subject: renderer-native: Advertise _FEATURE_SWAP_THROTTLE
1004+
1005+Because it is implemented and always on. By advertising this fact
1006+the master clock is able to sync to the native refresh rate instead
1007+of always using the fallback of 60.00Hz.
1008+
1009+Patch 2 of 2
1010+
1011+Origin: https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
1012+Bug-GNOME: https://bugzilla.gnome.org/show_bug.cgi?id=781296
1013+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
1014+Applied-Upstream: https://gitlab.gnome.org/vanvugt/mutter/commit/e8c27603
1015+Forwarded: yes
1016+Last-Update: 2019-03-13
1017+---
1018+ src/backends/native/meta-renderer-native.c | 15 +++++++++++++--
1019+ 1 file changed, 13 insertions(+), 2 deletions(-)
1020+
1021+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
1022+index 0fd104b..dce7981 100644
1023+--- a/src/backends/native/meta-renderer-native.c
1024++++ b/src/backends/native/meta-renderer-native.c
1025+@@ -1997,6 +1997,13 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
1026+ COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
1027+ TRUE);
1028+
1029++ /* COGL_WINSYS_FEATURE_SWAP_THROTTLE is always true for this renderer
1030++ * because we have the call to wait_for_pending_flips on every frame.
1031++ */
1032++ COGL_FLAGS_SET (cogl_context->winsys_features,
1033++ COGL_WINSYS_FEATURE_SWAP_THROTTLE,
1034++ TRUE);
1035++
1036+ #ifdef HAVE_EGL_DEVICE
1037+ if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE)
1038+ COGL_FLAGS_SET (cogl_context->features,
1039+@@ -2625,8 +2632,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
1040+ }
1041+
1042+ onscreen = cogl_onscreen_new (context, width, height);
1043+- cogl_onscreen_set_swap_throttled (onscreen,
1044+- _clutter_get_sync_to_vblank ());
1045++
1046++ /* We have wait_for_pending_flips hardcoded, so throttling always. */
1047++ cogl_onscreen_set_swap_throttled (onscreen, TRUE);
1048++ if (!_clutter_get_sync_to_vblank ())
1049++ g_warning ("Request to disable sync-to-vblank is being ignored. "
1050++ "MetaRendererNative does not support disabling it.");
1051+
1052+ if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
1053+ {
1054diff --git a/debian/patches/monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch b/debian/patches/monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch
1055new file mode 100644
1056index 0000000..5512752
1057--- /dev/null
1058+++ b/debian/patches/monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch
1059@@ -0,0 +1,37 @@
1060+From: =?utf-8?q?Jonas_=C3=85dahl?= <jadahl@gmail.com>
1061+Date: Thu, 11 Oct 2018 08:16:26 -0500
1062+Subject: monitor-manager: Don't use switch-config when ensuring configuration
1063+
1064+Switch-configs are only to be used in certain circumstances (see
1065+meta_monitor_manager_can_switch_config()) so when ensuring
1066+configuration and attempting to create a linear configuration, use the
1067+linear configuration constructor function directly without going via the
1068+switch config method, otherwise we might incorrectly fall back to the
1069+fallback configuration (only enable primary monitor).
1070+
1071+This is a regression introduced by 6267732bec97773.
1072+
1073+Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/342
1074+
1075+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1772811
1076+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/262
1077+Applied-Upstream: yes, 3.32.0
1078+---
1079+ src/backends/meta-monitor-manager.c | 4 +---
1080+ 1 file changed, 1 insertion(+), 3 deletions(-)
1081+
1082+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
1083+index fde61eb..39ed813 100644
1084+--- a/src/backends/meta-monitor-manager.c
1085++++ b/src/backends/meta-monitor-manager.c
1086+@@ -582,9 +582,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
1087+ g_clear_object (&config);
1088+ }
1089+
1090+- config =
1091+- meta_monitor_config_manager_create_for_switch_config (manager->config_manager,
1092+- META_MONITOR_SWITCH_CONFIG_ALL_LINEAR);
1093++ config = meta_monitor_config_manager_create_linear (manager->config_manager);
1094+ if (config)
1095+ {
1096+ if (!meta_monitor_manager_apply_monitors_config (manager,
1097diff --git a/debian/patches/monitor-manager-use-MonitorsConfig-to-track-switch_config.patch b/debian/patches/monitor-manager-use-MonitorsConfig-to-track-switch_config.patch
1098new file mode 100644
1099index 0000000..a791f59
1100--- /dev/null
1101+++ b/debian/patches/monitor-manager-use-MonitorsConfig-to-track-switch_config.patch
1102@@ -0,0 +1,198 @@
1103+From: Daniel Drake <drake@endlessm.com>
1104+Date: Wed, 29 Aug 2018 19:34:53 -0500
1105+Subject: monitor-manager: use MonitorsConfig to track switch_config
1106+
1107+When constructing MetaMonitorsConfig objects, store which type
1108+of switch_config they are for (or UNKNOWN if it is not such
1109+type of config).
1110+
1111+Stop unconditionally setting current_switch_config to UNKNOWN when
1112+handling monitors changed events. Instead, set it to the switch_config
1113+type stored in the MonitorsConfig in the codepath that updates logical
1114+state. In addition to being called in the hotplug case along the same
1115+code flow that generates monitors changed events, this is also called
1116+in the coldplug case where a secondary monitor was connected before
1117+mutter was started.
1118+
1119+When creating the default linear display config, create it as a
1120+switch_config so that internal state gets updated to represent
1121+linear mode when this config is used.
1122+
1123+The previous behaviour of unconditionally resetting current_switch_config
1124+to UNKNOWN was breaking the internal state machine for display config
1125+switching, causing misbehaviour in gnome-shell's switchMonitor UI when
1126+using display switch hotkeys. The lack of internal tracking when the
1127+displays are already in the default "Join Displays" linear mode was
1128+then causing the first display switch hotkey press to do nothing
1129+(it would attempt to select "Join Displays" mode, but that was already
1130+active).
1131+
1132+Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/281
1133+https://gitlab.gnome.org/GNOME/mutter/merge_requests/213
1134+
1135+Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1772811
1136+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/213
1137+Applied-Upstream: yes, 3.30.1
1138+---
1139+ src/backends/meta-monitor-config-manager.c | 36 +++++++++++++++++++++++++-----
1140+ src/backends/meta-monitor-config-manager.h | 7 ++++++
1141+ src/backends/meta-monitor-manager.c | 25 ++++++++++++++++-----
1142+ 3 files changed, 56 insertions(+), 12 deletions(-)
1143+
1144+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
1145+index 197892b..ce61547 100644
1146+--- a/src/backends/meta-monitor-config-manager.c
1147++++ b/src/backends/meta-monitor-config-manager.c
1148+@@ -1007,6 +1007,7 @@ meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager
1149+ MetaMonitorSwitchConfigType config_type)
1150+ {
1151+ MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
1152++ MetaMonitorsConfig *config;
1153+
1154+ if (!meta_monitor_manager_can_switch_config (monitor_manager))
1155+ return NULL;
1156+@@ -1014,18 +1015,27 @@ meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager
1157+ switch (config_type)
1158+ {
1159+ case META_MONITOR_SWITCH_CONFIG_ALL_MIRROR:
1160+- return create_for_switch_config_all_mirror (config_manager);
1161++ config = create_for_switch_config_all_mirror (config_manager);
1162++ break;
1163+ case META_MONITOR_SWITCH_CONFIG_ALL_LINEAR:
1164+- return meta_monitor_config_manager_create_linear (config_manager);
1165++ config = meta_monitor_config_manager_create_linear (config_manager);
1166++ break;
1167+ case META_MONITOR_SWITCH_CONFIG_EXTERNAL:
1168+- return create_for_switch_config_external (config_manager);
1169++ config = create_for_switch_config_external (config_manager);
1170++ break;
1171+ case META_MONITOR_SWITCH_CONFIG_BUILTIN:
1172+- return create_for_switch_config_builtin (config_manager);
1173++ config = create_for_switch_config_builtin (config_manager);
1174++ break;
1175+ case META_MONITOR_SWITCH_CONFIG_UNKNOWN:
1176++ default:
1177+ g_warn_if_reached ();
1178+- break;
1179++ return NULL;
1180+ }
1181+- return NULL;
1182++
1183++ if (config)
1184++ _meta_monitors_config_set_switch_config (config, config_type);
1185++
1186++ return config;
1187+ }
1188+
1189+ void
1190+@@ -1217,6 +1227,19 @@ meta_monitors_config_key_equal (gconstpointer data_a,
1191+ return TRUE;
1192+ }
1193+
1194++MetaMonitorSwitchConfigType
1195++_meta_monitors_config_get_switch_config (MetaMonitorsConfig *config)
1196++{
1197++ return config->switch_config;
1198++}
1199++
1200++void
1201++_meta_monitors_config_set_switch_config (MetaMonitorsConfig *config,
1202++ MetaMonitorSwitchConfigType switch_config)
1203++{
1204++ config->switch_config = switch_config;
1205++}
1206++
1207+ MetaMonitorsConfig *
1208+ meta_monitors_config_new_full (GList *logical_monitor_configs,
1209+ GList *disabled_monitor_specs,
1210+@@ -1232,6 +1255,7 @@ meta_monitors_config_new_full (GList *logical_monitor_con
1211+ disabled_monitor_specs);
1212+ config->layout_mode = layout_mode;
1213+ config->flags = flags;
1214++ config->switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN;
1215+
1216+ return config;
1217+ }
1218+diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
1219+index 269d8e1..4ac0b1d 100644
1220+--- a/src/backends/meta-monitor-config-manager.h
1221++++ b/src/backends/meta-monitor-config-manager.h
1222+@@ -69,6 +69,8 @@ struct _MetaMonitorsConfig
1223+ MetaMonitorsConfigFlag flags;
1224+
1225+ MetaLogicalMonitorLayoutMode layout_mode;
1226++
1227++ MetaMonitorSwitchConfigType switch_config;
1228+ };
1229+
1230+ #define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ())
1231+@@ -124,6 +126,11 @@ MetaMonitorsConfig * meta_monitors_config_new (MetaMonitorManager *mon
1232+ MetaLogicalMonitorLayoutMode layout_mode,
1233+ MetaMonitorsConfigFlag flags);
1234+
1235++MetaMonitorSwitchConfigType _meta_monitors_config_get_switch_config (MetaMonitorsConfig *config);
1236++
1237++void _meta_monitors_config_set_switch_config (MetaMonitorsConfig *config,
1238++ MetaMonitorSwitchConfigType switch_config);
1239++
1240+ unsigned int meta_monitors_config_key_hash (gconstpointer config_key);
1241+
1242+ gboolean meta_monitors_config_key_equal (gconstpointer config_key_a,
1243+diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
1244+index ec18600..fde61eb 100644
1245+--- a/src/backends/meta-monitor-manager.c
1246++++ b/src/backends/meta-monitor-manager.c
1247+@@ -582,7 +582,9 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
1248+ g_clear_object (&config);
1249+ }
1250+
1251+- config = meta_monitor_config_manager_create_linear (manager->config_manager);
1252++ config =
1253++ meta_monitor_config_manager_create_for_switch_config (manager->config_manager,
1254++ META_MONITOR_SWITCH_CONFIG_ALL_LINEAR);
1255+ if (config)
1256+ {
1257+ if (!meta_monitor_manager_apply_monitors_config (manager,
1258+@@ -2652,8 +2654,6 @@ meta_monitor_manager_read_current_state (MetaMonitorManager *manager)
1259+ static void
1260+ meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
1261+ {
1262+- manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN;
1263+-
1264+ meta_backend_monitors_changed (manager->backend);
1265+
1266+ g_signal_emit (manager, signals[MONITORS_CHANGED_INTERNAL], 0);
1267+@@ -2710,10 +2710,17 @@ meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
1268+ MetaMonitorsConfig *config)
1269+ {
1270+ if (config)
1271+- manager->layout_mode = config->layout_mode;
1272++ {
1273++ manager->layout_mode = config->layout_mode;
1274++ manager->current_switch_config =
1275++ _meta_monitors_config_get_switch_config (config);
1276++ }
1277+ else
1278+- manager->layout_mode =
1279+- meta_monitor_manager_get_default_layout_mode (manager);
1280++ {
1281++ manager->layout_mode =
1282++ meta_monitor_manager_get_default_layout_mode (manager);
1283++ manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN;
1284++ }
1285+
1286+ meta_monitor_manager_rebuild_logical_monitors (manager, config);
1287+ }
1288+@@ -2755,6 +2762,12 @@ void
1289+ meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager,
1290+ MetaMonitorsConfig *config)
1291+ {
1292++ if (config)
1293++ manager->current_switch_config =
1294++ _meta_monitors_config_get_switch_config (config);
1295++ else
1296++ manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN;
1297++
1298+ manager->layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
1299+
1300+ meta_monitor_manager_rebuild_logical_monitors_derived (manager, config);
1301diff --git a/debian/patches/series b/debian/patches/series
1302index 198db5a..8ff6307 100644
1303--- a/debian/patches/series
1304+++ b/debian/patches/series
1305@@ -1,8 +1,13 @@
1306 theme-use-gtk_render_icon_suface-to-paint-button-icon.patch
1307 theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch
1308-clutter-Smooth-out-master-clock-to-smooth-visuals.patch
1309 clutter-Fix-offscreen-effect-painting-of-clones.patch
1310 bgo768531_workaround-startup-notifications.patch
1311+monitor-manager-use-MonitorsConfig-to-track-switch_config.patch
1312+monitor-manager-Don-t-use-switch-config-when-ensuring-con.patch
1313+clutter-x11-Implement-keycode-remap-to-keysyms-on-virtual.patch
1314+clutter-x11-Consider-remapped-keys-when-guessing-the-keyc.patch
1315+lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
1316+lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
1317 debian/synaptics-support.patch
1318 debian/skip-failing-tests.patch
1319 debian/skip-failing-tests-325.patch

Subscribers

People subscribed via source and target branches