stage: Introduce MetaStageWatch and family

MetaStageWatch, watch modes and the watch function are part
of the new stage view watching API. It's design does not
rely on signals on purpose; the number of signals that would
be emitted would be too high, and would impact performance.

MetaStageWatch is an opaque structure outside of MetaStage.

This will be used by the screencast code to monitor a single
view, which has a one-to-one relatioship to logical monitors.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
This commit is contained in:
Georges Basile Stavracas Neto 2019-06-17 21:43:05 -03:00
parent 088117a619
commit 9b5d9f3cb3
No known key found for this signature in database
GPG Key ID: 886C17EE170D1385
2 changed files with 125 additions and 0 deletions

View File

@ -27,8 +27,21 @@
G_BEGIN_DECLS
typedef struct _MetaStageWatch MetaStageWatch;
typedef struct _MetaOverlay MetaOverlay;
typedef enum
{
META_STAGE_WATCH_BEFORE_PAINT,
META_STAGE_WATCH_AFTER_ACTOR_PAINT,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT,
META_STAGE_WATCH_AFTER_PAINT,
} MetaStageWatchPhase;
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
ClutterStageView *view,
gpointer user_data);
ClutterActor *meta_stage_new (MetaBackend *backend);
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
@ -43,6 +56,15 @@ void meta_stage_update_cursor_overlay (MetaStage *stage,
void meta_stage_set_active (MetaStage *stage,
gboolean is_active);
MetaStageWatch * meta_stage_watch_view (MetaStage *stage,
ClutterStageView *view,
MetaStageWatchPhase watch_mode,
MetaStageWatchFunc callback,
gpointer user_data);
void meta_stage_remove_watch (MetaStage *stage,
MetaStageWatch *watch);
G_END_DECLS
#endif /* META_STAGE_PRIVATE_H */

View File

@ -30,6 +30,8 @@
#include "meta/meta-monitor-manager.h"
#include "meta/util.h"
#define N_WATCH_MODES 4
enum
{
ACTORS_PAINTED,
@ -39,6 +41,13 @@ enum
static guint signals[N_SIGNALS];
struct _MetaStageWatch
{
ClutterStageView *view;
MetaStageWatchFunc callback;
gpointer user_data;
};
struct _MetaOverlay
{
gboolean enabled;
@ -55,6 +64,9 @@ struct _MetaStage
{
ClutterStage parent;
GPtrArray *watchers[N_WATCH_MODES];
ClutterStageView *current_view;
GList *overlays;
gboolean is_active;
};
@ -135,6 +147,7 @@ meta_stage_finalize (GObject *object)
{
MetaStage *stage = META_STAGE (object);
GList *l;
int i;
l = stage->overlays;
while (l)
@ -143,9 +156,33 @@ meta_stage_finalize (GObject *object)
l = g_list_delete_link (l, l);
}
for (i = 0; i < N_WATCH_MODES; i++)
g_clear_pointer (&stage->watchers[i], g_ptr_array_unref);
G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
}
static void
notify_watchers_for_mode (MetaStage *stage,
ClutterStageView *view,
MetaStageWatchPhase watch_phase)
{
GPtrArray *watchers;
int i;
watchers = stage->watchers[watch_phase];
for (i = 0; i < watchers->len; i++)
{
MetaStageWatch *watch = g_ptr_array_index (watchers, i);
if (watch->view && view != watch->view)
continue;
watch->callback (stage, view, watch->user_data);
}
}
static void
meta_stage_paint (ClutterActor *actor)
{
@ -154,10 +191,30 @@ meta_stage_paint (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
for (l = stage->overlays; l; l = l->next)
meta_overlay_paint (l->data);
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
}
static void
meta_stage_paint_view (ClutterStage *stage,
ClutterStageView *view)
{
MetaStage *meta_stage = META_STAGE (stage);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
meta_stage->current_view = view;
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
}
static void
@ -202,6 +259,7 @@ meta_stage_class_init (MetaStageClass *klass)
stage_class->activate = meta_stage_activate;
stage_class->deactivate = meta_stage_deactivate;
stage_class->paint_view = meta_stage_paint_view;
signals[ACTORS_PAINTED] = g_signal_new ("actors-painted",
G_TYPE_FROM_CLASS (klass),
@ -214,6 +272,10 @@ meta_stage_class_init (MetaStageClass *klass)
static void
meta_stage_init (MetaStage *stage)
{
int i;
for (i = 0; i < N_WATCH_MODES; i++)
stage->watchers[i] = g_ptr_array_new_with_free_func (g_free);
}
ClutterActor *
@ -345,3 +407,44 @@ meta_stage_set_active (MetaStage *stage,
*/
clutter_stage_event (CLUTTER_STAGE (stage), &event);
}
MetaStageWatch *
meta_stage_watch_view (MetaStage *stage,
ClutterStageView *view,
MetaStageWatchPhase watch_phase,
MetaStageWatchFunc callback,
gpointer user_data)
{
MetaStageWatch *watch;
GPtrArray *watchers;
watch = g_new0 (MetaStageWatch, 1);
watch->view = view;
watch->callback = callback;
watch->user_data = user_data;
watchers = stage->watchers[watch_phase];
g_ptr_array_add (watchers, watch);
return watch;
}
void
meta_stage_remove_watch (MetaStage *stage,
MetaStageWatch *watch)
{
GPtrArray *watchers;
gboolean removed = FALSE;
int i;
for (i = 0; i < N_WATCH_MODES; i++)
{
watchers = stage->watchers[i];
removed = g_ptr_array_remove_fast (watchers, watch);
if (removed)
break;
}
g_assert (removed);
}