root/ui/snapshot/snapshot_gtk.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SnapshotCallback
  2. GrabViewSnapshot
  3. GrabWindowSnapshot
  4. GrabWindowSnapshotAndScaleAsync
  5. GrabViewSnapshotAsync
  6. GrabWindowSnapshotAsync

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/snapshot/snapshot.h"

#include <gdk/gdkx.h>
#include <gtk/gtk.h>

#include "base/callback.h"
#include "base/logging.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/rect.h"

namespace {

cairo_status_t SnapshotCallback(void* closure,
                                const unsigned char* data,
                                unsigned int length) {
  std::vector<unsigned char>* png_representation =
      static_cast<std::vector<unsigned char>*>(closure);

  size_t old_size = png_representation->size();
  png_representation->resize(old_size + length);
  memcpy(&(*png_representation)[old_size], data, length);
  return CAIRO_STATUS_SUCCESS;
}

}  // namespace

namespace ui {

bool GrabViewSnapshot(gfx::NativeView view_handle,
                        std::vector<unsigned char>* png_representation,
                        const gfx::Rect& snapshot_bounds) {
  GdkWindow* gdk_window = gtk_widget_get_window(view_handle);
  Display* display = GDK_WINDOW_XDISPLAY(gdk_window);
  XID win = GDK_WINDOW_XID(gdk_window);

  gfx::Rect window_bounds;
  if (ui::GetWindowRect(win, &window_bounds) == 0) {
    LOG(ERROR) << "Couldn't get window bounds";
    return false;
  }

  DCHECK_LE(snapshot_bounds.right(), window_bounds.width());
  DCHECK_LE(snapshot_bounds.bottom(), window_bounds.height());

  ui::XScopedImage image(XGetImage(
      display, win, snapshot_bounds.x(), snapshot_bounds.y(),
      snapshot_bounds.width(), snapshot_bounds.height(), AllPlanes, ZPixmap));
  if (!image.get()) {
    LOG(ERROR) << "Couldn't get image";
    return false;
  }
  if (image->depth != 24) {
    LOG(ERROR)<< "Unsupported image depth " << image->depth;
    return false;
  }
  cairo_surface_t* surface =
      cairo_image_surface_create_for_data(
          reinterpret_cast<unsigned char*>(image->data),
          CAIRO_FORMAT_RGB24,
          image->width,
          image->height,
          image->bytes_per_line);

  if (!surface) {
    LOG(ERROR) << "Unable to create Cairo surface from XImage data";
    return false;
  }
  cairo_surface_write_to_png_stream(
      surface, SnapshotCallback, png_representation);
  cairo_surface_destroy(surface);

  return true;
}

bool GrabWindowSnapshot(gfx::NativeWindow window_handle,
                        std::vector<unsigned char>* png_representation,
                        const gfx::Rect& snapshot_bounds) {
  return GrabViewSnapshot(GTK_WIDGET(window_handle), png_representation,
      snapshot_bounds);
}

void GrabWindowSnapshotAndScaleAsync(
    gfx::NativeWindow window,
    const gfx::Rect& snapshot_bounds,
    const gfx::Size& target_size,
    scoped_refptr<base::TaskRunner> background_task_runner,
    GrabWindowSnapshotAsyncCallback callback) {
  callback.Run(gfx::Image());
}

void GrabViewSnapshotAsync(
    gfx::NativeView view,
    const gfx::Rect& source_rect,
    scoped_refptr<base::TaskRunner> background_task_runner,
    const GrabWindowSnapshotAsyncPNGCallback& callback) {
  callback.Run(scoped_refptr<base::RefCountedBytes>());
}

void GrabWindowSnapshotAsync(
    gfx::NativeWindow window,
    const gfx::Rect& source_rect,
    scoped_refptr<base::TaskRunner> background_task_runner,
    const GrabWindowSnapshotAsyncPNGCallback& callback) {
  callback.Run(scoped_refptr<base::RefCountedBytes>());
}

}  // namespace ui

/* [<][>][^][v][top][bottom][index][help] */