mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 03:10:09 +00:00
API: widget: Add gtk_widget_set_clip() API
And handle the fact that drawing bounds are now handled by this API and the corresponding gtk_widget_get_clip(). Also add _gtk_widget_supports_clip() function to check if a widget has been ported to the new world.
This commit is contained in:
parent
1d897a9bf2
commit
4f89eb05cf
@ -5475,6 +5475,8 @@ gtk_widget_get_allocated_height
|
||||
gtk_widget_get_allocation
|
||||
gtk_widget_set_allocation
|
||||
gtk_widget_get_allocated_baseline
|
||||
gtk_widget_get_clip
|
||||
gtk_widget_set_clip
|
||||
gtk_widget_get_app_paintable
|
||||
gtk_widget_get_can_default
|
||||
gtk_widget_set_can_default
|
||||
|
143
gtk/gtkwidget.c
143
gtk/gtkwidget.c
@ -439,6 +439,7 @@ struct _GtkWidgetPrivate
|
||||
guint multidevice : 1;
|
||||
guint has_shape_mask : 1;
|
||||
guint in_reparent : 1;
|
||||
guint supports_clip : 1;
|
||||
|
||||
/* Queue-resize related flags */
|
||||
guint alloc_needed : 1;
|
||||
@ -485,6 +486,7 @@ struct _GtkWidgetPrivate
|
||||
/* The widget's allocated size */
|
||||
GtkAllocation allocation;
|
||||
gint allocated_baseline;
|
||||
GtkAllocation clip;
|
||||
|
||||
/* The widget's requested sizes */
|
||||
SizeRequestCache requests;
|
||||
@ -4539,10 +4541,10 @@ gtk_widget_queue_draw_child (GtkWidget *widget)
|
||||
parent = priv->parent;
|
||||
if (parent && gtk_widget_is_drawable (parent))
|
||||
gtk_widget_queue_draw_area (parent,
|
||||
priv->allocation.x,
|
||||
priv->allocation.y,
|
||||
priv->allocation.width,
|
||||
priv->allocation.height);
|
||||
priv->clip.x,
|
||||
priv->clip.y,
|
||||
priv->clip.width,
|
||||
priv->clip.height);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4949,7 +4951,7 @@ gtk_widget_map (GtkWidget *widget)
|
||||
g_signal_emit (widget, widget_signals[MAP], 0);
|
||||
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
|
||||
gdk_window_invalidate_rect (priv->window, &priv->clip, FALSE);
|
||||
|
||||
if (widget->priv->context)
|
||||
_gtk_style_context_update_animating (widget->priv->context);
|
||||
@ -4979,7 +4981,7 @@ gtk_widget_unmap (GtkWidget *widget)
|
||||
gtk_widget_push_verify_invariants (widget);
|
||||
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
|
||||
gdk_window_invalidate_rect (priv->window, &priv->clip, FALSE);
|
||||
_gtk_tooltip_hide (widget);
|
||||
|
||||
if (widget->priv->context)
|
||||
@ -5588,7 +5590,7 @@ gtk_widget_queue_draw (GtkWidget *widget)
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
gtk_widget_get_allocation (widget, &rect);
|
||||
gtk_widget_get_clip (widget, &rect);
|
||||
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
gtk_widget_queue_draw_area (widget,
|
||||
@ -5825,7 +5827,7 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
GdkRectangle real_allocation;
|
||||
GdkRectangle old_allocation;
|
||||
GdkRectangle old_allocation, old_clip;
|
||||
GdkRectangle adjusted_allocation;
|
||||
gboolean alloc_needed;
|
||||
gboolean size_changed;
|
||||
@ -5882,6 +5884,7 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
|
||||
priv->alloc_needed = FALSE;
|
||||
|
||||
old_allocation = priv->allocation;
|
||||
old_clip = priv->clip;
|
||||
old_baseline = priv->allocated_baseline;
|
||||
real_allocation = *allocation;
|
||||
|
||||
@ -5973,20 +5976,35 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
|
||||
if (!alloc_needed && !size_changed && !position_changed && !baseline_changed)
|
||||
goto out;
|
||||
|
||||
memset (&priv->clip, 0, sizeof (priv->clip));
|
||||
priv->supports_clip = FALSE;
|
||||
|
||||
priv->allocated_baseline = baseline;
|
||||
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
|
||||
|
||||
/* Size allocation is god... after consulting god, no further requests or allocations are needed */
|
||||
priv->alloc_needed = FALSE;
|
||||
|
||||
if (priv->supports_clip)
|
||||
{
|
||||
size_changed |= (old_clip.width != priv->clip.width ||
|
||||
old_clip.height != priv->clip.height);
|
||||
position_changed |= (old_clip.x != priv->clip.x ||
|
||||
old_clip.y != priv->clip.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->clip = priv->allocation;
|
||||
}
|
||||
|
||||
if (gtk_widget_get_mapped (widget) && priv->redraw_on_alloc)
|
||||
{
|
||||
if (!gtk_widget_get_has_window (widget) && position_changed)
|
||||
{
|
||||
/* Invalidate union(old_allaction,priv->allocation) in priv->window
|
||||
/* Invalidate union(old_clip,priv->clip) in priv->window
|
||||
*/
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->allocation);
|
||||
cairo_region_union_rectangle (invalidate, &old_allocation);
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->clip);
|
||||
cairo_region_union_rectangle (invalidate, &old_clip);
|
||||
|
||||
gdk_window_invalidate_region (priv->window, invalidate, FALSE);
|
||||
cairo_region_destroy (invalidate);
|
||||
@ -5994,10 +6012,10 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
|
||||
|
||||
if (size_changed || baseline_changed)
|
||||
{
|
||||
/* Invalidate union(old_allaction,priv->allocation) in priv->window and descendents owned by widget
|
||||
/* Invalidate union(old_clip,priv->clip) in priv->window and descendents owned by widget
|
||||
*/
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->allocation);
|
||||
cairo_region_union_rectangle (invalidate, &old_allocation);
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->clip);
|
||||
cairo_region_union_rectangle (invalidate, &old_clip);
|
||||
|
||||
gtk_widget_invalidate_widget_windows (widget, invalidate);
|
||||
cairo_region_destroy (invalidate);
|
||||
@ -6007,7 +6025,7 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
|
||||
if ((size_changed || position_changed || baseline_changed) && priv->parent &&
|
||||
gtk_widget_get_realized (priv->parent) && _gtk_container_get_reallocate_redraws (GTK_CONTAINER (priv->parent)))
|
||||
{
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->allocation);
|
||||
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->clip);
|
||||
gtk_widget_invalidate_widget_windows (priv->parent, invalidate);
|
||||
cairo_region_destroy (invalidate);
|
||||
}
|
||||
@ -6843,9 +6861,10 @@ _gtk_widget_draw_internal (GtkWidget *widget,
|
||||
if (clip_to_size)
|
||||
{
|
||||
cairo_rectangle (cr,
|
||||
0, 0,
|
||||
widget->priv->allocation.width,
|
||||
widget->priv->allocation.height);
|
||||
widget->priv->clip.x - widget->priv->allocation.x,
|
||||
widget->priv->clip.y - widget->priv->allocation.y,
|
||||
widget->priv->clip.width,
|
||||
widget->priv->clip.height);
|
||||
cairo_clip (cr);
|
||||
}
|
||||
|
||||
@ -8873,6 +8892,7 @@ _gtk_widget_set_visible_flag (GtkWidget *widget,
|
||||
priv->allocation.y = -1;
|
||||
priv->allocation.width = 1;
|
||||
priv->allocation.height = 1;
|
||||
memset (&priv->clip, 0, sizeof (priv->clip));
|
||||
}
|
||||
}
|
||||
|
||||
@ -15307,6 +15327,93 @@ gtk_widget_get_has_tooltip (GtkWidget *widget)
|
||||
return has_tooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_get_clip:
|
||||
* @widget: a #GtkWidget
|
||||
* @clip: (out): a pointer to a #GtkAllocation to copy to
|
||||
*
|
||||
* Retrieves the widget’s clip area.
|
||||
*
|
||||
* The clip area is the area in which all of @widget's drawing will
|
||||
* happen. Other toolkits call it the bounding box.
|
||||
*
|
||||
* Historically, in GTK the clip area has been equal to the allocation
|
||||
* retrieved via gtk_widget_get_allocation().
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
void
|
||||
gtk_widget_get_clip (GtkWidget *widget,
|
||||
GtkAllocation *clip)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (clip != NULL);
|
||||
|
||||
priv = widget->priv;
|
||||
|
||||
*clip = priv->clip;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_set_clip:
|
||||
* @widget: a #GtkWidget
|
||||
* @clip: a pointer to a #GtkAllocation to copy from
|
||||
*
|
||||
* Sets the widget’s clip. This must not be used
|
||||
* directly, but from within a widget’s size_allocate method.
|
||||
*
|
||||
* The clip set should be the area that @widget draws on. If @widget is a
|
||||
* #GtkContainer, the area must contain all children's clips.
|
||||
*
|
||||
* If this function is not called by @widget during a size_allocate handler,
|
||||
* it is assumed to be equal to the allocation. However, if the function is
|
||||
* not called, certain features that might extend a widget's allocation will
|
||||
* not be available:
|
||||
*
|
||||
* * The GtkWidget::draw signal will be clipped to the widget's allocation
|
||||
* to avoid overdraw.
|
||||
* * Calling gtk_render_background() will not draw outset shadows.
|
||||
*
|
||||
* It is therefor suggested that you always call gtk_widget_set_clip() during
|
||||
* a size_allocate handler.
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
void
|
||||
gtk_widget_set_clip (GtkWidget *widget,
|
||||
const GtkAllocation *clip)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (gtk_widget_get_visible (widget) || gtk_widget_is_toplevel (widget));
|
||||
g_return_if_fail (clip != NULL);
|
||||
|
||||
priv = widget->priv;
|
||||
|
||||
priv->clip = *clip;
|
||||
priv->supports_clip = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_widget_supports_clip:
|
||||
* @widget: The #GtkWidget to check
|
||||
*
|
||||
* Returns %TRUE if the widget called gtk_widget_set_clip() during
|
||||
* size allocation. See that function for details.
|
||||
*
|
||||
* Returns: %TRUE if the widget handles a clip separate from its allocation.
|
||||
**/
|
||||
gboolean
|
||||
_gtk_widget_supports_clip (GtkWidget *widget)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
|
||||
|
||||
return widget->priv->supports_clip;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_get_allocation:
|
||||
* @widget: a #GtkWidget
|
||||
|
@ -945,6 +945,12 @@ void gtk_widget_get_allocation (GtkWidget *widget,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_set_allocation (GtkWidget *widget,
|
||||
const GtkAllocation *allocation);
|
||||
GDK_AVAILABLE_IN_3_14
|
||||
void gtk_widget_set_clip (GtkWidget *widget,
|
||||
const GtkAllocation *allocation);
|
||||
GDK_AVAILABLE_IN_3_14
|
||||
void gtk_widget_get_clip (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
|
||||
GDK_DEPRECATED_IN_3_0_FOR(gtk_widget_get_preferred_width & gtk_widget_get_preferred_height)
|
||||
|
||||
|
@ -133,6 +133,7 @@ void _gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
|
||||
GtkStyle * _gtk_widget_get_style (GtkWidget *widget);
|
||||
void _gtk_widget_set_style (GtkWidget *widget,
|
||||
GtkStyle *style);
|
||||
gboolean _gtk_widget_supports_clip (GtkWidget *widget);
|
||||
|
||||
typedef gboolean (*GtkCapturedEventHandler) (GtkWidget *widget, GdkEvent *event);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user