static gboolean
on_window_draw (GtkWidget  *window,
		cairo_t    *cr,
                WindowInfo *info)
{
  cairo_rectangle_int_t allocation;
  gtk_widget_get_allocation (window, &allocation);
  double x_offset, y_offset;

  /* We draw an arbitrary pattern of red lines near the border of the
   * window to make it more clear than empty windows if something
   * is drastrically wrong.
   */

  cairo_save (cr);
  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);

  if (info->alpha)
    cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
  else
    cairo_set_source_rgb (cr, 1, 1, 1);

  cairo_paint (cr);
  cairo_restore (cr);

  if (info->redraws)
    {
      double position = (info->time - info->start_time) / 1000000.;
      x_offset = 20 * cos (2 * M_PI * position);
      y_offset = 20 * sin (2 * M_PI * position);
    }
  else
    {
      x_offset = y_offset = 0;
    }

  cairo_set_source_rgb (cr, 1, 0, 0);
  cairo_set_line_width (cr, 10);
  cairo_move_to (cr, 0, 40 + y_offset);
  cairo_line_to (cr, allocation.width, 40 + y_offset);
  cairo_move_to (cr, 0, allocation.height - 40 + y_offset);
  cairo_line_to (cr, allocation.width, allocation.height - 40 + y_offset);
  cairo_move_to (cr, 40 + x_offset, 0);
  cairo_line_to (cr, 40 + x_offset, allocation.height);
  cairo_move_to (cr, allocation.width - 40 + x_offset, 0);
  cairo_line_to (cr, allocation.width - 40 + x_offset, allocation.height);
  cairo_stroke (cr);

  info->exposed = TRUE;

  if (info->exposed && info->mapped && info->pending)
    {
      info->pending = FALSE;
      check_finish_wait_windows ();
    }

  return FALSE;
}
static void
destroy_windows (void)
{
  GList *l;

  for (l = our_windows; l; l = l->next)
    {
      WindowInfo *info = l->data;
      gtk_widget_destroy (info->window);
      free (info);
    }

  g_list_free (our_windows);
  our_windows = NULL;

  check_finish_wait_windows ();
}
static void
handle_method_call (GDBusConnection       *connection,
		    const gchar           *sender,
		    const gchar           *object_path,
		    const gchar           *interface_name,
		    const gchar           *method_name,
		    GVariant              *parameters,
		    GDBusMethodInvocation *invocation,
		    gpointer               user_data)
{
  /* Push off the idle timeout */
  establish_timeout ();

  if (g_strcmp0 (method_name, "Exit") == 0)
    {
      destroy_windows ();

      g_dbus_method_invocation_return_value (invocation, NULL);
      g_dbus_connection_flush_sync (connection, NULL, NULL);

      gtk_main_quit ();
    }
  else if (g_strcmp0 (method_name, "CreateWindow") == 0)
    {
      int width, height;
      gboolean alpha, maximized;

      g_variant_get (parameters, "(iibb)", &width, &height, &alpha, &maximized);

      create_window (width, height, alpha, maximized);
      g_dbus_method_invocation_return_value (invocation, NULL);
    }
  else if (g_strcmp0 (method_name, "WaitWindows") == 0)
    {
      wait_windows_invocations = g_list_prepend (wait_windows_invocations, invocation);
      check_finish_wait_windows ();
    }
  else if (g_strcmp0 (method_name, "DestroyWindows") == 0)
    {
      destroy_windows ();
      g_dbus_method_invocation_return_value (invocation, NULL);
    }
}