Sophie

Sophie

distrib > Mageia > 1 > i586 > media > core-updates-src > by-pkgid > d043847aa27480c55fe107cb41a6f83f > files > 17

gdm-2.32.1-1.1.mga1.src.rpm

diff -p -up gdm-2.30.3/gui/simple-greeter/branding.c.improve-greeter-transparency gdm-2.30.3/gui/simple-greeter/branding.c
--- gdm-2.30.3/gui/simple-greeter/branding.c.improve-greeter-transparency	2010-06-29 15:05:18.000000000 +0200
+++ gdm-2.30.3/gui/simple-greeter/branding.c	2010-06-29 15:05:18.000000000 +0200
@@ -0,0 +1,1508 @@
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <string.h>
+#include <time.h>
+#include "branding.h"
+
+
+#define TYPE_BACKGROUND_MONITOR         (background_monitor_get_type ())
+#define BACKGROUND_MONITOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o),      \
+					       TYPE_BACKGROUND_MONITOR,        \
+					       BackgroundMonitor))
+#define BACKGROUND_MONITOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k),         \
+					       TYPE_BACKGROUND_MONITOR,        \
+					       BackgroundMonitorClass))
+#define IS_BACKGROUND_MONITOR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o),      \
+					       TYPE_BACKGROUND_MONITOR))
+#define IS_BACKGROUND_MONITOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k),         \
+					       TYPE_BACKGROUND_MONITOR))
+#define BACKGROUND_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),       \
+					       TYPE_BACKGROUND_MONITOR,        \
+					       BackgroundMonitorClass))
+
+typedef struct _BackgroundMonitorClass BackgroundMonitorClass;
+
+GType                   background_monitor_get_type       (void);
+
+
+static GdkPixbuf *
+cairo_rgbdata_to_pixbuf (unsigned char *data,
+				    int            width,
+				    int            height)
+{
+	GdkPixbuf     *retval;
+	unsigned char *dstptr;
+	unsigned char *srcptr;
+	int            align;
+
+	g_assert (width > 0 && height > 0);
+
+	if (!data)
+		return NULL;
+
+	retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+	if (!retval)
+		return NULL;
+
+	dstptr = gdk_pixbuf_get_pixels (retval);
+	srcptr = data;
+	align  = gdk_pixbuf_get_rowstride (retval) - (width * 3);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+/* cairo == 00RRGGBB */
+#define CAIRO_RED 2
+#define CAIRO_GREEN 1
+#define CAIRO_BLUE 0
+#else
+/* cairo == BBGGRR00 */
+#define CAIRO_RED 1
+#define CAIRO_GREEN 2
+#define CAIRO_BLUE 3
+#endif
+
+	while (height--) {
+		int x = width;
+		while (x--) {
+			/* pixbuf == BBGGRR */
+			dstptr[0] = srcptr[CAIRO_RED];
+			dstptr[1] = srcptr[CAIRO_GREEN];
+			dstptr[2] = srcptr[CAIRO_BLUE];
+
+			dstptr += 3;
+			srcptr += 4;
+		}
+
+		dstptr += align;
+	}
+#undef CAIRO_RED
+#undef CAIRO_GREEN
+#undef CAIRO_BLUE
+
+	return retval;
+}
+
+
+
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+
+static void background_monitor_changed (BackgroundMonitor *monitor);
+
+static GdkFilterReturn background_monitor_xevent_filter (GdkXEvent *xevent,
+							       GdkEvent  *event,
+							       gpointer   data);
+
+struct _BackgroundMonitorClass {
+	GObjectClass   parent_class;
+	void         (*changed) (BackgroundMonitor *monitor);
+};
+
+struct _BackgroundMonitor {
+	GObject    parent_instance;
+
+	GdkScreen *screen;
+
+	Window     xwindow;
+	GdkWindow *gdkwindow;
+
+	Atom       xatom;
+	GdkAtom    gdkatom;
+
+	GdkPixmap *gdkpixmap;
+	GdkPixbuf *gdkpixbuf;
+
+	int        width;
+	int        height;
+
+	gboolean   display_grabbed;
+};
+
+G_DEFINE_TYPE (BackgroundMonitor, background_monitor, G_TYPE_OBJECT)
+
+static BackgroundMonitor **global_background_monitors = NULL;
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+static void
+background_monitor_finalize (GObject *object)
+{
+	BackgroundMonitor *monitor;
+
+	monitor = BACKGROUND_MONITOR (object);
+
+	gdk_window_remove_filter (
+		monitor->gdkwindow, background_monitor_xevent_filter, monitor);
+	g_signal_handlers_disconnect_by_func (monitor->screen, 
+		background_monitor_changed, monitor);
+
+	if (monitor->gdkpixmap)
+		g_object_unref (monitor->gdkpixmap);
+	monitor->gdkpixmap = NULL;
+
+	if (monitor->gdkpixbuf)
+		g_object_unref (monitor->gdkpixbuf);
+	monitor->gdkpixbuf = NULL;
+
+	G_OBJECT_CLASS (background_monitor_parent_class)->finalize (object);
+}
+
+static void
+background_monitor_class_init (BackgroundMonitorClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	signals [CHANGED] = 
+		g_signal_new ("changed",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (BackgroundMonitorClass, changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	object_class->finalize = background_monitor_finalize;
+}
+
+static void
+background_monitor_init (BackgroundMonitor *monitor)
+{
+	monitor->screen = NULL;
+
+	monitor->gdkwindow = NULL;
+	monitor->xwindow   = None;
+
+	monitor->gdkatom = gdk_atom_intern_static_string ("_XROOTPMAP_ID");
+	monitor->xatom   = gdk_x11_atom_to_xatom (monitor->gdkatom);
+
+	monitor->gdkpixmap = NULL;
+	monitor->gdkpixbuf = NULL;
+
+	monitor->display_grabbed = FALSE;
+}
+
+static void
+background_monitor_connect_to_screen (BackgroundMonitor *monitor,
+					    GdkScreen              *screen)
+{
+	if (monitor->screen != NULL && monitor->gdkwindow != NULL) {
+		gdk_window_remove_filter (monitor->gdkwindow,
+					  background_monitor_xevent_filter,
+					  monitor);
+	}
+
+	monitor->screen = screen;
+	g_signal_connect_swapped (screen, "size-changed", 
+	    G_CALLBACK (background_monitor_changed), monitor);
+
+	monitor->gdkwindow = gdk_screen_get_root_window (screen);
+	monitor->xwindow   = gdk_x11_drawable_get_xid (monitor->gdkwindow);
+
+	gdk_window_add_filter (
+		monitor->gdkwindow, background_monitor_xevent_filter, monitor);
+
+	gdk_window_set_events (
+		monitor->gdkwindow, 
+		gdk_window_get_events (monitor->gdkwindow) | GDK_PROPERTY_CHANGE_MASK);
+}
+
+static BackgroundMonitor *
+background_monitor_new (GdkScreen *screen)
+{
+	BackgroundMonitor *monitor;
+
+	monitor = g_object_new (TYPE_BACKGROUND_MONITOR, NULL);
+
+	background_monitor_connect_to_screen (monitor, screen);
+
+	return monitor;
+}
+
+static BackgroundMonitor *
+background_monitor_get_for_screen (GdkScreen *screen)
+{
+	int screen_number;
+
+	screen_number = gdk_screen_get_number (screen);
+
+	if (!global_background_monitors) {
+		int n_screens;
+
+		n_screens = gdk_display_get_n_screens (gdk_display_get_default ());
+
+		global_background_monitors = g_new0 (BackgroundMonitor *, n_screens);
+	}
+
+	if (!global_background_monitors [screen_number]) {
+		global_background_monitors [screen_number] =
+				background_monitor_new (screen);
+
+		g_object_add_weak_pointer (
+			G_OBJECT (global_background_monitors [screen_number]),
+			(void **) &global_background_monitors [screen_number]);
+
+		return global_background_monitors [screen_number];
+	}
+
+	return g_object_ref (global_background_monitors [screen_number]);
+}
+
+static void
+background_monitor_changed (BackgroundMonitor *monitor)
+{
+	if (monitor->gdkpixmap)
+		g_object_unref (monitor->gdkpixmap);
+	monitor->gdkpixmap = NULL;
+
+	if (monitor->gdkpixbuf)
+		g_object_unref (monitor->gdkpixbuf);
+	monitor->gdkpixbuf = NULL;
+
+	g_signal_emit (monitor, signals [CHANGED], 0);
+}
+
+static GdkFilterReturn
+background_monitor_xevent_filter (GdkXEvent *xevent,
+					GdkEvent  *event,
+					gpointer   data)
+{
+	BackgroundMonitor *monitor;
+	XEvent                 *xev;
+
+	g_return_val_if_fail (IS_BACKGROUND_MONITOR (data), GDK_FILTER_CONTINUE);
+
+	monitor = BACKGROUND_MONITOR (data);
+	xev     = (XEvent *) xevent;
+
+	if (xev->type == PropertyNotify &&
+	    xev->xproperty.atom == monitor->xatom &&
+	    xev->xproperty.window == monitor->xwindow)
+		background_monitor_changed (monitor);
+
+	return GDK_FILTER_CONTINUE;
+}
+
+static void
+background_monitor_setup_pixmap (BackgroundMonitor *monitor)
+{
+	Pixmap	*prop_data = NULL;
+	GdkAtom	 prop_type;
+
+	g_assert (monitor->display_grabbed);
+
+	if (!gdk_property_get (
+		monitor->gdkwindow, monitor->gdkatom,
+		gdk_x11_xatom_to_atom (XA_PIXMAP), 0, 10, 
+		FALSE, &prop_type, NULL, NULL, (gpointer) &prop_data))
+		return;
+
+	if ((prop_type == GDK_TARGET_PIXMAP) && prop_data && prop_data [0]) {
+		GdkDisplay *display;
+
+		g_assert (monitor->gdkpixmap == NULL);
+
+		display = gdk_screen_get_display (monitor->screen);
+
+		monitor->gdkpixmap = gdk_pixmap_foreign_new_for_display (display,
+									 prop_data [0]);
+
+		if (!monitor->gdkpixmap)
+			g_warning ("couldn't get background pixmap\n");
+	}
+
+	g_free (prop_data);
+}
+
+static GdkPixbuf *
+background_monitor_tile_background (BackgroundMonitor *monitor,
+					  int                     width,
+					  int                     height)
+{
+	GdkPixbuf *retval;
+	int        tilewidth, tileheight;
+
+	retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+
+	tilewidth  = gdk_pixbuf_get_width (monitor->gdkpixbuf);
+	tileheight = gdk_pixbuf_get_height (monitor->gdkpixbuf);
+
+	if (tilewidth == 1 && tileheight == 1) {
+		guchar  *pixels;
+		int      n_channels;
+		guint32  pixel = 0;
+
+		n_channels = gdk_pixbuf_get_n_channels (monitor->gdkpixbuf);
+		pixels     = gdk_pixbuf_get_pixels (monitor->gdkpixbuf);
+
+		if (pixels) {
+			if (n_channels == 4)
+				pixel = ((guint32 *) pixels) [0];
+			else if (n_channels == 3)
+				pixel = pixels [0] << 24 | pixels [1] << 16 | pixels [2] << 8;
+		}
+
+		gdk_pixbuf_fill (retval, pixel);
+	} else {
+		unsigned char   *data;
+		cairo_t         *cr;
+		cairo_surface_t *surface;
+		cairo_pattern_t *pattern;
+
+		data = g_malloc (width * height * 4);
+		if (!data)
+			return NULL;
+
+		surface = cairo_image_surface_create_for_data (data,
+							       CAIRO_FORMAT_RGB24,
+							       width, height,
+							       width * 4);
+		cr = cairo_create (surface);
+		cairo_set_source_rgb (cr, 1, 1, 1);
+		cairo_paint (cr);
+
+		gdk_cairo_set_source_pixbuf (cr, monitor->gdkpixbuf, 0, 0);
+		pattern = cairo_get_source (cr);
+		cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+		cairo_rectangle (cr, 0, 0, width, height);
+		cairo_fill (cr);
+
+		cairo_destroy (cr);
+		cairo_surface_destroy (surface);
+
+		retval = cairo_rgbdata_to_pixbuf (data, width, height);
+
+		g_free (data);
+	}
+
+	return retval;
+}
+
+static void 
+background_monitor_setup_pixbuf (BackgroundMonitor *monitor)
+{
+	GdkColormap *colormap = NULL;
+	GdkDisplay  *display;
+	int          rwidth, rheight;
+	int          pwidth, pheight;
+
+	display = gdk_screen_get_display (monitor->screen);
+
+	gdk_x11_display_grab (display);
+	monitor->display_grabbed = TRUE;
+
+	if (!monitor->gdkpixmap)
+		background_monitor_setup_pixmap (monitor);
+
+	if (!monitor->gdkpixmap) {
+		gdk_x11_display_ungrab (display);
+		monitor->display_grabbed = FALSE;
+		return;
+	}
+
+	gdk_drawable_get_size (
+		GDK_DRAWABLE (monitor->gdkpixmap), &pwidth, &pheight);
+
+	gdk_window_get_geometry (monitor->gdkwindow,
+				 NULL, NULL, &rwidth, &rheight, NULL);
+
+	monitor->width  = MIN (pwidth,  rwidth);
+	monitor->height = MIN (pheight, rheight);
+
+	colormap = gdk_drawable_get_colormap (monitor->gdkwindow);
+
+	g_assert (monitor->gdkpixbuf == NULL);
+	monitor->gdkpixbuf = gdk_pixbuf_get_from_drawable (
+					NULL, monitor->gdkpixmap, colormap,
+					0, 0, 0, 0, 
+					monitor->width, monitor->height);
+
+	gdk_x11_display_ungrab (display);
+	monitor->display_grabbed = FALSE;
+
+	if (monitor->gdkpixbuf == NULL)
+		return;
+
+	if ((monitor->width < rwidth || monitor->height < rheight)) {
+		GdkPixbuf *tiled;
+
+		tiled = background_monitor_tile_background (
+						monitor, rwidth, rheight);
+		g_object_unref (monitor->gdkpixbuf);
+		monitor->gdkpixbuf = tiled;
+
+		monitor->width  = rwidth;
+		monitor->height = rheight;
+	}
+}
+
+static GdkPixbuf *
+background_monitor_get_region (BackgroundMonitor *monitor,
+				     int                     x,
+				     int                     y,
+				     int                     width,
+				     int                     height)
+{
+	GdkPixbuf *pixbuf, *tmpbuf;
+	int        subwidth, subheight;
+	int        subx, suby;
+
+	if (!monitor->gdkpixbuf)
+		background_monitor_setup_pixbuf (monitor);
+
+	if (!monitor->gdkpixbuf)
+		return NULL;
+
+	subwidth  = MIN (width,  monitor->width - x);
+	subheight = MIN (height, monitor->height - y);
+	/* if x or y are negative numbers */
+	subwidth  = MIN (subwidth, width + x);
+	subheight  = MIN (subheight, height + y);
+
+	subx = MAX (x, 0);
+	suby = MAX (y, 0);
+
+	if ((subwidth <= 0) || (subheight <= 0) ||
+	    (monitor->width-x < 0) || (monitor->height-y < 0) )
+		/* region is completely offscreen */
+		return gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+				       width, height);
+
+	pixbuf = gdk_pixbuf_new_subpixbuf (
+			monitor->gdkpixbuf, subx, suby, subwidth, subheight);
+
+	if ((subwidth < width) || (subheight < height)) {
+		tmpbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+					 width, height);
+		gdk_pixbuf_copy_area (pixbuf, 0, 0, subwidth, subheight,
+				      tmpbuf, (x < 0) ? -x : 0, (y < 0) ? -y : 0);
+		g_object_unref (pixbuf);
+		pixbuf = tmpbuf;
+	}
+
+	return pixbuf;
+}
+
+
+typedef struct 
+{
+  GdkPixbuf *pixbuf;
+  GSList    *scaled;
+  gboolean   stretch;
+  gint       border_left;
+  gint       border_right;
+  gint       border_bottom;
+  gint       border_top;
+  guint      hints[3][3];
+} ConstraintScale;
+typedef enum
+{
+  COMPONENT_NORTH_WEST = 1 << 0,
+  COMPONENT_NORTH      = 1 << 1,
+  COMPONENT_NORTH_EAST = 1 << 2, 
+  COMPONENT_WEST       = 1 << 3,
+  COMPONENT_CENTER     = 1 << 4,
+  COMPONENT_EAST       = 1 << 5, 
+  COMPONENT_SOUTH_EAST = 1 << 6,
+  COMPONENT_SOUTH      = 1 << 7,
+  COMPONENT_SOUTH_WEST = 1 << 8,
+  COMPONENT_ALL 	  = 1 << 9
+} ConstraintScaleComponent;
+
+typedef enum {
+  THEME_CONSTANT_ROWS = 1 << 0,
+  THEME_CONSTANT_COLS = 1 << 1,
+  THEME_MISSING = 1 << 2
+} ThemeRenderHints;
+
+
+
+static GdkPixbuf *
+bilinear_gradient (GdkPixbuf    *src,
+		   gint          src_x,
+		   gint          src_y,
+		   gint          width,
+		   gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  guchar *src_pixels = gdk_pixbuf_get_pixels (src);
+  guchar *p1, *p2, *p3, *p4;
+  guint dest_rowstride;
+  guchar *dest_pixels;
+  GdkPixbuf *result;
+  int i, j, k;
+
+  p1 = src_pixels + (src_y - 1) * src_rowstride + (src_x - 1) * n_channels;
+  p2 = p1 + n_channels;
+  p3 = src_pixels + src_y * src_rowstride + (src_x - 1) * n_channels;
+  p4 = p3 + n_channels;
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+
+  for (i = 0; i < height; i++)
+    {
+      guchar *p = dest_pixels + dest_rowstride *i;
+      guint v[4];
+      gint dv[4];
+
+      for (k = 0; k < n_channels; k++)
+	{
+	  guint start = ((height - i) * p1[k] + (1 + i) * p3[k]) / (height + 1);
+	  guint end = ((height -  i) * p2[k] + (1 + i) * p4[k]) / (height + 1);
+
+	  dv[k] = (((gint)end - (gint)start) << 16) / (width + 1);
+	  v[k] = (start << 16) + dv[k] + 0x8000;
+	}
+
+      for (j = width; j; j--)
+	{
+	  for (k = 0; k < n_channels; k++)
+	    {
+	      *(p++) = v[k] >> 16;
+	      v[k] += dv[k];
+	    }
+	}
+    }
+
+  return result;
+}
+
+static GdkPixbuf *
+horizontal_gradient (GdkPixbuf    *src,
+		     gint          src_x,
+		     gint          src_y,
+		     gint          width,
+		     gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  guchar *src_pixels = gdk_pixbuf_get_pixels (src);
+  guint dest_rowstride;
+  guchar *dest_pixels;
+  GdkPixbuf *result;
+  int i, j, k;
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+
+  for (i = 0; i < height; i++)
+    {
+      guchar *p = dest_pixels + dest_rowstride *i;
+      guchar *p1 = src_pixels + (src_y + i) * src_rowstride + (src_x - 1) * n_channels;
+      guchar *p2 = p1 + n_channels;
+
+      guint v[4];
+      gint dv[4];
+
+      for (k = 0; k < n_channels; k++)
+	{
+	  dv[k] = (((gint)p2[k] - (gint)p1[k]) << 16) / (width + 1);
+	  v[k] = (p1[k] << 16) + dv[k] + 0x8000;
+	}
+      
+      for (j = width; j; j--)
+	{
+	  for (k = 0; k < n_channels; k++)
+	    {
+	      *(p++) = v[k] >> 16;
+	      v[k] += dv[k];
+	    }
+	}
+    }
+
+  return result;
+}
+
+static GdkPixbuf *
+vertical_gradient (GdkPixbuf    *src,
+		   gint          src_x,
+		   gint          src_y,
+		   gint          width,
+		   gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  guchar *src_pixels = gdk_pixbuf_get_pixels (src);
+  guchar *top_pixels, *bottom_pixels;
+  guint dest_rowstride;
+  guchar *dest_pixels;
+  GdkPixbuf *result;
+  int i, j;
+
+  top_pixels = src_pixels + (src_y - 1) * src_rowstride + (src_x) * n_channels;
+  bottom_pixels = top_pixels + src_rowstride;
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+
+  for (i = 0; i < height; i++)
+    {
+      guchar *p = dest_pixels + dest_rowstride *i;
+      guchar *p1 = top_pixels;
+      guchar *p2 = bottom_pixels;
+
+      for (j = width * n_channels; j; j--)
+	*(p++) = ((height - i) * *(p1++) + (1 + i) * *(p2++)) / (height + 1);
+    }
+
+  return result;
+}
+
+static GdkPixbuf *
+replicate_single (GdkPixbuf    *src,
+		  gint          src_x,
+		  gint          src_y,
+		  gint          width,
+		  gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guchar *pixels = (gdk_pixbuf_get_pixels (src) +
+		    src_y * gdk_pixbuf_get_rowstride (src) +
+		    src_x * n_channels);
+  guchar r = *(pixels++);
+  guchar g = *(pixels++);
+  guchar b = *(pixels++);
+  guint dest_rowstride;
+  guchar *dest_pixels;
+  guchar a = 0;
+  GdkPixbuf *result;
+  int i, j;
+
+  if (n_channels == 4)
+    a = *(pixels++);
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+  
+  for (i = 0; i < height; i++)
+    {
+      guchar *p = dest_pixels + dest_rowstride *i;
+
+      for (j = 0; j < width; j++)
+	{
+	  *(p++) = r;
+	  *(p++) = g;
+	  *(p++) = b;
+
+	  if (n_channels == 4)
+	    *(p++) = a;
+	}
+    }
+
+  return result;
+}
+
+static GdkPixbuf *
+replicate_rows (GdkPixbuf    *src,
+		gint          src_x,
+		gint          src_y,
+		gint          width,
+		gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels);
+  guchar *dest_pixels;
+  GdkPixbuf *result;
+  guint dest_rowstride;
+  int i;
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+
+  for (i = 0; i < height; i++)
+    memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width);
+
+  return result;
+}
+
+static GdkPixbuf *
+replicate_cols (GdkPixbuf    *src,
+		gint          src_x,
+		gint          src_y,
+		gint          width,
+		gint          height)
+{
+  guint n_channels = gdk_pixbuf_get_n_channels (src);
+  guint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels);
+  guchar *dest_pixels;
+  GdkPixbuf *result;
+  guint dest_rowstride;
+  int i, j;
+
+  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
+			   width, height);
+  dest_rowstride = gdk_pixbuf_get_rowstride (result);
+  dest_pixels = gdk_pixbuf_get_pixels (result);
+
+  for (i = 0; i < height; i++)
+    {
+      guchar *p = dest_pixels + dest_rowstride * i;
+      guchar *q = pixels + src_rowstride * i;
+
+      guchar r = *(q++);
+      guchar g = *(q++);
+      guchar b = *(q++);
+      guchar a = 0;
+      
+      if (n_channels == 4)
+	a = *(q++);
+
+      for (j = 0; j < width; j++)
+	{
+	  *(p++) = r;
+	  *(p++) = g;
+	  *(p++) = b;
+
+	  if (n_channels == 4)
+	    *(p++) = a;
+	}
+    }
+
+  return result;
+}
+
+/* Scale the rectangle (src_x, src_y, src_width, src_height)
+ * onto the rectangle (dest_x, dest_y, dest_width, dest_height)
+ * of the destination, and render into a pixbuf
+ */
+
+static void
+cs_render (GdkPixbuf    *src,
+		  guint         hints,
+		  GdkPixbuf    *scaled,
+		  gint          src_x,
+		  gint          src_y,
+		  gint          src_width,
+		  gint          src_height,
+		  gint          dest_x,
+		  gint          dest_y,
+		  gint          dest_width,
+		  gint          dest_height)
+{
+  GdkPixbuf *tmp_pixbuf;
+  GdkRectangle rect;
+  int x_offset, y_offset;
+  gboolean has_alpha = gdk_pixbuf_get_has_alpha (src);
+  gint src_rowstride = gdk_pixbuf_get_rowstride (src);
+  gint src_n_channels = gdk_pixbuf_get_n_channels (src);
+
+  if (dest_width <= 0 || dest_height <= 0)
+    return;
+
+  rect.x = dest_x;
+  rect.y = dest_y;
+  rect.width = dest_width;
+  rect.height = dest_height;
+
+  if (hints & THEME_MISSING)
+    return;
+
+  if (dest_width == src_width && dest_height == src_height)
+    {
+      tmp_pixbuf = g_object_ref (src);
+
+      x_offset = src_x + rect.x - dest_x;
+      y_offset = src_y + rect.y - dest_y;
+    }
+  else if (src_width == 0 && src_height == 0)
+    {
+      tmp_pixbuf = bilinear_gradient (src, src_x, src_y, dest_width, dest_height);      
+      
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else if (src_width == 0 && dest_height == src_height)
+    {
+      tmp_pixbuf = horizontal_gradient (src, src_x, src_y, dest_width, dest_height);      
+      
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else if (src_height == 0 && dest_width == src_width)
+    {
+      tmp_pixbuf = vertical_gradient (src, src_x, src_y, dest_width, dest_height);
+      
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else if ((hints & THEME_CONSTANT_COLS) && (hints & THEME_CONSTANT_ROWS))
+    {
+      tmp_pixbuf = replicate_single (src, src_x, src_y, dest_width, dest_height);
+
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else if (dest_width == src_width && (hints & THEME_CONSTANT_COLS))
+    {
+      tmp_pixbuf = replicate_rows (src, src_x, src_y, dest_width, dest_height);
+
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else if (dest_height == src_height && (hints & THEME_CONSTANT_ROWS))
+    {
+      tmp_pixbuf = replicate_cols (src, src_x, src_y, dest_width, dest_height);
+
+      x_offset = rect.x - dest_x;
+      y_offset = rect.y - dest_y;
+    }
+  else 
+    {
+      double x_scale = (double)dest_width / src_width;
+      double y_scale = (double)dest_height / src_height;
+      guchar *pixels;
+      GdkPixbuf *partial_src;
+      
+      pixels = (gdk_pixbuf_get_pixels (src)
+		+ src_y * src_rowstride
+		+ src_x * src_n_channels);
+
+      partial_src = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB,
+					      has_alpha,
+					      8, src_width, src_height,
+					      src_rowstride,
+					      NULL, NULL);
+						  
+      tmp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+				   has_alpha, 8,
+				   rect.width, rect.height);
+
+      gdk_pixbuf_scale (partial_src, tmp_pixbuf,
+			0, 0, rect.width, rect.height,
+			dest_x - rect.x, dest_y - rect.y, 
+			x_scale, y_scale,
+			GDK_INTERP_BILINEAR);
+
+      gdk_pixbuf_unref (partial_src);
+
+      x_offset = 0;
+      y_offset = 0;
+    }
+
+  if (rect.x >= 0 && rect.x + rect.width <= gdk_pixbuf_get_width (scaled) &&
+      rect.y >= 0 && rect.y + rect.height <= gdk_pixbuf_get_height (scaled))	
+    {
+      gdk_pixbuf_copy_area (tmp_pixbuf,
+			    x_offset, y_offset,
+			    rect.width, rect.height,
+			    scaled,
+			    rect.x,
+			    rect.y);
+    }
+  gdk_pixbuf_unref (tmp_pixbuf);
+}
+
+static guint
+compute_hint (GdkPixbuf *pixbuf,
+	      gint       x0,
+	      gint       x1,
+	      gint       y0,
+	      gint       y1)
+{
+  int i, j;
+  int hints = THEME_CONSTANT_ROWS | THEME_CONSTANT_COLS | THEME_MISSING;
+  int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  
+  guchar *data = gdk_pixbuf_get_pixels (pixbuf);
+  int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+  if (x0 == x1 || y0 == y1)
+    return 0;
+
+  for (i = y0; i < y1; i++)
+    {
+      guchar *p = data + i * rowstride + x0 * n_channels;
+      guchar r = p[0];
+      guchar g = p[1];
+      guchar b = p[2];
+      guchar a = 0;
+      
+      if (n_channels == 4)
+	a = p[3];
+
+      for (j = x0; j < x1 ; j++)
+	{
+	  if (n_channels != 4 || p[3] != 0)
+	    {
+	      hints &= ~THEME_MISSING;
+	      if (!(hints & THEME_CONSTANT_ROWS))
+		goto cols;
+	    }
+	  
+	  if (r != *(p++) ||
+	      g != *(p++) ||
+	      b != *(p++) ||
+	      (n_channels != 4 && a != *(p++)))
+	    {
+	      hints &= ~THEME_CONSTANT_ROWS;
+	      if (!(hints & THEME_MISSING))
+		goto cols;
+	    }
+	}
+    }
+
+ cols:
+  for (i = y0 + 1; i < y1; i++)
+    {
+      guchar *base = data + y0 * rowstride + x0 * n_channels;
+      guchar *p = data + i * rowstride + x0 * n_channels;
+
+      if (memcmp (p, base, n_channels * (x1 - x0)) != 0)
+	{
+	  hints &= ~THEME_CONSTANT_COLS;
+	  return hints;
+	}
+    }
+
+  return hints;
+}
+
+static void
+constraint_scale_compute_hints (ConstraintScale *cs_pb)
+{
+  int i, j;
+  gint width = gdk_pixbuf_get_width (cs_pb->pixbuf);
+  gint height = gdk_pixbuf_get_height (cs_pb->pixbuf);
+
+  if (cs_pb->border_left + cs_pb->border_right > width ||
+      cs_pb->border_top + cs_pb->border_bottom > height)
+    {
+      g_warning ("Invalid borders specified");
+      if (cs_pb->border_left + cs_pb->border_right > width)
+	{
+	  cs_pb->border_left = width / 2;
+	  cs_pb->border_right = (width + 1) / 2;
+	}
+      if (cs_pb->border_bottom + cs_pb->border_top > height)
+	{
+	  cs_pb->border_top = height / 2;
+	  cs_pb->border_bottom = (height + 1) / 2;
+	}
+    }
+  
+  for (i = 0; i < 3; i++)
+    {
+      gint y0, y1;
+
+      switch (i)
+	{
+	case 0:
+	  y0 = 0;
+	  y1 = cs_pb->border_top;
+	  break;
+	case 1:
+	  y0 = cs_pb->border_top;
+	  y1 = height - cs_pb->border_bottom;
+	  break;
+	default:
+	  y0 = height - cs_pb->border_bottom;
+	  y1 = height;
+	  break;
+	}
+      
+      for (j = 0; j < 3; j++)
+	{
+	  gint x0, x1;
+	  
+	  switch (j)
+	    {
+	    case 0:
+	      x0 = 0;
+	      x1 = cs_pb->border_left;
+	      break;
+	    case 1:
+	      x0 = cs_pb->border_left;
+	      x1 = width - cs_pb->border_right;
+	      break;
+	    default:
+	      x0 = width - cs_pb->border_right;
+	      x1 = width;
+	      break;
+	    }
+
+	  cs_pb->hints[i][j] = compute_hint (cs_pb->pixbuf, x0, x1, y0, y1);
+	}
+    }
+  
+}
+
+static GdkPixbuf *
+constraint_scale (GdkPixbuf    *pixbuf,
+		  /*gint          x,
+		  gint          y,*/
+		  gint          width,
+		  gint          height,
+		  gint		border_left,
+		  gint		border_right,
+		  gint		border_bottom,
+		  gint		border_top)
+{
+  gint src_x[4], src_y[4], dest_x[4], dest_y[4];
+  gint pixbuf_width = gdk_pixbuf_get_width (pixbuf);
+  gint pixbuf_height = gdk_pixbuf_get_height (pixbuf);
+  ConstraintScale *cs_pb = g_new0 (ConstraintScale, 1);
+  guint         component_mask = COMPONENT_ALL;
+
+  cs_pb->pixbuf = pixbuf;
+  cs_pb->stretch = TRUE;
+  cs_pb->border_left = border_left;
+  cs_pb->border_right = border_right;
+  cs_pb->border_bottom = border_bottom;
+  cs_pb->border_top = border_top;
+  constraint_scale_compute_hints (cs_pb);
+
+  if (cs_pb->stretch)
+    {
+      GdkPixbuf *scaled = NULL;
+
+      if (!scaled)
+	{
+	  scaled = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (cs_pb->pixbuf),
+				   gdk_pixbuf_get_has_alpha (cs_pb->pixbuf),
+				   gdk_pixbuf_get_bits_per_sample (cs_pb->pixbuf),
+				   width, 
+				   height);
+
+	  gdk_pixbuf_fill (scaled, 0x00000000);
+
+
+	  src_x[0] = 0;
+	  src_x[1] = cs_pb->border_left;    
+	  src_x[2] = pixbuf_width - cs_pb->border_right;      
+	  src_x[3] = pixbuf_width;
+
+	  src_y[0] = 0;
+	  src_y[1] = cs_pb->border_top;      
+	  src_y[2] = pixbuf_height - cs_pb->border_bottom;	  
+	  src_y[3] = pixbuf_height;
+
+	  dest_x[0] = 0;
+	  dest_x[1] = cs_pb->border_left;
+	  dest_x[2] = width - cs_pb->border_right;
+	  dest_x[3] = width;
+
+	  dest_y[0] = 0;
+	  dest_y[1] = cs_pb->border_top;
+	  dest_y[2] = height - cs_pb->border_bottom;
+	  dest_y[3] = height;
+
+
+	  if (component_mask & COMPONENT_ALL)
+	    component_mask = (COMPONENT_ALL - 1) & ~component_mask;
+
+#define RENDER_COMPONENT(X1,X2,Y1,Y2)					         \
+	  cs_render (pixbuf, cs_pb->hints[Y1][X1],			 \
+			    scaled,						 \
+			    src_x[X1], src_y[Y1],				 \
+			    src_x[X2] - src_x[X1], src_y[Y2] - src_y[Y1],	 \
+			    dest_x[X1], dest_y[Y1],				 \
+			    dest_x[X2] - dest_x[X1], dest_y[Y2] - dest_y[Y1]);
+
+	  if (component_mask & COMPONENT_NORTH_WEST)	
+	    RENDER_COMPONENT (0, 1, 0, 1);  
+
+	  if (component_mask & COMPONENT_NORTH)
+	    RENDER_COMPONENT (1, 2, 0, 1);
+
+	  if (component_mask & COMPONENT_NORTH_EAST)
+	    RENDER_COMPONENT (2, 3, 0, 1);
+
+	  if (component_mask & COMPONENT_WEST)
+	    RENDER_COMPONENT (0, 1, 1, 2);
+
+	  if (component_mask & COMPONENT_CENTER)
+	    RENDER_COMPONENT (1, 2, 1, 2);
+
+	  if (component_mask & COMPONENT_EAST)
+	    RENDER_COMPONENT (2, 3, 1, 2);
+
+	  if (component_mask & COMPONENT_SOUTH_WEST)
+	    RENDER_COMPONENT (0, 1, 2, 3);
+
+	  if (component_mask & COMPONENT_SOUTH)
+	    RENDER_COMPONENT (1, 2, 2, 3);
+
+	  if (component_mask & COMPONENT_SOUTH_EAST)
+	    RENDER_COMPONENT (2, 3, 2, 3);
+	}
+
+      return scaled;
+    }
+  return NULL;
+}
+
+static GdkPixbuf *
+composite_image_onto_desktop (GdmWidgetBackground *background);
+
+
+static void
+free_prepared_resources (GdmWidgetBackground *background)
+{
+	background->prepared = FALSE;
+
+	if (background->pixmap)
+		g_object_unref (background->pixmap);
+	background->pixmap = NULL;
+}
+
+static void
+free_composited_resources (GdmWidgetBackground *background)
+{
+
+	free_prepared_resources (background);
+
+	background->composited = FALSE;
+
+	if (background->composited_image)
+		g_object_unref (background->composited_image);
+	background->composited_image = NULL;
+}
+
+static void
+load_background_file (GdmWidgetBackground *background)
+{
+	GError *error = NULL;
+
+	if (!g_file_test (background->image, G_FILE_TEST_IS_REGULAR))
+		return;
+
+	background->loaded_image = 
+		gdk_pixbuf_new_from_file (background->image, &error);
+	if (!background->loaded_image) {
+		g_assert (error != NULL);
+		g_warning (G_STRLOC ": unable to open '%s': %s",
+			   background->image, error->message);
+		g_error_free (error);
+	}
+
+}
+
+static void
+set_pixbuf_background (GdmWidgetBackground *background)
+{
+	g_assert (background->composited_image != NULL);
+	GtkStyle *style;
+
+	gdk_pixbuf_render_pixmap_and_mask_for_colormap (
+		background->composited_image,
+		background->colormap,
+		&background->pixmap, NULL, 128);
+
+	gdk_window_set_back_pixmap (
+		background->window, background->pixmap, FALSE);
+
+	  style = gtk_style_copy (background->widget->style);
+  if (style->bg_pixmap[GTK_STATE_NORMAL])
+    g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
+  style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (background->pixmap);
+  gtk_widget_set_style (background->widget, style);
+  g_object_unref (style);
+}
+
+static GdkPixbuf *
+get_scaled_pixbuf (GdmWidgetBackground *background)
+{
+	GdkPixbuf *scaled;
+	int        orig_width, orig_height;
+	int        widget_width, widget_height;
+
+	load_background_file (background);
+	if (!background->loaded_image)
+		return NULL;
+
+	orig_width  = gdk_pixbuf_get_width  (background->loaded_image);
+	orig_height = gdk_pixbuf_get_height (background->loaded_image);
+
+	widget_width  = background->region.width;
+	widget_height = background->region.height;
+
+
+	if (widget_width == orig_width &&
+	    widget_height == orig_height) {
+		scaled = background->loaded_image;
+		g_object_ref (scaled);
+	} else {
+		scaled = constraint_scale (background->loaded_image,
+			     widget_width, widget_height, 
+			     background->border_left, background->border_right,
+			     background->border_top, background->border_bottom);
+	}
+
+
+
+	return scaled;
+}
+
+
+static gboolean
+background_prepare (GdmWidgetBackground *background) {
+	if (!background->colormap || !background->transformed)
+		return FALSE;
+	free_prepared_resources (background);
+
+	set_pixbuf_background (background);
+
+	background->prepared = TRUE;
+
+//	background->notify_changed (background, background->user_data);
+
+	return TRUE;
+}
+
+static void
+free_transformed_resources (GdmWidgetBackground *background)
+{
+	free_composited_resources (background);
+
+	background->transformed = FALSE;
+
+
+	if (background->transformed_image)
+		g_object_unref (background->transformed_image);
+	background->transformed_image = NULL;
+}
+
+static gboolean
+background_composite (GdmWidgetBackground *background)
+{
+	free_composited_resources (background);
+
+	if (background->transformed_image) {
+			background->composited_image =
+				composite_image_onto_desktop (background);
+	}
+	background->composited = TRUE;
+
+	background_prepare (background);
+
+	return TRUE;
+}
+
+static gboolean
+background_transform (GdmWidgetBackground *background)
+{
+	if (background->region.width == -1)
+		return FALSE;
+
+	free_transformed_resources (background);
+
+	background->transformed_image =
+		get_scaled_pixbuf (background);
+
+	background->transformed = TRUE;
+
+	background_composite (background);
+
+	return TRUE;
+}
+
+
+
+static void
+background_changed (BackgroundMonitor *monitor,
+		    GdmWidgetBackground *background)
+{
+        GdkPixbuf *tmp;
+        tmp = background->desktop;
+        background->desktop = background_monitor_get_region (
+                                        background->monitor,
+                                        background->region.x,
+                                        background->region.y,
+                                        background->region.width,
+                                        background->region.height);
+
+        if (tmp)
+                g_object_unref (tmp);
+
+        background_composite (background);
+}
+
+
+static GdkPixbuf *
+get_desktop_pixbuf (GdmWidgetBackground *background)
+{
+	GdkPixbuf *desktop;
+
+	if (!background->monitor) {
+		background->monitor =
+			background_monitor_get_for_screen (
+				gdk_drawable_get_screen (background->window));
+
+		background->monitor_signal =
+			g_signal_connect (
+			background->monitor, "changed",
+                        G_CALLBACK (background_changed), background);
+	}
+
+	desktop = background_monitor_get_region (
+				background->monitor,
+				background->region.x,
+				background->region.y,
+				background->region.width,
+				background->region.height);
+
+	return desktop;
+}
+
+static GdkPixbuf *
+composite_image_onto_desktop (GdmWidgetBackground *background)
+{
+	GdkPixbuf       *retval;
+	int              width, height;
+	unsigned char   *data;
+	cairo_t         *cr;
+	cairo_surface_t *surface;
+	cairo_pattern_t *pattern;
+
+	if (!background->desktop)
+		background->desktop = get_desktop_pixbuf (background);
+
+	if (!background->desktop)
+		return NULL;
+
+	width  = gdk_pixbuf_get_width  (background->desktop);
+	height = gdk_pixbuf_get_height (background->desktop);
+
+	data = g_malloc (width * height * 4);
+	if (!data)
+		return NULL;
+
+	surface = cairo_image_surface_create_for_data (data,
+						       CAIRO_FORMAT_RGB24,
+						       width, height,
+						       width * 4);
+	cr = cairo_create (surface);
+	cairo_set_source_rgb (cr, 1, 1, 1);
+	cairo_paint (cr);
+
+	gdk_cairo_set_source_pixbuf (cr, background->desktop, 0, 0);
+	cairo_rectangle (cr, 0, 0, width, height);
+	cairo_fill (cr);
+
+	gdk_cairo_set_source_pixbuf (cr, background->transformed_image, 0, 0);
+	pattern = cairo_get_source (cr);
+	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+	cairo_rectangle (cr, 0, 0, width, height);
+	cairo_fill (cr);
+
+	cairo_destroy (cr);
+	cairo_surface_destroy (surface);
+
+	retval = cairo_rgbdata_to_pixbuf (data, width, height);
+
+	g_free (data);
+
+	return retval;
+}
+
+void
+gdm_widget_background_change_region (GdmWidgetBackground *background,
+				int              x,
+				int              y,
+				int              width,
+				int              height)
+{
+	gboolean need_to_retransform = FALSE;
+
+	if (background->region.x == x &&
+	    background->region.y == y &&
+	    background->region.width == width &&
+	    background->region.height == height) 
+		return;
+
+	if ((background->region.width != width ||
+		    background->region.height != height)) { 
+		need_to_retransform = TRUE;
+	}
+
+	background->region.x      = x;
+	background->region.y      = y;
+	background->region.width  = width;
+	background->region.height = height;
+
+	if (background->desktop)
+		g_object_unref (background->desktop);
+	background->desktop = NULL;
+
+	// FIXME
+	background_transform (background);
+
+	return;
+	if (need_to_retransform || ! background->transformed)
+		/* only retransform the background if we have in
+		   fact changed size*/
+		background_transform (background);
+	else
+		background_composite (background);
+}
+
+void
+gdm_widget_background_realized (GdmWidgetBackground *background,
+			   GtkWidget       *widget)
+{
+	g_return_if_fail (widget!= NULL);
+	g_return_if_fail (widget->window!= NULL);
+
+	if (background->window && background->colormap && background->gc)
+		return;
+
+	if (!background->window) {
+		background->window = g_object_ref (widget->window);
+	}
+
+	if (!background->colormap)
+		background->colormap =
+			g_object_ref (gdk_drawable_get_colormap (widget->window));
+
+	if (!background->gc)
+		background->gc = gdk_gc_new (widget->window);
+
+	if (!background->widget)
+		background->widget = g_object_ref (widget);
+
+	background_prepare (background);
+}
+
+void gdm_widget_background_init (GdmWidgetBackground *background) {
+	background->image = NULL;
+	background->loaded_image = NULL;
+	background->window = NULL;
+	background->monitor = NULL;
+	background->desktop = NULL;
+	background->monitor_signal = -1;
+	background->region.x = -1;
+	background->region.y = -1;
+	background->region.width = -1;
+	background->region.height = -1;
+	background->transformed_image = NULL;
+	background->composited_image = NULL;
+	background->pixmap = NULL;
+        background->colormap = NULL;
+	background->prepared = FALSE;
+	background->composited= FALSE;
+	background->transformed= FALSE;
+	background->gc = NULL;
+	background->border_left = 0;
+	background->border_right= 0;
+	background->border_top= 0;
+	background->border_bottom = 0;
+}
+
diff -p -up gdm-2.30.3/gui/simple-greeter/branding.h.improve-greeter-transparency gdm-2.30.3/gui/simple-greeter/branding.h
--- gdm-2.30.3/gui/simple-greeter/branding.h.improve-greeter-transparency	2010-06-29 15:05:18.000000000 +0200
+++ gdm-2.30.3/gui/simple-greeter/branding.h	2010-06-29 15:05:18.000000000 +0200
@@ -0,0 +1,49 @@
+#ifndef __BRANDING_H
+#define __BRANDING_H
+
+#include <gtk/gtk.h>
+
+typedef struct _BackgroundMonitor      BackgroundMonitor;
+
+
+typedef struct _GdmWidgetBackground GdmWidgetBackground;
+
+struct _GdmWidgetBackground {
+        char                   *image;
+        GdkPixbuf              *loaded_image; 
+
+	GdkWindow		*window;
+	GtkWidget		*widget;
+	BackgroundMonitor  *monitor;
+	GdkPixbuf		*desktop;
+	gulong			 monitor_signal;
+	GdkRectangle		region;
+	GdkPixbuf		*transformed_image;
+	GdkPixbuf		*composited_image;
+	GdkPixmap		*pixmap;
+        GdkColormap            *colormap;
+	gboolean		prepared;
+	gboolean		transformed;
+	gboolean		composited;
+	GdkGC			*gc;
+ 	gint		border_left;
+ 	gint		border_right;
+        gint		border_bottom;
+        gint		border_top;
+
+};
+
+void gdm_widget_background_init (GdmWidgetBackground *background);
+void gdm_widget_background_change_region (GdmWidgetBackground *background,
+				int              x,
+				int              y,
+				int              width,
+				int              height);
+void
+gdm_widget_background_realized (GdmWidgetBackground *background,
+			   GtkWidget *widget);
+
+
+
+
+#endif /* __BRANDING_H */
diff -p -up gdm-2.30.3/gui/simple-greeter/gdm-greeter-login-window.c.improve-greeter-transparency gdm-2.30.3/gui/simple-greeter/gdm-greeter-login-window.c
--- gdm-2.30.3/gui/simple-greeter/gdm-greeter-login-window.c.improve-greeter-transparency	2010-06-28 19:23:25.000000000 +0200
+++ gdm-2.30.3/gui/simple-greeter/gdm-greeter-login-window.c	2010-06-29 15:06:30.000000000 +0200
@@ -64,6 +64,8 @@
 #define PW_ENTRY_SIZE GDM_MAX_PASS
 #endif
 
+#include "branding.h"
+
 #define CK_NAME      "org.freedesktop.ConsoleKit"
 #define CK_PATH      "/org/freedesktop/ConsoleKit"
 #define CK_INTERFACE "org.freedesktop.ConsoleKit"
@@ -106,6 +108,7 @@ struct GdmGreeterLoginWindowPrivate
         guint            is_interactive : 1;
         guint            user_chooser_loaded : 1;
         GConfClient     *client;
+        GdmWidgetBackground background;
 
         gboolean         banner_message_enabled;
         guint            gconf_cnxn;
@@ -1138,6 +1141,7 @@ load_theme (GdmGreeterLoginWindow *login
         GtkWidget *box;
         GtkWidget *image;
         GError* error = NULL;
+        GdkColor color;
 
         gdm_profile_start (NULL);
 
@@ -1220,12 +1224,21 @@ load_theme (GdmGreeterLoginWindow *login
         box = GTK_WIDGET (gtk_builder_get_object (login_window->priv->builder, "computer-info-event-box"));
         g_signal_connect (box, "button-press-event", G_CALLBACK (on_computer_info_label_button_press), login_window);
 
+
         if (login_window->priv->user_list_disabled) {
                 switch_mode (login_window, MODE_AUTHENTICATION);
         } else {
                 switch_mode (login_window, MODE_SELECTION);
         }
 
+        gdk_color_parse ("white", &color);
+        gtk_widget_modify_fg (login_window->priv->auth_banner_label, GTK_STATE_NORMAL, &color);
+        gtk_widget_modify_fg (GTK_WIDGET(gtk_builder_get_object (login_window->priv->builder, "computer-info-name-label")), GTK_STATE_NORMAL, &color);
+        gtk_widget_modify_fg (GTK_WIDGET(gtk_builder_get_object (login_window->priv->builder, "auth-prompt-label")), GTK_STATE_NORMAL, &color);
+        gtk_widget_modify_fg (GTK_WIDGET(gtk_builder_get_object (login_window->priv->builder, "computer-info-version-label")), GTK_STATE_NORMAL, &color);
+        gtk_widget_modify_fg (GTK_WIDGET(gtk_builder_get_object (login_window->priv->builder, "auth-message-label")), GTK_STATE_NORMAL, &color);
+        gtk_widget_modify_fg (GTK_WIDGET(gtk_builder_get_object (login_window->priv->builder, "auth-message-label")), GTK_STATE_NORMAL, &color);
+
         gdm_profile_end (NULL);
 }
 
@@ -1340,6 +1353,54 @@ update_banner_message (GdmGreeterLoginWi
         }
 }
 
+static void 
+gdm_greeter_login_window_set_background_region (GdmGreeterLoginWindow *login_window) {
+        GtkWidget *widget;
+        int       origin_x = -1, origin_y = -1;
+
+        widget = GTK_WIDGET (login_window);
+
+        if (!gtk_widget_get_realized (widget))
+                return;
+
+        gdk_window_get_origin (widget->window, &origin_x, &origin_y);
+
+        gdm_widget_background_change_region (
+                &login_window->priv->background, 
+                origin_x, origin_y,
+                widget->allocation.width,
+                widget->allocation.height);
+}
+
+static gboolean
+configure_function (GtkWidget *widget,
+	      gpointer   user_data)
+{
+  gdm_greeter_login_window_set_background_region ((GdmGreeterLoginWindow*) (widget));
+  return FALSE;
+}
+
+static gboolean 
+map_function (GtkWidget *widget,
+		    GdkEvent  *event,
+		    gpointer   user_data)
+{
+   gdm_greeter_login_window_set_background_region ((GdmGreeterLoginWindow*) (widget));
+  return FALSE;
+}
+
+static void
+realize_function (GtkWidget *widget)
+{
+        GdmGreeterLoginWindow *login_window = (GdmGreeterLoginWindow *) widget;
+
+        GTK_WIDGET_CLASS (gdm_greeter_login_window_parent_class)->realize (widget);
+
+        gdm_widget_background_realized (&login_window->priv->background, widget);
+}
+
+
+
 static GObject *
 gdm_greeter_login_window_constructor (GType                  type,
                                       guint                  n_construct_properties,
@@ -1353,10 +1414,16 @@ gdm_greeter_login_window_constructor (GT
                                                                                                                       n_construct_properties,
                                                                                                                       construct_properties));
 
+	g_signal_connect (login_window, "map", G_CALLBACK (map_function), login_window);
+	g_signal_connect (login_window, "configure_event", G_CALLBACK (configure_function), login_window); 
+	g_signal_connect (login_window, "realize", G_CALLBACK (realize_function), login_window); 
+
 
         load_theme (login_window);
         update_banner_message (login_window);
 
+	gtk_frame_set_shadow_type(GTK_FRAME (gtk_builder_get_object (login_window->priv->builder, "window-frame")), GTK_SHADOW_NONE);
+
         gdm_profile_end (NULL);
 
         return G_OBJECT (login_window);
@@ -1532,6 +1599,14 @@ gdm_greeter_login_window_init (GdmGreete
         login_window->priv = GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE (login_window);
         login_window->priv->timed_login_enabled = FALSE;
         login_window->priv->dialog_mode = MODE_UNDEFINED;
+        gdm_widget_background_init(&login_window->priv->background);
+
+        login_window->priv->background.image = g_strdup (UIDIR "/" "box.png");
+        login_window->priv->background.border_left= 5;
+        login_window->priv->background.border_right= 5;
+        login_window->priv->background.border_bottom= 60;
+        login_window->priv->background.border_top= 60;
+
 
         client = gconf_client_get_default ();
         error = NULL;
@@ -1550,7 +1625,6 @@ gdm_greeter_login_window_init (GdmGreete
         login_window->priv->user_list_disabled = user_list_disable;
 
         gtk_window_set_title (GTK_WINDOW (login_window), _("Login Window"));
-        /*gtk_window_set_opacity (GTK_WINDOW (login_window), 0.85);*/
         gtk_window_set_position (GTK_WINDOW (login_window), GTK_WIN_POS_CENTER_ALWAYS);
         gtk_window_set_deletable (GTK_WINDOW (login_window), FALSE);
         gtk_window_set_decorated (GTK_WINDOW (login_window), FALSE);
diff -p -up gdm-2.30.3/gui/simple-greeter/gdm-greeter-panel.c.improve-greeter-transparency gdm-2.30.3/gui/simple-greeter/gdm-greeter-panel.c
--- gdm-2.30.3/gui/simple-greeter/gdm-greeter-panel.c.improve-greeter-transparency	2010-06-28 19:23:25.000000000 +0200
+++ gdm-2.30.3/gui/simple-greeter/gdm-greeter-panel.c	2010-06-29 15:07:53.000000000 +0200
@@ -56,6 +56,8 @@
 
 #include "na-tray.h"
 
+#include "branding.h"
+
 #define CK_NAME              "org.freedesktop.ConsoleKit"
 #define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
 #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
@@ -83,6 +85,7 @@ struct GdmGreeterPanelPrivate
         GtkWidget              *language_option_widget;
         GtkWidget              *layout_option_widget;
         GtkWidget              *session_option_widget;
+        GdmWidgetBackground     background;
 
         GdmTimer               *animation_timer;
         double                  progress;
@@ -230,6 +233,44 @@ on_screen_size_changed (GdkScreen
         gtk_widget_queue_resize (GTK_WIDGET (panel));
 }
 
+static void 
+gdm_greeter_panel_set_background_region (GdmGreeterPanel *panel) {
+        GtkWidget *widget;
+        int       origin_x = -1, origin_y = -1;
+
+        widget = GTK_WIDGET (panel);
+
+        if (!gtk_widget_get_realized (widget))
+                return;
+
+        gdk_window_get_origin (widget->window, &origin_x, &origin_y);
+
+        gdm_widget_background_change_region (
+                &panel->priv->background, 
+                origin_x, origin_y,
+                widget->allocation.width,
+                widget->allocation.height);
+}
+
+
+static gboolean
+configure_function (GtkWidget *widget,
+	      gpointer   user_data)
+{
+  gdm_greeter_panel_set_background_region((GdmGreeterPanel*) (widget));
+//  set_panelparent_bg (widget, get_overlay_pb (), 0, 0, 5, 0);
+  return FALSE;
+}
+
+static gboolean 
+map_function (GtkWidget *widget,
+		    GdkEvent  *event,
+		    gpointer   user_data)
+{
+  gdm_greeter_panel_set_background_region((GdmGreeterPanel*) (widget));
+
+  return FALSE;
+}
 static void
 gdm_greeter_panel_real_realize (GtkWidget *widget)
 {
@@ -245,6 +286,7 @@ gdm_greeter_panel_real_realize (GtkWidge
                           "size_changed",
                           G_CALLBACK (on_screen_size_changed),
                           widget);
+        gdm_widget_background_realized (&((GdmGreeterPanel *)widget)->priv->background, widget);
 }
 
 static void
@@ -862,7 +904,18 @@ setup_panel (GdmGreeterPanel *panel)
                                   G_CALLBACK (on_animation_tick),
                                   panel);
 
-        gdm_profile_end (NULL);
+        gdm_widget_background_init(&panel->priv->background);
+
+        panel->priv->background.image = g_strdup (UIDIR "/" "bottom-panel-image.png");
+        panel->priv->background.border_left= 0;
+        panel->priv->background.border_right = 0;
+        panel->priv->background.border_bottom= 5;
+        panel->priv->background.border_top= 0;
+
+	g_signal_connect (panel, "map", G_CALLBACK (map_function), panel);
+	g_signal_connect (panel, "configure_event", G_CALLBACK (configure_function), panel); 
+
+         gdm_profile_end (NULL);
 }
 
 static GObject *
diff -p -up gdm-2.30.3/gui/simple-greeter/Makefile.am.improve-greeter-transparency gdm-2.30.3/gui/simple-greeter/Makefile.am
--- gdm-2.30.3/gui/simple-greeter/Makefile.am.improve-greeter-transparency	2010-06-28 19:23:25.000000000 +0200
+++ gdm-2.30.3/gui/simple-greeter/Makefile.am	2010-06-29 15:05:18.000000000 +0200
@@ -85,6 +85,8 @@ test_greeter_login_window_SOURCES = 	\
 	gdm-user-chooser-widget.c	\
 	gdm-user-chooser-dialog.h	\
 	gdm-user-chooser-dialog.c	\
+	branding.c			\
+	branding.h			\
 	$(NULL)
 
 test_greeter_login_window_LDADD =	\
@@ -134,6 +136,8 @@ test_greeter_panel_SOURCES = 	\
 	gdm-sessions.c			\
 	gdm-session-option-widget.h	\
 	gdm-session-option-widget.c	\
+	branding.c			\
+	branding.h			\
 	$(NULL)
 
 test_greeter_panel_LDADD =	\
@@ -320,6 +324,8 @@ gdm_simple_greeter_SOURCES =  		\
 	gdm-session-option-widget.c	\
 	gdm-user-chooser-widget.h	\
 	gdm-user-chooser-widget.c	\
+	branding.c			\
+	branding.h			\
 	$(NULL)
 
 gdm_simple_greeter_LDADD = 		\