static gboolean
goo_canvas_draw (GtkWidget      *widget,
		 cairo_t        *cr)
{
  GooCanvas *canvas = GOO_CANVAS (widget);
  GooCanvasBounds clip_bounds, bounds, root_item_bounds;
  double x1, y1, x2, y2;

  if (!gtk_cairo_should_draw_window (cr, canvas->canvas_window))
    return FALSE;

  if (!canvas->root_item)
    {
      canvas->before_initial_draw = FALSE;
      return FALSE;
    }

  /* TODO: Need to worry about child widgets? */

  /* The clip extents tell us which parts of the window need to be drawn,
     in pixels, where (0,0) is the top-left of the widget window (not the
     entire canvas window as was the case with the expose_event signal). */
  cairo_clip_extents (cr, &clip_bounds.x1, &clip_bounds.y1,
		      &clip_bounds.x2, &clip_bounds.y2);

  cairo_save (cr);

  /* Get rid of the translation passed in by GTK+. We use our own. */
  cairo_identity_matrix (cr);

  /* Set our default drawing settins - antialias, line width. */
  goo_canvas_setup_cairo_context (canvas, cr);

  /* Clear the background. */
  if (canvas->clear_background)
    {
      const GtkStyle* style = gtk_widget_get_style (widget);
      const GtkStateType state = gtk_widget_get_state (widget);
      gdk_cairo_set_source_color (cr, &(style->base[state]));
      cairo_paint (cr);
      cairo_set_source_rgb (cr, 0, 0, 0);
   }

  if (canvas->need_update)
    goo_canvas_update_internal (canvas, cr);

  bounds = clip_bounds;
  goo_canvas_convert_from_window_pixels (canvas, &bounds.x1, &bounds.y1);
  goo_canvas_convert_from_window_pixels (canvas, &bounds.x2, &bounds.y2);

  /* Get rid of the current clip, as it uses the wrong coordinate space.
     FIXME: Maybe we should always set a clip with the new GTK+ drawing code. */
  cairo_reset_clip (cr);

  /* Translate it to use the canvas pixel offsets (used when the canvas is
     smaller than the window and the anchor isn't set to NORTH_WEST). */
  cairo_translate (cr, canvas->canvas_x_offset, canvas->canvas_y_offset);

  /* Scale it so we can use canvas coordinates. */
  cairo_scale (cr, canvas->device_to_pixels_x, canvas->device_to_pixels_y);

  /* Translate it so the top-left of the canvas becomes (0,0). */
  cairo_translate (cr, -canvas->bounds.x1, -canvas->bounds.y1);

  /* TODO: check this works OK with the clipping from GTK+ 3. */
  /* Clip to the canvas bounds, if necessary. We only need to clip if the
     items in the canvas extend outside the canvas bounds and the canvas
     bounds is less than the area being painted. */
  goo_canvas_item_get_bounds (canvas->root_item, &root_item_bounds);
  if ((root_item_bounds.x1 < canvas->bounds.x1
       && canvas->bounds.x1 > bounds.x1)
      || (root_item_bounds.x2 > canvas->bounds.x2
	  && canvas->bounds.x2 < bounds.x2)
      || (root_item_bounds.y1 < canvas->bounds.y1
	  && canvas->bounds.y1 > bounds.y1)
      || (root_item_bounds.y2 > canvas->bounds.y2
	  && canvas->bounds.y2 < bounds.y2))
    {
      /* Clip to the intersection of the canvas bounds and the expose
	 bounds, to avoid cairo's 16-bit limits. */
      x1 = MAX (canvas->bounds.x1, bounds.x1);
      y1 = MAX (canvas->bounds.y1, bounds.y1);
      x2 = MIN (canvas->bounds.x2, bounds.x2);
      y2 = MIN (canvas->bounds.y2, bounds.y2);

      cairo_new_path (cr);
      cairo_move_to (cr, x1, y1);
      cairo_line_to (cr, x2, y1);
      cairo_line_to (cr, x2, y2);
      cairo_line_to (cr, x1, y2);
      cairo_close_path (cr);
      cairo_clip (cr);
    }

#if 0
  g_print ("Painting bounds: %g, %g - %g, %g\n", bounds.x1, bounds.y1,
	   bounds.x2, bounds.y2);
#endif
  goo_canvas_item_paint (canvas->root_item, cr, &bounds, canvas->scale);

  cairo_restore (cr);

  paint_static_items (canvas, cr, &clip_bounds);

  GTK_WIDGET_CLASS (goo_canvas_parent_class)->draw (widget, cr);

  canvas->before_initial_draw = FALSE;

  return FALSE;
}
