/*
 * compile with:
 * gcc bug788556.c -Wall -o bug788556 `pkg-config --libs --cflags cairo x11 xext`
 */

#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main (int    argc,
          char **argv)
{
  Display *xdisplay;
  Window xwindow;
  XWindowAttributes attr;
  int stride;
  cairo_surface_t *surface;

  xdisplay = XOpenDisplay (NULL);

  xwindow = 0x32000f8;
  XGetWindowAttributes (xdisplay, xwindow, &attr);

  {
    XImage *image;

    image = XGetImage (xdisplay, xwindow,
                       0, 0, attr.width, attr.height,
                       AllPlanes, ZPixmap);

    stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, attr.width);
    surface = cairo_image_surface_create_for_data ((unsigned char *) image->data,
                                                   CAIRO_FORMAT_ARGB32,
                                                   attr.width, attr.height,
                                                   stride);

    cairo_surface_write_to_png (surface, "test1.png");
    cairo_surface_destroy (surface);
  }

  {
    XImage *image;
    XShmSegmentInfo shminfo;

    image = XShmCreateImage (xdisplay, attr.visual, attr.depth, ZPixmap, NULL,
                             &shminfo, attr.width, attr.height); 

    shminfo.shmid = shmget (IPC_PRIVATE, image->bytes_per_line * image->height,
                            IPC_CREAT | 0777);

    shminfo.readOnly = False;
    shminfo.shmaddr = shmat (shminfo.shmid, 0, 0);
    image->data = shminfo.shmaddr;

    XShmAttach (xdisplay, &shminfo);

    XShmGetImage (xdisplay, xwindow, image, 0, 0, AllPlanes);

    stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, attr.width);
    surface = cairo_image_surface_create_for_data ((unsigned char *) image->data,
                                                   CAIRO_FORMAT_ARGB32,
                                                   attr.width, attr.height,
                                                   stride);

    cairo_surface_write_to_png (surface, "test2.png");
    cairo_surface_destroy (surface);
  }

  return 0;
}
