static GtkWidget *window = NULL;
/* Pixmap for scribble area, to store current scribbles */
-static GdkPixmap *pixmap = NULL;
+static cairo_surface_t *surface = NULL;
-/* Create a new pixmap of the appropriate size to store our scribbles */
+/* Create a new surface of the appropriate size to store our scribbles */
static gboolean
scribble_configure_event (GtkWidget *widget,
GdkEventConfigure *event,
gpointer data)
{
- if (pixmap)
- g_object_unref (pixmap);
-
- pixmap = gdk_pixmap_new (widget->window,
- widget->allocation.width,
- widget->allocation.height,
- -1);
-
- /* Initialize the pixmap to white */
- gdk_draw_rectangle (pixmap,
- widget->style->white_gc,
- TRUE,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+ GtkAllocation allocation;
+ cairo_t *cr;
+
+ if (surface)
+ cairo_surface_destroy (surface);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+ CAIRO_CONTENT_COLOR,
+ allocation.width,
+ allocation.height);
+
+ /* Initialize the surface to white */
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
/* We've handled the configure event, no need for further processing. */
return TRUE;
}
-/* Redraw the screen from the pixmap */
+/* Redraw the screen from the surface */
static gboolean
-scribble_expose_event (GtkWidget *widget,
- GdkEventExpose *event,
- gpointer data)
+scribble_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
{
- /* We use the "foreground GC" for the widget since it already exists,
- * but honestly any GC would work. The only thing to worry about
- * is whether the GC has an inappropriate clip region set.
- */
-
- gdk_draw_drawable (widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
- pixmap,
- /* Only copy the area that was exposed. */
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
return FALSE;
}
gdouble y)
{
GdkRectangle update_rect;
+ cairo_t *cr;
update_rect.x = x - 3;
update_rect.y = y - 3;
update_rect.width = 6;
update_rect.height = 6;
- /* Paint to the pixmap, where we store our state */
- gdk_draw_rectangle (pixmap,
- widget->style->black_gc,
- TRUE,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height);
+ /* Paint to the surface, where we store our state */
+ cr = cairo_create (surface);
+
+ gdk_cairo_rectangle (cr, &update_rect);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
/* Now invalidate the affected region of the drawing area. */
- gdk_window_invalidate_rect (widget->window,
+ gdk_window_invalidate_rect (gtk_widget_get_window (widget),
&update_rect,
FALSE);
}
GdkEventButton *event,
gpointer data)
{
- if (pixmap == NULL)
+ if (surface == NULL)
return FALSE; /* paranoia check, in case we haven't gotten a configure event */
if (event->button == 1)
int x, y;
GdkModifierType state;
- if (pixmap == NULL)
+ if (surface == NULL)
return FALSE; /* paranoia check, in case we haven't gotten a configure event */
/* This call is very important; it requests the next motion event.
static gboolean
-checkerboard_expose (GtkWidget *da,
- GdkEventExpose *event,
- gpointer data)
+checkerboard_draw (GtkWidget *da,
+ cairo_t *cr,
+ gpointer data)
{
- gint i, j, xcount, ycount;
- GdkGC *gc1, *gc2;
- GdkColor color;
+ gint i, j, xcount, ycount, width, height;
#define CHECK_SIZE 10
#define SPACING 2
- /* At the start of an expose handler, a clip region of event->area
- * is set on the window, and event->area has been cleared to the
+ /* At the start of a draw handler, a clip region has been set on
+ * the Cairo context, and the contents have been cleared to the
* widget's background color. The docs for
* gdk_window_begin_paint_region() give more details on how this
* works.
*/
- /* It would be a bit more efficient to keep these
- * GC's around instead of recreating on each expose, but
- * this is the lazy/slow way.
- */
- gc1 = gdk_gc_new (da->window);
- color.red = 30000;
- color.green = 0;
- color.blue = 30000;
- gdk_gc_set_rgb_fg_color (gc1, &color);
-
- gc2 = gdk_gc_new (da->window);
- color.red = 65535;
- color.green = 65535;
- color.blue = 65535;
- gdk_gc_set_rgb_fg_color (gc2, &color);
-
xcount = 0;
+ width = gtk_widget_get_allocated_width (da);
+ height = gtk_widget_get_allocated_height (da);
i = SPACING;
- while (i < da->allocation.width)
+ while (i < width)
{
j = SPACING;
ycount = xcount % 2; /* start with even/odd depending on row */
- while (j < da->allocation.height)
+ while (j < height)
{
- GdkGC *gc;
-
if (ycount % 2)
- gc = gc1;
+ cairo_set_source_rgb (cr, 0.45777, 0, 0.45777);
else
- gc = gc2;
+ cairo_set_source_rgb (cr, 1, 1, 1);
- /* If we're outside event->area, this will do nothing.
- * It might be mildly more efficient if we handled
- * the clipping ourselves, but again we're feeling lazy.
+ /* If we're outside the clip, this will do nothing.
*/
- gdk_draw_rectangle (da->window,
- gc,
- TRUE,
- i, j,
- CHECK_SIZE,
- CHECK_SIZE);
+ cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
+ cairo_fill (cr);
j += CHECK_SIZE + SPACING;
++ycount;
++xcount;
}
- g_object_unref (gc1);
- g_object_unref (gc2);
-
/* return TRUE because we've handled this event, so no
* further processing is required.
*/
{
window = NULL;
- if (pixmap)
- g_object_unref (pixmap);
- pixmap = NULL;
+ if (surface)
+ cairo_surface_destroy (surface);
+ surface = NULL;
}
GtkWidget *
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
- vbox = gtk_vbox_new (FALSE, 8);
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_container_add (GTK_CONTAINER (frame), da);
- g_signal_connect (da, "expose-event",
- G_CALLBACK (checkerboard_expose), NULL);
+ g_signal_connect (da, "draw",
+ G_CALLBACK (checkerboard_draw), NULL);
/*
* Create the scribble area
gtk_container_add (GTK_CONTAINER (frame), da);
- /* Signals used to handle backing pixmap */
+ /* Signals used to handle backing surface */
- g_signal_connect (da, "expose-event",
- G_CALLBACK (scribble_expose_event), NULL);
+ g_signal_connect (da, "draw",
+ G_CALLBACK (scribble_draw), NULL);
g_signal_connect (da,"configure-event",
G_CALLBACK (scribble_configure_event), NULL);