clutter/stage: Add ClutterStage:paint-view

Now that ClutterStageView is embraced as part of the public
set of Clutter classes, is it possible to give consumers
of this API more information and control over the drawing
routines of ClutterStage.

Introduce ClutterStage:paint-view, a signal that is emitted
for painting a specific view. It's defined as a RUN_LAST
signal to give anyone connecting to it the ability to run
before the view is actually painted, or after (using the
G_CONNECT_AFTER flag, or g_signal_connect_after).

This signal has a corresponding class handler, which allows
Mutter to have much finer control over the painting routines.
In fact, this will allow us to implement a "paint phase watcher"
mechanism in the following patches.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
This commit is contained in:
Georges Basile Stavracas Neto 2019-06-17 21:33:42 -03:00
parent 0cd54c5735
commit 4a19628829
No known key found for this signature in database
GPG Key ID: 886C17EE170D1385
2 changed files with 50 additions and 2 deletions

View File

@ -149,6 +149,8 @@ struct _ClutterStagePrivate
gpointer paint_data;
GDestroyNotify paint_notify;
cairo_rectangle_int_t view_clip;
int update_freeze_count;
guint relayout_pending : 1;
@ -186,6 +188,7 @@ enum
DEACTIVATE,
DELETE_EVENT,
AFTER_PAINT,
PAINT_VIEW,
PRESENTED,
LAST_SIGNAL
@ -682,7 +685,15 @@ _clutter_stage_paint_view (ClutterStage *stage,
COGL_TRACE_BEGIN_SCOPED (ClutterStagePaintView, "Paint (view)");
clutter_stage_do_paint_view (stage, view, clip);
priv->view_clip = *clip;
if (g_signal_has_handler_pending (stage, stage_signals[PAINT_VIEW],
0, TRUE))
g_signal_emit (stage, stage_signals[PAINT_VIEW], 0, view);
else
CLUTTER_STAGE_GET_CLASS (stage)->paint_view (stage, view);
priv->view_clip = (cairo_rectangle_int_t) { 0 };
}
void
@ -1851,6 +1862,16 @@ clutter_stage_finalize (GObject *object)
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
}
static void
clutter_stage_real_paint_view (ClutterStage *stage,
ClutterStageView *view)
{
ClutterStagePrivate *priv = stage->priv;
const cairo_rectangle_int_t *clip = &priv->view_clip;
clutter_stage_do_paint_view (stage, view, clip);
}
static void
clutter_stage_class_init (ClutterStageClass *klass)
{
@ -1880,6 +1901,8 @@ clutter_stage_class_init (ClutterStageClass *klass)
actor_class->queue_redraw = clutter_stage_real_queue_redraw;
actor_class->apply_transform = clutter_stage_real_apply_transform;
klass->paint_view = clutter_stage_real_paint_view;
/**
* ClutterStage:cursor-visible:
*
@ -2123,6 +2146,28 @@ clutter_stage_class_init (ClutterStageClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* ClutterStage::paint-view:
* @stage: the stage that received the event
* @view: a #ClutterStageView
*
* The ::paint-view signal is emitted before a #ClutterStageView is being
* painted.
*
* The view is painted in the default handler. Hence, if you want to perform
* some action after the view is painted, like reading the contents of the
* framebuffer, use g_signal_connect_after() or pass %G_CONNECT_AFTER.
*/
stage_signals[PAINT_VIEW] =
g_signal_new (I_("paint-view"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterStageClass, paint_view),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_STAGE_VIEW);
/**
* ClutterStage::presented: (skip)
* @stage: the stage that received the event

View File

@ -84,9 +84,12 @@ struct _ClutterStageClass
gboolean (* delete_event) (ClutterStage *stage,
ClutterEvent *event);
void (* paint_view) (ClutterStage *stage,
ClutterStageView *view);
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[31];
gpointer _padding_dummy[30];
};
/**