gtkframe: Don't queue a redraw on the entire widget every size allocate

Lots of applications often use GtkFrame as a giant toplevel container,
and that means that they get size allocated often. When frames get size
allocated, they invalidate their entire widget tree, even if they
haven't changed size or anything like that happens at all. This is
because the shadow / label needs to be redrawn if the child changes
size. We can optimize this out and only mark ourselves for a redraw if
the child has actually changed its size.
This commit is contained in:
Jasper St. Pierre 2015-07-14 18:24:42 -07:00
parent 2dda89cbd5
commit 18dbe181fb

View File

@ -706,6 +706,16 @@ gtk_frame_draw (GtkWidget *widget,
return FALSE; return FALSE;
} }
static gboolean
rectangle_equal (const GdkRectangle *a,
const GdkRectangle *b)
{
return a->x == b->x
&& a->y == b->y
&& a->width == b->width
&& a->height == b->height;
}
static void static void
gtk_frame_size_allocate (GtkWidget *widget, gtk_frame_size_allocate (GtkWidget *widget,
GtkAllocation *allocation) GtkAllocation *allocation)
@ -719,11 +729,11 @@ gtk_frame_size_allocate (GtkWidget *widget,
gtk_widget_set_allocation (widget, allocation); gtk_widget_set_allocation (widget, allocation);
gtk_frame_compute_child_allocation (frame, &new_allocation); gtk_frame_compute_child_allocation (frame, &new_allocation);
/* If the child allocation changed, that means that the frame is drawn /* If the child allocation changed, that means that the frame is drawn
* in a new place, so we must redraw the entire widget. * in a new place, so we must redraw the entire widget.
*/ */
if (gtk_widget_get_mapped (widget)) if (gtk_widget_get_mapped (widget) && !rectangle_equal (&priv->child_allocation, &new_allocation))
{ {
gdk_window_invalidate_rect (gtk_widget_get_window (widget), allocation, FALSE); gdk_window_invalidate_rect (gtk_widget_get_window (widget), allocation, FALSE);
} }