[mutter] util: Move MetaLater to its own file
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] util: Move MetaLater to its own file
- Date: Thu, 16 Apr 2020 14:09:33 +0000 (UTC)
commit d682cdb078f281b03084e3e0d7ab40d3ea382c1f
Author: Jonas Ådahl <jadahl gmail com>
Date: Tue Mar 3 08:46:11 2020 +0100
util: Move MetaLater to its own file
While at it, fix some style inconsistencies, for now use a single
singleton struct instead of multiple static variables, and
other non-functional cleanups. Semantically, there is no changes
introduced.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
src/compositor/meta-later.c | 321 ++++++++++++++++++++++++++++++++++++++++++++
src/core/util.c | 285 ---------------------------------------
src/meson.build | 1 +
3 files changed, 322 insertions(+), 285 deletions(-)
---
diff --git a/src/compositor/meta-later.c b/src/compositor/meta-later.c
new file mode 100644
index 000000000..1b71f58bb
--- /dev/null
+++ b/src/compositor/meta-later.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2005 Elijah Newren
+ * Copyright (C) 2020 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "cogl/cogl.h"
+#include "meta/util.h"
+
+typedef struct _MetaLater
+{
+ unsigned int id;
+ unsigned int ref_count;
+ MetaLaterType when;
+
+ GSourceFunc func;
+ gpointer user_data;
+ GDestroyNotify destroy_notify;
+
+ guint source_id;
+ gboolean run_once;
+} MetaLater;
+
+typedef struct _MetaLaters MetaLaters;
+
+#define META_LATER_N_TYPES (META_LATER_IDLE + 1)
+
+struct _MetaLaters
+{
+ unsigned int last_later_id;
+
+ GSList *laters[META_LATER_N_TYPES];
+
+ ClutterTimeline *timeline;
+ guint repaint_func;
+};
+
+static MetaLaters _laters;
+
+static MetaLater *
+meta_later_ref (MetaLater *later)
+{
+ later->ref_count++;
+ return later;
+}
+
+static void
+meta_later_unref (MetaLater *later)
+{
+ if (--later->ref_count == 0)
+ {
+ if (later->destroy_notify)
+ {
+ later->destroy_notify (later->user_data);
+ later->destroy_notify = NULL;
+ }
+
+ g_slice_free (MetaLater, later);
+ }
+}
+
+static void
+meta_later_destroy (MetaLater *later)
+{
+ g_clear_handle_id (&later->source_id, g_source_remove);
+ later->func = NULL;
+ meta_later_unref (later);
+}
+
+#ifdef COGL_HAS_TRACING
+static const char *
+later_type_to_string (MetaLaterType when)
+{
+ switch (when)
+ {
+ case META_LATER_RESIZE:
+ return "Later (resize)";
+ case META_LATER_CALC_SHOWING:
+ return "Later (calc-showing)";
+ case META_LATER_CHECK_FULLSCREEN:
+ return "Later (check-fullscreen)";
+ case META_LATER_SYNC_STACK:
+ return "Later (sync-stack)";
+ case META_LATER_BEFORE_REDRAW:
+ return "Later (before-redraw)";
+ case META_LATER_IDLE:
+ return "Later (idle)";
+ }
+
+ return "unknown";
+}
+#endif
+
+static gboolean
+meta_later_invoke (MetaLater *later)
+{
+ COGL_TRACE_BEGIN_SCOPED (later, later_type_to_string (later->when));
+ return later->func (later->user_data);
+}
+
+static gboolean
+remove_later_from_list (unsigned int 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);
+ meta_later_destroy (later);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+run_repaint_laters (GSList **laters_list)
+{
+ g_autoptr (GSList) laters_copy = NULL;
+ GSList *l;
+
+ for (l = *laters_list; l; l = l->next)
+ {
+ MetaLater *later = l->data;
+
+ if (!later->source_id ||
+ (later->when <= META_LATER_BEFORE_REDRAW && !later->run_once))
+ laters_copy = g_slist_prepend (laters_copy, meta_later_ref (later));
+ }
+ laters_copy = g_slist_reverse (laters_copy);
+
+ for (l = laters_copy; l; l = l->next)
+ {
+ MetaLater *later = l->data;
+
+ if (!later->func)
+ remove_later_from_list (later->id, laters_list);
+ else if (!meta_later_invoke (later))
+ remove_later_from_list (later->id, laters_list);
+
+ meta_later_unref (later);
+ }
+}
+
+static gboolean
+run_all_repaint_laters (gpointer data)
+{
+ MetaLaters *laters = data;
+ unsigned int i;
+ GSList *l;
+ gboolean keep_timeline_running = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (laters->laters); i++)
+ run_repaint_laters (&laters->laters[i]);
+
+ for (i = 0; i < G_N_ELEMENTS (laters->laters); i++)
+ {
+ for (l = laters->laters[i]; l; l = l->next)
+ {
+ MetaLater *later = l->data;
+
+ if (!later->source_id)
+ keep_timeline_running = TRUE;
+ }
+ }
+
+ if (!keep_timeline_running)
+ clutter_timeline_stop (laters->timeline);
+
+ return TRUE;
+}
+
+static void
+ensure_later_repaint_func (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);
+}
+
+static gboolean
+invoke_later_idle (gpointer data)
+{
+ MetaLater *later = data;
+
+ if (!later->func (later->user_data))
+ {
+ meta_later_remove (later->id);
+ return FALSE;
+ }
+ else
+ {
+ later->run_once = TRUE;
+ return TRUE;
+ }
+}
+
+static unsigned int
+meta_laters_add (MetaLaters *laters,
+ MetaLaterType when,
+ GSourceFunc func,
+ gpointer user_data,
+ GDestroyNotify notify)
+{
+ MetaLater *later = g_slice_new0 (MetaLater);
+
+ later->id = ++laters->last_later_id;
+ later->ref_count = 1;
+ later->when = when;
+ later->func = func;
+ later->user_data = user_data;
+ later->destroy_notify = notify;
+
+ laters->laters[when] = g_slist_prepend (laters->laters[when], later);
+
+ switch (when)
+ {
+ case META_LATER_RESIZE:
+ later->source_id = g_idle_add_full (META_PRIORITY_RESIZE,
+ invoke_later_idle,
+ later, NULL);
+ g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle");
+ ensure_later_repaint_func (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);
+ break;
+ case META_LATER_IDLE:
+ later->source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ invoke_later_idle,
+ later, NULL);
+ g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle");
+ break;
+ }
+
+ return later->id;
+}
+
+/**
+ * meta_later_add:
+ * @when: enumeration value determining the phase at which to run the callback
+ * @func: callback to run later
+ * @data: data to pass to the callback
+ * @notify: function to call to destroy @data when it is no longer in use, or %NULL
+ *
+ * Sets up a callback to be called at some later time. @when determines the
+ * particular later occasion at which it is called. This is much like g_idle_add(),
+ * except that the functions interact properly with clutter event handling.
+ * If a "later" function is added from a clutter event handler, and is supposed
+ * to be run before the stage is redrawn, it will be run before that redraw
+ * of the stage, not the next one.
+ *
+ * Return value: an integer ID (guaranteed to be non-zero) that can be used
+ * to cancel the callback and prevent it from being run.
+ */
+unsigned int
+meta_later_add (MetaLaterType when,
+ GSourceFunc func,
+ gpointer data,
+ GDestroyNotify notify)
+{
+ return meta_laters_add (&_laters, when, func, data, notify);
+}
+
+static void
+meta_laters_remove (MetaLaters *laters,
+ unsigned int later_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < G_N_ELEMENTS (laters->laters); i++)
+ {
+ if (remove_later_from_list (later_id, &laters->laters[i]))
+ return;
+ }
+}
+
+/**
+ * meta_later_remove:
+ * @later_id: the integer ID returned from meta_later_add()
+ *
+ * Removes a callback added with meta_later_add()
+ */
+void
+meta_later_remove (unsigned int later_id)
+{
+ meta_laters_remove (&_laters, later_id);
+}
diff --git a/src/core/util.c b/src/core/util.c
index 3854b3737..f01ef39d7 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -50,9 +50,6 @@ meta_topic_real_valist (MetaDebugTopic topic,
va_list args) G_GNUC_PRINTF(2, 0);
#endif
-static gboolean
-meta_later_remove_from_list (guint later_id, GSList **laters_list);
-
static gint verbose_topics = 0;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
@@ -715,288 +712,6 @@ meta_show_dialog (const char *type,
return child_pid;
}
-/***************************************************************************
- * Later functions: like idles but integrated with the Clutter repaint loop
- ***************************************************************************/
-
-static guint last_later_id = 0;
-
-typedef struct
-{
- guint id;
- guint ref_count;
- MetaLaterType when;
- GSourceFunc func;
- gpointer data;
- GDestroyNotify notify;
- int source;
- gboolean run_once;
-} MetaLater;
-
-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 */
-static ClutterTimeline *later_timeline;
-static guint later_repaint_func = 0;
-
-static void ensure_later_repaint_func (void);
-
-static void
-unref_later (MetaLater *later)
-{
- if (--later->ref_count == 0)
- {
- if (later->notify)
- {
- later->notify (later->data);
- later->notify = NULL;
- }
- g_slice_free (MetaLater, later);
- }
-}
-
-static void
-destroy_later (MetaLater *later)
-{
- g_clear_handle_id (&later->source, g_source_remove);
- later->func = NULL;
- unref_later (later);
-}
-
-#ifdef COGL_HAS_TRACING
-static const char *
-later_type_to_string (MetaLaterType when)
-{
- switch (when)
- {
- case META_LATER_RESIZE:
- return "Later (resize)";
- case META_LATER_CALC_SHOWING:
- return "Later (calc-showing)";
- case META_LATER_CHECK_FULLSCREEN:
- return "Later (check-fullscreen)";
- case META_LATER_SYNC_STACK:
- return "Later (sync-stack)";
- case META_LATER_BEFORE_REDRAW:
- return "Later (before-redraw)";
- case META_LATER_IDLE:
- return "Later (idle)";
- }
-
- return "unknown";
-}
-#endif
-
-static gboolean
-call_later_func (MetaLater *later)
-{
- COGL_TRACE_BEGIN_SCOPED (later, later_type_to_string (later->when));
- return later->func (later->data);
-}
-
-static void
-run_repaint_laters (GSList **laters_list)
-{
- GSList *laters_copy;
- GSList *l;
-
- laters_copy = NULL;
- for (l = *laters_list; l; l = l->next)
- {
- MetaLater *later = l->data;
- if (later->source == 0 ||
- (later->when <= META_LATER_BEFORE_REDRAW && !later->run_once))
- {
- later->ref_count++;
- laters_copy = g_slist_prepend (laters_copy, later);
- }
- }
- laters_copy = g_slist_reverse (laters_copy);
-
- for (l = laters_copy; l; l = l->next)
- {
- MetaLater *later = l->data;
-
- if (!later->func || !call_later_func (later))
- 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)
- keep_timeline_running = TRUE;
- }
- }
-
- if (!keep_timeline_running)
- clutter_timeline_stop (later_timeline);
-
- /* Just keep the repaint func around - it's cheap if the lists are empty */
- return TRUE;
-}
-
-static void
-ensure_later_repaint_func (void)
-{
- if (!later_timeline)
- later_timeline = clutter_timeline_new (G_MAXUINT);
-
- if (later_repaint_func == 0)
- later_repaint_func = clutter_threads_add_repaint_func (run_all_repaint_laters,
- NULL, NULL);
-
- /* Make sure the repaint function gets run */
- clutter_timeline_start (later_timeline);
-}
-
-static gboolean
-call_idle_later (gpointer data)
-{
- MetaLater *later = data;
-
- if (!later->func (later->data))
- {
- meta_later_remove (later->id);
- return FALSE;
- }
- else
- {
- later->run_once = TRUE;
- return TRUE;
- }
-}
-
-/**
- * meta_later_add:
- * @when: enumeration value determining the phase at which to run the callback
- * @func: callback to run later
- * @data: data to pass to the callback
- * @notify: function to call to destroy @data when it is no longer in use, or %NULL
- *
- * Sets up a callback to be called at some later time. @when determines the
- * particular later occasion at which it is called. This is much like g_idle_add(),
- * except that the functions interact properly with clutter event handling.
- * If a "later" function is added from a clutter event handler, and is supposed
- * to be run before the stage is redrawn, it will be run before that redraw
- * of the stage, not the next one.
- *
- * Return value: an integer ID (guaranteed to be non-zero) that can be used
- * to cancel the callback and prevent it from being run.
- */
-guint
-meta_later_add (MetaLaterType when,
- GSourceFunc func,
- gpointer data,
- GDestroyNotify notify)
-{
- MetaLater *later = g_slice_new0 (MetaLater);
-
- later->id = ++last_later_id;
- later->ref_count = 1;
- later->when = when;
- later->func = func;
- later->data = data;
- later->notify = notify;
-
- laters[when] = g_slist_prepend (laters[when], later);
-
- switch (when)
- {
- case META_LATER_RESIZE:
- /* We add this one two ways - as a high-priority idle and as a
- * repaint func. If we are in a clutter event callback, the repaint
- * handler will get hit first, and we'll take care of this function
- * there so it gets called before the stage is redrawn, even if
- * we haven't gotten back to the main loop. Otherwise, the idle
- * handler will get hit first and we want to call this function
- * there so it will happen before GTK+ repaints.
- */
- later->source = g_idle_add_full (META_PRIORITY_RESIZE, call_idle_later, later, NULL);
- g_source_set_name_by_id (later->source, "[mutter] call_idle_later");
- ensure_later_repaint_func ();
- 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 ();
- break;
- case META_LATER_IDLE:
- later->source = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, call_idle_later, later, NULL);
- g_source_set_name_by_id (later->source, "[mutter] call_idle_later");
- break;
- }
-
- 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:
- * @later_id: the integer ID returned from meta_later_add()
- *
- * Removes a callback added with meta_later_add()
- */
-void
-meta_later_remove (guint later_id)
-{
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (laters); i++)
- {
- if (meta_later_remove_from_list (later_id, &laters[i]))
- return;
- }
-}
-
MetaLocaleDirection
meta_get_locale_direction (void)
{
diff --git a/src/meson.build b/src/meson.build
index bb1b48b44..c5ff7966d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -300,6 +300,7 @@ mutter_sources = [
'compositor/meta-dnd.c',
'compositor/meta-feedback-actor.c',
'compositor/meta-feedback-actor-private.h',
+ 'compositor/meta-later.c',
'compositor/meta-module.c',
'compositor/meta-module.h',
'compositor/meta-plugin.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]