mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-30 15:31:34 +00:00
widget: Redo how gtk_widget_queue_draw() works
Before, we would immediately invalidate the GdkWindow of the widget, now we call the parent's GtkWidgetClass.queue_draw_child() function. This allows the parent to track redraw queueing of children. By default GtkWidgetClass.queue_draw_child() will again chain up to its parent while respecting the GdkWindow hierarchy for clipping. GtkWindow is then the only widget actually invalidating the GdkWindow. This essentially moves redraw queueing from GDK to GTK.
This commit is contained in:
parent
77038a9b0b
commit
27ab75250c
@ -705,6 +705,9 @@ static void gtk_widget_real_state_flags_changed (GtkWidget
|
||||
GtkStateFlags old_state);
|
||||
static void gtk_widget_real_queue_draw_region (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
static void gtk_widget_real_queue_draw_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
const cairo_region_t *region);
|
||||
static AtkObject* gtk_widget_real_get_accessible (GtkWidget *widget);
|
||||
static void gtk_widget_accessible_interface_init (AtkImplementorIface *iface);
|
||||
static AtkObject* gtk_widget_ref_accessible (AtkImplementor *implementor);
|
||||
@ -1067,6 +1070,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation;
|
||||
klass->adjust_baseline_allocation = gtk_widget_real_adjust_baseline_allocation;
|
||||
klass->queue_draw_region = gtk_widget_real_queue_draw_region;
|
||||
klass->queue_draw_child = gtk_widget_real_queue_draw_child;
|
||||
|
||||
widget_props[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
@ -5023,12 +5027,58 @@ gtk_widget_unrealize (GtkWidget *widget)
|
||||
*****************************************/
|
||||
|
||||
static void
|
||||
gtk_widget_real_queue_draw_region (GtkWidget *widget,
|
||||
gtk_widget_real_queue_draw_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
const cairo_region_t *child_region)
|
||||
{
|
||||
GdkWindow *child_window, *window;
|
||||
cairo_region_t *region;
|
||||
|
||||
window = gtk_widget_get_window (widget);
|
||||
child_window = gtk_widget_get_window (child);
|
||||
|
||||
if (child_window == window)
|
||||
gtk_widget_queue_draw_region (widget, child_region);
|
||||
|
||||
region = cairo_region_copy (child_region);
|
||||
while (child_window != window && !cairo_region_is_empty (region))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
/* clip to current window */
|
||||
cairo_region_intersect_rectangle (region, &(GdkRectangle) {
|
||||
0, 0,
|
||||
gdk_window_get_width (child_window),
|
||||
gdk_window_get_height (child_window)});
|
||||
|
||||
/* make region relative to next window */
|
||||
gdk_window_get_position (child_window, &x, &y);
|
||||
cairo_region_translate (region, x, y);
|
||||
child_window = gdk_window_get_parent (child_window);
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw_region (widget, region);
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_queue_draw_child (GtkWidget *parent,
|
||||
GtkWidget *child,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
WIDGET_CLASS (parent)->queue_draw_child (parent, child, region);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_real_queue_draw_region (GtkWidget *widget,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GtkWidgetPrivate *priv = widget->priv;
|
||||
GtkWidget *parent = _gtk_widget_get_parent (widget);
|
||||
|
||||
gdk_window_invalidate_region (priv->window, region, TRUE);
|
||||
if (parent == NULL)
|
||||
return;
|
||||
|
||||
gtk_widget_queue_draw_child (parent, widget, region);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5053,17 +5103,14 @@ void
|
||||
gtk_widget_queue_draw_region (GtkWidget *widget,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
if (cairo_region_is_empty (region))
|
||||
return;
|
||||
|
||||
/* Just return if the widget or one of its ancestors isn't mapped */
|
||||
for (w = widget; w != NULL; w = w->priv->parent)
|
||||
if (!_gtk_widget_get_mapped (w))
|
||||
return;
|
||||
/* Just return if the widget isn't mapped */
|
||||
if (!_gtk_widget_get_mapped (widget))
|
||||
return;
|
||||
|
||||
WIDGET_CLASS (widget)->queue_draw_region (widget, region);
|
||||
}
|
||||
|
@ -333,8 +333,9 @@ struct _GtkWidget
|
||||
* @adjust_baseline_request:
|
||||
* @adjust_baseline_allocation:
|
||||
* @queue_draw_region: Invalidates the area of widget defined by
|
||||
* region by calling gdk_window_invalidate_region() on the widget's
|
||||
* window and all its child windows.
|
||||
* region.
|
||||
* @queue_draw_child: Child wants to be redrawn. The region given is in
|
||||
* the child's coordinate system.
|
||||
*/
|
||||
struct _GtkWidgetClass
|
||||
{
|
||||
@ -555,10 +556,13 @@ struct _GtkWidgetClass
|
||||
void (* adjust_baseline_request)(GtkWidget *widget,
|
||||
gint *minimum_baseline,
|
||||
gint *natural_baseline);
|
||||
void (* adjust_baseline_allocation) (GtkWidget *widget,
|
||||
gint *baseline);
|
||||
void (*queue_draw_region) (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
void (* adjust_baseline_allocation) (GtkWidget *widget,
|
||||
gint *baseline);
|
||||
void (* queue_draw_region) (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
void (* queue_draw_child) (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
const cairo_region_t *region);
|
||||
|
||||
GskRenderNode *(* get_render_node) (GtkWidget *widget,
|
||||
GskRenderer *renderer);
|
||||
|
@ -519,6 +519,8 @@ static void gtk_window_do_popup (GtkWindow *window,
|
||||
static void gtk_window_style_updated (GtkWidget *widget);
|
||||
static void gtk_window_state_flags_changed (GtkWidget *widget,
|
||||
GtkStateFlags previous_state);
|
||||
static void gtk_window_queue_draw_region (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
|
||||
static GSList *toplevel_list = NULL;
|
||||
static guint window_signals[LAST_SIGNAL] = { 0 };
|
||||
@ -776,6 +778,7 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
widget_class->state_flags_changed = gtk_window_state_flags_changed;
|
||||
widget_class->style_updated = gtk_window_style_updated;
|
||||
widget_class->get_render_node = gtk_window_get_render_node;
|
||||
widget_class->queue_draw_region = gtk_window_queue_draw_region;
|
||||
|
||||
container_class->remove = gtk_window_remove;
|
||||
container_class->check_resize = gtk_window_check_resize;
|
||||
@ -8198,6 +8201,19 @@ gtk_window_style_updated (GtkWidget *widget)
|
||||
update_themed_icon (GTK_WINDOW (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_queue_draw_region (GtkWidget *widget,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
if (_gtk_widget_get_parent (widget))
|
||||
{
|
||||
GTK_WIDGET_CLASS (gtk_window_parent_class)->queue_draw_region (widget, region);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_window_invalidate_region (_gtk_widget_get_window (widget), region, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_window_unset_focus_and_default:
|
||||
* @window: a #GtkWindow
|
||||
|
Loading…
Reference in New Issue
Block a user