From b51c468c0facc3be5df597a6fe0c8c35b95a1fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 3 Mar 2020 10:04:16 +0100 Subject: [PATCH] later: Listen to MetaCompositor signal instead of clutter We need to coordinate with MetaCompositor during pre-paint so that we have control over whether MetaLater callbacks happen first, or the MetaCompositor pre-paint logic. In order to do so, make MetaLater listen to a new signal "pre-paint" on MetaCompositor, that is called MetaCompositors own pre-paint handling. This fixes an issue where the top window actor was calculated after the MetaCompositor pre-paint handling, meaning the top actor being painted was out-of-date. https://gitlab.gnome.org/GNOME/mutter/merge_requests/798 --- src/compositor/compositor.c | 22 ++++++++++++-- src/compositor/meta-later-private.h | 3 +- src/compositor/meta-later.c | 46 ++++++++++++++--------------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 06b5ee6a3..7c94687dd 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -97,6 +97,15 @@ enum static GParamSpec *obj_props[N_PROPS] = { NULL, }; +enum +{ + PRE_PAINT, + + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + typedef struct _MetaCompositorPrivate { GObject parent; @@ -1124,7 +1133,8 @@ meta_compositor_pre_paint (MetaCompositor *compositor) { COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint, "Compositor (pre-paint)"); - META_COMPOSITOR_GET_CLASS (compositor)->pre_paint (compositor); + + g_signal_emit (compositor, signals[PRE_PAINT], 0); } static gboolean @@ -1247,7 +1257,7 @@ meta_compositor_init (MetaCompositor *compositor) compositor, NULL); - priv->laters = meta_laters_new (); + priv->laters = meta_laters_new (compositor); } static void @@ -1300,6 +1310,14 @@ meta_compositor_class_init (MetaCompositorClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, obj_props); + + signals[PRE_PAINT] = + g_signal_new ("pre-paint", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MetaCompositorClass, pre_paint), + NULL, NULL, NULL, + G_TYPE_NONE, 0); } /** diff --git a/src/compositor/meta-later-private.h b/src/compositor/meta-later-private.h index b1c88766f..c8d0f80a8 100644 --- a/src/compositor/meta-later-private.h +++ b/src/compositor/meta-later-private.h @@ -19,8 +19,9 @@ #define META_LATER_PRIVATE_H typedef struct _MetaLaters MetaLaters; +typedef struct _MetaCompositor MetaCompositor; -MetaLaters * meta_laters_new (void); +MetaLaters * meta_laters_new (MetaCompositor *compositor); void meta_laters_free (MetaLaters *laters); diff --git a/src/compositor/meta-later.c b/src/compositor/meta-later.c index aaa0f11d4..b68e59a5b 100644 --- a/src/compositor/meta-later.c +++ b/src/compositor/meta-later.c @@ -44,12 +44,14 @@ typedef struct _MetaLater struct _MetaLaters { + MetaCompositor *compositor; + unsigned int last_later_id; GSList *laters[META_LATER_N_TYPES]; ClutterTimeline *timeline; - guint repaint_func; + gulong pre_paint_handler_id; }; static MetaLater * @@ -163,10 +165,10 @@ run_repaint_laters (GSList **laters_list) } } -static gboolean -run_all_repaint_laters (gpointer data) +static void +on_pre_paint (MetaCompositor *compositor, + MetaLaters *laters) { - MetaLaters *laters = data; unsigned int i; GSList *l; gboolean keep_timeline_running = FALSE; @@ -187,24 +189,11 @@ run_all_repaint_laters (gpointer data) if (!keep_timeline_running) clutter_timeline_stop (laters->timeline); - - return TRUE; } static void -ensure_later_repaint_func (MetaLaters *laters) +ensure_timeline_running (MetaLaters *laters) { - if (!laters->timeline) - laters->timeline = clutter_timeline_new (G_MAXUINT); - - if (laters->repaint_func == 0) - { - laters->repaint_func = - clutter_threads_add_repaint_func (run_all_repaint_laters, - laters, NULL); - } - - /* Make sure the repaint function gets run */ clutter_timeline_start (laters->timeline); } @@ -250,13 +239,13 @@ meta_laters_add (MetaLaters *laters, invoke_later_idle, later, NULL); g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle"); - ensure_later_repaint_func (laters); + ensure_timeline_running (laters); break; case META_LATER_CALC_SHOWING: case META_LATER_CHECK_FULLSCREEN: case META_LATER_SYNC_STACK: case META_LATER_BEFORE_REDRAW: - ensure_later_repaint_func (laters); + ensure_timeline_running (laters); break; case META_LATER_IDLE: later->source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, @@ -331,9 +320,19 @@ meta_later_remove (unsigned int later_id) } MetaLaters * -meta_laters_new (void) +meta_laters_new (MetaCompositor *compositor) { - return g_new0 (MetaLaters, 1); + MetaLaters *laters; + + laters = g_new0 (MetaLaters, 1); + laters->compositor = compositor; + laters->timeline = clutter_timeline_new (G_MAXUINT); + + laters->pre_paint_handler_id = g_signal_connect (compositor, "pre-paint", + G_CALLBACK (on_pre_paint), + laters); + + return laters; } void @@ -345,7 +344,6 @@ meta_laters_free (MetaLaters *laters) g_slist_free_full (laters->laters[i], (GDestroyNotify) meta_later_unref); g_clear_object (&laters->timeline); - if (laters->repaint_func) - clutter_threads_remove_repaint_func (laters->repaint_func); + g_clear_signal_handler (&laters->pre_paint_handler_id, laters->compositor); g_free (laters); }