summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-08-25 11:31:56 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2016-10-18 11:49:16 +0100
commitdace0791a9bab4a5d1a69e4bde87973814ca217a (patch)
treebcf8e20b5813fdf1ed613ec1d3a13682a20786d5 /gtk
parenta9bbb020aac9f20d7366b29219ada2e77349642a (diff)
downloadgtk+-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.c70
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,