// Copyright (c) 2011 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 "chrome/browser/ui/window_snapshot/window_snapshot.h" #include #include #include "base/logging.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/rect.h" namespace browser { static cairo_status_t SnapshotCallback( void *closure, const unsigned char *data, unsigned int length) { std::vector* png_representation = static_cast*>(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; } bool GrabWindowSnapshot(gfx::NativeWindow window_handle, std::vector* png_representation, const gfx::Rect& snapshot_bounds) { GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_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()); XImage* image = XGetImage( display, win, snapshot_bounds.x(), snapshot_bounds.y(), snapshot_bounds.width(), snapshot_bounds.height(), AllPlanes, ZPixmap); if (!image) { 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(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; } } // namespace browser