Home | History | Annotate | Download | only in window_snapshot
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/window_snapshot/window_snapshot.h"
      6 
      7 #include <gdk/gdkx.h>
      8 #include <gtk/gtk.h>
      9 
     10 #include "base/logging.h"
     11 #include "ui/base/x/x11_util.h"
     12 #include "ui/gfx/rect.h"
     13 
     14 namespace browser {
     15 
     16 static cairo_status_t SnapshotCallback(
     17     void *closure, const unsigned char *data, unsigned int length) {
     18   std::vector<unsigned char>* png_representation =
     19       static_cast<std::vector<unsigned char>*>(closure);
     20 
     21   size_t old_size = png_representation->size();
     22   png_representation->resize(old_size + length);
     23   memcpy(&(*png_representation)[old_size], data, length);
     24   return CAIRO_STATUS_SUCCESS;
     25 }
     26 
     27 gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window,
     28                              std::vector<unsigned char>* png_representation) {
     29   GdkWindow* gdk_window = GTK_WIDGET(gtk_window)->window;
     30   Display* display = GDK_WINDOW_XDISPLAY(gdk_window);
     31   XID win = GDK_WINDOW_XID(gdk_window);
     32   XWindowAttributes attr;
     33   if (XGetWindowAttributes(display, win, &attr) == 0) {
     34     LOG(ERROR) << "Couldn't get window attributes";
     35     return gfx::Rect();
     36   }
     37   XImage* image = XGetImage(
     38       display, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
     39   if (!image) {
     40     LOG(ERROR) << "Couldn't get image";
     41     return gfx::Rect();
     42   }
     43   if (image->depth != 24) {
     44     LOG(ERROR)<< "Unsupported image depth " << image->depth;
     45     return gfx::Rect();
     46   }
     47   cairo_surface_t* surface =
     48       cairo_image_surface_create_for_data(
     49           reinterpret_cast<unsigned char*>(image->data),
     50           CAIRO_FORMAT_RGB24,
     51           image->width,
     52           image->height,
     53           image->bytes_per_line);
     54 
     55   if (!surface) {
     56     LOG(ERROR) << "Unable to create Cairo surface from XImage data";
     57     return gfx::Rect();
     58   }
     59   cairo_surface_write_to_png_stream(
     60       surface, SnapshotCallback, png_representation);
     61   cairo_surface_destroy(surface);
     62 
     63   return gfx::Rect(image->width, image->height);
     64 }
     65 
     66 }  // namespace browser
     67