MetaLater: Invoke later callbacks queued by earlier ones

If a MetaLater callback queued another MetaLater with a scheduling
later than the one currently being invoked, make it so that the newly
scheduled callback will actually be invoked.

The fact that it doesn't already do this is a regression from
cd7a968093.

https://bugzilla.gnome.org/show_bug.cgi?id=755605
This commit is contained in:
Jonas Ådahl 2015-09-14 22:31:32 +08:00
parent 00139755ff
commit 35da6a9078

View File

@ -49,6 +49,9 @@ meta_topic_real_valist (MetaDebugTopic topic,
va_list args) G_GNUC_PRINTF(2, 0); va_list args) G_GNUC_PRINTF(2, 0);
#endif #endif
static gboolean
meta_later_remove_from_list (guint later_id, GSList **laters_list);
static gint verbose_topics = 0; static gint verbose_topics = 0;
static gboolean is_debugging = FALSE; static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE; static gboolean replace_current = FALSE;
@ -739,7 +742,14 @@ typedef struct
gboolean run_once; gboolean run_once;
} MetaLater; } MetaLater;
static GSList *laters = NULL; static GSList *laters[] = {
NULL, /* META_LATER_RESIZE */
NULL, /* META_LATER_CALC_SHOWING */
NULL, /* META_LATER_CHECK_FULLSCREEN */
NULL, /* META_LATER_SYNC_STACK */
NULL, /* META_LATER_BEFORE_REDRAW */
NULL, /* META_LATER_IDLE */
};
/* This is a dummy timeline used to get the Clutter master clock running */ /* This is a dummy timeline used to get the Clutter master clock running */
static ClutterTimeline *later_timeline; static ClutterTimeline *later_timeline;
static guint later_repaint_func = 0; static guint later_repaint_func = 0;
@ -772,25 +782,14 @@ destroy_later (MetaLater *later)
unref_later (later); unref_later (later);
} }
/* Used to sort the list of laters with the highest priority static void
* functions first. run_repaint_laters (GSList **laters_list)
*/
static int
compare_laters (gconstpointer a,
gconstpointer b)
{
return ((const MetaLater *)a)->when - ((const MetaLater *)b)->when;
}
static gboolean
run_repaint_laters (gpointer data)
{ {
GSList *laters_copy; GSList *laters_copy;
GSList *l; GSList *l;
gboolean keep_timeline_running = FALSE;
laters_copy = NULL; laters_copy = NULL;
for (l = laters; l; l = l->next) for (l = *laters_list; l; l = l->next)
{ {
MetaLater *later = l->data; MetaLater *later = l->data;
if (later->source == 0 || if (later->source == 0 ||
@ -806,22 +805,41 @@ run_repaint_laters (gpointer data)
{ {
MetaLater *later = l->data; MetaLater *later = l->data;
if (later->func && later->func (later->data)) if (!later->func || !later->func (later->data))
meta_later_remove_from_list (later->id, laters_list);
unref_later (later);
}
g_slist_free (laters_copy);
}
static gboolean
run_all_repaint_laters (gpointer data)
{
guint i;
GSList *l;
gboolean keep_timeline_running = FALSE;
for (i = 0; i < G_N_ELEMENTS (laters); i++)
{ {
run_repaint_laters (&laters[i]);
}
for (i = 0; i < G_N_ELEMENTS (laters); i++)
{
for (l = laters[i]; l; l = l->next)
{
MetaLater *later = l->data;
if (later->source == 0) if (later->source == 0)
keep_timeline_running = TRUE; keep_timeline_running = TRUE;
} }
else
meta_later_remove (later->id);
unref_later (later);
} }
if (!keep_timeline_running) if (!keep_timeline_running)
clutter_timeline_stop (later_timeline); clutter_timeline_stop (later_timeline);
g_slist_free (laters_copy); /* Just keep the repaint func around - it's cheap if the lists are empty */
/* Just keep the repaint func around - it's cheap if the list is empty */
return TRUE; return TRUE;
} }
@ -832,7 +850,7 @@ ensure_later_repaint_func (void)
later_timeline = clutter_timeline_new (G_MAXUINT); later_timeline = clutter_timeline_new (G_MAXUINT);
if (later_repaint_func == 0) if (later_repaint_func == 0)
later_repaint_func = clutter_threads_add_repaint_func (run_repaint_laters, later_repaint_func = clutter_threads_add_repaint_func (run_all_repaint_laters,
NULL, NULL); NULL, NULL);
/* Make sure the repaint function gets run */ /* Make sure the repaint function gets run */
@ -888,7 +906,7 @@ meta_later_add (MetaLaterType when,
later->data = data; later->data = data;
later->notify = notify; later->notify = notify;
laters = g_slist_insert_sorted (laters, later, compare_laters); laters[when] = g_slist_prepend (laters[when], later);
switch (when) switch (when)
{ {
@ -920,6 +938,29 @@ meta_later_add (MetaLaterType when,
return later->id; return later->id;
} }
static gboolean
meta_later_remove_from_list (guint later_id, GSList **laters_list)
{
GSList *l;
for (l = *laters_list; l; l = l->next)
{
MetaLater *later = l->data;
if (later->id == later_id)
{
*laters_list = g_slist_delete_link (*laters_list, l);
/* If this was a "repaint func" later, we just let the
* repaint func run and get removed
*/
destroy_later (later);
return TRUE;
}
}
return FALSE;
}
/** /**
* meta_later_remove: * meta_later_remove:
* @later_id: the integer ID returned from meta_later_add() * @later_id: the integer ID returned from meta_later_add()
@ -929,21 +970,13 @@ meta_later_add (MetaLaterType when,
void void
meta_later_remove (guint later_id) meta_later_remove (guint later_id)
{ {
GSList *l; guint i;
for (l = laters; l; l = l->next) for (i = 0; i < G_N_ELEMENTS (laters); i++)
{ {
MetaLater *later = l->data; if (meta_later_remove_from_list (later_id, &laters[i]))
if (later->id == later_id)
{
laters = g_slist_delete_link (laters, l);
/* If this was a "repaint func" later, we just let the
* repaint func run and get removed
*/
destroy_later (later);
return; return;
} }
}
} }
MetaLocaleDirection MetaLocaleDirection