From 867ab99b1a0aff0c1fecaf350c1ebc6adad018f2 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 2 Sep 2010 23:26:13 +0200 Subject: [PATCH] API: Add gtk_cairo_should_draw_window() See the function documentation for its purpose and the next commit(s) for examples on how to use it. --- gtk/gtk.symbols | 1 + gtk/gtkwidget.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 867f490abd..30923d3658 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -4176,6 +4176,7 @@ gtk_vseparator_new #if IN_HEADER(__GTK_WIDGET_H__) #if IN_FILE(__GTK_WIDGET_C__) +gtk_cairo_should_draw_window gtk_requisition_copy gtk_requisition_free gtk_requisition_get_type G_GNUC_CONST diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 9ea11ad282..fb63f4b51a 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5070,10 +5070,59 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget, return TRUE; } +static const cairo_user_data_key_t window_key; + +static GdkWindow * +gtk_cairo_get_window (cairo_t *cr) +{ + g_return_val_if_fail (cr != NULL, NULL); + + return cairo_get_user_data (cr, &window_key); +} + +/** + * gtk_cairo_should_draw_window: + * @cr: a cairo context + * @window: the window to check + * + * This function is supposed to be called in GtkWidget::draw + * implementations for widgets that support multiple windows. + * @cr must be untransformed from invoking of the draw function. + * This function will return %TRUE if the contents of the given + * @window are supposed to be drawn and %FALSE otherwise. Note + * that when the drawing was not initiated by the windowing + * system this function will return %TRUE for all windows, so + * you need to draw the bottommost window first. Also, do not + * use "else if" statements to check which window should be drawn. + * + * Returns: %TRUE if @window should be drawn + **/ +gboolean +gtk_cairo_should_draw_window (cairo_t *cr, + GdkWindow *window) +{ + GdkWindow *cairo_window; + + g_return_val_if_fail (cr != NULL, FALSE); + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + + cairo_window = gtk_cairo_get_window (cr); + + return cairo_window == NULL || + cairo_window == window; +} + +static void +gtk_cairo_set_window (cairo_t *cr, + GdkWindow *window) +{ + cairo_set_user_data (cr, &window_key, window, NULL); +} static gboolean gtk_widget_real_expose_event (GtkWidget *widget, GdkEventExpose *expose) { + GdkWindow *window; gboolean result = FALSE; cairo_t *cr; @@ -5081,9 +5130,34 @@ gtk_widget_real_expose_event (GtkWidget *widget, return FALSE; cr = gdk_cairo_create (expose->window); + gtk_cairo_set_window (cr, expose->window); + gdk_cairo_region (cr, expose->region); cairo_clip (cr); + /* translate cairo context properly */ + window = gtk_widget_get_window (widget); + if (window != expose->window) + { + int x, y; + + if (gdk_window_get_parent (expose->window) == window) + { + gdk_window_get_position (expose->window, &x, &y); + } + else + { + int ex, ey; + gdk_window_get_origin (expose->window, &ex, &ey); + gdk_window_get_origin (window, &x, &y); + x = ex - x; + y = ey - y; + } + + cairo_translate (cr, -x, -y); + } + + if (!gtk_widget_get_has_window (widget)) { cairo_translate (cr, @@ -5094,7 +5168,10 @@ gtk_widget_real_expose_event (GtkWidget *widget, g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result); - + + /* unset here, so if someone keeps a reference to cr we + * don't leak the window. */ + gtk_cairo_set_window (cr, NULL); cairo_destroy (cr); return result;