gtk: Use GskRenderNode to render widgets
We need a virtual function to retrieve the GskRenderNode for each widget, which is supposed to attach its own children's GskRenderNodes. Additionally, we want to maintain the existing GtkWidget::draw mechanism for widgets that do not implement get_render_node() — as well as widgets that have handlers connected to the ::draw signal.
This commit is contained in:
105
gtk/gtkwidget.c
105
gtk/gtkwidget.c
@@ -16052,27 +16052,116 @@ 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_get_render_node (GtkWidget *widget,
|
||||
GskRenderer *renderer)
|
||||
{
|
||||
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
|
||||
GskRenderNode *node;
|
||||
|
||||
if (klass->get_render_node == NULL)
|
||||
{
|
||||
GskRenderNode *tmp;
|
||||
graphene_rect_t bounds;
|
||||
GtkAllocation clip;
|
||||
cairo_t *cr;
|
||||
|
||||
gtk_widget_get_clip (widget, &clip);
|
||||
graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
|
||||
|
||||
tmp = gsk_render_node_new ();
|
||||
gsk_render_node_set_bounds (tmp, &bounds);
|
||||
cr = gsk_render_node_get_draw_context (tmp);
|
||||
|
||||
gtk_widget_draw (widget, cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
node = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = klass->get_render_node (widget, renderer);
|
||||
|
||||
if (klass->draw != NULL ||
|
||||
g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
|
||||
{
|
||||
GskRenderNode *tmp;
|
||||
graphene_rect_t bounds;
|
||||
GtkAllocation clip;
|
||||
gboolean result;
|
||||
cairo_t *cr;
|
||||
|
||||
gtk_widget_get_clip (widget, &clip);
|
||||
graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
|
||||
|
||||
tmp = gsk_render_node_new ();
|
||||
gsk_render_node_set_bounds (tmp, &bounds);
|
||||
cr = gsk_render_node_get_draw_context (tmp);
|
||||
|
||||
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
|
||||
{
|
||||
g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
|
||||
}
|
||||
else if (klass->draw != NULL)
|
||||
{
|
||||
klass->draw (widget, cr);
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
gsk_render_node_append_child (node, tmp);
|
||||
gsk_render_node_unref (tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_render (GtkWidget *widget,
|
||||
GdkWindow *window,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GdkDrawingContext *context;
|
||||
gboolean do_clip;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
GskRenderer *renderer;
|
||||
GskRenderNode *root;
|
||||
|
||||
/* We only render double buffered on native windows */
|
||||
if (!gdk_window_has_native (window))
|
||||
return;
|
||||
|
||||
renderer = gtk_widget_get_renderer (widget);
|
||||
if (renderer == NULL)
|
||||
return;
|
||||
|
||||
root = gtk_widget_get_render_node (widget, renderer);
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
context = gdk_window_begin_draw_frame (window, region);
|
||||
cr = gdk_drawing_context_get_cairo_context (context);
|
||||
|
||||
do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
|
||||
cairo_translate (cr, -x, -y);
|
||||
|
||||
gtk_widget_draw_internal (widget, cr, do_clip);
|
||||
gsk_renderer_render (renderer, root, context);
|
||||
gsk_render_node_unref (root);
|
||||
|
||||
gdk_window_end_draw_frame (window, context);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gsk.h>
|
||||
#include <gtk/gtkaccelgroup.h>
|
||||
#include <gtk/gtkborder.h>
|
||||
#include <gtk/gtktypes.h>
|
||||
@@ -595,12 +596,14 @@ struct _GtkWidgetClass
|
||||
void (*queue_draw_region) (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
|
||||
GskRenderNode *(* get_render_node) (GtkWidget *widget,
|
||||
GskRenderer *renderer);
|
||||
|
||||
/*< private >*/
|
||||
|
||||
GtkWidgetClassPrivate *priv;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved6) (void);
|
||||
void (*_gtk_reserved7) (void);
|
||||
};
|
||||
|
||||
|
||||
@@ -297,6 +297,9 @@ void gtk_widget_render (GtkWidget
|
||||
const cairo_region_t *region);
|
||||
|
||||
|
||||
GskRenderNode * gtk_widget_get_render_node (GtkWidget *widget,
|
||||
GskRenderer *renderer);
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline gboolean
|
||||
|
||||
@@ -7328,6 +7328,8 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
{
|
||||
graphene_rect_t viewport;
|
||||
graphene_matrix_t projection;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_point3d_t tmp;
|
||||
|
||||
graphene_rect_init (&viewport, 0, 0, allocation->width, allocation->height);
|
||||
gsk_renderer_set_viewport (priv->renderer, &viewport);
|
||||
@@ -7337,6 +7339,10 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
0, allocation->height,
|
||||
-1, 1);
|
||||
gsk_renderer_set_projection (priv->renderer, &projection);
|
||||
|
||||
graphene_matrix_init_translate (&modelview,
|
||||
graphene_point3d_init (&tmp, 0.f, 0.f, 0.f));
|
||||
gsk_renderer_set_modelview (priv->renderer, &modelview);
|
||||
}
|
||||
|
||||
get_shadow_width (window, &window_border);
|
||||
|
||||
Reference in New Issue
Block a user