diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2016-08-25 11:31:56 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2016-10-18 11:49:16 +0100 |
commit | dace0791a9bab4a5d1a69e4bde87973814ca217a (patch) | |
tree | bcf8e20b5813fdf1ed613ec1d3a13682a20786d5 /gtk | |
parent | a9bbb020aac9f20d7366b29219ada2e77349642a (diff) | |
download | gtk+-dace0791a9bab4a5d1a69e4bde87973814ca217a.tar.gz |
gsk: Add the ability to create fallback renderers
While porting GTK to GskRenderer we noticed that the current fallback
code for widgets using Cairo to draw is not enough to cover all the
possible cases.
For instance, if a container widget still uses GtkWidget::draw to render
its children, and at least one of them has been ported to using render
nodes instead, the container won't know how to draw it.
For this reason we want to provide to layers above GSK the ability to
create a "fallback" renderer instance, created using a "parent"
GskRenderer instance, but using a Cairo context as the rendering target
instead of a GdkDrawingContext.
GTK will use this inside the gtk_widget_draw() implementation, if a
widget implements GtkWidgetClass.get_render_node().
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkwidget.c | 70 |
1 files changed, 50 insertions, 20 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 1f6b06db94..ad54378617 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -6354,6 +6354,18 @@ gtk_cairo_set_marked_for_draw (cairo_t *cr, cairo_set_user_data (cr, &mark_for_draw_key, NULL, NULL); } +static GskRenderer * +gtk_widget_get_renderer (GtkWidget *widget) +{ + GtkWidget *toplevel; + + toplevel = _gtk_widget_get_toplevel (widget); + if (_gtk_widget_is_toplevel (toplevel)) + return gtk_window_get_renderer (GTK_WINDOW (toplevel)); + + return NULL; +} + /** * gtk_cairo_should_draw_window: * @cr: a cairo context @@ -6421,6 +6433,7 @@ gtk_widget_draw_internal (GtkWidget *widget, if (gdk_cairo_get_clip_rectangle (cr, NULL)) { + GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (widget); GdkWindow *event_window = NULL; gboolean result; gboolean push_group; @@ -6453,17 +6466,46 @@ gtk_widget_draw_internal (GtkWidget *widget, g_warning ("%s %p is drawn without a current allocation. This should not happen.", G_OBJECT_TYPE_NAME (widget), widget); #endif - if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE)) + /* If the widget uses GSK render nodes then we need a fallback path to + * render on the Cairo context; otherwise we just go through the old + * GtkWidget::draw path + */ + if (widget_class->get_render_node != NULL) { - g_signal_emit (widget, widget_signals[DRAW], - 0, cr, - &result); + GskRenderer *renderer = gtk_widget_get_renderer (widget); + GskRenderer *fallback; + graphene_rect_t viewport; + GskRenderNode *node; + + graphene_rect_init (&viewport, + widget->priv->clip.x, + widget->priv->clip.y, + widget->priv->clip.width, + widget->priv->clip.height); + fallback = gsk_renderer_create_fallback (renderer, &viewport, cr); + node = gtk_widget_get_render_node (widget, fallback); + if (node != NULL) + { + gsk_renderer_render (fallback, node, NULL); + gsk_render_node_unref (node); + } + + g_object_unref (fallback); } - else if (GTK_WIDGET_GET_CLASS (widget)->draw) + else { - cairo_save (cr); - GTK_WIDGET_GET_CLASS (widget)->draw (widget, cr); - cairo_restore (cr); + if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE)) + { + g_signal_emit (widget, widget_signals[DRAW], + 0, cr, + &result); + } + else if (GTK_WIDGET_GET_CLASS (widget)->draw) + { + cairo_save (cr); + GTK_WIDGET_GET_CLASS (widget)->draw (widget, cr); + cairo_restore (cr); + } } #ifdef G_ENABLE_DEBUG @@ -15827,18 +15869,6 @@ gtk_widget_reset_controllers (GtkWidget *widget) } } -GskRenderer * -gtk_widget_get_renderer (GtkWidget *widget) -{ - GtkWidget *toplevel; - - toplevel = _gtk_widget_get_toplevel (widget); - if (_gtk_widget_is_toplevel (toplevel)) - return gtk_window_get_renderer (GTK_WINDOW (toplevel)); - - return NULL; -} - GskRenderNode * gtk_widget_create_render_node (GtkWidget *widget, GskRenderer *renderer, |