widget: Remove GtkWidget.draw vfunc

Widgets are exclusively snapshot now.

The draw signal still exists.
This commit is contained in:
Benjamin Otte 2018-04-02 08:34:08 +02:00
parent c06a790694
commit 56e018b91c
2 changed files with 40 additions and 223 deletions

View File

@ -963,7 +963,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->direction_changed = gtk_widget_real_direction_changed;
klass->grab_notify = NULL;
klass->child_notify = NULL;
klass->draw = NULL;
klass->snapshot = gtk_widget_real_snapshot;
klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
klass->grab_focus = gtk_widget_real_grab_focus;
@ -1688,7 +1687,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
g_signal_new (I_("draw"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, draw),
0,
_gtk_boolean_handled_accumulator, NULL,
gtk_widget_draw_marshaller,
G_TYPE_BOOLEAN, 1,
@ -5232,153 +5231,6 @@ gtk_widget_get_renderer (GtkWidget *widget)
return NULL;
}
typedef enum {
RENDER_SNAPSHOT,
RENDER_DRAW
} RenderMode;
static RenderMode
get_render_mode (GtkWidgetClass *klass)
{
GtkWidgetClass *parent_class;
for (parent_class = g_type_class_peek_parent (klass);
parent_class != gtk_widget_parent_class;
parent_class = g_type_class_peek_parent (klass))
{
if (klass->snapshot != parent_class->snapshot)
return RENDER_SNAPSHOT;
else if (klass->draw != parent_class->draw)
return RENDER_DRAW;
klass = parent_class;
}
return RENDER_SNAPSHOT;
}
static void
gtk_widget_draw_internal (GtkWidget *widget,
cairo_t *cr)
{
if (!_gtk_widget_is_drawable (widget))
return;
cairo_rectangle (cr,
0, 0,
widget->priv->allocation.width,
widget->priv->allocation.height);
cairo_clip (cr);
if (gdk_cairo_get_clip_rectangle (cr, NULL))
{
GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (widget);
GdkSurface *event_surface = NULL;
gboolean result;
RenderMode mode;
#ifdef G_ENABLE_CONSISTENCY_CHECKS
if (_gtk_widget_get_alloc_needed (widget))
g_warning ("%s %p is drawn without a current allocation. This should not happen.", G_OBJECT_TYPE_NAME (widget), widget);
#endif
/* 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
*/
mode = get_render_mode (widget_class);
if (mode == RENDER_SNAPSHOT)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
snapshot = gtk_snapshot_new (FALSE, "Fallback<%s>", G_OBJECT_TYPE_NAME (widget));
gtk_widget_snapshot (widget, snapshot);
node = gtk_snapshot_free_to_node (snapshot);
if (node != NULL)
{
gsk_render_node_draw (node, cr);
gsk_render_node_unref (node);
}
}
else
{
gboolean push_group =
widget->priv->alpha != 255 && !_gtk_widget_is_toplevel (widget);
if (push_group)
cairo_push_group (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);
}
if (push_group)
{
cairo_pop_group_to_source (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_paint_with_alpha (cr, widget->priv->alpha / 255.0);
}
}
#ifdef G_ENABLE_DEBUG
if (GTK_DISPLAY_DEBUG_CHECK (gtk_widget_get_display (widget), BASELINES))
{
gint baseline = gtk_widget_get_allocated_baseline (widget);
gint width = gtk_widget_get_allocated_width (widget);
if (baseline != -1)
{
cairo_save (cr);
cairo_new_path (cr);
cairo_move_to (cr, 0, baseline+0.5);
cairo_line_to (cr, width, baseline+0.5);
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgba (cr, 1.0, 0, 0, 0.25);
cairo_stroke (cr);
cairo_restore (cr);
}
}
if (widget->priv->highlight_resize)
{
GtkAllocation alloc;
gtk_widget_get_allocation (widget, &alloc);
cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
cairo_set_source_rgba (cr, 1, 0, 0, 0.2);
cairo_fill (cr);
gtk_widget_queue_draw (widget);
widget->priv->highlight_resize = FALSE;
}
#endif
if (cairo_status (cr) &&
event_surface != NULL)
{
/* We check the event so we only warn about internal GTK+ calls.
* Errors might come from PDF streams having write failures and
* we don't want to spam stderr in that case.
* We do want to catch errors from
*/
g_warning ("drawing failure for widget '%s': %s",
G_OBJECT_TYPE_NAME (widget),
cairo_status_to_string (cairo_status (cr)));
}
}
}
static gboolean
gtk_widget_real_key_press_event (GtkWidget *widget,
GdkEventKey *event)
@ -13483,7 +13335,6 @@ gtk_widget_create_render_node (GtkWidget *widget,
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
GtkWidgetPrivate *priv = widget->priv;
GtkCssValue *filter_value;
RenderMode mode;
double opacity;
GtkCssStyle *style;
GtkAllocation allocation;
@ -13492,11 +13343,6 @@ gtk_widget_create_render_node (GtkWidget *widget,
snapshot = gtk_snapshot_new_child (parent_snapshot, "%s<%p>", gtk_widget_get_name (widget), widget);
/* Compatibility mode: if the widget does not have a render node, we draw
* using gtk_widget_draw() on a temporary node
*/
mode = get_render_mode (klass);
filter_value = _gtk_style_context_peek_property (_gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_FILTER);
gtk_css_filter_value_push_snapshot (filter_value, snapshot);
@ -13508,8 +13354,35 @@ gtk_widget_create_render_node (GtkWidget *widget,
_gtk_widget_get_allocation (widget, &allocation);
if (mode == RENDER_DRAW)
if (opacity < 1.0)
gtk_snapshot_push_opacity (snapshot, opacity, "Opacity<%s,%f>", G_OBJECT_TYPE_NAME (widget), opacity);
if (!GTK_IS_WINDOW (widget))
{
gtk_snapshot_offset (snapshot, margin.left, margin.top);
gtk_css_style_snapshot_background (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_css_style_snapshot_border (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
}
/* Offset to content allocation */
gtk_snapshot_offset (snapshot, margin.left + padding.left + border.left, margin.top + border.top + padding.top);
if (gtk_widget_get_width (widget) > 0 && gtk_widget_get_height (widget) > 0)
klass->snapshot (widget, snapshot);
gtk_snapshot_offset (snapshot, - (margin.left + padding.left + border.left), -(margin.top + border.top + padding.top));
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
{
/* Compatibility mode: if there's a ::draw signal handler, we add a
* child node with the contents of the handler
*/
gboolean result;
cairo_t *cr;
graphene_rect_t bounds;
cairo_rectangle_int_t offset_clip;
@ -13526,74 +13399,21 @@ gtk_widget_create_render_node (GtkWidget *widget,
offset_clip.height);
cr = gtk_snapshot_append_cairo (snapshot,
&bounds, "Fallback<%s>",
G_OBJECT_TYPE_NAME (widget));
gtk_widget_draw_internal (widget, cr);
&bounds,
"DrawSignalContents<%s>", G_OBJECT_TYPE_NAME (widget));
g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
cairo_destroy (cr);
}
else
{
if (opacity < 1.0)
gtk_snapshot_push_opacity (snapshot, opacity, "Opacity<%s,%f>", G_OBJECT_TYPE_NAME (widget), opacity);
if (!GTK_IS_WINDOW (widget))
{
gtk_snapshot_offset (snapshot, margin.left, margin.top);
gtk_css_style_snapshot_background (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_css_style_snapshot_border (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
}
gtk_snapshot_offset (snapshot, margin.left, margin.top);
gtk_css_style_snapshot_outline (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
/* Offset to content allocation */
gtk_snapshot_offset (snapshot, margin.left + padding.left + border.left, margin.top + border.top + padding.top);
if (gtk_widget_get_width (widget) > 0 && gtk_widget_get_height (widget) > 0)
klass->snapshot (widget, snapshot);
gtk_snapshot_offset (snapshot, - (margin.left + padding.left + border.left), -(margin.top + border.top + padding.top));
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
{
/* Compatibility mode: if there's a ::draw signal handler, we add a
* child node with the contents of the handler
*/
gboolean result;
cairo_t *cr;
graphene_rect_t bounds;
cairo_rectangle_int_t offset_clip;
offset_clip.x = 0;
offset_clip.y = 0;
offset_clip.width = priv->allocation.width;
offset_clip.height = priv->allocation.height;
graphene_rect_init (&bounds,
offset_clip.x,
offset_clip.y,
offset_clip.width,
offset_clip.height);
cr = gtk_snapshot_append_cairo (snapshot,
&bounds,
"DrawSignalContents<%s>", G_OBJECT_TYPE_NAME (widget));
g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
cairo_destroy (cr);
}
gtk_snapshot_offset (snapshot, margin.left, margin.top);
gtk_css_style_snapshot_outline (style,
snapshot,
allocation.width - margin.left - margin.right,
allocation.height - margin.top - margin.bottom);
gtk_snapshot_offset (snapshot, - margin.left, - margin.top);
if (opacity < 1.0)
gtk_snapshot_pop (snapshot);
}
if (opacity < 1.0)
gtk_snapshot_pop (snapshot);
gtk_css_filter_value_pop_snapshot (filter_value, snapshot);

View File

@ -164,7 +164,6 @@ struct _GtkWidget
* when it becomes unshadowed due to a grab being removed.
* @child_notify: Signal emitted for each child property that has
* changed on an object.
* @draw: Signal emitted when a widget is supposed to render itself.
* @get_request_mode: This allows a widget to tell its parent container whether
* it prefers to be allocated in %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or
* %GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT mode.
@ -268,8 +267,6 @@ struct _GtkWidgetClass
gboolean was_grabbed);
void (* child_notify) (GtkWidget *widget,
GParamSpec *child_property);
gboolean (* draw) (GtkWidget *widget,
cairo_t *cr);
/* size requests */
GtkSizeRequestMode (* get_request_mode) (GtkWidget *widget);