#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

typedef struct
{
  GdkScreen *screen;
  GdkWindow *window;
  Window     xwindow;
  GdkAtom    gdkatom;
  Atom       xatom;
} FilterData;

static GdkPixmap *
get_pixmap_from_property (GdkWindow *window,
			  GdkAtom    atom)
{
  GdkPixmap *retval = NULL;
  Pixmap    *prop_data = NULL;
  GdkAtom    prop_type;

  if (gdk_property_get (window, atom,
			gdk_x11_xatom_to_atom (XA_PIXMAP),
			0, 10,  FALSE, &prop_type, NULL, NULL,
			(gpointer) &prop_data))
    {
      if ((prop_type == GDK_TARGET_PIXMAP) && prop_data && prop_data [0])
	{
	  retval = gdk_pixmap_foreign_new (prop_data [0]);
	}

      g_free (prop_data);
    }

  return retval;
}

static GdkPixbuf *
get_pixbuf_from_pixmap (GdkPixmap *pixmap,
			GdkWindow *root_window)
{
  GdkColormap *colormap;
  int          width;
  int          height;
  int          rwidth;
  int          rheight;

  gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
  gdk_drawable_get_size (GDK_DRAWABLE (root_window), &rwidth, &rheight);

  width  = MIN (width,  rwidth);
  height = MIN (height, rheight);
  
  colormap = gdk_drawable_get_colormap (root_window);

  return gdk_pixbuf_get_from_drawable (NULL,
				       pixmap,
				       colormap,
				       0, 0, 0, 0,
				       width,
				       height);
}

static GdkFilterReturn
root_window_xevent_filter (GdkXEvent  *xevent,
			   GdkEvent   *event,
			   FilterData *d)
{
  XEvent *xev;
  
  xev = (XEvent *) xevent;


  if (xev->type == PropertyNotify &&
      xev->xproperty.atom == d->xatom &&
      xev->xproperty.window == d->xwindow)
    {
      GdkPixmap *pixmap;

      g_print ("_XROOTPMAP_ID changed\n");

      pixmap = get_pixmap_from_property (d->window, d->gdkatom);
      if (pixmap)
	{
	  GdkPixbuf *pixbuf;

	  g_print ("Successfully obtained the foreign pixmap\n");

	  pixbuf = get_pixbuf_from_pixmap (pixmap, d->window);
	  if (pixbuf)
	    {
	      g_print ("Successfully obtained a copy of the background image\n");
	      g_object_unref (pixbuf);
	    }
	  else
	    {
	      g_warning ("Failed to get pixbuf from pixmap\n");
	    }

	  g_object_unref (pixmap);
	}
      else
	{
	  g_warning ("Failed to get background pixmap\n");
	}
    }

  return GDK_FILTER_CONTINUE;
}

int
main (int argc, char **argv)
{
  FilterData d = { 0, };

  gtk_init (&argc, &argv);

  d.screen = gdk_screen_get_default ();
  d.window = gdk_screen_get_root_window (d.screen);
  d.xwindow = gdk_x11_drawable_get_xid (d.window);

  d.gdkatom = gdk_atom_intern ("_XROOTPMAP_ID", FALSE);
  d.xatom   = gdk_x11_atom_to_xatom (d.gdkatom);

  gdk_window_add_filter (d.window, (GdkFilterFunc) root_window_xevent_filter, &d);
  gdk_window_set_events (d.window,
			 gdk_window_get_events (d.window) | GDK_PROPERTY_CHANGE_MASK);


  gtk_main ();

  return 0;
}
