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
This commit is contained in:
Jonas Ådahl 2020-03-03 10:04:16 +01:00
parent 2e7d02f1ce
commit b51c468c0f
3 changed files with 44 additions and 27 deletions

View File

@ -97,6 +97,15 @@ enum
static GParamSpec *obj_props[N_PROPS] = { NULL, }; static GParamSpec *obj_props[N_PROPS] = { NULL, };
enum
{
PRE_PAINT,
N_SIGNALS
};
static guint signals[N_SIGNALS];
typedef struct _MetaCompositorPrivate typedef struct _MetaCompositorPrivate
{ {
GObject parent; GObject parent;
@ -1124,7 +1133,8 @@ meta_compositor_pre_paint (MetaCompositor *compositor)
{ {
COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint, COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint,
"Compositor (pre-paint)"); "Compositor (pre-paint)");
META_COMPOSITOR_GET_CLASS (compositor)->pre_paint (compositor);
g_signal_emit (compositor, signals[PRE_PAINT], 0);
} }
static gboolean static gboolean
@ -1247,7 +1257,7 @@ meta_compositor_init (MetaCompositor *compositor)
compositor, compositor,
NULL); NULL);
priv->laters = meta_laters_new (); priv->laters = meta_laters_new (compositor);
} }
static void static void
@ -1300,6 +1310,14 @@ meta_compositor_class_init (MetaCompositorClass *klass)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props); 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);
} }
/** /**

View File

@ -19,8 +19,9 @@
#define META_LATER_PRIVATE_H #define META_LATER_PRIVATE_H
typedef struct _MetaLaters MetaLaters; 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); void meta_laters_free (MetaLaters *laters);

View File

@ -44,12 +44,14 @@ typedef struct _MetaLater
struct _MetaLaters struct _MetaLaters
{ {
MetaCompositor *compositor;
unsigned int last_later_id; unsigned int last_later_id;
GSList *laters[META_LATER_N_TYPES]; GSList *laters[META_LATER_N_TYPES];
ClutterTimeline *timeline; ClutterTimeline *timeline;
guint repaint_func; gulong pre_paint_handler_id;
}; };
static MetaLater * static MetaLater *
@ -163,10 +165,10 @@ run_repaint_laters (GSList **laters_list)
} }
} }
static gboolean static void
run_all_repaint_laters (gpointer data) on_pre_paint (MetaCompositor *compositor,
MetaLaters *laters)
{ {
MetaLaters *laters = data;
unsigned int i; unsigned int i;
GSList *l; GSList *l;
gboolean keep_timeline_running = FALSE; gboolean keep_timeline_running = FALSE;
@ -187,24 +189,11 @@ run_all_repaint_laters (gpointer data)
if (!keep_timeline_running) if (!keep_timeline_running)
clutter_timeline_stop (laters->timeline); clutter_timeline_stop (laters->timeline);
return TRUE;
} }
static void 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); clutter_timeline_start (laters->timeline);
} }
@ -250,13 +239,13 @@ meta_laters_add (MetaLaters *laters,
invoke_later_idle, invoke_later_idle,
later, NULL); later, NULL);
g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle"); g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle");
ensure_later_repaint_func (laters); ensure_timeline_running (laters);
break; break;
case META_LATER_CALC_SHOWING: case META_LATER_CALC_SHOWING:
case META_LATER_CHECK_FULLSCREEN: case META_LATER_CHECK_FULLSCREEN:
case META_LATER_SYNC_STACK: case META_LATER_SYNC_STACK:
case META_LATER_BEFORE_REDRAW: case META_LATER_BEFORE_REDRAW:
ensure_later_repaint_func (laters); ensure_timeline_running (laters);
break; break;
case META_LATER_IDLE: case META_LATER_IDLE:
later->source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, later->source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
@ -331,9 +320,19 @@ meta_later_remove (unsigned int later_id)
} }
MetaLaters * 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 void
@ -345,7 +344,6 @@ meta_laters_free (MetaLaters *laters)
g_slist_free_full (laters->laters[i], (GDestroyNotify) meta_later_unref); g_slist_free_full (laters->laters[i], (GDestroyNotify) meta_later_unref);
g_clear_object (&laters->timeline); g_clear_object (&laters->timeline);
if (laters->repaint_func) g_clear_signal_handler (&laters->pre_paint_handler_id, laters->compositor);
clutter_threads_remove_repaint_func (laters->repaint_func);
g_free (laters); g_free (laters);
} }