static gboolean
on_lock_preview_draw (GtkWidget         *widget,
                      cairo_t           *cr,
                      CcBackgroundPanel *panel)
{
  CcBackgroundPanelPrivate *priv = panel->priv;
  update_display_preview (panel, widget, priv->current_lock_background);
  return TRUE;
}
static gboolean
on_preview_draw (GtkWidget         *widget,
                 cairo_t           *cr,
                 CcBackgroundPanel *panel)
{
  CcBackgroundPanelPrivate *priv = panel->priv;
  /* we have another shot in flight or an existing cache */
  if (panel->priv->display_screenshot == NULL
      && panel->priv->screenshot_path == NULL)
    {
      get_screenshot_async (panel);
    }
  else
    update_display_preview (panel, widget, priv->current_background);

  return TRUE;
}
static gboolean
on_preview_draw (GtkWidget         *widget,
                 cairo_t           *cr,
                 CcBackgroundPanel *panel)
{
  /* we have another shot in flight or an existing cache */
  if (panel->priv->display_screenshot == NULL
      && panel->priv->screenshot_path == NULL)
    {
      GdkRectangle rect;

      gdk_screen_get_monitor_geometry (gtk_widget_get_screen (widget), 0, &rect);
      get_screenshot_async (panel, &rect);
    }
  else
    update_display_preview (panel);

  return TRUE;
}
static void
on_screenshot_finished (GObject *source,
                        GAsyncResult *res,
                        gpointer user_data)
{
  ScreenshotData *data = user_data;
  CcBackgroundPanel *panel = data->panel;
  CcBackgroundPanelPrivate *priv;
  GError *error;
  GdkPixbuf *pixbuf;
  cairo_surface_t *surface;
  cairo_t *cr;
  GVariant *result;

  error = NULL;
  result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
                                          res,
                                          &error);

  if (result == NULL) {
    if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
      g_error_free (error);
      return;
    }
    g_debug ("Unable to get screenshot: %s",
             error->message);
    g_error_free (error);
    /* fallback? */
    priv = panel->priv;
    goto out;
  }
  g_variant_unref (result);

  priv = panel->priv;

  pixbuf = gdk_pixbuf_new_from_file (panel->priv->screenshot_path, &error);
  if (pixbuf == NULL)
    {
      g_debug ("Unable to use GNOME Shell's builtin screenshot interface: %s",
               error->message);
      g_error_free (error);
      goto out;
    }

  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                        data->monitor_rect.width, data->monitor_rect.height);
  cr = cairo_create (surface);
  gdk_cairo_set_source_pixbuf (cr, pixbuf,
                               data->capture_rect.x - data->monitor_rect.x,
                               data->capture_rect.y - data->monitor_rect.y);
  cairo_paint (cr);
  g_object_unref (pixbuf);

  if (data->whole_monitor) {
    /* clear the workarea */
    cairo_save (cr);
    cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
    cairo_rectangle (cr, data->workarea_rect.x - data->monitor_rect.x,
                     data->workarea_rect.y - data->monitor_rect.y,
                     data->workarea_rect.width,
                     data->workarea_rect.height);
    cairo_fill (cr);
    cairo_restore (cr);
  }

  g_clear_object (&panel->priv->display_screenshot);
  panel->priv->display_screenshot = gdk_pixbuf_get_from_surface (surface,
                                                                 0, 0,
                                                                 data->monitor_rect.width,
                                                                 data->monitor_rect.height);

  g_free (data);

  /* remove the temporary file created by the shell */
  g_unlink (panel->priv->screenshot_path);
  g_clear_pointer (&priv->screenshot_path, g_free);

  cairo_destroy (cr);
  cairo_surface_destroy (surface);

 out:
  update_display_preview (panel, WID ("background-desktop-drawingarea"), priv->current_background);
}
static void
on_screenshot_finished (GObject *source,
                        GAsyncResult *res,
                        gpointer user_data)
{
  CcBackgroundPanel *panel = user_data;
  CcBackgroundPanelPrivate *priv = panel->priv;
  GError *error;
  GdkRectangle rect;
  GtkWidget *widget;
  GdkPixbuf *pixbuf;
  cairo_surface_t *surface;
  cairo_t *cr;
  int width;
  int height;

  error = NULL;
  g_dbus_connection_call_finish (panel->priv->connection,
                                 res,
                                 &error);

  if (error != NULL) {
    g_debug ("Unable to get screenshot: %s",
             error->message);
    g_error_free (error);
    /* fallback? */
    goto out;
  }

  pixbuf = gdk_pixbuf_new_from_file (panel->priv->screenshot_path, &error);
  if (error != NULL)
    {
      g_debug ("Unable to use GNOME Shell's builtin screenshot interface: %s",
               error->message);
      g_error_free (error);
      goto out;
    }

  width = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                        width, height);
  cr = cairo_create (surface);
  gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
  cairo_paint (cr);
  g_object_unref (pixbuf);

  /* clear the workarea */
   widget = WID ("background-desktop-drawingarea");
  gdk_screen_get_monitor_workarea (gtk_widget_get_screen (widget), 0, &rect);

  cairo_save (cr);
  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
  cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
  cairo_fill (cr);
  cairo_restore (cr);

  g_clear_object (&panel->priv->display_screenshot);
  panel->priv->display_screenshot = gdk_pixbuf_get_from_surface (surface,
                                                                 0, 0,
                                                                 width,
                                                                 height);
  /* remove the temporary file created by the shell */
  g_unlink (panel->priv->screenshot_path);
  g_free (priv->screenshot_path);
  priv->screenshot_path = NULL;

  cairo_destroy (cr);
  cairo_surface_destroy (surface);

 out:
  update_display_preview (panel);
}