From 4a196288290223b3cf9bc51e7865792a63922f9d Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 17 Jun 2019 21:33:42 -0300 Subject: [PATCH] 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 --- clutter/clutter/clutter-stage.c | 47 ++++++++++++++++++++++++++++++++- clutter/clutter/clutter-stage.h | 5 +++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index bb7227221..c95c47327 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -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 diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h index f7e697f2c..c28904bd0 100644 --- a/clutter/clutter/clutter-stage.h +++ b/clutter/clutter/clutter-stage.h @@ -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]; }; /**