File compiz-0.7.8-NOMAD.diff of Package compiz

diff --git a/gtk/window-decorator/gtk-window-decorator.c b/gtk/window-decorator/gtk-window-decorator.c
index d018a42..48a2716 100644
--- a/gtk/window-decorator/gtk-window-decorator.c
+++ b/gtk/window-decorator/gtk-window-decorator.c
@@ -236,6 +236,7 @@ int right_click_action  = RIGHT_CLICK_ACTION_DEFAULT;
 int wheel_action        = WHEEL_ACTION_DEFAULT;
 
 static gboolean minimal = FALSE;
+static gboolean reduced_resources = FALSE;
 
 static double decoration_alpha = 0.5;
 
@@ -304,8 +305,9 @@ static decor_shadow_t *switcher_shadow = NULL;
 static GdkPixmap *decor_normal_pixmap = NULL;
 static GdkPixmap *decor_active_pixmap = NULL;
 
-static Atom frame_window_atom;
 static Atom win_decor_atom;
+static Atom win_decor_active_atom;
+static Atom frame_window_atom;
 static Atom win_blur_decor_atom;
 static Atom wm_move_resize_atom;
 static Atom restack_window_atom;
@@ -371,6 +373,23 @@ static struct _pos {
     { 6, 2, 16, 16,   0, 0, 0, 0, 0, 0 }
 };
 
+static char *wm_action_name[3][3] = {
+    {
+	"_COMPIZ_WM_WINDOW_SIZE_TOPLEFT_DECOR",
+	"_COMPIZ_WM_WINDOW_SIZE_TOP_DECOR",
+	"_COMPIZ_WM_WINDOW_SIZE_TOPRIGHT_DECOR"
+    }, {
+	"_COMPIZ_WM_WINDOW_SIZE_LEFT_DECOR",
+	"_COMPIZ_WM_WINDOW_MOVE_DECOR",
+	"_COMPIZ_WM_WINDOW_SIZE_RIGHT_DECOR"
+    }, {
+	"_COMPIZ_WM_WINDOW_SIZE_BOTTOMLEFT_DECOR",
+	"_COMPIZ_WM_WINDOW_SIZE_BOTTOM_DECOR",
+	"_COMPIZ_WM_WINDOW_SIZE_BOTTOMRIGHT_DECOR"
+    }
+};
+static Atom wm_action_atom[3][3];
+
 typedef struct _decor_color {
     double r;
     double g;
@@ -384,8 +403,9 @@ typedef struct _decor {
     Window	      event_windows[3][3];
     Window	      button_windows[BUTTON_NUM];
     guint	      button_states[BUTTON_NUM];
-    GdkPixmap	      *pixmap;
     GdkPixmap	      *buffer_pixmap;
+    GdkPixmap	      *pixmap;
+    GdkPixmap	      *active_pixmap;
     GdkGC	      *gc;
     decor_layout_t    border_layout;
     decor_context_t   *context;
@@ -477,32 +497,26 @@ static Window    switcher_selected_window = None;
 static XRenderPictFormat *xformat;
 
 static void
-decor_update_blur_property (decor_t *d,
-			    int     width,
-			    int     height,
-			    Region  top_region,
-			    int     top_offset,
-			    Region  bottom_region,
-			    int     bottom_offset,
-			    Region  left_region,
-			    int     left_offset,
-			    Region  right_region,
-			    int     right_offset)
+decor_update_box_property (decor_t *d,
+			   XID     xid,
+			   Atom    property,
+			   int     value0,
+			   int     value1,
+			   int     width,
+			   int     height,
+			   Region  top_region,
+			   int     top_offset,
+			   Region  bottom_region,
+			   int     bottom_offset,
+			   Region  left_region,
+			   int     left_offset,
+			   Region  right_region,
+			   int     right_offset)
 {
     Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
     long    *data = NULL;
     int     size = 0;
 
-    if (blur_type != BLUR_TYPE_ALL)
-    {
-	bottom_region = NULL;
-	left_region   = NULL;
-	right_region  = NULL;
-
-	if (blur_type != BLUR_TYPE_TITLEBAR)
-	    top_region = NULL;
-    }
-
     if (top_region)
 	size += top_region->numRects;
     if (bottom_region)
@@ -517,15 +531,18 @@ decor_update_blur_property (decor_t *d,
 
     if (data)
     {
-	decor_region_to_blur_property (data, 4, 0, width, height,
-				       top_region, top_offset,
-				       bottom_region, bottom_offset,
-				       left_region, left_offset,
-				       right_region, right_offset);
+	data[0] = value0;
+	data[1] = value1;
+
+	decor_region_to_box_property (data + 2, width, height,
+				      top_region, top_offset,
+				      bottom_region, bottom_offset,
+				      left_region, left_offset,
+				      right_region, right_offset);
 
 	gdk_error_trap_push ();
-	XChangeProperty (xdisplay, d->prop_xid,
-			 win_blur_decor_atom,
+	XChangeProperty (xdisplay, xid,
+			 property,
 			 XA_INTEGER,
 			 32, PropModeReplace, (guchar *) data,
 			 2 + size * 6);
@@ -537,13 +554,52 @@ decor_update_blur_property (decor_t *d,
     else
     {
 	gdk_error_trap_push ();
-	XDeleteProperty (xdisplay, d->prop_xid, win_blur_decor_atom);
+	XDeleteProperty (xdisplay, xid, property);
 	gdk_display_sync (gdk_display_get_default ());
 	gdk_error_trap_pop ();
     }
 }
 
 static void
+decor_update_blur_property (decor_t *d,
+			    int     width,
+			    int     height,
+			    Region  top_region,
+			    int     top_offset,
+			    Region  bottom_region,
+			    int     bottom_offset,
+			    Region  left_region,
+			    int     left_offset,
+			    Region  right_region,
+			    int     right_offset)
+{
+    if (blur_type != BLUR_TYPE_ALL)
+    {
+	bottom_region = NULL;
+	left_region   = NULL;
+	right_region  = NULL;
+
+	if (blur_type != BLUR_TYPE_TITLEBAR)
+	    top_region = NULL;
+    }
+
+    decor_update_box_property (d,
+			       d->prop_xid,
+			       win_blur_decor_atom,
+			       4, 0,
+			       width,
+			       height,
+			       top_region,
+			       top_offset,
+			       bottom_region,
+			       bottom_offset,
+			       left_region,
+			       left_offset,
+			       right_region,
+			       right_offset);
+}
+
+static void
 decor_update_window_property (decor_t *d)
 {
     long	    data[256];
@@ -572,6 +628,24 @@ decor_update_window_property (decor_t *d)
 
     extents.top += titlebar_height;
 
+    if (d->active_pixmap)
+    {
+	decor_quads_to_property (data, GDK_PIXMAP_XID (d->active_pixmap),
+				 &extents, &extents,
+				 ICON_SPACE + d->button_width,
+				 0,
+				 quads, nQuad);
+
+	gdk_error_trap_push ();
+	XChangeProperty (xdisplay, d->prop_xid,
+			 win_decor_active_atom,
+			 win_decor_atom,
+			 32, PropModeReplace, (guchar *) data,
+			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+	gdk_display_sync (gdk_display_get_default ());
+	gdk_error_trap_pop ();
+    }
+
     decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap),
 			     &extents, &extents,
 			     ICON_SPACE + d->button_width,
@@ -581,7 +655,7 @@ decor_update_window_property (decor_t *d)
     gdk_error_trap_push ();
     XChangeProperty (xdisplay, d->prop_xid,
 		     win_decor_atom,
-		     XA_INTEGER,
+		     win_decor_atom,
 		     32, PropModeReplace, (guchar *) data,
 		     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     gdk_display_sync (gdk_display_get_default ());
@@ -650,7 +724,7 @@ decor_update_switcher_property (decor_t *d)
     gdk_error_trap_push ();
     XChangeProperty (xdisplay, d->prop_xid,
 		     win_decor_atom,
-		     XA_INTEGER,
+		     win_decor_atom,
 		     32, PropModeReplace, (guchar *) data,
 		     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     gdk_display_sync (gdk_display_get_default ());
@@ -976,7 +1050,9 @@ button_state_paint (cairo_t	  *cr,
 }
 
 static void
-draw_window_decoration (decor_t *d)
+draw_window_decoration_to_pixmap (decor_t   *d,
+				  GdkPixmap *pixmap,
+				  gint      active)
 {
     cairo_t       *cr;
     GtkStyle	  *style;
@@ -987,7 +1063,7 @@ draw_window_decoration (decor_t *d)
     int		  top;
     int		  button_x;
 
-    if (!d->pixmap)
+    if (!pixmap)
 	return;
 
     style = gtk_widget_get_style (style_window);
@@ -1003,7 +1079,7 @@ draw_window_decoration (decor_t *d)
     if (d->buffer_pixmap)
 	cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap));
     else
-	cr = gdk_cairo_create (GDK_DRAWABLE (d->pixmap));
+	cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
 
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
@@ -1020,7 +1096,7 @@ draw_window_decoration (decor_t *d)
 
     draw_shadow_background (d, cr, d->shadow, d->context);
 
-    if (d->active)
+    if (active)
     {
 	decor_color_t *title_color = _title_color;
 
@@ -1145,7 +1221,7 @@ draw_window_decoration (decor_t *d)
 
     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
-    if (d->active)
+    if (active)
     {
 	gdk_cairo_set_source_color_alpha (cr,
 					  &style->fg[GTK_STATE_NORMAL],
@@ -1219,7 +1295,7 @@ draw_window_decoration (decor_t *d)
 
 	button_x -= 17;
 
-	if (d->active)
+	if (active)
 	{
 	    cairo_move_to (cr, x, y);
 	    draw_close_button (d, cr, 3.0);
@@ -1247,7 +1323,7 @@ draw_window_decoration (decor_t *d)
 
 	cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
 
-	if (d->active)
+	if (active)
 	{
 	    gdk_cairo_set_source_color_alpha (cr,
 					      &style->fg[GTK_STATE_NORMAL],
@@ -1288,7 +1364,7 @@ draw_window_decoration (decor_t *d)
 
 	button_x -= 17;
 
-	if (d->active)
+	if (active)
 	{
 	    gdk_cairo_set_source_color_alpha (cr,
 					      &style->fg[GTK_STATE_NORMAL],
@@ -1311,7 +1387,7 @@ draw_window_decoration (decor_t *d)
 
     if (d->layout)
     {
-	if (d->active)
+	if (active)
 	{
 	    cairo_move_to (cr,
 			   d->context->left_space + 21.0,
@@ -1348,7 +1424,7 @@ draw_window_decoration (decor_t *d)
 	cairo_rectangle (cr, 0.0, 0.0, 16.0, 16.0);
 	cairo_clip (cr);
 
-	if (d->active)
+	if (active)
 	    cairo_paint (cr);
 	else
 	    cairo_paint_with_alpha (cr, alpha);
@@ -1357,7 +1433,7 @@ draw_window_decoration (decor_t *d)
     cairo_destroy (cr);
 
     if (d->buffer_pixmap)
-	gdk_draw_drawable  (d->pixmap,
+	gdk_draw_drawable  (pixmap,
 			    d->gc,
 			    d->buffer_pixmap,
 			    0,
@@ -1366,6 +1442,20 @@ draw_window_decoration (decor_t *d)
 			    0,
 			    d->width,
 			    d->height);
+}
+
+static void
+draw_window_decoration (decor_t *d)
+{
+    if (d->active_pixmap)
+    {
+	draw_window_decoration_to_pixmap (d, d->pixmap, FALSE);
+	draw_window_decoration_to_pixmap (d, d->active_pixmap, TRUE);
+    }
+    else
+    {
+	draw_window_decoration_to_pixmap (d, d->pixmap, d->active);
+    }		
 
     if (d->prop_xid)
     {
@@ -1430,6 +1520,24 @@ decor_update_meta_window_property (decor_t	  *d,
     extents.top += titlebar_height;
     max_extents.top += max_titlebar_height;
 
+    if (d->active_pixmap)
+    {
+	decor_quads_to_property (data, GDK_PIXMAP_XID (d->active_pixmap),
+				 &extents, &max_extents,
+				 ICON_SPACE + d->button_width,
+				 0,
+				 quads, nQuad);
+
+	gdk_error_trap_push ();
+	XChangeProperty (xdisplay, d->prop_xid,
+			 win_decor_active_atom,
+			 win_decor_atom,
+			 32, PropModeReplace, (guchar *) data,
+			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+	gdk_display_sync (gdk_display_get_default ());
+	gdk_error_trap_pop ();
+    }
+
     decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap),
 			     &extents, &max_extents,
 			     ICON_SPACE + d->button_width,
@@ -1439,7 +1547,7 @@ decor_update_meta_window_property (decor_t	  *d,
     gdk_error_trap_push ();
     XChangeProperty (xdisplay, d->prop_xid,
 		     win_decor_atom,
-		     XA_INTEGER,
+		     win_decor_atom,
 		     32, PropModeReplace, (guchar *) data,
 		     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     gdk_display_sync (gdk_display_get_default ());
@@ -1823,9 +1931,6 @@ meta_get_decoration_geometry (decor_t		*d,
     if (d->actions & WNCK_WINDOW_ACTION_SHADE)
 	*flags |= META_FRAME_ALLOWS_SHADE;
 
-    if (d->active)
-	*flags |= META_FRAME_HAS_FOCUS;
-
 #define META_MAXIMIZED (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | \
 			WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)
 
@@ -1880,17 +1985,25 @@ meta_get_decoration_geometry (decor_t		*d,
 }
 
 static void
-meta_draw_window_decoration (decor_t *d)
+meta_draw_window_decoration_to_pixmap (decor_t        *d,
+				       GdkPixmap      *pixmap,
+				       MetaTheme      *theme,
+				       gint           active,
+				       gint           bg,
+				       Region         *top_region_return,
+				       Region         *bottom_region_return,
+				       Region         *left_region_return,
+				       Region         *right_region_return,
+				       MetaFrameFlags *flags_return)
 {
     Display	      *xdisplay =
 	GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-    GdkPixmap	      *pixmap;
+    GdkPixmap         *pix;
     Picture	      src;
     MetaButtonState   button_states[META_BUTTON_TYPE_LAST];
     MetaButtonLayout  button_layout;
     MetaFrameGeometry fgeom;
     MetaFrameFlags    flags;
-    MetaTheme	      *theme;
     GtkStyle	      *style;
     cairo_t	      *cr;
     gint	      size, i;
@@ -1900,14 +2013,14 @@ meta_draw_window_decoration (decor_t *d)
     Region	      bottom_region = NULL;
     Region	      left_region = NULL;
     Region	      right_region = NULL;
-    double	      alpha = (d->active) ? meta_active_opacity : meta_opacity;
-    gboolean	      shade_alpha = (d->active) ? meta_active_shade_opacity :
+    double	      alpha = (active) ? meta_active_opacity : meta_opacity;
+    gboolean	      shade_alpha = (active) ? meta_active_shade_opacity :
 	meta_shade_opacity;
     MetaFrameStyle    *frame_style;
     GdkColor	      bg_color;
     double	      bg_alpha;
 
-    if (!d->pixmap || !d->picture)
+    if (!pixmap || !d->picture)
 	return;
 
     if (decoration_alpha == 1.0)
@@ -1915,20 +2028,19 @@ meta_draw_window_decoration (decor_t *d)
 
     style = gtk_widget_get_style (style_window);
 
-    drawable = d->buffer_pixmap ? d->buffer_pixmap : d->pixmap;
+    drawable = d->buffer_pixmap ? d->buffer_pixmap : pixmap;
 
     cr = gdk_cairo_create (GDK_DRAWABLE (drawable));
 
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
-    theme = meta_theme_get_current ();
-
     meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
 				  &clip);
 
-    /* we only have to redraw the shadow background when decoration
-       changed size */
-    if (d->prop_xid || !d->buffer_pixmap)
+    if (active)
+	flags |= META_FRAME_HAS_FOCUS;
+
+    if (bg)
 	draw_shadow_background (d, cr, d->shadow, d->context);
 
     for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
@@ -1962,14 +2074,14 @@ meta_draw_window_decoration (decor_t *d)
 
     if (rect.width && size)
     {
-	pixmap = create_pixmap (rect.width, size);
+	pix = create_pixmap (rect.width, size);
 
-	cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
+	cr = gdk_cairo_create (GDK_DRAWABLE (pix));
 	gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha);
 	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
 	src = XRenderCreatePicture (xdisplay,
-				    GDK_PIXMAP_XID (pixmap),
+				    GDK_PIXMAP_XID (pix),
 				    xformat, 0, NULL);
 
 	if (fgeom.top_height)
@@ -1980,7 +2092,7 @@ meta_draw_window_decoration (decor_t *d)
 
 	    meta_theme_draw_frame (theme,
 				   style_window,
-				   pixmap,
+				   pix,
 				   &rect,
 				   0, 0,
 				   META_FRAME_TYPE_NORMAL,
@@ -2019,7 +2131,7 @@ meta_draw_window_decoration (decor_t *d)
 
 	    meta_theme_draw_frame (theme,
 				   style_window,
-				   pixmap,
+				   pix,
 				   &rect,
 				   0,
 				   -(clip.height - fgeom.bottom_height),
@@ -2053,7 +2165,7 @@ meta_draw_window_decoration (decor_t *d)
 
 	cairo_destroy (cr);
 
-	g_object_unref (G_OBJECT (pixmap));
+	g_object_unref (G_OBJECT (pix));
 
 	XRenderFreePicture (xdisplay, src);
     }
@@ -2064,14 +2176,14 @@ meta_draw_window_decoration (decor_t *d)
 
     if (size && rect.height)
     {
-	pixmap = create_pixmap (size, rect.height);
+	pix = create_pixmap (size, rect.height);
 
-	cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
+	cr = gdk_cairo_create (GDK_DRAWABLE (pix));
 	gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha);
 	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
 	src = XRenderCreatePicture (xdisplay,
-				    GDK_PIXMAP_XID (pixmap),
+				    GDK_PIXMAP_XID (pix),
 				    xformat, 0, NULL);
 
 	if (fgeom.left_width)
@@ -2082,7 +2194,7 @@ meta_draw_window_decoration (decor_t *d)
 
 	    meta_theme_draw_frame (theme,
 				   style_window,
-				   pixmap,
+				   pix,
 				   &rect,
 				   0,
 				   -fgeom.top_height,
@@ -2122,7 +2234,7 @@ meta_draw_window_decoration (decor_t *d)
 
 	    meta_theme_draw_frame (theme,
 				   style_window,
-				   pixmap,
+				   pix,
 				   &rect,
 				   -(clip.width - fgeom.right_width),
 				   -fgeom.top_height,
@@ -2156,13 +2268,13 @@ meta_draw_window_decoration (decor_t *d)
 
 	cairo_destroy (cr);
 
-	g_object_unref (G_OBJECT (pixmap));
+	g_object_unref (G_OBJECT (pix));
 
 	XRenderFreePicture (xdisplay, src);
     }
 
     if (d->buffer_pixmap)
-	gdk_draw_drawable  (d->pixmap,
+	gdk_draw_drawable  (pixmap,
 			    d->gc,
 			    d->buffer_pixmap,
 			    0,
@@ -2172,16 +2284,119 @@ meta_draw_window_decoration (decor_t *d)
 			    d->width,
 			    d->height);
 
-    if (d->prop_xid)
+    /* translate from frame to client window space */
+    if (top_region_return)
     {
-	/* translate from frame to client window space */
 	if (top_region)
 	    XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height);
+
+	*top_region_return = top_region;
+    }
+    else if (top_region)
+    {
+	XDestroyRegion (top_region);
+    }
+
+    if (bottom_region_return)
+    {
 	if (bottom_region)
 	    XOffsetRegion (bottom_region, -fgeom.left_width, 0);
+
+	*bottom_region_return = bottom_region;
+    }
+    else if (bottom_region)
+    {
+	XDestroyRegion (bottom_region);
+    }
+
+    if (left_region_return)
+    {
 	if (left_region)
 	    XOffsetRegion (left_region, -fgeom.left_width, 0);
 
+	*left_region_return = left_region;
+    }
+    else if (left_region)
+    {
+	XDestroyRegion (left_region);
+    }
+
+    if (right_region_return)
+    {
+        *right_region_return = right_region;
+    }
+    else if (right_region)
+    {
+	XDestroyRegion (right_region);
+    }
+
+    *flags_return = flags;
+}
+
+static void
+meta_draw_window_decoration (decor_t *d)
+{
+    MetaTheme      *theme = meta_theme_get_current ();
+    MetaFrameFlags flags;
+    Region         top_region = NULL;
+    Region         bottom_region = NULL;
+    Region         left_region = NULL;
+    Region         right_region = NULL;
+    Region         *top_region_ptr = NULL;
+    Region         *bottom_region_ptr = NULL;
+    Region         *left_region_ptr = NULL;
+    Region         *right_region_ptr = NULL;
+    gint           bg = FALSE;
+
+    if (d->prop_xid)
+    {
+	bg = TRUE;
+
+	top_region_ptr    = &top_region;
+	bottom_region_ptr = &bottom_region;
+	left_region_ptr   = &left_region;
+	right_region_ptr  = &right_region;
+    }
+    else if (!d->buffer_pixmap)
+    {
+	bg = TRUE;
+    }
+
+    if (d->active_pixmap)
+    {
+	meta_draw_window_decoration_to_pixmap (d,
+					       d->pixmap,
+					       theme,
+					       FALSE,
+					       bg,
+					       NULL, NULL, NULL, NULL, &flags);
+	meta_draw_window_decoration_to_pixmap (d,
+					       d->active_pixmap,
+					       theme,
+					       TRUE,
+					       FALSE,
+					       top_region_ptr,
+					       bottom_region_ptr,
+					       left_region_ptr,
+					       right_region_ptr,
+					       &flags);
+    }
+    else
+    {
+	meta_draw_window_decoration_to_pixmap (d,
+					       d->pixmap,
+					       theme,
+					       d->active,
+					       bg,
+					       top_region_ptr,
+					       bottom_region_ptr,
+					       left_region_ptr,
+					       right_region_ptr,
+					       &flags);
+    }
+
+    if (d->prop_xid)
+    {
 	decor_update_meta_window_property (d, theme, flags,
 					   top_region,
 					   bottom_region,
@@ -2564,7 +2779,7 @@ update_default_decorations (GdkScreen *screen)
 
 	XChangeProperty (xdisplay, xroot,
 			 bareAtom,
-			 XA_INTEGER,
+			 win_decor_atom,
 			 32, PropModeReplace, (guchar *) data,
 			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
@@ -2572,12 +2787,12 @@ update_default_decorations (GdkScreen *screen)
 	{
 	    XChangeProperty (xdisplay, xroot,
 			     normalAtom,
-			     XA_INTEGER,
+			     win_decor_atom,
 			     32, PropModeReplace, (guchar *) data,
 			     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 	    XChangeProperty (xdisplay, xroot,
 			     activeAtom,
-			     XA_INTEGER,
+			     win_decor_atom,
 			     32, PropModeReplace, (guchar *) data,
 			     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 	}
@@ -2635,7 +2850,7 @@ update_default_decorations (GdkScreen *screen)
 
 	XChangeProperty (xdisplay, xroot,
 			 normalAtom,
-			 XA_INTEGER,
+			 win_decor_atom,
 			 32, PropModeReplace, (guchar *) data,
 			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     }
@@ -2661,7 +2876,7 @@ update_default_decorations (GdkScreen *screen)
 
 	XChangeProperty (xdisplay, xroot,
 			 activeAtom,
-			 XA_INTEGER,
+			 win_decor_atom,
 			 32, PropModeReplace, (guchar *) data,
 			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     }
@@ -3081,13 +3296,21 @@ update_event_windows (WnckWindow *win)
 {
     Display *xdisplay;
     decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
-    gint    x0, y0, width, height, x, y, w, h;
+    Region  move_xregion;
+    REGION  xregion;
+    gint    x0, y0, x1, y1, width, height, x, y, w, h;
     gint    i, j, k, l;
     gint    actions = d->actions;
 
     xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
-    wnck_window_get_client_window_geometry (win, &x0, &y0, &width, &height);
+    wnck_window_get_geometry (win, &x0, &y0, &width, &height);
+    wnck_window_get_client_window_geometry (win, &x1, &y1, &width, &height);
+
+    move_xregion = XCreateRegion ();
+
+    xregion.rects = &xregion.extents;
+    xregion.numRects = xregion.size = 1;
 
     if (d->state & WNCK_WINDOW_STATE_SHADED)
     {
@@ -3134,6 +3357,16 @@ update_event_windows (WnckWindow *win)
 		XMapWindow (xdisplay, d->event_windows[i][j]);
 		XMoveResizeWindow (xdisplay, d->event_windows[i][j],
 				   x, y, w, h);
+
+		xregion.extents.x1 = x;
+		xregion.extents.y1 = y;
+		xregion.extents.x2 = x + w;
+		xregion.extents.y2 = y + h;
+
+		if (i == 1 && j == 1)
+		    XUnionRegion (move_xregion, &xregion, move_xregion);
+		else
+		    XSubtractRegion (move_xregion, &xregion, move_xregion);
 	    }
 	    else
 	    {
@@ -3181,6 +3414,13 @@ update_event_windows (WnckWindow *win)
 	{
 	    XMapWindow (xdisplay, d->button_windows[i]);
 	    XMoveResizeWindow (xdisplay, d->button_windows[i], x, y, w, h);
+
+	    xregion.extents.x1 = x;
+	    xregion.extents.y1 = y;
+	    xregion.extents.x2 = x + w;
+	    xregion.extents.y2 = y + h;
+
+	    XSubtractRegion (move_xregion, &xregion, move_xregion);
 	}
 	else
 	{
@@ -3188,6 +3428,28 @@ update_event_windows (WnckWindow *win)
 	}
     }
 
+    XOffsetRegion (move_xregion, x0 - x1, y0 - y1);
+
+    xregion.extents.x1 = 0;
+    xregion.extents.y1 = 0;
+    xregion.extents.x2 = width;
+    xregion.extents.y2 = height;
+
+    XSubtractRegion (move_xregion, &xregion, move_xregion);
+
+    decor_update_box_property (d,
+			       wnck_window_get_xid (win),
+			       wm_action_atom[1][1],
+			       0,
+			       1,
+			       width, height,
+			       move_xregion, width / 2,
+			       NULL, 0,
+			       NULL, 0,
+			       NULL, 0);
+
+    XDestroyRegion (move_xregion);
+
     gdk_display_sync (gdk_display_get_default ());
     gdk_error_trap_pop ();
 }
@@ -3488,7 +3750,7 @@ static gboolean
 update_window_decoration_size (WnckWindow *win)
 {
     decor_t   *d = g_object_get_data (G_OBJECT (win), "decor");
-    GdkPixmap *pixmap, *buffer_pixmap = NULL;
+    GdkPixmap *pixmap, *active_pixmap = NULL, *buffer_pixmap = NULL;
     Picture   picture;
     gint      width, height;
     gint      w, h, name_width;
@@ -3510,10 +3772,21 @@ update_window_decoration_size (WnckWindow *win)
     if (!pixmap)
 	return FALSE;
 
+    if (!reduced_resources)
+    {
+	active_pixmap = create_pixmap (width, height);
+	if (!active_pixmap)
+	{
+	    g_object_unref (G_OBJECT (pixmap));
+	    return FALSE;
+	}
+    }
+
     buffer_pixmap = create_pixmap (width, height);
     if (!buffer_pixmap)
     {
 	g_object_unref (G_OBJECT (pixmap));
+	g_object_unref (G_OBJECT (active_pixmap));
 	return FALSE;
     }
 
@@ -3523,6 +3796,9 @@ update_window_decoration_size (WnckWindow *win)
     if (d->pixmap)
 	g_object_unref (G_OBJECT (d->pixmap));
 
+    if (d->active_pixmap)
+	g_object_unref (G_OBJECT (d->active_pixmap));
+
     if (d->buffer_pixmap)
 	g_object_unref (G_OBJECT (d->buffer_pixmap));
 
@@ -3532,7 +3808,8 @@ update_window_decoration_size (WnckWindow *win)
     if (d->picture)
 	XRenderFreePicture (xdisplay, d->picture);
 
-    d->pixmap	     = pixmap;
+    d->pixmap        = pixmap;
+    d->active_pixmap = active_pixmap;
     d->buffer_pixmap = buffer_pixmap;
     d->gc	     = gdk_gc_new (pixmap);
 
@@ -3792,6 +4069,7 @@ update_switcher_window (WnckWindow *win,
     g_object_ref (G_OBJECT (buffer_pixmap));
 
     d->pixmap	     = pixmap;
+    d->active_pixmap = NULL;
     d->buffer_pixmap = buffer_pixmap;
     d->gc	     = gdk_gc_new (pixmap);
 
@@ -3822,6 +4100,12 @@ remove_frame_window (WnckWindow *win)
 	d->pixmap = NULL;
     }
 
+    if (d->active_pixmap)
+    {
+	g_object_unref (G_OBJECT (d->active_pixmap));
+	d->active_pixmap = NULL;
+    }
+
     if (d->buffer_pixmap)
     {
 	g_object_unref (G_OBJECT (d->buffer_pixmap));
@@ -3999,10 +4283,11 @@ active_window_changed (WnckScreen *screen)
     if (win)
     {
 	d = g_object_get_data (G_OBJECT (win), "decor");
-	if (d && d->pixmap)
+	if (d)
 	{
 	    d->active = wnck_window_is_active (win);
-	    queue_decor_draw (d);
+	    if (d->pixmap && !d->active_pixmap)
+		queue_decor_draw (d);
 	}
     }
 
@@ -4010,10 +4295,11 @@ active_window_changed (WnckScreen *screen)
     if (win)
     {
 	d = g_object_get_data (G_OBJECT (win), "decor");
-	if (d && d->pixmap)
+	if (d)
 	{
 	    d->active = wnck_window_is_active (win);
-	    queue_decor_draw (d);
+	    if (d->pixmap && !d->active_pixmap)
+		queue_decor_draw (d);
 	}
     }
 }
@@ -6909,6 +7195,10 @@ main (int argc, char *argv[])
 	{
 	    replace = TRUE;
 	}
+	else if (strcmp (argv[i], "--reduced-resources") == 0)
+	{
+	    reduced_resources = TRUE;
+	}
 	else if (strcmp (argv[i], "--blur") == 0)
 	{
 	    if (argc > ++i)
@@ -6957,6 +7247,7 @@ main (int argc, char *argv[])
 	    fprintf (stderr, "%s "
 		     "[--minimal] "
 		     "[--replace] "
+		     "[--reduced-resources] "
 		     "[--blur none|titlebar|all] "
 
 #ifdef USE_METACITY
@@ -6999,8 +7290,12 @@ main (int argc, char *argv[])
     xdisplay   = gdk_x11_display_get_xdisplay (gdkdisplay);
     gdkscreen  = gdk_display_get_default_screen (gdkdisplay);
 
+    win_decor_atom	  = XInternAtom (xdisplay, DECOR_WINDOW_ATOM_NAME,
+					 FALSE);
+    win_decor_active_atom = XInternAtom (xdisplay, DECOR_ACTIVE_ATOM_NAME,
+					 FALSE);
+
     frame_window_atom	= XInternAtom (xdisplay, "_NET_FRAME_WINDOW", FALSE);
-    win_decor_atom	= XInternAtom (xdisplay, DECOR_WINDOW_ATOM_NAME, FALSE);
     win_blur_decor_atom	= XInternAtom (xdisplay, DECOR_BLUR_ATOM_NAME, FALSE);
     wm_move_resize_atom = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", FALSE);
     restack_window_atom = XInternAtom (xdisplay, "_NET_RESTACK_WINDOW", FALSE);
@@ -7027,6 +7322,12 @@ main (int argc, char *argv[])
     panel_action_run_dialog_atom =
 	XInternAtom (xdisplay, "_GNOME_PANEL_ACTION_RUN_DIALOG", FALSE);
 
+    for (i = 0; i < 3; i++)
+	for (j = 0; j < 3; j++)
+	    wm_action_atom[i][j] = XInternAtom (xdisplay,
+						wm_action_name[i][j],
+						FALSE);
+
     status = decor_acquire_dm_session (xdisplay,
 				       gdk_screen_get_number (gdkscreen),
 				       "gwd", replace, &dm_sn_timestamp);
diff --git a/include/compiz-core.h b/include/compiz-core.h
index 38257e6..ee3d72e 100644
--- a/include/compiz-core.h
+++ b/include/compiz-core.h
@@ -1,3 +1,4 @@
+
 /*
  * Copyright © 2007 Novell, Inc.
  *
@@ -48,6 +49,9 @@
 #include <GL/gl.h>
 #include <GL/glx.h>
 
+#undef CORE_ABIVERSION
+#define CORE_ABIVERSION 20081121
+
 COMPIZ_BEGIN_DECLS
 
 #if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR > 2
@@ -80,6 +84,8 @@ typedef struct _CompCursor	  CompCursor;
 typedef struct _CompMatch	  CompMatch;
 typedef struct _CompOutput        CompOutput;
 typedef struct _CompWalker        CompWalker;
+typedef struct _CompPainter       CompPainter;
+typedef struct _CompTransform     CompTransform;
 
 /* virtual modifiers */
 
@@ -219,6 +225,8 @@ extern Bool       useCow;
 extern Bool       noDetection;
 extern Bool	  useDesktopHints;
 extern Bool       onlyCurrentScreen;
+extern Bool       windowManagement;
+extern Bool       manualCompositeManagement;
 
 extern int  defaultRefreshRate;
 extern char *defaultTextureFilter;
@@ -736,6 +744,657 @@ void
 removeFileWatch (CompFileWatchHandle handle);
 
 
+/* window.c */
+
+typedef struct _CompMatrix {
+    float xx; float yx;
+    float xy; float yy;
+    float x0; float y0;
+} CompMatrix;
+
+typedef struct _CompGroup {
+    struct _CompGroup *next;
+    unsigned int      refCnt;
+    Window	      id;
+} CompGroup;
+
+/* XXX: scale and translate fields will be removed */
+typedef struct _WindowPaintAttrib {
+    GLushort opacity;
+    GLushort brightness;
+    GLushort saturation;
+    GLfloat  xScale;
+    GLfloat  yScale;
+    GLfloat  xTranslate;
+    GLfloat  yTranslate;
+} WindowPaintAttrib;
+
+typedef void (*DrawWindowGeometryProc) (CompWindow *window);
+
+typedef Bool (*PaintWindowProc) (CompWindow		 *window,
+				 const WindowPaintAttrib *attrib,
+				 const CompTransform     *transform,
+				 Region			 region,
+				 unsigned int		 mask);
+
+#define WINDOW_INVISIBLE(w)				       \
+    ((w)->attrib.map_state != IsViewable		    || \
+     (!(w)->damaged)					    || \
+     (w)->attrib.x + (w)->width  + (w)->output.right  <= 0  || \
+     (w)->attrib.y + (w)->height + (w)->output.bottom <= 0  || \
+     (w)->attrib.x - (w)->output.left >= (w)->screen->width || \
+     (w)->attrib.y - (w)->output.top >= (w)->screen->height)
+
+typedef enum {
+    CompStackingUpdateModeNone = 0,
+    CompStackingUpdateModeNormal,
+    CompStackingUpdateModeAboveFullscreen,
+    CompStackingUpdateModeInitialMap,
+    CompStackingUpdateModeInitialMapDeniedFocus
+} CompStackingUpdateMode;
+
+struct _CompWindowExtents {
+    int left;
+    int right;
+    int top;
+    int bottom;
+};
+
+typedef struct _CompStruts {
+    XRectangle left;
+    XRectangle right;
+    XRectangle top;
+    XRectangle bottom;
+} CompStruts;
+
+struct _CompWindow {
+    CompObject base;
+
+    CompScreen *screen;
+
+    CompWindow *parent;
+    CompWindow *next;
+    CompWindow *prev;
+
+    CompWindow *windows;
+    CompWindow *reverseWindows;
+
+    Bool substructureRedirect;
+    Bool redirectSubwindows;
+
+    int viewportOffsetX;
+    int viewportOffsetY;
+
+    int		      refcnt;
+    Window	      id;
+    Window	      frame;
+    unsigned int      mapNum;
+    unsigned int      activeNum;
+    XWindowAttributes attrib;
+    int		      serverX;
+    int		      serverY;
+    int		      serverWidth;
+    int		      serverHeight;
+    int		      serverBorderWidth;
+    Window	      transientFor;
+    Window	      clientLeader;
+    XSizeHints	      sizeHints;
+    Pixmap	      pixmap;
+    CompTexture       *texture;
+    CompMatrix        matrix;
+    Damage	      damage;
+    Bool	      inputHint;
+    Bool	      alpha;
+    GLint	      width;
+    GLint	      height;
+    Region	      region;
+    Region	      clip;
+    unsigned int      wmType;
+    unsigned int      type;
+    unsigned int      state;
+    unsigned int      actions;
+    unsigned int      protocols;
+    unsigned int      mwmDecor;
+    unsigned int      mwmFunc;
+    Bool	      invisible;
+    Bool	      destroyed;
+    Bool	      damaged;
+    Bool	      redirected;
+    Bool	      managed;
+    Bool	      bindFailed;
+    Bool	      overlayWindow;
+    int		      destroyRefCnt;
+    int		      unmapRefCnt;
+
+    unsigned int initialViewportX;
+    unsigned int initialViewportY;
+
+    Time initialTimestamp;
+    Bool initialTimestampSet;
+
+    Bool placed;
+    Bool minimized;
+    Bool inShowDesktopMode;
+    Bool shaded;
+    Bool hidden;
+    Bool grabbed;
+
+    unsigned int desktop;
+
+    int pendingUnmaps;
+    int pendingMaps;
+
+    char *startupId;
+    char *resName;
+    char *resClass;
+
+    CompGroup *group;
+
+    unsigned int lastPong;
+    Bool	 alive;
+
+    WindowPaintAttrib paint;
+    WindowPaintAttrib lastPaint;
+
+    unsigned int lastMask;
+
+    CompWindowExtents input;
+    CompWindowExtents output;
+
+    CompStruts *struts;
+
+    CompIcon **icon;
+    int	     nIcon;
+
+    XRectangle iconGeometry;
+    Bool       iconGeometrySet;
+
+    XWindowChanges saveWc;
+    int		   saveMask;
+
+    XSyncCounter  syncCounter;
+    XSyncValue	  syncValue;
+    XSyncAlarm	  syncAlarm;
+    unsigned long syncAlarmConnection;
+    unsigned int  syncWaitHandle;
+
+    Bool syncWait;
+    int	 syncX;
+    int	 syncY;
+    int	 syncWidth;
+    int	 syncHeight;
+    int	 syncBorderWidth;
+
+    Bool   syncStateSupport;
+    Window supportingWmCheckWindow;
+    Window activeChild;
+    Window previousActiveChild;
+
+    Bool closeRequests;
+    Time lastCloseRequestTime;
+
+    XRectangle *damageRects;
+    int	       sizeDamage;
+    int	       nDamage;
+
+    int desktopWindowCount;
+
+    GLfloat  *vertices;
+    int      vertexSize;
+    int      vertexStride;
+    GLushort *indices;
+    int      indexSize;
+    int      vCount;
+    int      texUnits;
+    int      texCoordSize;
+    int      indexCount;
+
+    /* must be set by addWindowGeometry */
+    DrawWindowGeometryProc drawWindowGeometry;
+
+    PaintWindowProc paintWindowStack;
+};
+
+#define GET_CORE_WINDOW(object) ((CompWindow *) (object))
+#define CORE_WINDOW(object) CompWindow *w = GET_CORE_WINDOW (object)
+
+CompBool
+allocWindowObjectPrivates (CompObject *object,
+			   CompObject *parent);
+
+int
+allocWindowObjectPrivateIndex (CompObject *parent);
+
+void
+freeWindowObjectPrivateIndex (CompObject *parent,
+			      int	 index);
+
+CompBool
+forEachWindowObject (CompObject	        *parent,
+		     ObjectCallBackProc proc,
+		     void	        *closure);
+
+char *
+nameWindowObject (CompObject *object);
+
+CompObject *
+findWindowObject (CompObject *parent,
+		  const char *name);
+
+int
+allocateWindowPrivateIndex (CompScreen *screen);
+
+void
+freeWindowPrivateIndex (CompScreen *screen,
+			int	   index);
+
+unsigned int
+windowStateMask (CompDisplay *display,
+		 Atom	     state);
+
+unsigned int
+windowStateFromString (const char *str);
+
+unsigned int
+getWindowState (CompDisplay *display,
+		Window      id);
+
+void
+setWindowState (CompDisplay  *display,
+		unsigned int state,
+		Window       id);
+
+void
+changeWindowState (CompWindow   *w,
+		   unsigned int newState);
+
+void
+recalcWindowActions (CompWindow *w);
+
+unsigned int
+constrainWindowState (unsigned int state,
+		      unsigned int actions);
+
+unsigned int
+windowTypeFromString (const char *str);
+
+unsigned int
+getWindowType (CompDisplay *display,
+	       Window      id);
+
+void
+recalcWindowType (CompWindow *w);
+
+void
+getMwmHints (CompDisplay  *display,
+	     Window	  id,
+	     unsigned int *func,
+	     unsigned int *decor);
+
+unsigned int
+getProtocols (CompDisplay *display,
+	      Window      id);
+
+unsigned int
+getWindowProp (CompDisplay  *display,
+	       Window	    id,
+	       Atom	    property,
+	       unsigned int defaultValue);
+
+void
+setWindowProp (CompDisplay  *display,
+	       Window       id,
+	       Atom	    property,
+	       unsigned int value);
+
+Bool
+readWindowProp32 (CompDisplay    *display,
+		  Window	 id,
+		  Atom		 property,
+		  unsigned short *returnValue);
+
+unsigned short
+getWindowProp32 (CompDisplay	*display,
+		 Window		id,
+		 Atom		property,
+		 unsigned short defaultValue);
+
+void
+setWindowProp32 (CompDisplay    *display,
+		 Window         id,
+		 Atom		property,
+		 unsigned short value);
+
+void
+updateNormalHints (CompWindow *window);
+
+void
+updateWmHints (CompWindow *w);
+
+void
+updateWindowClassHints (CompWindow *window);
+
+void
+updateTransientHint (CompWindow *w);
+
+void
+updateIconGeometry (CompWindow *w);
+
+Window
+getClientLeader (CompWindow *w);
+
+Window
+getFrameWindow (CompWindow *w);
+
+char *
+getStartupId (CompWindow *w);
+
+int
+getWmState (CompDisplay *display,
+	    Window      id);
+
+void
+setWmState (CompDisplay *display,
+	    int		state,
+	    Window      id);
+
+void
+setWindowFrameExtents (CompWindow	 *w,
+		       CompWindowExtents *input);
+
+void
+updateWindowOutputExtents (CompWindow *w);
+
+void
+updateWindowRegion (CompWindow *w);
+
+Bool
+updateWindowStruts (CompWindow *w);
+
+void
+initRootWindow (CompScreen *s,
+		CompWindow *root);
+
+void
+addWindow (CompWindow *parent,
+	   Window     id,
+	   Window     aboveId);
+
+void
+removeWindow (CompWindow *w);
+
+void
+destroyWindow (CompWindow *w);
+
+void
+sendConfigureNotify (CompWindow *w);
+
+void
+mapWindow (CompWindow *w);
+
+void
+unmapWindow (CompWindow *w);
+
+Bool
+bindWindow (CompWindow *w);
+
+void
+releaseWindow (CompWindow *w);
+
+void
+moveWindow (CompWindow *w,
+	    int        dx,
+	    int        dy,
+	    Bool       damage,
+	    Bool       immediate);
+
+void
+configureXWindow (CompWindow	 *w,
+		  unsigned int	 valueMask,
+		  XWindowChanges *xwc);
+
+unsigned int
+adjustConfigureRequestForGravity (CompWindow     *w,
+				  XWindowChanges *xwc,
+				  unsigned int   xwcm,
+				  int            gravity,
+				  int		 direction);
+
+void
+moveResizeWindow (CompWindow     *w,
+		  XWindowChanges *xwc,
+		  unsigned int   xwcm,
+		  int            gravity,
+		  unsigned int   source);
+
+void
+syncWindowPosition (CompWindow *w);
+
+void
+syncWait (CompWindow *w);
+
+void
+sendSyncRequest (CompWindow *w);
+
+Bool
+resizeWindow (CompWindow *w,
+	      int	 x,
+	      int	 y,
+	      int	 width,
+	      int	 height,
+	      int	 borderWidth);
+
+void
+configureWindow (CompWindow	 *w,
+		 XConfigureEvent *ce);
+
+void
+circulateWindow (CompWindow	 *w,
+		 XCirculateEvent *ce);
+
+void
+addWindowDamageRect (CompWindow *w,
+		     BoxPtr     rect);
+
+void
+getOutputExtentsForWindow (CompWindow	     *w,
+			   CompWindowExtents *output);
+
+void
+getAllowedActionsForWindow (CompWindow   *w,
+			    unsigned int *setActions,
+			    unsigned int *clearActions);
+
+void
+addWindowDamage (CompWindow *w);
+
+void
+damageWindowOutputExtents (CompWindow *w);
+
+Bool
+damageWindowRect (CompWindow *w,
+		  Bool       initial,
+		  BoxPtr     rect);
+
+void
+damageTransformedWindowRect (CompWindow *w,
+			     float	xScale,
+			     float	yScale,
+			     float	xTranslate,
+			     float	yTranslate,
+			     BoxPtr     rect);
+
+Bool
+focusWindow (CompWindow *w);
+
+Bool
+placeWindow (CompWindow *w,
+	     int        x,
+	     int        y,
+	     int        *newX,
+	     int        *newY);
+
+void
+validateWindowResizeRequest (CompWindow     *w,
+			     unsigned int   *mask,
+			     XWindowChanges *xwc,
+			     unsigned int   source);
+
+void
+windowResizeNotify (CompWindow *w,
+		    int	       dx,
+		    int	       dy,
+		    int	       dwidth,
+		    int	       dheight);
+
+void
+windowMoveNotify (CompWindow *w,
+		  int	     dx,
+		  int	     dy,
+		  Bool	     immediate);
+
+void
+windowGrabNotify (CompWindow   *w,
+		  int	       x,
+		  int	       y,
+		  unsigned int state,
+		  unsigned int mask);
+
+void
+windowUngrabNotify (CompWindow *w);
+
+void
+windowStateChangeNotify (CompWindow   *w,
+			 unsigned int lastState);
+
+void
+moveInputFocusToWindow (CompWindow *w);
+
+void
+updateWindowSize (CompWindow *w);
+
+void
+raiseWindow (CompWindow *w);
+
+void
+lowerWindow (CompWindow *w);
+
+void
+restackWindowAbove (CompWindow *w,
+		    CompWindow *sibling);
+
+void
+restackWindowBelow (CompWindow *w,
+		    CompWindow *sibling);
+
+void
+updateWindowAttributes (CompWindow             *w,
+			CompStackingUpdateMode stackingMode);
+
+void
+activateWindow (CompWindow *w);
+
+void
+closeWindow (CompWindow *w,
+	     Time	serverTime);
+
+Bool
+constrainNewWindowSize (CompWindow *w,
+			int        width,
+			int        height,
+			int        *newWidth,
+			int        *newHeight);
+
+void
+hideWindow (CompWindow *w);
+
+void
+showWindow (CompWindow *w);
+
+void
+minimizeWindow (CompWindow *w);
+
+void
+unminimizeWindow (CompWindow *w);
+
+void
+maximizeWindow (CompWindow *w,
+		int	   state);
+
+Bool
+getWindowUserTime (CompWindow *w,
+		   Time       *time);
+
+void
+setWindowUserTime (CompWindow *w,
+		   Time       time);
+
+Bool
+allowWindowFocus (CompWindow   *w,
+		  unsigned int noFocusMask,
+		  unsigned int viewportX,
+		  unsigned int viewportY,
+		  Time         timestamp);
+
+void
+unredirectWindow (CompWindow *w);
+
+void
+redirectWindow (CompWindow *w);
+
+void
+defaultViewportForWindow (CompWindow *w,
+			  int	     *vx,
+			  int        *vy);
+
+CompIcon *
+getWindowIcon (CompWindow *w,
+	       int	  width,
+	       int	  height);
+
+void
+freeWindowIcons (CompWindow *w);
+
+int
+outputDeviceForWindow (CompWindow *w);
+
+Bool
+onCurrentDesktop (CompWindow *w);
+
+void
+setDesktopForWindow (CompWindow   *w,
+		     unsigned int desktop);
+
+int
+compareWindowActiveness (CompWindow *w1,
+			 CompWindow *w2);
+
+Bool
+windowOnAllViewports (CompWindow *w);
+
+void
+getWindowMovementForOffset (CompWindow *w,
+			    int        offX,
+			    int        offY,
+			    int        *retX,
+			    int        *retY);
+
+void
+enterSyncWaitState (CompWindow *w);
+
+void
+leaveSyncWaitState (CompWindow *w);
+
+void
+insertWindow (CompWindow *parent,
+	      CompWindow *w,
+	      Window	 aboveId);
+
+void
+unhookWindow (CompWindow *parent,
+	      CompWindow *w);
+
+
 /* display.c */
 
 #define COMP_DISPLAY_OPTION_ABI                              0
@@ -1053,6 +1712,8 @@ struct _CompDisplay {
 
     Atom startupIdAtom;
 
+    Atom syncStateAtom;
+
     unsigned int      lastPing;
     CompTimeoutHandle pingHandle;
 
@@ -1163,6 +1824,12 @@ addDisplay (const char *name);
 void
 removeDisplay (CompDisplay *d);
 
+Bool
+manageDisplay (CompDisplay *d);
+
+void
+updatePlugins (CompDisplay *d);
+
 Time
 getCurrentTimeFromDisplay (CompDisplay *d);
 
@@ -1180,6 +1847,10 @@ findWindowAtDisplay (CompDisplay *display,
 		     Window      id);
 
 CompWindow *
+findClientWindowAtDisplay (CompDisplay *d,
+			   Window      id);
+
+CompWindow *
 findTopLevelWindowAtDisplay (CompDisplay *d,
 			     Window      id);
 
@@ -1190,6 +1861,9 @@ virtualToRealModMask (CompDisplay  *d,
 void
 updateModifierMappings (CompDisplay *d);
 
+void
+handleTimeouts (struct timeval *tv);
+
 unsigned int
 keycodeToModifiers (CompDisplay *d,
 		    int         keycode);
@@ -1305,9 +1979,9 @@ clearTargetOutput (CompDisplay	*display,
 
 #define DEG2RAD (M_PI / 180.0f)
 
-typedef struct _CompTransform {
+struct _CompTransform {
     float m[16];
-} CompTransform;
+};
 
 typedef union _CompVector {
     float v[4];
@@ -1330,26 +2004,9 @@ typedef struct _ScreenPaintAttrib {
     GLfloat zCamera;
 } ScreenPaintAttrib;
 
-/* XXX: scale and translate fields will be removed */
-typedef struct _WindowPaintAttrib {
-    GLushort opacity;
-    GLushort brightness;
-    GLushort saturation;
-    GLfloat  xScale;
-    GLfloat  yScale;
-    GLfloat  xTranslate;
-    GLfloat  yTranslate;
-} WindowPaintAttrib;
-
 extern ScreenPaintAttrib defaultScreenPaintAttrib;
 extern WindowPaintAttrib defaultWindowPaintAttrib;
 
-typedef struct _CompMatrix {
-    float xx; float yx;
-    float xy; float yy;
-    float x0; float y0;
-} CompMatrix;
-
 #define COMP_TEX_COORD_X(m, vx) ((m)->xx * (vx) + (m)->x0)
 #define COMP_TEX_COORD_Y(m, vy) ((m)->yy * (vy) + (m)->y0)
 
@@ -1407,7 +2064,7 @@ typedef void (*DisableOutputClippingProc) (CompScreen *screen);
 typedef void (*WalkerFiniProc) (CompScreen *screen,
 				CompWalker *walker);
 
-typedef CompWindow *(*WalkInitProc) (CompScreen *screen);
+typedef CompWindow *(*WalkInitProc) (CompWindow *parent);
 typedef CompWindow *(*WalkStepProc) (CompWindow *window);
 
 struct _CompWalker {
@@ -1420,6 +2077,16 @@ struct _CompWalker {
     WalkStepProc prev;
 };
 
+typedef void (*PainterFiniProc) (CompScreen  *screen,
+				 CompPainter *painter);
+
+struct _CompPainter {
+    PainterFiniProc fini;
+    CompPrivate	    priv;
+
+    PaintWindowProc paintObject;
+};
+
 /*
   window paint flags
 
@@ -1450,6 +2117,12 @@ struct _CompWalker {
 #define PAINT_WINDOW_WITH_OFFSET_MASK           (1 << 2)
 
 /*
+  this flag is present when occlusion detection has been
+  performed and the window clip region is properly set.
+*/
+#define PAINT_WINDOW_CLIP_MASK                  (1 << 3)
+
+/*
   flag indicate that window is translucent.
 */
 #define PAINT_WINDOW_TRANSLUCENT_MASK           (1 << 16)
@@ -1470,12 +2143,11 @@ struct _CompWalker {
 */
 #define PAINT_WINDOW_BLEND_MASK			(1 << 19)
 
+/*
+  flag indicate that there might be transformed child windows.
+*/
+#define PAINT_WINDOW_WITH_TRANSFORMED_CHILD_MASK (1 << 20)
 
-typedef Bool (*PaintWindowProc) (CompWindow		 *window,
-				 const WindowPaintAttrib *attrib,
-				 const CompTransform     *transform,
-				 Region			 region,
-				 unsigned int		 mask);
 
 typedef Bool (*DrawWindowProc) (CompWindow	     *window,
 				const CompTransform  *transform,
@@ -1494,8 +2166,6 @@ typedef void (*DrawWindowTextureProc) (CompWindow	    *w,
 				       const FragmentAttrib *fragment,
 				       unsigned int	    mask);
 
-typedef void (*DrawWindowGeometryProc) (CompWindow *window);
-
 typedef void (*PaintCursorProc) (CompCursor	     *cursor,
 				 const CompTransform *transform,
 				 Region		     region,
@@ -1594,6 +2264,11 @@ paintWindow (CompWindow		     *w,
 	     unsigned int	     mask);
 
 void
+drawTransformedWindowWithChildren (CompWindow              *w,
+				   const WindowPaintAttrib *attrib,
+				   const CompTransform     *transform);
+
+void
 paintCursor (CompCursor		 *cursor,
 	     const CompTransform *transform,
 	     Region		 region,
@@ -1901,8 +2576,12 @@ typedef void (*WindowStateChangeNotifyProc) (CompWindow   *window,
 typedef void (*OutputChangeNotifyProc) (CompScreen *screen);
 
 typedef void (*InitWindowWalkerProc) (CompScreen *screen,
+				      CompWindow *parent,
 				      CompWalker *walker);
 
+typedef void (*InitObjectPainterProc) (CompScreen  *screen,
+				       CompPainter *painter);
+
 #define COMP_SCREEN_DAMAGE_PENDING_MASK (1 << 0)
 #define COMP_SCREEN_DAMAGE_REGION_MASK  (1 << 1)
 #define COMP_SCREEN_DAMAGE_ALL_MASK     (1 << 2)
@@ -1925,12 +2604,6 @@ typedef struct _CompGrab {
     const char *name;
 } CompGrab;
 
-typedef struct _CompGroup {
-    struct _CompGroup *next;
-    unsigned int      refCnt;
-    Window	      id;
-} CompGroup;
-
 typedef struct _CompStartupSequence {
     struct _CompStartupSequence *next;
     SnStartupSequence		*sequence;
@@ -2019,8 +2692,8 @@ struct _CompScreen {
 
     CompScreen  *next;
     CompDisplay *display;
-    CompWindow	*windows;
-    CompWindow	*reverseWindows;
+
+    CompWindow root;
 
     char *windowPrivateIndices;
     int  windowPrivateLen;
@@ -2038,7 +2711,6 @@ struct _CompScreen {
     REGION	      region;
     Region	      damage;
     unsigned long     damageMask;
-    Window	      root;
     Window	      overlay;
     Window	      output;
     XWindowAttributes attrib;
@@ -2061,7 +2733,6 @@ struct _CompScreen {
     CompTexture       backgroundTexture;
     Bool	      backgroundLoaded;
     unsigned int      pendingDestroys;
-    int		      desktopWindowCount;
     unsigned int      mapNum;
     unsigned int      activeNum;
 
@@ -2071,9 +2742,6 @@ struct _CompScreen {
     CompOutput fullscreenOutput;
     Bool       hasOverlappingOutputs;
 
-    int windowOffsetX;
-    int windowOffsetY;
-
     XRectangle lastViewport;
 
     CompActiveWindowHistory history[ACTIVE_WINDOW_HISTORY_NUM];
@@ -2220,7 +2888,8 @@ struct _CompScreen {
 
     OutputChangeNotifyProc outputChangeNotify;
 
-    InitWindowWalkerProc initWindowWalker;
+    InitWindowWalkerProc  initWindowWalker;
+    InitObjectPainterProc initObjectPainter;
 };
 
 #define GET_CORE_SCREEN(object) ((CompScreen *) (object))
@@ -2283,6 +2952,12 @@ void
 detectRefreshRateOfScreen (CompScreen *s);
 
 void
+getSupportingWmCheck (CompWindow *w);
+
+void
+getDesktopHints (CompScreen *s);
+
+void
 showOutputWindow (CompScreen *s);
 
 void
@@ -2312,15 +2987,6 @@ void
 damagePendingOnScreen (CompScreen *s);
 
 void
-insertWindowIntoScreen (CompScreen *s,
-			CompWindow *w,
-			Window	   aboveId);
-
-void
-unhookWindowFromScreen (CompScreen *s,
-			CompWindow *w);
-
-void
 forEachWindowOnScreen (CompScreen	 *screen,
 		       ForEachWindowProc proc,
 		       void		 *closure);
@@ -2330,6 +2996,10 @@ findWindowAtScreen (CompScreen *s,
 		    Window     id);
 
 CompWindow *
+findClientWindowAtScreen (CompScreen *s,
+			  Window      id);
+
+CompWindow *
 findTopLevelWindowAtScreen (CompScreen *s,
 			    Window      id);
 
@@ -2436,7 +3106,7 @@ disableScreenEdge (CompScreen *s,
 		   int	      edge);
 
 Window
-getTopWindow (CompScreen *s);
+getTopWindow (CompWindow *parent);
 
 void
 makeScreenCurrent (CompScreen *s);
@@ -2523,579 +3193,6 @@ setWindowPaintOffset (CompScreen *s,
 		      int        y);
 
 
-/* window.c */
-
-#define WINDOW_INVISIBLE(w)				       \
-    ((w)->attrib.map_state != IsViewable		    || \
-     (!(w)->damaged)					    || \
-     (w)->attrib.x + (w)->width  + (w)->output.right  <= 0  || \
-     (w)->attrib.y + (w)->height + (w)->output.bottom <= 0  || \
-     (w)->attrib.x - (w)->output.left >= (w)->screen->width || \
-     (w)->attrib.y - (w)->output.top >= (w)->screen->height)
-
-typedef enum {
-    CompStackingUpdateModeNone = 0,
-    CompStackingUpdateModeNormal,
-    CompStackingUpdateModeAboveFullscreen,
-    CompStackingUpdateModeInitialMap,
-    CompStackingUpdateModeInitialMapDeniedFocus
-} CompStackingUpdateMode;
-
-struct _CompWindowExtents {
-    int left;
-    int right;
-    int top;
-    int bottom;
-};
-
-typedef struct _CompStruts {
-    XRectangle left;
-    XRectangle right;
-    XRectangle top;
-    XRectangle bottom;
-} CompStruts;
-
-struct _CompWindow {
-    CompObject base;
-
-    CompScreen *screen;
-    CompWindow *next;
-    CompWindow *prev;
-
-    int		      refcnt;
-    Window	      id;
-    Window	      frame;
-    unsigned int      mapNum;
-    unsigned int      activeNum;
-    XWindowAttributes attrib;
-    int		      serverX;
-    int		      serverY;
-    int		      serverWidth;
-    int		      serverHeight;
-    int		      serverBorderWidth;
-    Window	      transientFor;
-    Window	      clientLeader;
-    XSizeHints	      sizeHints;
-    Pixmap	      pixmap;
-    CompTexture       *texture;
-    CompMatrix        matrix;
-    Damage	      damage;
-    Bool	      inputHint;
-    Bool	      alpha;
-    GLint	      width;
-    GLint	      height;
-    Region	      region;
-    Region	      clip;
-    unsigned int      wmType;
-    unsigned int      type;
-    unsigned int      state;
-    unsigned int      actions;
-    unsigned int      protocols;
-    unsigned int      mwmDecor;
-    unsigned int      mwmFunc;
-    Bool	      invisible;
-    Bool	      destroyed;
-    Bool	      damaged;
-    Bool	      redirected;
-    Bool	      managed;
-    Bool	      bindFailed;
-    Bool	      overlayWindow;
-    int		      destroyRefCnt;
-    int		      unmapRefCnt;
-
-    unsigned int initialViewportX;
-    unsigned int initialViewportY;
-
-    Time initialTimestamp;
-    Bool initialTimestampSet;
-
-    Bool placed;
-    Bool minimized;
-    Bool inShowDesktopMode;
-    Bool shaded;
-    Bool hidden;
-    Bool grabbed;
-
-    unsigned int desktop;
-
-    int pendingUnmaps;
-    int pendingMaps;
-
-    char *startupId;
-    char *resName;
-    char *resClass;
-
-    CompGroup *group;
-
-    unsigned int lastPong;
-    Bool	 alive;
-
-    WindowPaintAttrib paint;
-    WindowPaintAttrib lastPaint;
-
-    unsigned int lastMask;
-
-    CompWindowExtents input;
-    CompWindowExtents output;
-
-    CompStruts *struts;
-
-    CompIcon **icon;
-    int	     nIcon;
-
-    XRectangle iconGeometry;
-    Bool       iconGeometrySet;
-
-    XWindowChanges saveWc;
-    int		   saveMask;
-
-    XSyncCounter  syncCounter;
-    XSyncValue	  syncValue;
-    XSyncAlarm	  syncAlarm;
-    unsigned long syncAlarmConnection;
-    unsigned int  syncWaitHandle;
-
-    Bool syncWait;
-    int	 syncX;
-    int	 syncY;
-    int	 syncWidth;
-    int	 syncHeight;
-    int	 syncBorderWidth;
-
-    Bool closeRequests;
-    Time lastCloseRequestTime;
-
-    XRectangle *damageRects;
-    int	       sizeDamage;
-    int	       nDamage;
-
-    GLfloat  *vertices;
-    int      vertexSize;
-    int      vertexStride;
-    GLushort *indices;
-    int      indexSize;
-    int      vCount;
-    int      texUnits;
-    int      texCoordSize;
-    int      indexCount;
-
-    /* must be set by addWindowGeometry */
-    DrawWindowGeometryProc drawWindowGeometry;
-};
-
-#define GET_CORE_WINDOW(object) ((CompWindow *) (object))
-#define CORE_WINDOW(object) CompWindow *w = GET_CORE_WINDOW (object)
-
-CompBool
-allocWindowObjectPrivates (CompObject *object,
-			   CompObject *parent);
-
-int
-allocWindowObjectPrivateIndex (CompObject *parent);
-
-void
-freeWindowObjectPrivateIndex (CompObject *parent,
-			      int	 index);
-
-CompBool
-forEachWindowObject (CompObject	        *parent,
-		     ObjectCallBackProc proc,
-		     void	        *closure);
-
-char *
-nameWindowObject (CompObject *object);
-
-CompObject *
-findWindowObject (CompObject *parent,
-		  const char *name);
-
-int
-allocateWindowPrivateIndex (CompScreen *screen);
-
-void
-freeWindowPrivateIndex (CompScreen *screen,
-			int	   index);
-
-unsigned int
-windowStateMask (CompDisplay *display,
-		 Atom	     state);
-
-unsigned int
-windowStateFromString (const char *str);
-
-unsigned int
-getWindowState (CompDisplay *display,
-		Window      id);
-
-void
-setWindowState (CompDisplay  *display,
-		unsigned int state,
-		Window       id);
-
-void
-changeWindowState (CompWindow   *w,
-		   unsigned int newState);
-
-void
-recalcWindowActions (CompWindow *w);
-
-unsigned int
-constrainWindowState (unsigned int state,
-		      unsigned int actions);
-
-unsigned int
-windowTypeFromString (const char *str);
-
-unsigned int
-getWindowType (CompDisplay *display,
-	       Window      id);
-
-void
-recalcWindowType (CompWindow *w);
-
-void
-getMwmHints (CompDisplay  *display,
-	     Window	  id,
-	     unsigned int *func,
-	     unsigned int *decor);
-
-unsigned int
-getProtocols (CompDisplay *display,
-	      Window      id);
-
-unsigned int
-getWindowProp (CompDisplay  *display,
-	       Window	    id,
-	       Atom	    property,
-	       unsigned int defaultValue);
-
-void
-setWindowProp (CompDisplay  *display,
-	       Window       id,
-	       Atom	    property,
-	       unsigned int value);
-
-Bool
-readWindowProp32 (CompDisplay    *display,
-		  Window	 id,
-		  Atom		 property,
-		  unsigned short *returnValue);
-
-unsigned short
-getWindowProp32 (CompDisplay	*display,
-		 Window		id,
-		 Atom		property,
-		 unsigned short defaultValue);
-
-void
-setWindowProp32 (CompDisplay    *display,
-		 Window         id,
-		 Atom		property,
-		 unsigned short value);
-
-void
-updateNormalHints (CompWindow *window);
-
-void
-updateWmHints (CompWindow *w);
-
-void
-updateWindowClassHints (CompWindow *window);
-
-void
-updateTransientHint (CompWindow *w);
-
-void
-updateIconGeometry (CompWindow *w);
-
-Window
-getClientLeader (CompWindow *w);
-
-char *
-getStartupId (CompWindow *w);
-
-int
-getWmState (CompDisplay *display,
-	    Window      id);
-
-void
-setWmState (CompDisplay *display,
-	    int		state,
-	    Window      id);
-
-void
-setWindowFrameExtents (CompWindow	 *w,
-		       CompWindowExtents *input);
-
-void
-updateWindowOutputExtents (CompWindow *w);
-
-void
-updateWindowRegion (CompWindow *w);
-
-Bool
-updateWindowStruts (CompWindow *w);
-
-void
-addWindow (CompScreen *screen,
-	   Window     id,
-	   Window     aboveId);
-
-void
-removeWindow (CompWindow *w);
-
-void
-destroyWindow (CompWindow *w);
-
-void
-sendConfigureNotify (CompWindow *w);
-
-void
-mapWindow (CompWindow *w);
-
-void
-unmapWindow (CompWindow *w);
-
-Bool
-bindWindow (CompWindow *w);
-
-void
-releaseWindow (CompWindow *w);
-
-void
-moveWindow (CompWindow *w,
-	    int        dx,
-	    int        dy,
-	    Bool       damage,
-	    Bool       immediate);
-
-void
-configureXWindow (CompWindow	 *w,
-		  unsigned int	 valueMask,
-		  XWindowChanges *xwc);
-
-unsigned int
-adjustConfigureRequestForGravity (CompWindow     *w,
-				  XWindowChanges *xwc,
-				  unsigned int   xwcm,
-				  int            gravity);
-
-void
-moveResizeWindow (CompWindow     *w,
-		  XWindowChanges *xwc,
-		  unsigned int   xwcm,
-		  int            gravity,
-		  unsigned int   source);
-
-void
-syncWindowPosition (CompWindow *w);
-
-void
-sendSyncRequest (CompWindow *w);
-
-Bool
-resizeWindow (CompWindow *w,
-	      int	 x,
-	      int	 y,
-	      int	 width,
-	      int	 height,
-	      int	 borderWidth);
-
-void
-configureWindow (CompWindow	 *w,
-		 XConfigureEvent *ce);
-
-void
-circulateWindow (CompWindow	 *w,
-		 XCirculateEvent *ce);
-
-void
-addWindowDamageRect (CompWindow *w,
-		     BoxPtr     rect);
-
-void
-getOutputExtentsForWindow (CompWindow	     *w,
-			   CompWindowExtents *output);
-
-void
-getAllowedActionsForWindow (CompWindow   *w,
-			    unsigned int *setActions,
-			    unsigned int *clearActions);
-
-void
-addWindowDamage (CompWindow *w);
-
-void
-damageWindowOutputExtents (CompWindow *w);
-
-Bool
-damageWindowRect (CompWindow *w,
-		  Bool       initial,
-		  BoxPtr     rect);
-
-void
-damageTransformedWindowRect (CompWindow *w,
-			     float	xScale,
-			     float	yScale,
-			     float	xTranslate,
-			     float	yTranslate,
-			     BoxPtr     rect);
-
-Bool
-focusWindow (CompWindow *w);
-
-Bool
-placeWindow (CompWindow *w,
-	     int        x,
-	     int        y,
-	     int        *newX,
-	     int        *newY);
-
-void
-validateWindowResizeRequest (CompWindow     *w,
-			     unsigned int   *mask,
-			     XWindowChanges *xwc,
-			     unsigned int   source);
-
-void
-windowResizeNotify (CompWindow *w,
-		    int	       dx,
-		    int	       dy,
-		    int	       dwidth,
-		    int	       dheight);
-
-void
-windowMoveNotify (CompWindow *w,
-		  int	     dx,
-		  int	     dy,
-		  Bool	     immediate);
-
-void
-windowGrabNotify (CompWindow   *w,
-		  int	       x,
-		  int	       y,
-		  unsigned int state,
-		  unsigned int mask);
-
-void
-windowUngrabNotify (CompWindow *w);
-
-void
-windowStateChangeNotify (CompWindow   *w,
-			 unsigned int lastState);
-
-void
-moveInputFocusToWindow (CompWindow *w);
-
-void
-updateWindowSize (CompWindow *w);
-
-void
-raiseWindow (CompWindow *w);
-
-void
-lowerWindow (CompWindow *w);
-
-void
-restackWindowAbove (CompWindow *w,
-		    CompWindow *sibling);
-
-void
-restackWindowBelow (CompWindow *w,
-		    CompWindow *sibling);
-
-void
-updateWindowAttributes (CompWindow             *w,
-			CompStackingUpdateMode stackingMode);
-
-void
-activateWindow (CompWindow *w);
-
-void
-closeWindow (CompWindow *w,
-	     Time	serverTime);
-
-Bool
-constrainNewWindowSize (CompWindow *w,
-			int        width,
-			int        height,
-			int        *newWidth,
-			int        *newHeight);
-
-void
-hideWindow (CompWindow *w);
-
-void
-showWindow (CompWindow *w);
-
-void
-minimizeWindow (CompWindow *w);
-
-void
-unminimizeWindow (CompWindow *w);
-
-void
-maximizeWindow (CompWindow *w,
-		int	   state);
-
-Bool
-getWindowUserTime (CompWindow *w,
-		   Time       *time);
-
-void
-setWindowUserTime (CompWindow *w,
-		   Time       time);
-
-Bool
-allowWindowFocus (CompWindow   *w,
-		  unsigned int noFocusMask,
-		  unsigned int viewportX,
-		  unsigned int viewportY,
-		  Time         timestamp);
-
-void
-unredirectWindow (CompWindow *w);
-
-void
-redirectWindow (CompWindow *w);
-
-void
-defaultViewportForWindow (CompWindow *w,
-			  int	     *vx,
-			  int        *vy);
-
-CompIcon *
-getWindowIcon (CompWindow *w,
-	       int	  width,
-	       int	  height);
-
-void
-freeWindowIcons (CompWindow *w);
-
-int
-outputDeviceForWindow (CompWindow *w);
-
-Bool
-onCurrentDesktop (CompWindow *w);
-
-void
-setDesktopForWindow (CompWindow   *w,
-		     unsigned int desktop);
-
-int
-compareWindowActiveness (CompWindow *w1,
-			 CompWindow *w2);
-
-Bool
-windowOnAllViewports (CompWindow *w);
-
-void
-getWindowMovementForOffset (CompWindow *w,
-			    int        offX,
-			    int        offY,
-			    int        *retX,
-			    int        *retY);
-
 /* plugin.c */
 
 #define HOME_PLUGINDIR ".compiz/plugins"
diff --git a/include/decoration.h b/include/decoration.h
index 5eed043..9bc6552 100644
--- a/include/decoration.h
+++ b/include/decoration.h
@@ -196,19 +196,32 @@ decor_property_to_quads (long		 *data,
 			 decor_quad_t    *quad);
 
 void
+decor_region_to_box_property (long   *data,
+			      int    width,
+			      int    height,
+			      Region topRegion,
+			      int    topOffset,
+			      Region bottomRegion,
+			      int    bottomOffset,
+			      Region leftRegion,
+			      int    leftOffset,
+			      Region rightRegion,
+			      int    rightOffset);
+
+void
 decor_region_to_blur_property (long   *data,
 			       int    threshold,
 			       int    filter,
 			       int    width,
 			       int    height,
-			       Region topRegion,
-			       int    topOffset,
-			       Region bottomRegion,
-			       int    bottomOffset,
-			       Region leftRegion,
-			       int    leftOffset,
-			       Region rightRegion,
-			       int    rightOffset);
+			       Region top_region,
+			       int    top_offset,
+			       Region bottom_region,
+			       int    bottom_offset,
+			       Region left_region,
+			       int    left_offset,
+			       Region right_region,
+			       int    right_offset);
 
 void
 decor_apply_gravity (int gravity,
diff --git a/kde/window-decorator-kde4/decorator.cpp b/kde/window-decorator-kde4/decorator.cpp
index 96b818d..6ca2a39 100644
--- a/kde/window-decorator-kde4/decorator.cpp
+++ b/kde/window-decorator-kde4/decorator.cpp
@@ -403,7 +403,7 @@ KWD::Decorator::updateShadow (void)
 	KWD::trapXError ();
 	XChangeProperty (QX11Info::display(), QX11Info::appRootWindow(),
 			 Atoms::netWindowDecorBare,
-			 XA_INTEGER,
+			 Atoms::netWindowDecor,
 			 32, PropModeReplace, (unsigned char *) data,
 			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 	KWD::popXError ();
diff --git a/kde/window-decorator-kde4/switcher.cpp b/kde/window-decorator-kde4/switcher.cpp
index 2978e69..860b8aa 100644
--- a/kde/window-decorator-kde4/switcher.cpp
+++ b/kde/window-decorator-kde4/switcher.cpp
@@ -261,15 +261,18 @@ KWD::Switcher::updateBlurProperty (int topOffset,
 
     if (size)
     {
-	long data[size * 6 + 2];
-
-	decor_region_to_blur_property (data, 4, 0,
-				       mGeometry.width (),
-				       mGeometry.height (),
-				       topRegion, topOffset,
-				       bottomRegion, bottomOffset,
-				       leftRegion, leftOffset,
-				       rightRegion, rightOffset);
+      	long data[size * 6 + 2];
+
+        data[0] = 4;
+	data[1] = 0;
+
+	decor_region_to_box_property (data + 2,
+                                      mGeometry.width (),
+                                      mGeometry.height (),
+                                      topRegion, topOffset,
+                                      bottomRegion, bottomOffset,
+                                      leftRegion, leftOffset,
+                                      rightRegion, rightOffset);
 
 	KWD::trapXError ();
 	XChangeProperty (QX11Info::display (), mId, atom, XA_INTEGER,
diff --git a/kde/window-decorator-kde4/window.cpp b/kde/window-decorator-kde4/window.cpp
index d2d362b..1e7d8c5 100644
--- a/kde/window-decorator-kde4/window.cpp
+++ b/kde/window-decorator-kde4/window.cpp
@@ -1426,13 +1426,16 @@ KWD::Window::updateBlurProperty (int topOffset,
     {
 	long data[size * 6 + 2];
 
-	decor_region_to_blur_property (data, 4, 0,
-				       mGeometry.width (),
-				       mGeometry.height (),
-				       topRegion, topOffset,
-				       bottomRegion, bottomOffset,
-				       leftRegion, leftOffset,
-				       rightRegion, rightOffset);
+        data[0] = 4;
+	data[1] = 0;
+
+	decor_region_to_box_property (data + 2,
+                                      mGeometry.width (),
+                                      mGeometry.height (),
+                                      topRegion, topOffset,
+                                      bottomRegion, bottomOffset,
+                                      leftRegion, leftOffset,
+                                      rightRegion, rightOffset);
 
 	KWD::trapXError ();
 	XChangeProperty (QX11Info::display(), mClientId, atom,
@@ -1542,7 +1545,7 @@ KWD::Window::updateProperty (void)
 
     KWD::trapXError ();
     XChangeProperty (QX11Info::display(), mClientId, atom,
-		     XA_INTEGER,
+		     Atoms::netWindowDecor,
 		     32, PropModeReplace, (unsigned char *) data,
 		     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     KWD::popXError ();
diff --git a/kde/window-decorator/decorator.cpp b/kde/window-decorator/decorator.cpp
index 2d5ada0..03819dc 100644
--- a/kde/window-decorator/decorator.cpp
+++ b/kde/window-decorator/decorator.cpp
@@ -530,7 +530,7 @@ KWD::Decorator::updateShadow (void)
 	KWD::trapXError ();
 	XChangeProperty (qt_xdisplay (), qt_xrootwin (),
 			 Atoms::netWindowDecorBare,
-			 XA_INTEGER,
+			 Atoms::netWindowDecor,
 			 32, PropModeReplace, (unsigned char *) data,
 			 BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 	KWD::popXError ();
diff --git a/kde/window-decorator/window.cpp b/kde/window-decorator/window.cpp
index 55580e6..9e73e1a 100644
--- a/kde/window-decorator/window.cpp
+++ b/kde/window-decorator/window.cpp
@@ -1323,13 +1323,16 @@ KWD::Window::updateBlurProperty (int topOffset,
     {
 	long data[size * 6 + 2];
 
-	decor_region_to_blur_property (data, 4, 0,
-				       mGeometry.width (),
-				       mGeometry.height (),
-				       topRegion, topOffset,
-				       bottomRegion, bottomOffset,
-				       leftRegion, leftOffset,
-				       rightRegion, rightOffset);
+        data[0] = 4;
+	data[1] = 0;
+
+	decor_region_to_box_property (data + 2,
+                                      mGeometry.width (),
+                                      mGeometry.height (),
+                                      topRegion, topOffset,
+                                      bottomRegion, bottomOffset,
+                                      leftRegion, leftOffset,
+                                      rightRegion, rightOffset);
 
 	KWD::trapXError ();
 	XChangeProperty (qt_xdisplay (), mClientId, atom,
@@ -1442,7 +1445,7 @@ KWD::Window::updateProperty (void)
 
     KWD::trapXError ();
     XChangeProperty (qt_xdisplay (), mClientId, atom,
-		     XA_INTEGER,
+		     Atoms::netWindowDecor,
 		     32, PropModeReplace, (unsigned char *) data,
 		     BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
     KWD::popXError ();
diff --git a/libdecoration/decoration.c b/libdecoration/decoration.c
index 1f3407c..b261045 100644
--- a/libdecoration/decoration.c
+++ b/libdecoration/decoration.c
@@ -205,13 +205,13 @@ decor_property_to_quads (long		 *data,
 }
 
 static int
-add_blur_boxes (long   *data,
-		BoxPtr box,
-		int    n_box,
-		int    width,
-		int    height,
-		int    gravity,
-		int    offset)
+add_boxes (long   *data,
+	   BoxPtr box,
+	   int    n_box,
+	   int    width,
+	   int    height,
+	   int    gravity,
+	   int    offset)
 {
     int x1, y1, x2, y2;
     int more_gravity;
@@ -289,6 +289,52 @@ add_blur_boxes (long   *data,
 }
 
 void
+decor_region_to_box_property (long   *data,
+			      int    width,
+			      int    height,
+			      Region top_region,
+			      int    top_offset,
+			      Region bottom_region,
+			      int    bottom_offset,
+			      Region left_region,
+			      int    left_offset,
+			      Region right_region,
+			      int    right_offset)
+{
+    if (top_region)
+	data += add_boxes (data,
+			   top_region->rects,
+			   top_region->numRects,
+			   width, height,
+			   GRAVITY_NORTH,
+			   top_offset);
+
+    if (bottom_region)
+	data += add_boxes (data,
+			   bottom_region->rects,
+			   bottom_region->numRects,
+			   width, height,
+			   GRAVITY_SOUTH,
+			   bottom_offset);
+
+    if (left_region)
+	data += add_boxes (data,
+			   left_region->rects,
+			   left_region->numRects,
+			   width, height,
+			   GRAVITY_WEST,
+			   left_offset);
+
+    if (right_region)
+	data += add_boxes (data,
+			   right_region->rects,
+			   right_region->numRects,
+			   width, height,
+			   GRAVITY_EAST,
+			   right_offset);
+}
+
+void
 decor_region_to_blur_property (long   *data,
 			       int    threshold,
 			       int    filter,
@@ -303,40 +349,14 @@ decor_region_to_blur_property (long   *data,
 			       Region right_region,
 			       int    right_offset)
 {
-    *data++ = threshold;
-    *data++ = filter;
-
-    if (top_region)
-	data += add_blur_boxes (data,
-				top_region->rects,
-				top_region->numRects,
-				width, height,
-				GRAVITY_NORTH,
-				top_offset);
-
-    if (bottom_region)
-	data += add_blur_boxes (data,
-				bottom_region->rects,
-				bottom_region->numRects,
-				width, height,
-				GRAVITY_SOUTH,
-				bottom_offset);
-
-    if (left_region)
-	data += add_blur_boxes (data,
-				left_region->rects,
-				left_region->numRects,
-				width, height,
-				GRAVITY_WEST,
-				left_offset);
-
-    if (right_region)
-	data += add_blur_boxes (data,
-				right_region->rects,
-				right_region->numRects,
-				width, height,
-				GRAVITY_EAST,
-				right_offset);
+    data[0] = threshold;
+    data[1] = filter;
+
+    decor_region_to_box_property (data + 2, width, height,
+				  top_region, top_offset,
+				  bottom_region, bottom_offset,
+				  left_region, left_offset,
+				  right_region, right_offset);
 }
 
 void
diff --git a/metadata/Makefile.am b/metadata/Makefile.am
index 666d989..eeb208a 100644
--- a/metadata/Makefile.am
+++ b/metadata/Makefile.am
@@ -11,6 +11,7 @@ xml_in_files =		  \
 	fs.xml.in	  \
 	gconf.xml.in	  \
 	glib.xml.in	  \
+	glx.xml.in	  \
 	ini.xml.in	  \
 	inotify.xml.in	  \
 	kconfig.xml.in	  \
@@ -28,6 +29,7 @@ xml_in_files =		  \
 	switcher.xml.in   \
 	video.xml.in      \
 	water.xml.in      \
+	wm.xml.in	  \
 	wobbly.xml.in     \
 	zoom.xml.in
 xml_files    = $(xml_in_files:.xml.in=.xml)
diff --git a/metadata/annotate.xml.in b/metadata/annotate.xml.in
index 46a2b09..486b84a 100644
--- a/metadata/annotate.xml.in
+++ b/metadata/annotate.xml.in
@@ -2,6 +2,14 @@
     <plugin name="annotate">
 	<_short>Annotate</_short>
 	<_long>Annotate plugin</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	    <relation type="after">
+		<plugin>glx</plugin>
+	    </relation>
+	</deps>
 	<display>
 	    <option name="initiate_button" type="button">
 		<_short>Initiate</_short>
diff --git a/metadata/blur.xml.in b/metadata/blur.xml.in
index 21be0f0..1fd674f 100644
--- a/metadata/blur.xml.in
+++ b/metadata/blur.xml.in
@@ -4,6 +4,9 @@
 	<_long>Blur windows</_long>
 	<feature>blur</feature>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>video</plugin>
 	    </relation>
diff --git a/metadata/clone.xml.in b/metadata/clone.xml.in
index d7c7ce4..7735f7c 100644
--- a/metadata/clone.xml.in
+++ b/metadata/clone.xml.in
@@ -2,6 +2,11 @@
     <plugin name="clone">
 	<_short>Clone Output</_short>
 	<_long>Output clone handler</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="initiate_button" type="button">
 		<_short>Initiate</_short>
diff --git a/metadata/cube.xml.in b/metadata/cube.xml.in
index f07da8b..ff9b114 100644
--- a/metadata/cube.xml.in
+++ b/metadata/cube.xml.in
@@ -4,6 +4,9 @@
 	<_long>Place windows on cube</_long>
 	<feature>largedesktop</feature>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>switcher</plugin>
 		<plugin>scale</plugin>
diff --git a/metadata/fade.xml.in b/metadata/fade.xml.in
index 7e1ddff..a327e1e 100644
--- a/metadata/fade.xml.in
+++ b/metadata/fade.xml.in
@@ -3,6 +3,9 @@
 	<_short>Fading Windows</_short>
 	<_long>Fade in windows when mapped and fade out windows when unmapped</_long>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>cube</plugin>
 		<plugin>scale</plugin>
diff --git a/metadata/glx.xml.in b/metadata/glx.xml.in
new file mode 100644
index 0000000..9f25dcd
--- /dev/null
+++ b/metadata/glx.xml.in
@@ -0,0 +1,9 @@
+<compiz>
+    <plugin name="glx">
+	<_short>GLX</_short>
+	<_long>GLX compositing output</_long>
+	<display>
+	    <option name="abi" type="int" read_only="true"/>
+	</display>
+    </plugin>
+</compiz>
\ No newline at end of file
diff --git a/metadata/minimize.xml.in b/metadata/minimize.xml.in
index 4968549..f9e8077 100644
--- a/metadata/minimize.xml.in
+++ b/metadata/minimize.xml.in
@@ -4,6 +4,9 @@
 	<_long>Transform windows when they are minimized and unminimized</_long>
 	<feature>windowanimations</feature>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>cube</plugin>
 		<plugin>scale</plugin>
diff --git a/metadata/place.xml.in b/metadata/place.xml.in
index 19625ba..fd9b524 100644
--- a/metadata/place.xml.in
+++ b/metadata/place.xml.in
@@ -2,6 +2,11 @@
     <plugin name="place">
 	<_short>Place Windows</_short>
 	<_long>Place windows at appropriate positions when mapped</_long>
+	<deps>
+	    <requirement>
+		<plugin>wm</plugin>
+	    </requirement>
+	</deps>
 	<screen>
 	    <option name="workarounds" type="bool">
 		<_short>Workarounds</_short>
diff --git a/metadata/scale.xml.in b/metadata/scale.xml.in
index c551aa3..f85132c 100644
--- a/metadata/scale.xml.in
+++ b/metadata/scale.xml.in
@@ -2,6 +2,11 @@
     <plugin name="scale">
 	<_short>Scale</_short>
 	<_long>Scale windows</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="abi" type="int" read_only="true"/>
 	    <option name="index" type="int" read_only="true"/>
diff --git a/metadata/screenshot.xml.in b/metadata/screenshot.xml.in
index d7b528e..8de85e7 100644
--- a/metadata/screenshot.xml.in
+++ b/metadata/screenshot.xml.in
@@ -2,6 +2,11 @@
     <plugin name="screenshot">
 	<_short>Screenshot</_short>
 	<_long>Screenshot plugin</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="initiate_button" type="button">
 		<_short>Initiate</_short>
diff --git a/metadata/svg.xml.in b/metadata/svg.xml.in
index 7eaa8b8..eaa0293 100644
--- a/metadata/svg.xml.in
+++ b/metadata/svg.xml.in
@@ -4,5 +4,10 @@
 	<_long>Svg image loader</_long>
 	<feature>imageext:svg</feature>
 	<feature>imagemime:image/svg+xml</feature>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
     </plugin>
 </compiz>
diff --git a/metadata/switcher.xml.in b/metadata/switcher.xml.in
index e829cc3..03c01e5 100644
--- a/metadata/switcher.xml.in
+++ b/metadata/switcher.xml.in
@@ -2,6 +2,11 @@
     <plugin name="switcher">
 	<_short>Application Switcher</_short>
 	<_long>Application Switcher</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="next_button" type="button">
 		<_short>Next window</_short>
diff --git a/metadata/video.xml.in b/metadata/video.xml.in
index 09c5076..1a7cedc 100644
--- a/metadata/video.xml.in
+++ b/metadata/video.xml.in
@@ -3,6 +3,11 @@
 	<_short>Video Playback</_short>
 	<_long>Video playback</_long>
 	<feature>video</feature>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="yv12" type="bool">
 		<_short>YV12 colorspace</_short>
diff --git a/metadata/water.xml.in b/metadata/water.xml.in
index 9d3b9d2..4ea35a1 100644
--- a/metadata/water.xml.in
+++ b/metadata/water.xml.in
@@ -3,6 +3,9 @@
 	<_short>Water Effect</_short>
 	<_long>Adds water effects to different desktop actions</_long>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>blur</plugin>
 		<plugin>video</plugin>
diff --git a/metadata/wm.xml.in b/metadata/wm.xml.in
new file mode 100644
index 0000000..5c5a023
--- /dev/null
+++ b/metadata/wm.xml.in
@@ -0,0 +1,9 @@
+<compiz>
+    <plugin name="wm">
+	<_short>Window Management</_short>
+	<_long>Window management</_long>
+	<display>
+	    <option name="abi" type="int" read_only="true"/>
+	</display>
+    </plugin>
+</compiz>
diff --git a/metadata/wobbly.xml.in b/metadata/wobbly.xml.in
index 005ef3d..c2fb951 100644
--- a/metadata/wobbly.xml.in
+++ b/metadata/wobbly.xml.in
@@ -3,6 +3,9 @@
 	<_short>Wobbly Windows</_short>
 	<_long>Use spring model for wobbly window effect</_long>
 	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
 	    <relation type="before">
 		<plugin>fade</plugin>
 		<plugin>cube</plugin>
diff --git a/metadata/zoom.xml.in b/metadata/zoom.xml.in
index 1a5bd5b..6903c5e 100644
--- a/metadata/zoom.xml.in
+++ b/metadata/zoom.xml.in
@@ -2,6 +2,11 @@
     <plugin name="zoom">
 	<_short>Zoom Desktop</_short>
 	<_long>Zoom and pan desktop cube</_long>
+	<deps>
+	    <requirement>
+		<plugin>glx</plugin>
+	    </requirement>
+	</deps>
 	<display>
 	    <option name="initiate_button" type="button">
 		<_short>Initiate</_short>
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 66e4ed7..7e1129d 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,3 +1,9 @@
+libwm_la_LDFLAGS = -module -avoid-version -no-undefined
+libwm_la_SOURCES = wm.c
+
+libglx_la_LDFLAGS = -module -avoid-version -no-undefined
+libglx_la_SOURCES = glx.c
+
 libfade_la_LDFLAGS = -module -avoid-version -no-undefined
 libfade_la_SOURCES = fade.c
 
@@ -19,7 +25,9 @@ libwobbly_la_SOURCES = wobbly.c
 libminimize_la_LDFLAGS = -module -avoid-version -no-undefined
 libminimize_la_SOURCES = minimize.c
 
+libmove_la_DEPENDENCIES = $(top_builddir)/libdecoration/libdecoration.la
 libmove_la_LDFLAGS = -module -avoid-version -no-undefined
+libmove_la_LIBADD = $(top_builddir)/libdecoration/libdecoration.la
 libmove_la_SOURCES = move.c
 
 libresize_la_LDFLAGS = -module -avoid-version -no-undefined
@@ -148,6 +156,8 @@ INCLUDES =					\
 moduledir = $(plugindir)
 
 module_LTLIBRARIES =		\
+	libwm.la		\
+	libglx.la		\
 	$(libglib_module)	\
 	$(libgconf_module)	\
 	$(libkconfig_module)	\
diff --git a/plugins/annotate.c b/plugins/annotate.c
index 6271260..e671468 100644
--- a/plugins/annotate.c
+++ b/plugins/annotate.c
@@ -118,7 +118,7 @@ annoCairoContext (CompScreen *s)
 	format = XRenderFindStandardFormat (s->display->display,
 					    PictStandardARGB32);
 
-	as->pixmap = XCreatePixmap (s->display->display, s->root, w, h, 32);
+	as->pixmap = XCreatePixmap (s->display->display, s->root.id, w, h, 32);
 
 	if (!bindPixmapToTexture (s, &as->texture, as->pixmap, w, h, 32))
 	{
@@ -497,7 +497,7 @@ annoTerminate (CompDisplay     *d,
     {
 	ANNO_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (as->grabIndex)
@@ -758,7 +758,8 @@ annoInitDisplay (CompPlugin  *p,
 {
     AnnoDisplay *ad;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     ad = malloc (sizeof (AnnoDisplay));
diff --git a/plugins/blur.c b/plugins/blur.c
index d7da5da..ecb3a6d 100644
--- a/plugins/blur.c
+++ b/plugins/blur.c
@@ -588,7 +588,7 @@ blurSetScreenOption (CompPlugin      *plugin,
 	{
 	    CompWindow *w;
 
-	    for (w = screen->windows; w; w = w->next)
+	    for (w = screen->root.windows; w; w = w->next)
 		blurUpdateWindowMatch (bs, w);
 
 	    bs->moreBlur = TRUE;
@@ -784,7 +784,7 @@ blurPreparePaintScreen (CompScreen *s,
 
 	bs->moreBlur = FALSE;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    BLUR_WINDOW (w);
 
@@ -843,7 +843,7 @@ blurPreparePaintScreen (CompScreen *s,
 	    int	       x1, y1, x2, y2;
 	    int	       count = 0;
 
-	    for (w = s->windows; w; w = w->next)
+	    for (w = s->root.windows; w; w = w->next)
 	    {
 		BLUR_WINDOW (w);
 
@@ -914,7 +914,7 @@ blurPaintOutput (CompScreen		 *s,
 
 	XSubtractRegion (&emptyRegion, &emptyRegion, bs->occlusion);
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    XSubtractRegion (&emptyRegion, &emptyRegion,
 			     GET_BLUR_WINDOW (w, bs)->clip);
     }
@@ -944,7 +944,7 @@ blurPaintTransformedOutput (CompScreen		    *s,
 
 	XSubtractRegion (&emptyRegion, &emptyRegion, bs->occlusion);
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    XSubtractRegion (&emptyRegion, &emptyRegion,
 			     GET_BLUR_WINDOW (w, bs)->clip);
     }
@@ -964,7 +964,7 @@ blurDonePaintScreen (CompScreen *s)
     {
 	CompWindow *w;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    BLUR_WINDOW (w);
 
@@ -2715,7 +2715,7 @@ blurMatchExpHandlerChanged (CompDisplay *d)
     {
 	BLUR_SCREEN (s);
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    blurUpdateWindowMatch (bs, w);
     }
 }
@@ -2735,10 +2735,10 @@ blurMatchPropertyChanged (CompDisplay *d,
 }
 
 static void
-blurWindowAdd (CompScreen *s,
+blurWindowAdd (CompObject *parent,
 	       CompWindow *w)
 {
-    BLUR_SCREEN (s);
+    BLUR_SCREEN (w->screen);
 
     blurWindowUpdate (w, BLUR_STATE_CLIENT);
     blurWindowUpdate (w, BLUR_STATE_DECOR);
@@ -2772,7 +2772,8 @@ blurInitCore (CompPlugin *p,
 {
     BlurCore *bc;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     bc = malloc (sizeof (BlurCore));
@@ -3112,7 +3113,7 @@ blurInitWindow (CompPlugin *p,
     w->base.privates[bs->windowPrivateIndex].ptr = bw;
 
     if (w->base.parent)
-	blurWindowAdd (w->screen, w);
+	blurWindowAdd (w->base.parent, w);
 
     return TRUE;
 }
diff --git a/plugins/clone.c b/plugins/clone.c
index 31b78a6..4854406 100644
--- a/plugins/clone.c
+++ b/plugins/clone.c
@@ -167,7 +167,7 @@ cloneFinish (CompScreen *s)
 
 		    clone->input =
 			XCreateWindow (s->display->display,
-				       s->root, x, y,
+				       s->root.id, x, y,
 				       s->outputDev[cs->dst].width,
 				       s->outputDev[cs->dst].height,
 				       0, 0, InputOnly, CopyFromParent,
@@ -400,7 +400,7 @@ clonePaintOutput (CompScreen		  *s,
 	if (cs->offset == 0.0f)
 	    s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    if (w->destroyed)
 		continue;
@@ -515,7 +515,7 @@ cloneTerminate (CompDisplay     *d,
     {
 	CLONE_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (cs->grabIndex)
@@ -723,7 +723,8 @@ cloneInitDisplay (CompPlugin  *p,
 {
     CloneDisplay *cd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     cd = malloc (sizeof (CloneDisplay));
diff --git a/plugins/cube.c b/plugins/cube.c
index 91845f8..eaf76ed 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -1277,59 +1277,6 @@ cubePaintInside (CompScreen		 *s,
 }
 
 static void
-cubeEnableOutputClipping (CompScreen 	      *s,
-			  const CompTransform *transform,
-			  Region	      region,
-			  CompOutput 	      *output)
-{
-    CUBE_SCREEN (s);
-
-    if (cs->rotationState != RotationNone)
-    {
-	glPushMatrix ();
-	glLoadMatrixf (transform->m);
-	glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
-	glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
-
-	if (cs->invert == 1)
-	{
-	    GLdouble clipPlane0[] = {  1.0, 0.0, 0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane1[] = {  -1.0,  0.0, 0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane2[] = {  0.0,  -1.0, 0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane3[] = { 0.0,  1.0, 0.5 / cs->distance, 0.0 };
-	    glClipPlane (GL_CLIP_PLANE0, clipPlane0);
-	    glClipPlane (GL_CLIP_PLANE1, clipPlane1);
-	    glClipPlane (GL_CLIP_PLANE2, clipPlane2);
-	    glClipPlane (GL_CLIP_PLANE3, clipPlane3);
-	}
-	else
-	{
-	    GLdouble clipPlane0[] = {  -1.0, 0.0, -0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane1[] = {  1.0,  0.0, -0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane2[] = {  0.0,  1.0, -0.5 / cs->distance, 0.0 };
-	    GLdouble clipPlane3[] = { 0.0,  -1.0, -0.5 / cs->distance, 0.0 };
-	    glClipPlane (GL_CLIP_PLANE0, clipPlane0);
-	    glClipPlane (GL_CLIP_PLANE1, clipPlane1);
-	    glClipPlane (GL_CLIP_PLANE2, clipPlane2);
-	    glClipPlane (GL_CLIP_PLANE3, clipPlane3);
-	}
-
-	glEnable (GL_CLIP_PLANE0);
-	glEnable (GL_CLIP_PLANE1);
-	glEnable (GL_CLIP_PLANE2);
-	glEnable (GL_CLIP_PLANE3);
-
-	glPopMatrix ();
-    }
-    else
-    {
-	UNWRAP (cs, s, enableOutputClipping);
-	(*s->enableOutputClipping) (s, transform, region, output);
-	WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
-    }
-}
-
-static void
 cubePaintViewport (CompScreen              *s,
 		   const ScreenPaintAttrib *sAttrib,
 		   const CompTransform     *transform,
@@ -1580,7 +1527,8 @@ cubePaintWindow (CompWindow		  *w,
     CompScreen *s = w->screen;
     CUBE_SCREEN (s);
 
-    if ((w->type & CompWindowTypeDesktopMask) &&
+    if (w->parent == &s->root &&
+	(w->type & CompWindowTypeDesktopMask) &&
 	(attrib->opacity != cs->desktopOpacity))
     {
 	WindowPaintAttrib wAttrib = *attrib;
@@ -1602,12 +1550,12 @@ cubePaintWindow (CompWindow		  *w,
 }
 
 static void
-cubeInitWindowWalker (CompScreen *s, CompWalker* walker)
+cubeInitWindowWalker (CompScreen *s, CompWindow *w, CompWalker* walker)
 {
     CUBE_SCREEN (s);
 
     UNWRAP (cs, s, initWindowWalker);
-    (*s->initWindowWalker) (s, walker);
+    (*s->initWindowWalker) (s, w, walker);
     WRAP (cs, s, initWindowWalker, cubeInitWindowWalker);
 
     if (cs->paintOrder == FTB)
@@ -1701,7 +1649,7 @@ cubeFold (CompDisplay     *d,
     {
 	CUBE_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (cs->grabIndex)
@@ -1806,7 +1754,7 @@ cubeSetOptionForPlugin (CompObject      *o,
     status = (*core.setOptionForPlugin) (o, plugin, name, value);
     WRAP (cc, &core, setOptionForPlugin, cubeSetOptionForPlugin);
 
-    if (status && o->type == COMP_OBJECT_TYPE_SCREEN)
+    if (status && o->parent && o->type == COMP_OBJECT_TYPE_SCREEN)
     {
 	if (strcmp (plugin, "core") == 0 && strcmp (name, "hsize") == 0)
 	{
@@ -1864,7 +1812,8 @@ cubeInitCore (CompPlugin *p,
 {
     CubeCore *cc;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     cc = malloc (sizeof (CubeCore));
@@ -2081,7 +2030,6 @@ cubeInitScreen (CompPlugin *p,
     WRAP (cs, s, paintScreen, cubePaintScreen);
     WRAP (cs, s, paintOutput, cubePaintOutput);
     WRAP (cs, s, paintTransformedOutput, cubePaintTransformedOutput);
-    WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
     WRAP (cs, s, paintWindow, cubePaintWindow);
     WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
     WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
@@ -2107,7 +2055,6 @@ cubeFiniScreen (CompPlugin *p,
     UNWRAP (cs, s, paintScreen);
     UNWRAP (cs, s, paintOutput);
     UNWRAP (cs, s, paintTransformedOutput);
-    UNWRAP (cs, s, enableOutputClipping);
     UNWRAP (cs, s, paintWindow);
     UNWRAP (cs, s, applyScreenTransform);
     UNWRAP (cs, s, outputChangeNotify);
diff --git a/plugins/dbus.c b/plugins/dbus.c
index bcc6f28..97f6218 100644
--- a/plugins/dbus.c
+++ b/plugins/dbus.c
@@ -65,8 +65,10 @@ typedef struct _DbusCore {
 
     CompFileWatchHandle fileWatch[DBUS_FILE_WATCH_NUM];
 
-    InitPluginForObjectProc initPluginForObject;
-    SetOptionForPluginProc  setOptionForPlugin;
+    SetOptionForPluginProc setOptionForPlugin;
+
+    ObjectAddProc    objectAdd;
+    ObjectRemoveProc objectRemove;
 } DbusCore;
 
 typedef struct _DbusDisplay {
@@ -2169,62 +2171,6 @@ dbusUnregisterPluginsForScreen (DBusConnection *connection,
 }
 
 static CompBool
-dbusInitPluginForDisplay (CompPlugin  *p,
-			  CompDisplay *d)
-{
-    char objectPath[256];
-
-    DBUS_CORE (&core);
-
-    snprintf (objectPath, 256, "%s/%s/%s", COMPIZ_DBUS_ROOT_PATH,
-	      p->vTable->name, "allscreens");
-    dbusRegisterOptions (dc->connection, objectPath);
-
-    return TRUE;
-}
-
-static Bool
-dbusInitPluginForScreen (CompPlugin *p,
-			 CompScreen *s)
-{
-    char objectPath[256];
-
-    DBUS_CORE (&core);
-
-    snprintf (objectPath, 256, "%s/%s/screen%d", COMPIZ_DBUS_ROOT_PATH,
-	      p->vTable->name, s->screenNum);
-    dbusRegisterOptions (dc->connection, objectPath);
-
-    return TRUE;
-}
-
-static CompBool
-dbusInitPluginForObject (CompPlugin *p,
-			 CompObject *o)
-{
-    CompBool status;
-
-    DBUS_CORE (&core);
-
-    UNWRAP (dc, &core, initPluginForObject);
-    status = (*core.initPluginForObject) (p, o);
-    WRAP (dc, &core, initPluginForObject, dbusInitPluginForObject);
-
-    if (status && p->vTable->getObjectOptions)
-    {
-	static InitPluginForObjectProc dispTab[] = {
-	    (InitPluginForObjectProc) 0, /* InitPluginForCore */
-	    (InitPluginForObjectProc) dbusInitPluginForDisplay,
-	    (InitPluginForObjectProc) dbusInitPluginForScreen
-	};
-
-	RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
-    }
-
-    return status;
-}
-
-static CompBool
 dbusSetOptionForPlugin (CompObject      *object,
 			const char      *plugin,
 			const char      *name,
@@ -2297,6 +2243,81 @@ dbusSendPluginsChangedSignal (const char *name,
     dbus_message_unref (signal);
 }
 
+static void
+dbusDisplayAdd (CompCore    *c,
+		CompDisplay *d)
+{
+    DBUS_CORE (&core);
+
+    dbusUpdatePluginList (d);
+    dbusRegisterPluginsForDisplay (dc->connection, d);
+}
+
+static void
+dbusDisplayRemove (CompCore    *c,
+		   CompDisplay *d)
+{
+    DBUS_CORE (&core);
+
+    dbusUnregisterPluginsForDisplay (dc->connection, d);
+}
+
+static void
+dbusScreenAdd (CompDisplay *d,
+	       CompScreen  *s)
+{
+    DBUS_CORE (&core);
+
+    dbusRegisterPluginsForScreen (dc->connection, s);
+}
+
+static void
+dbusScreenRemove (CompDisplay *d,
+		  CompScreen  *s)
+{
+    DBUS_CORE (&core);
+
+    dbusUnregisterPluginsForScreen (dc->connection, s);
+}
+
+static void
+dbusObjectAdd (CompObject *parent,
+	       CompObject *object)
+{
+    static ObjectAddProc dispTab[] = {
+	(ObjectAddProc) 0, /* CoreAdd */
+	(ObjectAddProc) dbusDisplayAdd,
+	(ObjectAddProc) dbusScreenAdd
+    };
+
+    DBUS_CORE (&core);
+
+    UNWRAP (dc, &core, objectAdd);
+    (*core.objectAdd) (parent, object);
+    WRAP (dc, &core, objectAdd, dbusObjectAdd);
+
+    DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), (parent, object));
+}
+
+static void
+dbusObjectRemove (CompObject *parent,
+		  CompObject *object)
+{
+    static ObjectRemoveProc dispTab[] = {
+	(ObjectRemoveProc) 0, /* CoreRemove */
+	(ObjectRemoveProc) dbusDisplayRemove,
+	(ObjectRemoveProc) dbusScreenRemove
+    };
+
+    DBUS_CORE (&core);
+
+    DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), (parent, object));
+
+    UNWRAP (dc, &core, objectRemove);
+    (*core.objectRemove) (parent, object);
+    WRAP (dc, &core, objectRemove, dbusObjectRemove);
+}
+
 static Bool
 dbusInitCore (CompPlugin *p,
 	      CompCore   *c)
@@ -2415,7 +2436,8 @@ dbusInitCore (CompPlugin *p,
 	}
     }
 
-    WRAP (dc, c, initPluginForObject, dbusInitPluginForObject);
+    WRAP (dc, c, objectAdd, dbusObjectAdd);
+    WRAP (dc, c, objectRemove, dbusObjectRemove);
     WRAP (dc, c, setOptionForPlugin, dbusSetOptionForPlugin);
 
     c->base.privates[corePrivateIndex].ptr = dc;
@@ -2452,7 +2474,8 @@ dbusFiniCore (CompPlugin *p,
       dbus_connection_unref (dc->connection);
     */
 
-    UNWRAP (dc, c, initPluginForObject);
+    UNWRAP (dc, c, objectAdd);
+    UNWRAP (dc, c, objectRemove);
     UNWRAP (dc, c, setOptionForPlugin);
 
     free (dc);
@@ -2475,8 +2498,8 @@ dbusInitDisplay (CompPlugin  *p,
 
     d->base.privates[displayPrivateIndex].ptr = dd;
     
-    dbusUpdatePluginList (d);
-    dbusRegisterPluginsForDisplay (dc->connection, d);
+    if (d->base.parent)
+	dbusObjectAdd (d->base.parent, &d->base);
 
     return TRUE;
 }
@@ -2485,10 +2508,10 @@ static void
 dbusFiniDisplay (CompPlugin  *p,
 		 CompDisplay *d)
 {
-    DBUS_CORE (&core);
     DBUS_DISPLAY (d);
 
-    dbusUnregisterPluginsForDisplay (dc->connection, d);
+    if (d->base.parent)
+	dbusObjectRemove (d->base.parent, &d->base);
 
     if (dd->pluginList)
     {
@@ -2506,9 +2529,8 @@ static Bool
 dbusInitScreen (CompPlugin *p,
 		CompScreen *s)
 {
-    DBUS_CORE (&core);
-
-    dbusRegisterPluginsForScreen (dc->connection, s);
+    if (s->base.parent)
+	dbusObjectAdd (s->base.parent, &s->base);
 
     return TRUE;
 }
@@ -2517,9 +2539,8 @@ static void
 dbusFiniScreen (CompPlugin *p,
 		CompScreen *s)
 {
-    DBUS_CORE (&core);
-
-    dbusUnregisterPluginsForScreen (dc->connection, s);
+    if (s->base.parent)
+	dbusObjectRemove (s->base.parent, &s->base);
 }
 
 static CompBool
diff --git a/plugins/decoration.c b/plugins/decoration.c
index 003685f..f168c45 100644
--- a/plugins/decoration.c
+++ b/plugins/decoration.c
@@ -121,10 +121,6 @@ typedef struct _DecorDisplay {
 typedef struct _DecorScreen {
     int	windowPrivateIndex;
 
-    Window dmWin;
-
-    Decoration *decor[DECOR_NUM];
-
     DrawWindowProc		  drawWindow;
     DamageWindowRectProc	  damageWindowRect;
     GetOutputExtentsForWindowProc getOutputExtentsForWindow;
@@ -139,7 +135,11 @@ typedef struct _DecorScreen {
 
 typedef struct _DecorWindow {
     WindowDecoration *wd;
-    Decoration	     *decor;
+
+    Window dmWin;
+    Window wmWin;
+
+    Decoration *decor[DECOR_NUM];
 
     CompTimeoutHandle resizeUpdateHandle;
 } DecorWindow;
@@ -188,6 +188,15 @@ decorDrawWindow (CompWindow	      *w,
     status = (*w->screen->drawWindow) (w, transform, attrib, region, mask);
     WRAP (ds, w->screen, drawWindow, decorDrawWindow);
 
+    if (!w->shaded)
+    {
+	if (w->attrib.map_state != IsViewable)
+	    return status;
+
+	if (!w->damaged)
+	    return status;
+    }
+
     if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
 	region = &infiniteRegion;
 
@@ -224,7 +233,7 @@ decorDrawWindow (CompWindow	      *w,
 					     attrib, mask);
     }
 
-    return status;
+    return TRUE;
 }
 
 static DecorTexture *
@@ -261,19 +270,26 @@ decorGetTexture (CompScreen *screen,
 	return NULL;
     }
 
-    if (!bindPixmapToTexture (screen, &texture->texture, pixmap,
-			      width, height, depth))
+    if (manualCompositeManagement)
     {
-	finiTexture (screen, &texture->texture);
-	free (texture);
-	return NULL;
-    }
+	if (!bindPixmapToTexture (screen, &texture->texture, pixmap,
+				  width, height, depth))
+	{
+	    finiTexture (screen, &texture->texture);
+	    free (texture);
+	    return NULL;
+	}
 
-    if (!dd->opt[DECOR_DISPLAY_OPTION_MIPMAP].value.b)
-	texture->texture.mipmap = FALSE;
+	if (!dd->opt[DECOR_DISPLAY_OPTION_MIPMAP].value.b)
+	    texture->texture.mipmap = FALSE;
 
-    texture->damage = XDamageCreate (screen->display->display, pixmap,
-				     XDamageReportRawRectangles);
+	texture->damage = XDamageCreate (screen->display->display, pixmap,
+					 XDamageReportRawRectangles);
+    }
+    else
+    {
+	texture->damage = None;
+    }
 
     texture->refCount = 1;
     texture->pixmap   = pixmap;
@@ -408,9 +424,11 @@ decorCreateDecoration (CompScreen *screen,
     int		    left, right, top, bottom;
     int		    x1, y1, x2, y2;
 
+    DECOR_DISPLAY (screen->display);
+
     result = XGetWindowProperty (screen->display->display, id,
 				 decorAtom, 0L, 1024L, FALSE,
-				 XA_INTEGER, &actual, &format,
+				 dd->winDecorAtom, &actual, &format,
 				 &n, &nleft, &data);
 
     if (result != Success || !n || !data)
@@ -532,19 +550,20 @@ decorReleaseDecoration (CompScreen *screen,
 }
 
 static void
-decorWindowUpdateDecoration (CompWindow *w)
+decorWindowUpdateDecoration (CompWindow *w,
+			     Atom       atom,
+			     int        type)
 {
     Decoration *decoration;
 
-    DECOR_DISPLAY (w->screen->display);
     DECOR_WINDOW (w);
 
-    decoration = decorCreateDecoration (w->screen, w->id, dd->winDecorAtom);
+    decoration = decorCreateDecoration (w->screen, w->id, atom);
 
-    if (dw->decor)
-	decorReleaseDecoration (w->screen, dw->decor);
+    if (dw->decor[type])
+	decorReleaseDecoration (w->screen, dw->decor[type]);
 
-    dw->decor = decoration;
+    dw->decor[type] = decoration;
 }
 
 static WindowDecoration *
@@ -654,6 +673,9 @@ updateWindowDecorationScale (CompWindow *w)
     if (!wd)
 	return;
 
+    if (!manualCompositeManagement)
+	return;
+
     for (i = 0; i < wd->nQuad; i++)
     {
 	computeQuadBox (&wd->decor->quad[i], w->width, w->height,
@@ -712,6 +734,17 @@ decorWindowShiftY (CompWindow *w)
 }
 
 static Bool
+decorIsActiveWindow (CompWindow *w)
+{
+    for (; w->parent; w = w->parent)
+    	if (w->parent->redirectSubwindows || w->parent->substructureRedirect)
+	    if (w->parent->activeChild != w->id)
+		return FALSE;
+
+    return TRUE;
+}
+
+static Bool
 decorWindowUpdate (CompWindow *w,
 		   Bool	      allowDecoration)
 {
@@ -727,6 +760,9 @@ decorWindowUpdate (CompWindow *w,
     DECOR_SCREEN (w->screen);
     DECOR_WINDOW (w);
 
+    if (!w->parent)
+	return FALSE;
+
     wd = dw->wd;
     old = (wd) ? wd->decor : NULL;
 
@@ -742,6 +778,9 @@ decorWindowUpdate (CompWindow *w,
 	break;
     }
 
+    if (!GET_DECOR_WINDOW (w->parent, ds)->wmWin)
+	decorate = FALSE;
+
     if (w->attrib.override_redirect)
 	decorate = FALSE;
 
@@ -754,16 +793,16 @@ decorWindowUpdate (CompWindow *w,
 
     if (decorate)
     {
-	if (dw->decor && decorCheckSize (w, dw->decor))
-	{
-	    decor = dw->decor;
-	}
-	else
+	decor = dw->decor[DECOR_NORMAL];
+	if (decorIsActiveWindow (w) && dw->decor[DECOR_ACTIVE])
+	    decor = dw->decor[DECOR_ACTIVE];
+		    
+	if (!decor || !decorCheckSize (w, decor))
 	{
-	    if (w->id == w->screen->display->activeWindow)
-		decor = ds->decor[DECOR_ACTIVE];
+	    if (decorIsActiveWindow (w))
+		decor = GET_DECOR_WINDOW (w->parent, ds)->decor[DECOR_ACTIVE];
 	    else
-		decor = ds->decor[DECOR_NORMAL];
+		decor = GET_DECOR_WINDOW (w->parent, ds)->decor[DECOR_NORMAL];
 	}
     }
     else
@@ -772,7 +811,7 @@ decorWindowUpdate (CompWindow *w,
 	if (matchEval (match, w))
 	{
 	    if (w->region->numRects == 1)
-		decor = ds->decor[DECOR_BARE];
+		decor = GET_DECOR_WINDOW (w->parent, ds)->decor[DECOR_BARE];
 
 	    if (decor)
 	    {
@@ -782,7 +821,7 @@ decorWindowUpdate (CompWindow *w,
 	}
     }
 
-    if (!ds->dmWin || !allowDecoration)
+    if (!GET_DECOR_WINDOW (w->parent, ds)->dmWin || !allowDecoration)
 	decor = NULL;
 
     if (decor == old)
@@ -829,7 +868,7 @@ decorWindowUpdate (CompWindow *w,
 	moveDy = -oldShiftY;
     }
 
-    if (w->placed && !w->attrib.override_redirect && (moveDx || moveDy))
+    if (w->placed && w->managed && (moveDx || moveDy))
     {
 	XWindowChanges xwc;
 	unsigned int   mask = CWX | CWY;
@@ -860,20 +899,49 @@ decorWindowUpdate (CompWindow *w,
 }
 
 static void
-decorCheckForDmOnScreen (CompScreen *s,
-			 Bool	    updateWindows)
+decorWindowUpdateTree (CompWindow *ancestor,
+		       Bool       allowDecoration)
 {
+    CompWindow *w;
+
+    w = ancestor;
+    for (;;)
+    {
+	decorWindowUpdate (w, allowDecoration);
+
+	if (w->windows)
+	{
+	    w = w->windows;
+	    continue;
+	}
+
+	while (!w->next && (w != ancestor))
+	    w = w->parent;
+	    
+	if (w == ancestor)
+	    break;
+
+	w = w->next;
+    }
+}
+
+static void
+decorCheckForDm (CompWindow *w,
+		 Bool	    updateWindows)
+{
+    CompScreen    *s = w->screen;
     CompDisplay   *d = s->display;
     Atom	  actual;
     int		  result, format;
     unsigned long n, left;
     unsigned char *data;
     Window	  dmWin = None;
+    Window	  wmWin = w->supportingWmCheckWindow;
 
     DECOR_DISPLAY (s->display);
-    DECOR_SCREEN (s);
+    DECOR_WINDOW (w);
 
-    result = XGetWindowProperty (d->display, s->root,
+    result = XGetWindowProperty (d->display, w->id,
 				 dd->supportingDmCheckAtom, 0L, 1L, FALSE,
 				 XA_WINDOW, &actual, &format,
 				 &n, &left, &data);
@@ -893,46 +961,58 @@ decorCheckForDmOnScreen (CompScreen *s,
 	    dmWin = None;
     }
 
-    if (dmWin != ds->dmWin)
+    if (dmWin != dw->dmWin)
     {
-	CompWindow *w;
+	CompWindow *c;
 	int	   i;
 
 	if (dmWin)
 	{
 	    for (i = 0; i < DECOR_NUM; i++)
-		ds->decor[i] =
-		    decorCreateDecoration (s, s->root, dd->decorAtom[i]);
+		dw->decor[i] = decorCreateDecoration (s,
+						      w->id,
+						      dd->decorAtom[i]);
 	}
 	else
 	{
+	    DECOR_SCREEN (w->screen);
+
 	    for (i = 0; i < DECOR_NUM; i++)
 	    {
-		if (ds->decor[i])
+		if (dw->decor[i])
 		{
-		    decorReleaseDecoration (s, ds->decor[i]);
-		    ds->decor[i] = 0;
+		    decorReleaseDecoration (s, dw->decor[i]);
+		    dw->decor[i] = 0;
 		}
 	    }
 
-	    for (w = s->windows; w; w = w->next)
+	    for (c = w->windows; c; c = c->next)
 	    {
-		DECOR_WINDOW (w);
+		DecorWindow *dc = GET_DECOR_WINDOW (c, ds);
 
-		if (dw->decor)
+		for (i = 0; i < DECOR_NUM; i++)
 		{
-		    decorReleaseDecoration (s, dw->decor);
-		    dw->decor = 0;
+		    if (dc->decor[i])
+		    {
+			decorReleaseDecoration (s, dc->decor[i]);
+			dc->decor[i] = 0;
+		    }
 		}
 	    }
 	}
+    }
 
-	ds->dmWin = dmWin;
+    if ((wmWin != dw->wmWin) || (dmWin != dw->dmWin))
+    {
+	dw->wmWin = wmWin;
+	dw->dmWin = dmWin;
 
 	if (updateWindows)
 	{
-	    for (w = s->windows; w; w = w->next)
-		decorWindowUpdate (w, TRUE);
+	    CompWindow *c;
+
+	    for (c = w->windows; c; c = c->next)
+		decorWindowUpdate (c, TRUE);
 	}
     }
 }
@@ -941,7 +1021,6 @@ static void
 decorHandleEvent (CompDisplay *d,
 		  XEvent      *event)
 {
-    Window     activeWindow = d->activeWindow;
     CompWindow *w;
 
     DECOR_DISPLAY (d);
@@ -949,12 +1028,16 @@ decorHandleEvent (CompDisplay *d,
     switch (event->type) {
     case DestroyNotify:
 	w = findWindowAtDisplay (d, event->xdestroywindow.window);
-	if (w)
+	if (w && (w = w->parent))
 	{
-	    DECOR_SCREEN (w->screen);
+	    DECOR_WINDOW (w);
 
-	    if (w->id == ds->dmWin)
-		decorCheckForDmOnScreen (w->screen, TRUE);
+	    if (w->supportingWmCheckWindow == event->xdestroywindow.window)
+		getSupportingWmCheck (w);
+
+	    if (event->xdestroywindow.window == dw->wmWin ||
+		event->xdestroywindow.window == dw->dmWin)
+		decorCheckForDm (w, TRUE);
 	}
 	break;
     case MapRequest:
@@ -982,7 +1065,8 @@ decorHandleEvent (CompDisplay *d,
 		    {
 			ds = GET_DECOR_SCREEN (s, dd);
 
-			for (w = s->windows; w; w = w->next)
+			w = s->root.windows;
+			for (;;)
 			{
 			    if (w->shaded || w->mapNum)
 			    {
@@ -991,6 +1075,20 @@ decorHandleEvent (CompDisplay *d,
 				if (dw->wd && dw->wd->decor->texture == t)
 				    damageWindowOutputExtents (w);
 			    }
+
+			    if (w->windows)
+			    {
+				w = w->windows;
+				continue;
+			    }
+
+			    while (!w->next && (w != &s->root))
+				w = w->parent;
+	    
+			    if (w == &s->root)
+				break;
+
+			    w = w->next;
 			}
 		    }
 		    return;
@@ -1004,25 +1102,47 @@ decorHandleEvent (CompDisplay *d,
     (*d->handleEvent) (d, event);
     WRAP (dd, d, handleEvent, decorHandleEvent);
 
-    if (d->activeWindow != activeWindow)
-    {
-	w = findWindowAtDisplay (d, activeWindow);
-	if (w)
-	    decorWindowUpdate (w, TRUE);
-
-	w = findWindowAtDisplay (d, d->activeWindow);
-	if (w)
-	    decorWindowUpdate (w, TRUE);
-    }
-
     switch (event->type) {
+    case FocusIn:
+	if (event->xfocus.mode != NotifyGrab)
+	{
+	    w = findTopLevelWindowAtDisplay (d, event->xfocus.window);
+	    if (w && w->managed && (w = w->parent))
+	    {
+		CompWindow *c;
+
+		for (c = w->windows; c; c = c->next)
+		    if (c->id == w->previousActiveChild ||
+			c->id == w->activeChild)
+			decorWindowUpdateTree (c, TRUE);
+	    }
+	}
+	break;
     case PropertyNotify:
-	if (event->xproperty.atom == dd->winDecorAtom)
+	if (event->xproperty.atom == d->winActiveAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w)
+	    {	
+		if (!w->substructureRedirect)
+		{
+		    CompWindow *c;
+
+		    for (c = w->windows; c; c = c->next)
+			if (c->id == w->previousActiveChild ||
+			    c->id == w->activeChild)
+			    decorWindowUpdateTree (c, TRUE);
+		}
+	    }
+	}
+	else if (event->xproperty.atom == dd->winDecorAtom)
 	{
 	    w = findWindowAtDisplay (d, event->xproperty.window);
 	    if (w)
 	    {
-		decorWindowUpdateDecoration (w);
+		decorWindowUpdateDecoration (w,
+					     dd->winDecorAtom,
+					     DECOR_NORMAL);
 		decorWindowUpdate (w, TRUE);
 	    }
 	}
@@ -1034,14 +1154,13 @@ decorHandleEvent (CompDisplay *d,
 	}
 	else
 	{
-	    CompScreen *s;
-
-	    s = findScreenAtDisplay (d, event->xproperty.window);
-	    if (s)
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w)
 	    {
-		if (event->xproperty.atom == dd->supportingDmCheckAtom)
+		if (event->xproperty.atom == d->supportingWmCheckAtom ||
+		    event->xproperty.atom == dd->supportingDmCheckAtom)
 		{
-		    decorCheckForDmOnScreen (s, TRUE);
+		    decorCheckForDm (w, TRUE);
 		}
 		else
 		{
@@ -1051,17 +1170,23 @@ decorHandleEvent (CompDisplay *d,
 		    {
 			if (event->xproperty.atom == dd->decorAtom[i])
 			{
-			    DECOR_SCREEN (s);
+			    DECOR_WINDOW (w);
 
-			    if (ds->decor[i])
-				decorReleaseDecoration (s, ds->decor[i]);
+			    decorWindowUpdateDecoration (w,
+							 dd->decorAtom[i],
+							 i);
 
-			    ds->decor[i] =
-				decorCreateDecoration (s, s->root,
-						       dd->decorAtom[i]);
+			    if (dw->dmWin)
+			    {
+				CompWindow *c;
 
-			    for (w = s->windows; w; w = w->next)
+				for (c = w->windows; c; c = c->next)
+				    decorWindowUpdate (c, TRUE);
+			    }
+			    else
+			    {
 				decorWindowUpdate (w, TRUE);
+			    }
 			}
 		    }
 		}
@@ -1132,10 +1257,11 @@ decorStartDecorator (void *closure)
 
     DECOR_DISPLAY (s->display);
     DECOR_SCREEN (s);
+    DECOR_WINDOW ((&s->root));
 
     ds->decoratorStartHandle = 0;
 
-    if (!ds->dmWin)
+    if (!dw->dmWin)
 	runCommand (s, dd->opt[DECOR_DISPLAY_OPTION_COMMAND].value.s);
 
     return FALSE;
@@ -1175,10 +1301,14 @@ decorSetDisplayOption (CompPlugin      *plugin,
 
 	    for (s = display->screens; s; s = s->next)
 	    {
+		DECOR_WINDOW ((&s->root));
 		DECOR_SCREEN (s);
 
-		if (!ds->dmWin)
-		    runCommand (s, o->value.s);
+		if (!dw->dmWin && !ds->decoratorStartHandle)
+		    ds->decoratorStartHandle =
+			compAddTimeout (0, -1,
+					decorStartDecorator,
+					s);
 	    }
 
 	    return TRUE;
@@ -1221,11 +1351,9 @@ decorSetDisplayOption (CompPlugin      *plugin,
 	if (compSetMatchOption (o, value))
 	{
 	    CompScreen *s;
-	    CompWindow *w;
 
 	    for (s = display->screens; s; s = s->next)
-		for (w = s->windows; w; w = w->next)
-		    decorWindowUpdate (w, TRUE);
+		decorWindowUpdateTree (&s->root, TRUE);
 	}
 	break;
     default:
@@ -1246,7 +1374,7 @@ decorWindowMoveNotify (CompWindow *w,
     DECOR_SCREEN (w->screen);
     DECOR_WINDOW (w);
 
-    if (dw->wd)
+    if (dw->wd && w->parent && w->parent->redirectSubwindows)
     {
 	WindowDecoration *wd = dw->wd;
 	int		 i;
@@ -1291,15 +1419,20 @@ decorWindowResizeNotify (CompWindow *w,
     DECOR_SCREEN (w->screen);
     DECOR_WINDOW (w);
 
-    /* FIXME: we should not need a timer for calling decorWindowUpdate,
-       and only call updateWindowDecorationScale if decorWindowUpdate
-       returns FALSE. Unfortunately, decorWindowUpdate may call
-       updateWindowOutputExtents, which may call WindowResizeNotify. As
-       we never should call a wrapped function that's currently
-       processed, we need the timer for the moment. updateWindowOutputExtents
-       should be fixed so that it does not emit a resize notification. */
-    dw->resizeUpdateHandle = compAddTimeout (0, 0, decorResizeUpdateTimeout, w);
-    updateWindowDecorationScale (w);
+    if (w->parent && w->parent->redirectSubwindows)
+    {
+	/* FIXME: we should not need a timer for calling decorWindowUpdate,
+	   and only call updateWindowDecorationScale if decorWindowUpdate
+	   returns FALSE. Unfortunately, decorWindowUpdate may call
+	   updateWindowOutputExtents, which may call WindowResizeNotify. As
+	   we never should call a wrapped function that's currently
+	   processed, we need the timer for the moment.
+	   updateWindowOutputExtents should be fixed so that it does not
+	   emit a resize notification. */
+	dw->resizeUpdateHandle =
+	    compAddTimeout (0, 0, decorResizeUpdateTimeout, w);
+	updateWindowDecorationScale (w);
+    }
 
     UNWRAP (ds, w->screen, windowResizeNotify);
     (*w->screen->windowResizeNotify) (w, dx, dy, dwidth, dheight);
@@ -1343,7 +1476,7 @@ decorMatchPropertyChanged (CompDisplay *d,
 }
 
 static void
-decorWindowAdd (CompScreen *s,
+decorWindowAdd (CompObject *parent,
 		CompWindow *w)
 {
     if (w->shaded || w->attrib.map_state == IsViewable)
@@ -1351,7 +1484,7 @@ decorWindowAdd (CompScreen *s,
 }
 
 static void
-decorWindowRemove (CompScreen *s,
+decorWindowRemove (CompObject *parent,
 		   CompWindow *w)
 {
     if (!w->destroyed)
@@ -1536,9 +1669,6 @@ decorInitScreen (CompPlugin *p,
 	return FALSE;
     }
 
-    memset (ds->decor, 0, sizeof (ds->decor));
-
-    ds->dmWin                = None;
     ds->decoratorStartHandle = 0;
 
     WRAP (ds, s, drawWindow, decorDrawWindow);
@@ -1550,12 +1680,6 @@ decorInitScreen (CompPlugin *p,
 
     s->base.privates[dd->screenPrivateIndex].ptr = ds;
 
-    decorCheckForDmOnScreen (s, FALSE);
-
-    if (!ds->dmWin)
-	ds->decoratorStartHandle = compAddTimeout (0, -1,
-						   decorStartDecorator, s);
-
     return TRUE;
 }
 
@@ -1563,14 +1687,8 @@ static void
 decorFiniScreen (CompPlugin *p,
 		 CompScreen *s)
 {
-    int	i;
-
     DECOR_SCREEN (s);
 
-    for (i = 0; i < DECOR_NUM; i++)
-	if (ds->decor[i])
-	    decorReleaseDecoration (s, ds->decor[i]);
-
     if (ds->decoratorStartHandle)
 	compRemoveTimeout (ds->decoratorStartHandle);
 
@@ -1591,6 +1709,7 @@ decorInitWindow (CompPlugin *p,
 		 CompWindow *w)
 {
     DecorWindow *dw;
+    int         i;
 
     DECOR_SCREEN (w->screen);
 
@@ -1598,18 +1717,46 @@ decorInitWindow (CompPlugin *p,
     if (!dw)
 	return FALSE;
 
-    dw->wd    = NULL;
-    dw->decor = NULL;
+    dw->wmWin = None;
+    dw->dmWin = None;
+    
+    dw->wd = NULL;
+
+    for (i = 0; i < DECOR_NUM; i++)
+	dw->decor[i] = 0;
 
     dw->resizeUpdateHandle = 0;
 
     w->base.privates[ds->windowPrivateIndex].ptr = dw;
 
-    if (!w->attrib.override_redirect)
-	decorWindowUpdateDecoration (w);
+    decorCheckForDm (w, FALSE);
+
+    if (w->parent)
+    {
+	if (!w->attrib.override_redirect)
+	{
+	    DECOR_DISPLAY (w->screen->display);
+
+	    decorWindowUpdateDecoration (w,
+					 dd->winDecorAtom,
+					 DECOR_NORMAL);
+	    decorWindowUpdateDecoration (w,
+					 dd->decorAtom[DECOR_ACTIVE],
+					 DECOR_ACTIVE);
+	}
+    }
+    else
+    {
+	DECOR_SCREEN (w->screen);
+
+	if (!dw->dmWin && !ds->decoratorStartHandle)
+	    ds->decoratorStartHandle = compAddTimeout (0, -1,
+						       decorStartDecorator,
+						       w->screen);
+    }
 
     if (w->base.parent)
-	decorWindowAdd (w->screen, w);
+	decorWindowAdd (w->base.parent, w);
 
     return TRUE;
 }
@@ -1618,19 +1765,22 @@ static void
 decorFiniWindow (CompPlugin *p,
 		 CompWindow *w)
 {
+    int i;
+
     DECOR_WINDOW (w);
 
     if (dw->resizeUpdateHandle)
 	compRemoveTimeout (dw->resizeUpdateHandle);
 
     if (w->base.parent)
-	decorWindowRemove (w->screen, w);
+	decorWindowRemove (w->base.parent, w);
 
     if (dw->wd)
 	destroyWindowDecoration (w->screen, dw->wd);
 
-    if (dw->decor)
-	decorReleaseDecoration (w->screen, dw->decor);
+    for (i = 0; i < DECOR_NUM; i++)
+	if (dw->decor[i])
+	    decorReleaseDecoration (w->screen, dw->decor[i]);
 
     free (dw);
 }
diff --git a/plugins/fade.c b/plugins/fade.c
index a30deef..4416615 100644
--- a/plugins/fade.c
+++ b/plugins/fade.c
@@ -196,16 +196,31 @@ fadePreparePaintScreen (CompScreen *s,
 	if (steps < 12)
 	    steps = 12;
 
-	for (w = s->windows; w; w = w->next)
+	w = s->root.windows;
+	for (;;)
 	{
 	    FadeWindow *fw = GET_FADE_WINDOW (w, fs);
 	    fw->steps    = steps;
 	    fw->fadeTime = 0;
-	}
 
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+	    	w = w->parent;
+	    
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
+	}	
 	break;
     case FADE_MODE_CONSTANTTIME:
-	for (w = s->windows; w; w = w->next)
+	w = s->root.windows;
+	for (;;)
 	{
 	    FadeWindow *fw = GET_FADE_WINDOW (w, fs);
 
@@ -220,8 +235,21 @@ fadePreparePaintScreen (CompScreen *s,
 	    {
 		fw->steps = 0;
 	    }
+
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+	    	w = w->parent;
+	    
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
 	}
-	
 	break;
     }
 
@@ -569,7 +597,7 @@ fadeHandleEvent (CompDisplay *d,
 			option = FADE_SCREEN_OPTION_FULLSCREEN_VISUAL_BELL;
 			if (fs->opt[option].value.b)
 			{
-			    for (w = s->windows; w; w = w->next)
+			    for (w = s->root.windows; w; w = w->next)
 			    {
 				if (w->destroyed)
 				    continue;
@@ -731,7 +759,8 @@ fadeInitDisplay (CompPlugin  *p,
 {
     FadeDisplay *fd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     fd = malloc (sizeof (FadeDisplay));
diff --git a/plugins/gconf.c b/plugins/gconf.c
index 8d365e0..abb94b6 100644
--- a/plugins/gconf.c
+++ b/plugins/gconf.c
@@ -701,12 +701,12 @@ gconfSendGLibNotify (CompDisplay *d)
     xev.xclient.format  = 32;
 
     xev.xclient.message_type = XInternAtom (dpy, "_COMPIZ_GLIB_NOTIFY", 0);
-    xev.xclient.window	     = d->screens->root;
+    xev.xclient.window	     = d->screens->root.id;
 
     memset (xev.xclient.data.l, 0, sizeof (xev.xclient.data.l));
 
     XSendEvent (dpy,
-		d->screens->root,
+		d->screens->root.id,
 		FALSE,
 		SubstructureRedirectMask | SubstructureNotifyMask,
 		&xev);
diff --git a/plugins/glx.c b/plugins/glx.c
new file mode 100644
index 0000000..5bf6274
--- /dev/null
+++ b/plugins/glx.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <compiz-core.h>
+
+static CompMetadata glxMetadata;
+
+static CompOption *
+glxGetDisplayOptions (CompPlugin  *plugin,
+		      CompDisplay *display,
+		      int	  *count)
+{
+    *count = 1;
+    return &display->opt[COMP_DISPLAY_OPTION_ABI];
+}
+
+static Bool
+glxInitDisplay (CompPlugin  *p,
+		CompDisplay *d)
+{
+    int error, event;
+
+    if (!checkPluginABI ("core", CORE_ABIVERSION))
+	return FALSE;
+
+    if (!glXQueryExtension (d->display, &error, &event))
+    {
+	compLogMessage (p->vTable->name, CompLogLevelError,
+			"GLX extension is not available");
+	return FALSE;
+    }
+
+    if (manualCompositeManagement)
+	return TRUE;
+
+    if (d->screens)
+    {
+	compLogMessage (p->vTable->name, CompLogLevelError,
+			"%s plugin must be loaded before screens are "
+			"initialize", p->vTable->name);
+	return FALSE;
+    }
+
+    manualCompositeManagement = TRUE;
+
+    return TRUE;
+}
+
+static CompBool
+glxInitObject (CompPlugin *p,
+	       CompObject *o)
+{
+    static InitPluginObjectProc dispTab[] = {
+	(InitPluginObjectProc) 0, /* InitCore */
+	(InitPluginObjectProc) glxInitDisplay
+    };
+
+    RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static CompOption *
+glxGetObjectOptions (CompPlugin *plugin,
+		    CompObject *object,
+		    int	       *count)
+{
+    static GetPluginObjectOptionsProc dispTab[] = {
+	(GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
+	(GetPluginObjectOptionsProc) glxGetDisplayOptions
+    };
+
+    RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
+		     (void *) (*count = 0), (plugin, object, count));
+}
+
+static Bool
+glxInit (CompPlugin *p)
+{
+    if (!compInitPluginMetadataFromInfo (&glxMetadata, p->vTable->name,
+					 0, 0, 0, 0))
+	return FALSE;
+
+    compAddMetadataFromFile (&glxMetadata, p->vTable->name);
+
+    return TRUE;
+}
+
+static void
+glxFini (CompPlugin *p)
+{
+    compFiniMetadata (&glxMetadata);
+}
+
+static CompMetadata *
+glxGetMetadata (CompPlugin *plugin)
+{
+    return &glxMetadata;
+}
+
+CompPluginVTable glxVTable = {
+    "glx",
+    glxGetMetadata,
+    glxInit,
+    glxFini,
+    glxInitObject,
+    0, /* FiniObject */
+    glxGetObjectOptions,
+    0  /* SetObjectOption */
+};
+
+CompPluginVTable *
+getCompPluginInfo20070830 (void)
+{
+    return &glxVTable;
+}
diff --git a/plugins/minimize.c b/plugins/minimize.c
index eb82370..901c29c 100644
--- a/plugins/minimize.c
+++ b/plugins/minimize.c
@@ -312,7 +312,7 @@ minPreparePaintScreen (CompScreen *s,
 	{
 	    ms->moreAdjust = 0;
 
-	    for (w = s->windows; w; w = w->next)
+	    for (w = s->root.windows; w; w = w->next)
 	    {
 		MIN_WINDOW (w);
 
@@ -395,7 +395,7 @@ minPreparePaintScreen (CompScreen *s,
 
 	if (ms->moreAdjust)
 	{
-	    for (w = s->windows; w; w = w->next)
+	    for (w = s->root.windows; w; w = w->next)
 	    {
 		MIN_WINDOW (w);
 
@@ -431,7 +431,7 @@ minDonePaintScreen (CompScreen *s)
 	CompWindow *w;
 	int	   h;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    MIN_WINDOW (w);
 
@@ -762,7 +762,9 @@ minInitDisplay (CompPlugin  *p,
 {
     MinDisplay *md;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("wm",   CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     md = malloc (sizeof (MinDisplay));
diff --git a/plugins/move.c b/plugins/move.c
index 32fb456..e1df607 100644
--- a/plugins/move.c
+++ b/plugins/move.c
@@ -28,8 +28,10 @@
 #include <string.h>
 
 #include <X11/cursorfont.h>
+#include <X11/Xatom.h>
 
 #include <compiz-core.h>
+#include <decoration.h>
 
 static CompMetadata moveMetadata;
 
@@ -51,6 +53,11 @@ struct _MoveKeys {
 #define SNAP_BACK 20
 #define SNAP_OFF  100
 
+typedef struct _MoveBox {
+    decor_point_t p1;
+    decor_point_t p2;
+} MoveBox;
+
 static int displayPrivateIndex;
 
 #define MOVE_DISPLAY_OPTION_INITIATE_BUTTON   0
@@ -76,12 +83,16 @@ typedef struct _MoveDisplay {
     int        status;
     KeyCode    key[NUM_KEYS];
 
+    Atom moveAtom;
+
     int releaseButton;
 
     GLushort moveOpacity;
 } MoveDisplay;
 
 typedef struct _MoveScreen {
+    int windowPrivateIndex;
+
     PaintWindowProc paintWindow;
 
     int grabIndex;
@@ -94,6 +105,12 @@ typedef struct _MoveScreen {
     int	snapBackY;
 } MoveScreen;
 
+typedef struct _MoveWindow {
+    int     button;
+    MoveBox *box;
+    int     nBox;
+} MoveWindow;
+
 #define GET_MOVE_DISPLAY(d)					  \
     ((MoveDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
 
@@ -106,8 +123,106 @@ typedef struct _MoveScreen {
 #define MOVE_SCREEN(s)						        \
     MoveScreen *ms = GET_MOVE_SCREEN (s, GET_MOVE_DISPLAY (s->display))
 
+#define GET_MOVE_WINDOW(w, ms)					      \
+    ((MoveWindow *) (w)->base.privates[(ms)->windowPrivateIndex].ptr)
+
+#define MOVE_WINDOW(w)					     \
+    MoveWindow *mw = GET_MOVE_WINDOW  (w,		     \
+		     GET_MOVE_SCREEN  (w->screen,	     \
+		     GET_MOVE_DISPLAY (w->screen->display)))
+
+
 #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
 
+
+static Bool
+movePointInBoxes (int     x,
+		  int     y,
+		  MoveBox *box,
+		  int	  nBox,
+		  int	  width,
+		  int	  height)
+{
+    int x0, y0, x1, y1;
+
+    while (nBox--)
+    {
+	decor_apply_gravity (box->p1.gravity, box->p1.x, box->p1.y,
+			     width, height,
+			     &x0, &y0);
+
+	decor_apply_gravity (box->p2.gravity, box->p2.x, box->p2.y,
+			     width, height,
+			     &x1, &y1);
+
+	if (x >= x0 && x < x1 && y >= y0 && y < y1)
+	    return TRUE;
+
+	box++;
+    }
+
+    return FALSE;
+}
+
+static void
+moveWindowUpdate (CompWindow *w)
+{
+    Atom	  actual;
+    int		  result, format;
+    unsigned long n, left;
+    unsigned char *propData;
+    MoveBox	  *box = NULL;
+    int		  nBox = 0;
+
+    MOVE_DISPLAY (w->screen->display);
+    MOVE_WINDOW (w);
+
+    result = XGetWindowProperty (w->screen->display->display, w->id,
+				 md->moveAtom, 0L, 8192L, FALSE,
+				 XA_INTEGER, &actual, &format,
+				 &n, &left, &propData);
+
+    if (result == Success && n && propData)
+    {
+	if (n >= 2)
+	{
+	    long *data = (long *) propData;
+
+	    mw->button = data[1];
+
+	    nBox = (n - 2) / 6;
+	    if (nBox)
+	    {
+		box = malloc (sizeof (MoveBox) * nBox);
+		if (box)
+		{
+		    int i;
+
+		    data += 2;
+
+		    for (i = 0; i < nBox; i++)
+		    {
+			box[i].p1.gravity = *data++;
+			box[i].p1.x       = *data++;
+			box[i].p1.y       = *data++;
+			box[i].p2.gravity = *data++;
+			box[i].p2.x       = *data++;
+			box[i].p2.y       = *data++;
+		    }
+		}
+	    }
+	}
+
+	XFree (propData);
+    }
+
+    if (mw->box)
+	free (mw->box);
+
+    mw->box  = box;
+    mw->nBox = nBox;
+}
+
 static Bool
 moveInitiate (CompDisplay     *d,
 	      CompAction      *action,
@@ -125,18 +240,25 @@ moveInitiate (CompDisplay     *d,
     w = findWindowAtDisplay (d, xid);
     if (w && (w->actions & CompWindowActionMoveMask))
     {
+	CompWindow   *p;
 	XRectangle   workArea;
 	unsigned int mods;
 	int          x, y, button;
 
 	MOVE_SCREEN (w->screen);
 
+	x = w->width / 2;
+	y = w->height / 2;
+	for (p = w; p; p = p->parent)
+	{
+	    x += p->attrib.x;
+	    y += p->attrib.y;
+	}
+
 	mods = getIntOptionNamed (option, nOption, "modifiers", 0);
 
-	x = getIntOptionNamed (option, nOption, "x",
-			       w->attrib.x + (w->width / 2));
-	y = getIntOptionNamed (option, nOption, "y",
-			       w->attrib.y + (w->height / 2));
+	x = getIntOptionNamed (option, nOption, "x", x);
+	y = getIntOptionNamed (option, nOption, "y", y);
 
 	button = getIntOptionNamed (option, nOption, "button", -1);
 
@@ -192,6 +314,12 @@ moveInitiate (CompDisplay     *d,
 
 	    md->releaseButton = button;
 
+	    for (p = w->parent; p; p = p->parent)
+	    {
+		x -= p->attrib.x;
+		y -= p->attrib.y;
+	    }
+
 	    (w->screen->windowGrabNotify) (w, x, y, mods,
 					   CompWindowGrabMoveMask |
 					   CompWindowGrabButtonMask);
@@ -298,7 +426,7 @@ moveGetYConstrainRegion (CompScreen *s)
 	getWorkareaForOutput (s, i, &workArea);
 	extents = s->outputDev[i].region.extents;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    if (!w->mapNum)
 		continue;
@@ -534,12 +662,18 @@ moveHandleMotionEvent (CompScreen *s,
 
 	if (dx || dy)
 	{
+	    Bool lazy = md->opt[MOVE_DISPLAY_OPTION_LAZY_POSITIONING].value.b;
+
 	    moveWindow (w,
 			wX + dx - w->attrib.x,
 			wY + dy - w->attrib.y,
 			TRUE, FALSE);
 
-	    if (md->opt[MOVE_DISPLAY_OPTION_LAZY_POSITIONING].value.b)
+	    /* lazy positioning cannot be used without manual compositing */
+	    if (!manualCompositeManagement)
+		lazy = FALSE;
+
+	    if (lazy)
 	    {
 		/* FIXME: This form of lazy positioning is broken and should
 		   be replaced asap. Current code exists just to avoid a
@@ -563,11 +697,62 @@ moveHandleEvent (CompDisplay *d,
 		 XEvent      *event)
 {
     CompScreen *s;
+    CompWindow *w;
 
     MOVE_DISPLAY (d);
 
     switch (event->type) {
     case ButtonPress:
+	w = findClientWindowAtDisplay (d, event->xbutton.window);
+	if (w)
+	{
+	    CompWindow *p;
+	    int        option = MOVE_DISPLAY_OPTION_INITIATE_BUTTON;
+	    int        x = event->xbutton.x_root;
+	    int        y = event->xbutton.y_root;
+
+	    MOVE_WINDOW (w);
+
+	    for (p = w; p; p = p->parent)
+	    {
+		x -= p->attrib.x;
+		y -= p->attrib.y;
+	    }
+
+	    if (event->xbutton.button == mw->button &&
+		movePointInBoxes (x, y,
+				  mw->box, mw->nBox,
+				  w->width, w->height))
+	    {
+		CompOption o[5];
+
+		o[0].type    = CompOptionTypeInt;
+		o[0].name    = "window";
+		o[0].value.i = w->id;
+
+		o[1].type    = CompOptionTypeInt;
+		o[1].name    = "modifiers";
+		o[1].value.i = event->xbutton.state;
+
+		o[2].type    = CompOptionTypeInt;
+		o[2].name    = "x";
+		o[2].value.i = event->xbutton.x_root;
+
+		o[3].type    = CompOptionTypeInt;
+		o[3].name    = "y";
+		o[3].value.i = event->xbutton.y_root;
+
+		o[4].type    = CompOptionTypeInt;
+		o[4].name    = "button";
+		o[4].value.i = event->xbutton.button;
+
+		moveInitiate (d,
+			      &md->opt[option].value.action,
+			      CompActionStateInitButton,
+			      o, 5);
+	    }
+	}
+	break;
     case ButtonRelease:
 	s = findScreenAtDisplay (d, event->xbutton.root);
 	if (s)
@@ -626,8 +811,6 @@ moveHandleEvent (CompDisplay *d,
     case ClientMessage:
 	if (event->xclient.message_type == d->wmMoveResizeAtom)
 	{
-	    CompWindow *w;
-
 	    if (event->xclient.data.l[2] == WmMoveResizeMove ||
 		event->xclient.data.l[2] == WmMoveResizeMoveKeyboard)
 	    {
@@ -658,7 +841,7 @@ moveHandleEvent (CompDisplay *d,
 
 			option = MOVE_DISPLAY_OPTION_INITIATE_BUTTON;
 
-			XQueryPointer (d->display, w->screen->root,
+			XQueryPointer (d->display, w->screen->root.id,
 				       &root, &child, &xRoot, &yRoot,
 				       &i, &i, &mods);
 
@@ -746,6 +929,18 @@ moveHandleEvent (CompDisplay *d,
     UNWRAP (md, d, handleEvent);
     (*d->handleEvent) (d, event);
     WRAP (md, d, handleEvent, moveHandleEvent);
+
+    if (event->type == PropertyNotify)
+    {
+	if (event->xproperty.atom == md->moveAtom)
+	{
+	    CompWindow *w;
+
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w)
+		moveWindowUpdate (w);
+	}
+    }
 }
 
 static Bool
@@ -876,6 +1071,8 @@ moveInitDisplay (CompPlugin  *p,
 	md->key[i] = XKeysymToKeycode (d->display,
 				       XStringToKeysym (mKeys[i].name));
 
+    md->moveAtom = XInternAtom (d->display, "_COMPIZ_WM_WINDOW_MOVE_DECOR", 0);
+
     WRAP (md, d, handleEvent, moveHandleEvent);
 
     d->base.privates[displayPrivateIndex].ptr = md;
@@ -910,6 +1107,13 @@ moveInitScreen (CompPlugin *p,
     if (!ms)
 	return FALSE;
 
+    ms->windowPrivateIndex = allocateWindowPrivateIndex (s);
+    if (ms->windowPrivateIndex < 0)
+    {
+	free (ms);
+	return FALSE;
+    }
+
     ms->grabIndex = 0;
 
     ms->moveCursor = XCreateFontCursor (s->display->display, XC_fleur);
@@ -932,9 +1136,46 @@ moveFiniScreen (CompPlugin *p,
     if (ms->moveCursor)
 	XFreeCursor (s->display->display, ms->moveCursor);
 
+    freeWindowPrivateIndex (s, ms->windowPrivateIndex);
+
     free (ms);
 }
 
+static Bool
+moveInitWindow (CompPlugin *p,
+		CompWindow *w)
+{
+    MoveWindow *mw;
+
+    MOVE_SCREEN (w->screen);
+
+    mw = malloc (sizeof (MoveWindow));
+    if (!mw)
+	return FALSE;
+
+    mw->button = 0;
+    mw->box    = NULL;
+    mw->nBox   = 0;
+
+    w->base.privates[ms->windowPrivateIndex].ptr = mw;
+
+    moveWindowUpdate (w);
+
+    return TRUE;
+}
+
+static void
+moveFiniWindow (CompPlugin *p,
+		CompWindow *w)
+{
+    MOVE_WINDOW (w);
+
+    if (mw->box)
+	free (mw->box);
+
+    free (mw);
+}
+
 static CompBool
 moveInitObject (CompPlugin *p,
 		CompObject *o)
@@ -942,7 +1183,8 @@ moveInitObject (CompPlugin *p,
     static InitPluginObjectProc dispTab[] = {
 	(InitPluginObjectProc) 0, /* InitCore */
 	(InitPluginObjectProc) moveInitDisplay,
-	(InitPluginObjectProc) moveInitScreen
+	(InitPluginObjectProc) moveInitScreen,
+	(InitPluginObjectProc) moveInitWindow
     };
 
     RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
@@ -955,7 +1197,8 @@ moveFiniObject (CompPlugin *p,
     static FiniPluginObjectProc dispTab[] = {
 	(FiniPluginObjectProc) 0, /* FiniCore */
 	(FiniPluginObjectProc) moveFiniDisplay,
-	(FiniPluginObjectProc) moveFiniScreen
+	(FiniPluginObjectProc) moveFiniScreen,
+	(FiniPluginObjectProc) moveFiniWindow
     };
 
     DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
diff --git a/plugins/obs.c b/plugins/obs.c
index bec8136..d526772 100644
--- a/plugins/obs.c
+++ b/plugins/obs.c
@@ -75,7 +75,6 @@ typedef struct _ObsScreen
     int windowPrivateIndex;
 
     PaintWindowProc paintWindow;
-    DrawWindowProc  drawWindow;
 
     CompOption *stepOptions[MODIFIER_COUNT];
     CompOption *matchOptions[MODIFIER_COUNT];
@@ -210,76 +209,32 @@ obsPaintWindow (CompWindow              *w,
 		Region                  region,
 		unsigned int            mask)
 {
-    CompScreen *s = w->screen;
-    Bool       status;
+    WindowPaintAttrib wAttrib = *attrib;
+    CompScreen        *s = w->screen;
+    int               factor;
+    Bool              status;
 
     OBS_SCREEN (s);
     OBS_WINDOW (w);
 
-    if (ow->customFactor[MODIFIER_OPACITY] != 100)
-	mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
-
-    UNWRAP (os, s, paintWindow);
-    status = (*s->paintWindow) (w, attrib, transform, region, mask);
-    WRAP (os, s, paintWindow, obsPaintWindow);
-
-    return status;
-}
-
-/* Note: Normally plugins should wrap into PaintWindow to modify opacity,
-	 brightness and saturation. As some plugins bypass paintWindow when
-	 they draw windows and our custom values always need to be applied,
-	 we wrap into DrawWindow here */
-
-static Bool
-obsDrawWindow (CompWindow           *w,
-	       const CompTransform  *transform,
-	       const FragmentAttrib *attrib,
-	       Region               region,
-	       unsigned int         mask)
-{
-    CompScreen *s = w->screen;
-    Bool       hasCustomFactor = FALSE;
-    Bool       status;
-    int        i;
-
-    OBS_SCREEN (s);
-    OBS_WINDOW (w);
-
-    for (i = 0; i < MODIFIER_COUNT; i++)
-	if (ow->customFactor[i] != 100)
-	{
-	    hasCustomFactor = TRUE;
-	    break;
-	}
-
-    if (hasCustomFactor)
+    factor = ow->customFactor[MODIFIER_OPACITY];
+    if (factor != 100)
     {
-	FragmentAttrib fragment = *attrib;
-	int            factor;
-
-	factor = ow->customFactor[MODIFIER_OPACITY];
-	if (factor != 100)
-	    fragment.opacity = (int) fragment.opacity * factor / 100;
+	wAttrib.opacity = (int) wAttrib.opacity * factor / 100;
+	mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+    }
 
-	factor = ow->customFactor[MODIFIER_BRIGHTNESS];
-	if (factor != 100)
-	    fragment.brightness = (int) fragment.brightness * factor / 100;
+    factor = ow->customFactor[MODIFIER_BRIGHTNESS];
+    if (factor != 100)
+	wAttrib.brightness = (int) wAttrib.brightness * factor / 100;
 
-	factor = ow->customFactor[MODIFIER_SATURATION];
-	if (factor != 100)
-	    fragment.saturation = (int) fragment.saturation * factor / 100;
+    factor = ow->customFactor[MODIFIER_SATURATION];
+    if (factor != 100)
+	wAttrib.saturation = (int) wAttrib.saturation * factor / 100;
 
-	UNWRAP (os, s, drawWindow);
-	status = (*s->drawWindow) (w, transform, &fragment, region, mask);
-	WRAP (os, s, drawWindow, obsDrawWindow);
-    }
-    else
-    {
-	UNWRAP (os, s, drawWindow);
-	status = (*s->drawWindow) (w, transform, attrib, region, mask);
-	WRAP (os, s, drawWindow, obsDrawWindow);
-    }
+    UNWRAP (os, s, paintWindow);
+    status = (*s->paintWindow) (w, &wAttrib, transform, region, mask);
+    WRAP (os, s, paintWindow, obsPaintWindow);
 
     return status;
 }
@@ -299,7 +254,7 @@ obsMatchExpHandlerChanged (CompDisplay *d)
 
     /* match options are up to date after the call to matchExpHandlerChanged */
     for (s = d->screens; s; s = s->next)
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    for (i = 0; i < MODIFIER_COUNT; i++)
 		updatePaintModifier (w, i);
 }
@@ -386,7 +341,7 @@ obsSetScreenOption (CompPlugin      *p,
 		for (j = 0; j < o->value.list.nValue; j++)
 		    matchUpdate (s->display, &o->value.list.value[j].match);
 
-		for (w = s->windows; w; w = w->next)
+		for (w = s->root.windows; w; w = w->next)
 		    updatePaintModifier (w, i);
 
 		return TRUE;
@@ -398,7 +353,7 @@ obsSetScreenOption (CompPlugin      *p,
 	    {
 		CompWindow *w;
 
-		for (w = s->windows; w; w = w->next)
+		for (w = s->root.windows; w; w = w->next)
 		    updatePaintModifier (w, i);
 
 		return TRUE;
@@ -599,7 +554,6 @@ obsInitScreen (CompPlugin *p,
     s->base.privates[od->screenPrivateIndex].ptr = os;
 
     WRAP (os, s, paintWindow, obsPaintWindow);
-    WRAP (os, s, drawWindow, obsDrawWindow);
 
     return TRUE;
 }
@@ -611,7 +565,6 @@ obsFiniScreen (CompPlugin *p,
     OBS_SCREEN (s);
 
     UNWRAP (os, s, paintWindow);
-    UNWRAP (os, s, drawWindow);
 
     damageScreen (s);
     
diff --git a/plugins/place.c b/plugins/place.c
index 596a3a5..cc04180 100644
--- a/plugins/place.c
+++ b/plugins/place.c
@@ -257,7 +257,7 @@ placeSendWindowMaximizationRequest (CompWindow *w)
     xev.xclient.data.l[3] = 0;
     xev.xclient.data.l[4] = 0;
 
-    XSendEvent (d->display, w->screen->root, FALSE,
+    XSendEvent (d->display, w->screen->root.id, FALSE,
 		SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 }
 
@@ -681,7 +681,7 @@ placeCascade (CompWindow *w,
     unsigned int count = 0;
 
     /* get the total window count */
-    for (wi = w->screen->windows; wi; wi = wi->next)
+    for (wi = w->screen->root.windows; wi; wi = wi->next)
 	count++;
 
     windows = malloc (sizeof (CompWindow *) * count);
@@ -692,7 +692,7 @@ placeCascade (CompWindow *w,
      * as placed window, may be shaded - if shaded we pretend it isn't
      * for placement purposes)
      */
-    for (wi = w->screen->windows, count = 0; wi; wi = wi->next)
+    for (wi = w->screen->root.windows, count = 0; wi; wi = wi->next)
     {
 	if (!IS_PLACE_RELEVANT (wi, w))
 	    continue;
@@ -813,7 +813,7 @@ placeSmart (CompWindow *w,
 	    cyt = yTmp;
 	    cyb = yTmp + ch;
 
-	    for (wi = w->screen->windows; wi; wi = wi->next)
+	    for (wi = w->screen->root.windows; wi; wi = wi->next)
 	    {
 		if (!IS_PLACE_RELEVANT (wi, w))
 		    continue;
@@ -871,7 +871,7 @@ placeSmart (CompWindow *w,
 		possible -= cw;
 
 	    /* compare to the position of each client on the same desk */
-	    for (wi = w->screen->windows; wi; wi = wi->next)
+	    for (wi = w->screen->root.windows; wi; wi = wi->next)
 	    {
 		if (!IS_PLACE_RELEVANT (wi, w))
 		    continue;
@@ -906,7 +906,7 @@ placeSmart (CompWindow *w,
 		possible -= ch;
 
 	    /* test the position of each window on the desk */
-	    for (wi = w->screen->windows; wi; wi = wi->next)
+	    for (wi = w->screen->root.windows; wi; wi = wi->next)
 	    {
 		if (!IS_PLACE_RELEVANT (wi, w))
 		    continue;
@@ -1047,7 +1047,7 @@ placeGetPlacementOutput (CompWindow        *w,
 	    /* this means a server roundtrip, which kind of sucks; thus
 	       this code should be replaced as soon as we have software
 	       cursor rendering and thus have a cached pointer coordinate */
-	    if (XQueryPointer (s->display->display, s->root,
+	    if (XQueryPointer (s->display->display, s->root.id,
 			       &wDummy, &wDummy, &xPointer, &yPointer,
 			       &iDummy, &iDummy, &uiDummy))
 	    {
@@ -1443,7 +1443,8 @@ placeInitDisplay (CompPlugin  *p,
 {
     PlaceDisplay *pd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("wm",   CORE_ABIVERSION))
 	return FALSE;
 
     pd = malloc (sizeof (PlaceDisplay));
diff --git a/plugins/resize.c b/plugins/resize.c
index 5b8b12b..d2de79b 100644
--- a/plugins/resize.c
+++ b/plugins/resize.c
@@ -269,7 +269,7 @@ resizeSendResizeNotify (CompDisplay *d)
     xev.xclient.data.l[4] = 0;
 
     XSendEvent (d->display,
-		rd->w->screen->root,
+		rd->w->screen->root.id,
 		FALSE,
 		SubstructureRedirectMask | SubstructureNotifyMask,
 		&xev);
@@ -438,6 +438,10 @@ resizeInitiate (CompDisplay     *d,
 	    }
 	}
 
+	/* only normal resize mode can be used without manual compositing */
+	if (!manualCompositeManagement)
+	    rd->mode = RESIZE_MODE_NORMAL;
+
 	if (!rs->grabIndex)
 	{
 	    Cursor cursor;
@@ -900,7 +904,7 @@ resizeHandleEvent (CompDisplay *d,
 
 			option = RESIZE_DISPLAY_OPTION_INITIATE_BUTTON;
 
-			XQueryPointer (d->display, w->screen->root,
+			XQueryPointer (d->display, w->screen->root.id,
 				       &root, &child, &xRoot, &yRoot,
 				       &i, &i, &mods);
 
diff --git a/plugins/rotate.c b/plugins/rotate.c
index 8b76d4d..1369d62 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -368,7 +368,37 @@ rotatePreparePaintScreen (CompScreen *s,
 		    /* flag end of rotation */
 		    cs->rotationState = RotationNone;
 
-		    moveScreenViewport (s, tx, 0, TRUE);
+		    if (s->root.substructureRedirect)
+		    {
+			moveScreenViewport (s, tx, 0, TRUE);
+		    }
+		    else
+		    {
+			CompDisplay *d = s->display;
+			XEvent      xev;
+
+			xev.xclient.type    = ClientMessage;
+			xev.xclient.display = d->display;
+			xev.xclient.format  = 32;
+
+			xev.xclient.message_type = d->desktopViewportAtom;
+			xev.xclient.window	 = s->root.id;
+
+			xev.xclient.data.l[0] = (s->x - tx) * s->width;
+			xev.xclient.data.l[1] = s->y * s->height;
+			xev.xclient.data.l[2] = 0;
+			xev.xclient.data.l[3] = 0;
+			xev.xclient.data.l[4] = 0;
+
+			XSendEvent (s->display->display,
+				    s->root.id,
+				    FALSE,
+				    SubstructureRedirectMask |
+				    SubstructureNotifyMask,
+				    &xev);
+
+			moveScreenViewport (s, tx, 0, FALSE);
+		    }
 
 		    rs->xrot = 0.0f;
 		    rs->yrot = 0.0f;
@@ -680,7 +710,7 @@ rotateTerminate (CompDisplay     *d,
     {
 	ROTATE_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (rs->grabIndex)
@@ -750,7 +780,7 @@ rotate (CompDisplay     *d,
 
 	    o[2].type	 = CompOptionTypeInt;
 	    o[2].name	 = "root";
-	    o[2].value.i = s->root;
+	    o[2].value.i = s->root.id;
 
 	    rotateInitiate (d, NULL, 0, o, 3);
 	}
@@ -839,7 +869,7 @@ rotateWithWindow (CompDisplay     *d,
 
 	    o[2].type	 = CompOptionTypeInt;
 	    o[2].name	 = "root";
-	    o[2].value.i = s->root;
+	    o[2].value.i = s->root.id;
 
 	    rotateInitiate (d, NULL, 0, o, 3);
 	}
@@ -1014,7 +1044,7 @@ rotateFlipLeft (void *closure)
 
     o[2].type	 = CompOptionTypeInt;
     o[2].name	 = "root";
-    o[2].value.i = s->root;
+    o[2].value.i = s->root.id;
 
     o[3].type	 = CompOptionTypeInt;
     o[3].name	 = "direction";
@@ -1059,7 +1089,7 @@ rotateFlipRight (void *closure)
 
     o[2].type	 = CompOptionTypeInt;
     o[2].name	 = "root";
-    o[2].value.i = s->root;
+    o[2].value.i = s->root.id;
 
     o[3].type	 = CompOptionTypeInt;
     o[3].name	 = "direction";
@@ -1139,7 +1169,7 @@ rotateEdgeFlip (CompScreen      *s,
 
     o[2].type	 = CompOptionTypeInt;
     o[2].name	 = "root";
-    o[2].value.i = s->root;
+    o[2].value.i = s->root.id;
 
     o[3].type	 = CompOptionTypeInt;
     o[3].name	 = "direction";
@@ -1256,7 +1286,7 @@ rotateFlipTerminate (CompDisplay     *d,
     {
 	ROTATE_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (rs->rotateHandle)
@@ -1383,7 +1413,7 @@ rotateTo (CompDisplay     *d,
 
 	o[2].type    = CompOptionTypeInt;
 	o[2].name    = "root";
-	o[2].value.i = s->root;
+	o[2].value.i = s->root.id;
 
 	o[3].type    = CompOptionTypeInt;
 	o[3].name    = "direction";
@@ -1443,7 +1473,7 @@ rotateToWithWindow (CompDisplay     *d,
 
 	o[2].type    = CompOptionTypeInt;
 	o[2].name    = "root";
-	o[2].value.i = s->root;
+	o[2].value.i = s->root.id;
 
 	o[3].type    = CompOptionTypeInt;
 	o[3].name    = "direction";
@@ -1464,6 +1494,7 @@ rotateHandleEvent (CompDisplay *d,
 		   XEvent      *event)
 {
     CompScreen *s;
+    int        dx = 0;
 
     ROTATE_DISPLAY (d);
 
@@ -1512,13 +1543,14 @@ rotateHandleEvent (CompDisplay *d,
 	}
 	break;
     case ClientMessage:
+	if (!windowManagement)
+	    break;
+
 	if (event->xclient.message_type == d->desktopViewportAtom)
 	{
 	    s = findScreenAtDisplay (d, event->xclient.window);
 	    if (s)
 	    {
-		int dx;
-
 		ROTATE_SCREEN (s);
 
 		if (otherScreenGrabExist (s, "rotate", "switcher", "cube", 0))
@@ -1535,7 +1567,7 @@ rotateHandleEvent (CompDisplay *d,
 		    unsigned int ui;
 		    CompOption   o[4];
 
-		    XQueryPointer (d->display, s->root,
+		    XQueryPointer (d->display, s->root.id,
 				   &win, &win, &x, &y, &i, &i, &ui);
 
 		    if (dx * 2 > s->hsize)
@@ -1553,7 +1585,7 @@ rotateHandleEvent (CompDisplay *d,
 
 		    o[2].type	 = CompOptionTypeInt;
 		    o[2].name	 = "root";
-		    o[2].value.i = s->root;
+		    o[2].value.i = s->root.id;
 
 		    o[3].type	 = CompOptionTypeInt;
 		    o[3].name	 = "direction";
@@ -1570,6 +1602,29 @@ rotateHandleEvent (CompDisplay *d,
     UNWRAP (rd, d, handleEvent);
     (*d->handleEvent) (d, event);
     WRAP (rd, d, handleEvent, rotateHandleEvent);
+
+    switch (event->type) {
+    case ClientMessage:
+	if (!dx)
+	    break;
+
+	if (event->xclient.message_type == d->desktopViewportAtom)
+	{
+	    s = findScreenAtDisplay (d, event->xclient.window);
+	    if (s)
+	    {
+		ROTATE_SCREEN (s);
+
+		if (rs->moving)
+		{
+		    rs->moveTo   += (360.0f / s->hsize) * -dx;
+		    rs->baseXrot += (360.0f / s->hsize) * dx;
+		}
+	    }
+	}
+    default:
+	break;
+    }
 }
 
 static void
@@ -1596,7 +1651,7 @@ rotateActivateWindow (CompWindow *w)
 	    unsigned int ui;
 	    CompOption   o[5];
 
-	    XQueryPointer (s->display->display, s->root,
+	    XQueryPointer (s->display->display, s->root.id,
 			   &win, &win, &x, &y, &i, &i, &ui);
 
 	    if (dx * 2 > s->hsize)
@@ -1614,7 +1669,7 @@ rotateActivateWindow (CompWindow *w)
 
 	    o[2].type    = CompOptionTypeInt;
 	    o[2].name    = "root";
-	    o[2].value.i = s->root;
+	    o[2].value.i = s->root.id;
 
 	    o[3].type    = CompOptionTypeInt;
 	    o[3].name    = "direction";
diff --git a/plugins/scale.c b/plugins/scale.c
index 5b4df25..7046b17 100644
--- a/plugins/scale.c
+++ b/plugins/scale.c
@@ -151,7 +151,7 @@ scaleActivateEvent (CompScreen *s,
 
     o[0].type = CompOptionTypeInt;
     o[0].name = "root";
-    o[0].value.i = s->root;
+    o[0].value.i = s->root.id;
 
     o[1].type = CompOptionTypeBool;
     o[1].name = "active";
@@ -313,6 +313,9 @@ setScaledPaintAttributes (CompWindow        *w,
     SCALE_SCREEN (w->screen);
     SCALE_WINDOW (w);
 
+    if (w->parent != &w->screen->root)
+	return FALSE;
+
     if (sw->adjust || sw->slot)
     {
 	SCALE_DISPLAY (w->screen->display);
@@ -379,7 +382,12 @@ scalePaintWindow (CompWindow		  *w,
 	scaled = (*ss->setScaledPaintAttributes) (w, &sAttrib);
 
 	if (sw->adjust || sw->slot)
+	{
+	    if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+		return FALSE;
+
 	    mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
+	}
 
 	UNWRAP (ss, s, paintWindow);
 	status = (*s->paintWindow) (w, &sAttrib, transform, region, mask);
@@ -387,16 +395,7 @@ scalePaintWindow (CompWindow		  *w,
 
 	if (scaled)
 	{
-	    FragmentAttrib fragment;
-	    CompTransform  wTransform = *transform;
-
-	    if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
-		return FALSE;
-
-	    initFragmentAttrib (&fragment, &w->lastPaint);
-
-	    if (w->alpha || fragment.opacity != OPAQUE)
-		mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+	    CompTransform wTransform = *transform;
 
 	    matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
 	    matrixScale (&wTransform, sw->scale, sw->scale, 1.0f);
@@ -405,13 +404,7 @@ scalePaintWindow (CompWindow		  *w,
 			     sw->ty / sw->scale - w->attrib.y,
 			     0.0f);
 
-	    glPushMatrix ();
-	    glLoadMatrixf (wTransform.m);
-
-	    (*s->drawWindow) (w, &wTransform, &fragment, region,
-			      mask | PAINT_WINDOW_TRANSFORMED_MASK);
-
-	    glPopMatrix ();
+	    drawTransformedWindowWithChildren (w, NULL, &wTransform);
 
 	    (*ss->scalePaintDecoration) (w, &sAttrib, transform, region, mask);
 	}
@@ -742,7 +735,7 @@ layoutThumbs (CompScreen *s)
     ss->nWindows = 0;
 
     /* add windows scale list, top most window first */
-    for (w = s->reverseWindows; w; w = w->prev)
+    for (w = s->root.reverseWindows; w; w = w->prev)
     {
 	SCALE_WINDOW (w);
 
@@ -897,7 +890,7 @@ scalePreparePaintScreen (CompScreen *s,
 	{
 	    ss->moreAdjust = 0;
 
-	    for (w = s->windows; w; w = w->next)
+	    for (w = s->root.windows; w; w = w->next)
 	    {
 		SCALE_WINDOW (w);
 
@@ -962,7 +955,7 @@ scaleCheckForWindowAt (CompScreen *s,
     int        x1, y1, x2, y2;
     CompWindow *w;
 
-    for (w = s->reverseWindows; w; w = w->prev)
+    for (w = s->root.reverseWindows; w; w = w->prev)
     {
 	SCALE_WINDOW (w);
 
@@ -1028,7 +1021,7 @@ scaleTerminate (CompDisplay     *d,
     {
 	SCALE_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (ss->grab)
@@ -1048,7 +1041,7 @@ scaleTerminate (CompDisplay     *d,
 	    {
 		CompWindow *w;
 
-		for (w = s->windows; w; w = w->next)
+		for (w = s->root.windows; w; w = w->next)
 		{
 		    SCALE_WINDOW (w);
 
@@ -1102,7 +1095,7 @@ scaleEnsureDndRedirectWindow (CompScreen *s)
 	attr.override_redirect = TRUE;
 
 	ss->dndTarget = XCreateWindow (s->display->display,
-				       s->root,
+				       s->root.id,
 				       0, 0, 1, 1, 0,
 				       CopyFromParent,
 				       InputOnly,
@@ -1420,7 +1413,7 @@ scaleMoveFocusWindow (CompScreen *s,
 	    cx = (sw->slot->x1 + sw->slot->x2) / 2;
 	    cy = (sw->slot->y1 + sw->slot->y2) / 2;
 
-	    for (w = s->windows; w; w = w->next)
+	    for (w = s->root.windows; w; w = w->next)
 	    {
 		slot = GET_SCALE_WINDOW (w, ss)->slot;
 		if (!slot)
@@ -1453,7 +1446,7 @@ scaleMoveFocusWindow (CompScreen *s,
 
 	SCALE_SCREEN (s);
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    if (!GET_SCALE_WINDOW (w, ss)->slot)
 		continue;
@@ -1548,7 +1541,7 @@ scaleWindowRemove (CompDisplay *d,
 
 			o.type    = CompOptionTypeInt;
 			o.name    = "root";
-			o.value.i = w->screen->root;
+			o.value.i = w->screen->root.id;
 
 			opt = SCALE_DISPLAY_OPTION_INITIATE_EDGE;
 			action = &sd->opt[opt].value.action;
@@ -1592,7 +1585,7 @@ scaleHoverTimeout (void *closure)
 
 	o.type    = CompOptionTypeInt;
 	o.name    = "root";
-	o.value.i = s->root;
+	o.value.i = s->root.id;
 
 	option = SCALE_DISPLAY_OPTION_INITIATE_EDGE;
 	scaleTerminate (s->display, &sd->opt[option].value.action, 0, &o, 1);
@@ -1649,7 +1642,7 @@ scaleHandleEvent (CompDisplay *d,
 
 		    o.type    = CompOptionTypeInt;
 		    o.name    = "root";
-		    o.value.i = s->root;
+		    o.value.i = s->root.id;
 
 		    if (scaleSelectWindowAt (s,
 					     event->xbutton.x_root,
@@ -1788,7 +1781,7 @@ scaleHandleEvent (CompDisplay *d,
 
 		    o.type    = CompOptionTypeInt;
 		    o.name    = "root";
-		    o.value.i = w->screen->root;
+		    o.value.i = w->screen->root.id;
 
 		    option = SCALE_DISPLAY_OPTION_INITIATE_EDGE;
 		    scaleTerminate (d, &sd->opt[option].value.action,
@@ -1926,7 +1919,8 @@ scaleInitDisplay (CompPlugin  *p,
 {
     ScaleDisplay *sd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     sd = malloc (sizeof (ScaleDisplay));
diff --git a/plugins/screenshot.c b/plugins/screenshot.c
index 74f44ba..899b2f0 100644
--- a/plugins/screenshot.c
+++ b/plugins/screenshot.c
@@ -122,7 +122,7 @@ shotTerminate (CompDisplay     *d,
     {
 	SHOT_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (ss->grabIndex)
@@ -436,7 +436,8 @@ shotInitDisplay (CompPlugin  *p,
 {
     ShotDisplay *sd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     sd = malloc (sizeof (ShotDisplay));
diff --git a/plugins/svg.c b/plugins/svg.c
index bd39174..0ebebbf 100644
--- a/plugins/svg.c
+++ b/plugins/svg.c
@@ -178,7 +178,7 @@ initSvgTexture (CompWindow *w,
 	XGetWindowAttributes (s->display->display, w->id, &attr);
 
 	depth = attr.depth;
-	texture->pixmap = XCreatePixmap (s->display->display, s->root,
+	texture->pixmap = XCreatePixmap (s->display->display, s->root.id,
 					 width, height, depth);
 
 	if (!bindPixmapToTexture (s,
@@ -795,7 +795,8 @@ svgInitDisplay (CompPlugin  *p,
     SvgDisplay *sd;
     CompScreen *s;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     sd = malloc (sizeof (SvgDisplay));
diff --git a/plugins/switcher.c b/plugins/switcher.c
index 13be8ad..b0acfec 100644
--- a/plugins/switcher.c
+++ b/plugins/switcher.c
@@ -328,7 +328,7 @@ switchActivateEvent (CompScreen *s,
 
     o[0].type = CompOptionTypeInt;
     o[0].name = "root";
-    o[0].value.i = s->root;
+    o[0].value.i = s->root.id;
 
     o[1].type = CompOptionTypeBool;
     o[1].name = "active";
@@ -415,7 +415,7 @@ switchCreateWindowList (CompScreen *s,
 
     ss->nWindows = 0;
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if (isSwitchWin (w))
 	    switchAddWindowToList (s, w);
@@ -475,7 +475,7 @@ switchToWindow (CompScreen *s,
 	    xev.xclient.format = 32;
 
 	    xev.xclient.message_type = s->display->desktopViewportAtom;
-	    xev.xclient.window = s->root;
+	    xev.xclient.window = s->root.id;
 
 	    xev.xclient.data.l[0] = x * s->width;
 	    xev.xclient.data.l[1] = y * s->height;
@@ -483,7 +483,7 @@ switchToWindow (CompScreen *s,
 	    xev.xclient.data.l[3] = 0;
 	    xev.xclient.data.l[4] = 0;
 
-	    XSendEvent (s->display->display, s->root, FALSE,
+	    XSendEvent (s->display->display, s->root.id, FALSE,
 			SubstructureRedirectMask | SubstructureNotifyMask,
 			&xev);
 	}
@@ -532,7 +532,7 @@ switchCountWindows (CompScreen *s)
     CompWindow *w;
     int	       count = 0;
 
-    for (w = s->windows; w && count < 5; w = w->next)
+    for (w = s->root.windows; w && count < 5; w = w->next)
 	if (isSwitchWin (w))
 	    count++;
 
@@ -600,7 +600,7 @@ switchInitiate (CompScreen            *s,
     if (count < 1)
 	return;
 
-    if (!ss->popupWindow && showPopup)
+    if (!ss->popupWindow && showPopup && s->root.substructureRedirect)
     {
 	Display		     *dpy = s->display->display;
 	XSizeHints	     xsh;
@@ -635,11 +635,11 @@ switchInitiate (CompScreen            *s,
 
 	attr.background_pixel = 0;
 	attr.border_pixel     = 0;
-	attr.colormap	      = XCreateColormap (dpy, s->root, visual,
+	attr.colormap	      = XCreateColormap (dpy, s->root.id, visual,
 						 AllocNone);
 
 	ss->popupWindow =
-	    XCreateWindow (dpy, s->root,
+	    XCreateWindow (dpy, s->root.id,
 			   s->width  / 2 - xsh.width / 2,
 			   s->height / 2 - xsh.height / 2,
 			   xsh.width, xsh.height, 0,
@@ -727,7 +727,7 @@ switchTerminate (CompDisplay     *d,
     {
 	SWITCH_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (ss->grabIndex)
@@ -989,7 +989,7 @@ switchWindowRemove (CompDisplay *d,
 
 	    o.type    = CompOptionTypeInt;
 	    o.name    = "root";
-	    o.value.i = w->screen->root;
+	    o.value.i = w->screen->root.id;
 
 	    switchTerminate (d, NULL, 0, &o, 1);
 	    return;
@@ -1322,8 +1322,9 @@ switchPaintOutput (CompScreen		   *s,
 		for (w = zoomed->prev; w && w->id <= 1; w = w->prev);
 		zoomedAbove = (w) ? w->id : None;
 
-		unhookWindowFromScreen (s, zoomed);
-		insertWindowIntoScreen (s, zoomed, s->reverseWindows->id);
+		unhookWindow (zoomed->parent, zoomed);
+		insertWindow (zoomed->parent, zoomed,
+			      zoomed->parent->reverseWindows->id);
 	    }
 	}
 	else
@@ -1356,8 +1357,8 @@ switchPaintOutput (CompScreen		   *s,
 
 	if (zoomed)
 	{
-	    unhookWindowFromScreen (s, zoomed);
-	    insertWindowIntoScreen (s, zoomed, zoomedAbove);
+	    unhookWindow (zoomed->parent, zoomed);
+	    insertWindow (zoomed->parent, zoomed, zoomedAbove);
 	}
 
 	if (switcher)
@@ -1445,7 +1446,6 @@ switchPaintThumb (CompWindow		  *w,
     if (w->texture->pixmap)
     {
 	AddWindowGeometryProc oldAddWindowGeometry;
-	FragmentAttrib	      fragment;
 	CompTransform	      wTransform = *transform;
 	int		      ww, wh;
 
@@ -1481,11 +1481,6 @@ switchPaintThumb (CompWindow		  *w,
 	sAttrib.xTranslate = wx - w->attrib.x + w->input.left * sAttrib.xScale;
 	sAttrib.yTranslate = wy - w->attrib.y + w->input.top  * sAttrib.yScale;
 
-	initFragmentAttrib (&fragment, &sAttrib);
-
-	if (w->alpha || fragment.opacity != OPAQUE)
-	    mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
-
 	matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
 	matrixScale (&wTransform, sAttrib.xScale, sAttrib.yScale, 1.0f);
 	matrixTranslate (&wTransform,
@@ -1493,20 +1488,14 @@ switchPaintThumb (CompWindow		  *w,
 			 sAttrib.yTranslate / sAttrib.yScale - w->attrib.y,
 			 0.0f);
 
-	glPushMatrix ();
-	glLoadMatrixf (wTransform.m);
-
 	/* XXX: replacing the addWindowGeometry function like this is
 	   very ugly but necessary until the vertex stage has been made
 	   fully pluggable. */
 	oldAddWindowGeometry = w->screen->addWindowGeometry;
 	w->screen->addWindowGeometry = addWindowGeometry;
-	(w->screen->drawWindow) (w, &wTransform, &fragment, &infiniteRegion,
-				 mask);
+	drawTransformedWindowWithChildren (w, &sAttrib, &wTransform);
 	w->screen->addWindowGeometry = oldAddWindowGeometry;
 
-	glPopMatrix ();
-
 	if (ss->opt[SWITCH_SCREEN_OPTION_ICON].value.b)
 	{
 	    icon = getWindowIcon (w, ICON_SIZE, ICON_SIZE);
@@ -1634,6 +1623,12 @@ switchPaintWindow (CompWindow		   *w,
 	status = (*s->paintWindow) (w, attrib, transform, region, mask);
 	WRAP (ss, s, paintWindow, switchPaintWindow);
 
+	if (w->attrib.map_state != IsViewable)
+	    return status;
+
+	if (!w->damaged)
+	    return status;
+
 	if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK) && region->numRects == 0)
 	    return TRUE;
 
@@ -1708,44 +1703,53 @@ switchPaintWindow (CompWindow		   *w,
 	status = (*s->paintWindow) (w, attrib, transform, region, mask);
 	WRAP (ss, s, paintWindow, switchPaintWindow);
     }
-    else if (ss->switching)
+    else if (w->parent == &s->root)
     {
-	WindowPaintAttrib sAttrib = *attrib;
-	GLuint            value;
-
-	value = ss->opt[SWITCH_SCREEN_OPTION_SATURATION].value.i;
-	if (value != 100)
-	    sAttrib.saturation = sAttrib.saturation * value / 100;
+	if (ss->switching)
+	{
+	    WindowPaintAttrib sAttrib = *attrib;
+	    GLuint            value;
 
-	value = ss->opt[SWITCH_SCREEN_OPTION_BRIGHTNESS].value.i;
-	if (value != 100)
-	    sAttrib.brightness = sAttrib.brightness * value / 100;
+	    value = ss->opt[SWITCH_SCREEN_OPTION_SATURATION].value.i;
+	    if (value != 100)
+		sAttrib.saturation = sAttrib.saturation * value / 100;
 
-	if (w->wmType & ~(CompWindowTypeDockMask | CompWindowTypeDesktopMask))
-	{
-	    value = ss->opt[SWITCH_SCREEN_OPTION_OPACITY].value.i;
+	    value = ss->opt[SWITCH_SCREEN_OPTION_BRIGHTNESS].value.i;
 	    if (value != 100)
-		sAttrib.opacity = sAttrib.opacity * value / 100;
-	}
+		sAttrib.brightness = sAttrib.brightness * value / 100;
 
-	if (ss->opt[SWITCH_SCREEN_OPTION_BRINGTOFRONT].value.b &&
-	    w->id == ss->zoomedWindow)
-	    zoomType = ZOOMED_WINDOW_MASK;
+	    if (w->wmType & ~(CompWindowTypeDockMask | CompWindowTypeDesktopMask))
+	    {
+		value = ss->opt[SWITCH_SCREEN_OPTION_OPACITY].value.i;
+		if (value != 100)
+		    sAttrib.opacity = sAttrib.opacity * value / 100;
+	    }
 
-	if (!(ss->zoomMask & zoomType))
-	    return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
-		FALSE : TRUE;
+	    if (ss->opt[SWITCH_SCREEN_OPTION_BRINGTOFRONT].value.b &&
+		w->id == ss->zoomedWindow)
+		zoomType = ZOOMED_WINDOW_MASK;
 
-	UNWRAP (ss, s, paintWindow);
-	status = (*s->paintWindow) (w, &sAttrib, transform, region, mask);
-	WRAP (ss, s, paintWindow, switchPaintWindow);
+	    if (!(ss->zoomMask & zoomType))
+		return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
+		    FALSE : TRUE;
+
+	    UNWRAP (ss, s, paintWindow);
+	    status = (*s->paintWindow) (w, &sAttrib, transform, region, mask);
+	    WRAP (ss, s, paintWindow, switchPaintWindow);
+	}
+	else
+	{
+	    if (!(ss->zoomMask & zoomType))
+		return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
+		    FALSE : TRUE;
+
+	    UNWRAP (ss, s, paintWindow);
+	    status = (*s->paintWindow) (w, attrib, transform, region, mask);
+	    WRAP (ss, s, paintWindow, switchPaintWindow);
+	}
     }
     else
     {
-	if (!(ss->zoomMask & zoomType))
-	    return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
-		FALSE : TRUE;
-
 	UNWRAP (ss, s, paintWindow);
 	status = (*s->paintWindow) (w, attrib, transform, region, mask);
 	WRAP (ss, s, paintWindow, switchPaintWindow);
@@ -1843,7 +1847,8 @@ switchInitDisplay (CompPlugin  *p,
 {
     SwitchDisplay *sd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     sd = malloc (sizeof (SwitchDisplay));
diff --git a/plugins/video.c b/plugins/video.c
index b95eb6b..6364e08 100644
--- a/plugins/video.c
+++ b/plugins/video.c
@@ -190,7 +190,7 @@ videoSetSupportedHint (CompScreen *s)
 	    data[n++] = vd->videoImageFormatAtom[i];
     }
 
-    XChangeProperty (s->display->display, s->root,
+    XChangeProperty (s->display->display, s->root.id,
 		     vd->videoSupportedAtom, XA_ATOM, 32,
 		     PropModeReplace, (unsigned char *) data, n);
 }
@@ -939,7 +939,7 @@ videoHandleEvent (CompDisplay *d,
 		    {
 			vs = GET_VIDEO_SCREEN (s, vd);
 
-			for (w = s->windows; w; w = w->next)
+			for (w = s->root.windows; w; w = w->next)
 			{
 			    if (w->shaded || w->mapNum)
 			    {
@@ -1045,7 +1045,8 @@ videoInitDisplay (CompPlugin  *p,
 {
     VideoDisplay *vd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     vd = malloc (sizeof (VideoDisplay));
@@ -1164,7 +1165,7 @@ videoFiniScreen (CompPlugin *p,
 
     freeWindowPrivateIndex (s, vs->windowPrivateIndex);
 
-    XDeleteProperty (s->display->display, s->root, vd->videoSupportedAtom);
+    XDeleteProperty (s->display->display, s->root.id, vd->videoSupportedAtom);
 
     videoDestroyFragmentFunctions (s, &vs->yv12Functions);
 
diff --git a/plugins/water.c b/plugins/water.c
index ef2f191..485060d 100644
--- a/plugins/water.c
+++ b/plugins/water.c
@@ -1040,6 +1040,7 @@ waterDrawWindowTexture (CompWindow	     *w,
 	Bool	       lighting = w->screen->lighting;
 	int	       param, function, unit;
 	GLfloat	       plane[4];
+	CompWindow     *p;
 
 	WATER_DISPLAY (w->screen->display);
 
@@ -1049,6 +1050,17 @@ waterDrawWindowTexture (CompWindow	     *w,
 	function = getBumpMapFragmentFunction (w->screen, texture, unit, param);
 	if (function)
 	{
+	    float dx = ws->tx / (GLfloat) w->screen->width;
+	    float dy = ws->ty / (GLfloat) w->screen->height;
+	    int   wx = 0;
+	    int   wy = 0;
+
+	    for (p = w->parent; p; p = p->parent)
+	    {
+		wx += p->attrib.x;
+		wy += p->attrib.y;
+	    }
+
 	    addFragmentFunction (&fa, function);
 
 	    screenLighting (w->screen, TRUE);
@@ -1058,16 +1070,16 @@ waterDrawWindowTexture (CompWindow	     *w,
 	    glBindTexture (ws->target, ws->texture[TINDEX (ws, 0)]);
 
 	    plane[1] = plane[2] = 0.0f;
-	    plane[0] = ws->tx / (GLfloat) w->screen->width;
-	    plane[3] = 0.0f;
+	    plane[0] = dx;
+	    plane[3] = dx * wx;
 
 	    glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
 	    glTexGenfv (GL_S, GL_EYE_PLANE, plane);
 	    glEnable (GL_TEXTURE_GEN_S);
 
 	    plane[0] = plane[2] = 0.0f;
-	    plane[1] = ws->ty / (GLfloat) w->screen->height;
-	    plane[3] = 0.0f;
+	    plane[1] = dy;
+	    plane[3] = dy * wy;
 
 	    glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
 	    glTexGenfv (GL_T, GL_EYE_PLANE, plane);
@@ -1268,7 +1280,8 @@ waterInitiate (CompDisplay     *d,
 	if (!ws->grabIndex)
 	    ws->grabIndex = pushScreenGrab (s, None, "water");
 
-	if (XQueryPointer (d->display, s->root, &root, &child, &xRoot, &yRoot,
+	if (XQueryPointer (d->display, s->root.id, &root, &child,
+			   &xRoot, &yRoot,
 			   &i, &i, &ui))
 	{
 	    XPoint p;
@@ -1594,7 +1607,8 @@ waterInitDisplay (CompPlugin  *p,
 {
     WaterDisplay *wd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     wd = malloc (sizeof (WaterDisplay));
diff --git a/plugins/wm.c b/plugins/wm.c
new file mode 100644
index 0000000..e797c36
--- /dev/null
+++ b/plugins/wm.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <compiz-core.h>
+
+static CompMetadata wmMetadata;
+
+static CompOption *
+wmGetDisplayOptions (CompPlugin  *plugin,
+		     CompDisplay *display,
+		     int	 *count)
+{
+    *count = 1;
+    return &display->opt[COMP_DISPLAY_OPTION_ABI];
+}
+
+static Bool
+wmInitDisplay (CompPlugin  *p,
+	       CompDisplay *d)
+{
+    if (!checkPluginABI ("core", CORE_ABIVERSION))
+	return FALSE;
+
+    if (windowManagement)
+	return TRUE;
+
+    if (d->screens)
+    {
+	compLogMessage (p->vTable->name, CompLogLevelError,
+			"%s plugin must be loaded before screens are "
+			"initialize", p->vTable->name);
+	return FALSE;
+    }
+
+    windowManagement = TRUE;
+
+    return TRUE;
+}
+
+static CompBool
+wmInitObject (CompPlugin *p,
+	      CompObject *o)
+{
+    static InitPluginObjectProc dispTab[] = {
+	(InitPluginObjectProc) 0, /* InitCore */
+	(InitPluginObjectProc) wmInitDisplay
+    };
+
+    RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static CompOption *
+wmGetObjectOptions (CompPlugin *plugin,
+		    CompObject *object,
+		    int	       *count)
+{
+    static GetPluginObjectOptionsProc dispTab[] = {
+	(GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
+	(GetPluginObjectOptionsProc) wmGetDisplayOptions
+    };
+
+    RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
+		     (void *) (*count = 0), (plugin, object, count));
+}
+
+static Bool
+wmInit (CompPlugin *p)
+{
+    if (!compInitPluginMetadataFromInfo (&wmMetadata, p->vTable->name,
+					 0, 0, 0, 0))
+	return FALSE;
+
+    compAddMetadataFromFile (&wmMetadata, p->vTable->name);
+
+    return TRUE;
+}
+
+static void
+wmFini (CompPlugin *p)
+{
+    compFiniMetadata (&wmMetadata);
+}
+
+static CompMetadata *
+wmGetMetadata (CompPlugin *plugin)
+{
+    return &wmMetadata;
+}
+
+CompPluginVTable wmVTable = {
+    "wm",
+    wmGetMetadata,
+    wmInit,
+    wmFini,
+    wmInitObject,
+    0, /* FiniObject */
+    wmGetObjectOptions,
+    0  /* SetObjectOption */
+};
+
+CompPluginVTable *
+getCompPluginInfo20070830 (void)
+{
+    return &wmVTable;
+}
diff --git a/plugins/wobbly.c b/plugins/wobbly.c
index d05c983..9b511a7 100644
--- a/plugins/wobbly.c
+++ b/plugins/wobbly.c
@@ -161,6 +161,12 @@ typedef struct _WobblyScreen {
     unsigned int grabMask;
     CompWindow	 *grabWindow;
     Bool         moveWindow;
+
+    Model *model;
+    int   x;
+    int   y;
+    float width;
+    float height;
 } WobblyScreen;
 
 #define WobblyInitial  (1L << 0)
@@ -270,7 +276,7 @@ findNextWestEdge (CompWindow *w,
 
 	v1 = w->screen->outputDev[output].region.extents.x1;
 
-	for (p = w->screen->windows; p; p = p->next)
+	for (p = w->parent->windows; p; p = p->next)
 	{
 	    if (w == p)
 		continue;
@@ -375,7 +381,7 @@ findNextEastEdge (CompWindow *w,
 
 	v1 = w->screen->outputDev[output].region.extents.x2;
 
-	for (p = w->screen->windows; p; p = p->next)
+	for (p = w->parent->windows; p; p = p->next)
 	{
 	    if (w == p)
 		continue;
@@ -480,7 +486,7 @@ findNextNorthEdge (CompWindow *w,
 
 	v1 = w->screen->outputDev[output].region.extents.y1;
 
-	for (p = w->screen->windows; p; p = p->next)
+	for (p = w->parent->windows; p; p = p->next)
 	{
 	    if (w == p)
 		continue;
@@ -583,7 +589,7 @@ findNextSouthEdge (CompWindow *w,
 
 	v1 = w->screen->outputDev[output].region.extents.y2;
 
-	for (p = w->screen->windows; p; p = p->next)
+	for (p = w->parent->windows; p; p = p->next)
 	{
 	    if (w == p)
 		continue;
@@ -1656,7 +1662,8 @@ wobblyPreparePaintScreen (CompScreen *s,
 	springK  = ws->opt[WOBBLY_SCREEN_OPTION_SPRING_K].value.f;
 
 	ws->wobblyWindows = 0;
-	for (w = s->windows; w; w = w->next)
+	w = s->root.windows;
+	for (;;)
 	{
 	    ww = GET_WOBBLY_WINDOW (w, ws);
 
@@ -1738,6 +1745,20 @@ wobblyPreparePaintScreen (CompScreen *s,
 
 		ws->wobblyWindows |= ww->wobbly;
 	    }
+
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+		w = w->parent;
+
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
 	}
     }
 
@@ -1806,19 +1827,17 @@ wobblyAddWindowGeometry (CompWindow *w,
 			 Region     region,
 			 Region     clip)
 {
-    WOBBLY_WINDOW (w);
     WOBBLY_SCREEN (w->screen);
 
-    if (ww->wobbly)
+    if (ws->model)
     {
-	BoxPtr   pClip;
-	int      nClip, nVertices, nIndices;
+	BoxPtr   pClip, pBox;
+	int      nClip, nBox, nVertices, nIndices;
 	GLushort *i;
 	GLfloat  *v;
 	int      x1, y1, x2, y2;
-	float    width, height;
 	float    deformedX, deformedY;
-	int      x, y, iw, ih, wx, wy;
+	int      x, y, iw, ih;
 	int      vSize, it;
 	int      gridW, gridH;
 	Bool     rect = TRUE;
@@ -1832,21 +1851,16 @@ wobblyAddWindowGeometry (CompWindow *w,
 	    }
 	}
 
-	wx     = WIN_X (w);
-	wy     = WIN_Y (w);
-	width  = WIN_W (w);
-	height = WIN_H (w);
-
-	gridW = width / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
+	gridW = ws->width / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
 	if (gridW < ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i)
 	    gridW = ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i;
 
-	gridH = height / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
+	gridH = ws->height / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
 	if (gridH < ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i)
 	    gridH = ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i;
 
-	nClip = region->numRects;
-	pClip = region->rects;
+	nBox = region->numRects;
+	pBox = region->rects;
 
 	w->texUnits = nMatrix;
 
@@ -1858,96 +1872,117 @@ wobblyAddWindowGeometry (CompWindow *w,
 	v = w->vertices + (nVertices * vSize);
 	i = w->indices  + nIndices;
 
-	while (nClip--)
+	while (nBox--)
 	{
-	    x1 = pClip->x1;
-	    y1 = pClip->y1;
-	    x2 = pClip->x2;
-	    y2 = pClip->y2;
+	    nClip = clip->numRects;
+	    pClip = clip->rects;
 
-	    iw = ((x2 - x1 - 1) / gridW) + 1;
-	    ih = ((y2 - y1 - 1) / gridH) + 1;
-
-	    if (nIndices + (iw * ih * 4) > w->indexSize)
+	    while (nClip--)
 	    {
-		if (!moreWindowIndices (w, nIndices + (iw * ih * 4)))
-		    return;
-
-		i = w->indices + nIndices;
-	    }
-
-	    iw++;
-	    ih++;
-
-	    for (y = 0; y < ih - 1; y++)
-	    {
-		for (x = 0; x < iw - 1; x++)
+		x1 = pClip->x1;
+		y1 = pClip->y1;
+		x2 = pClip->x2;
+		y2 = pClip->y2;
+
+		if (x1 < pBox->x1)
+		    x1 = pBox->x1;
+		if (y1 < pBox->y1)
+		    y1 = pBox->y1;
+		if (x2 > pBox->x2)
+		    x2 = pBox->x2;
+		if (y2 > pBox->y2)
+		    y2 = pBox->y2;
+
+		if (x1 < x2 && y1 < y2)
 		{
-		    *i++ = nVertices + iw * (y + 1) + x;
-		    *i++ = nVertices + iw * (y + 1) + x + 1;
-		    *i++ = nVertices + iw * y + x + 1;
-		    *i++ = nVertices + iw * y + x;
-
-		    nIndices += 4;
-		}
-	    }
-
-	    if (((nVertices + iw * ih) * vSize) > w->vertexSize)
-	    {
-		if (!moreWindowVertices (w, (nVertices + iw * ih) * vSize))
-		    return;
-
-		v = w->vertices + (nVertices * vSize);
-	    }
+		    iw = ((x2 - x1 - 1) / gridW) + 1;
+		    ih = ((y2 - y1 - 1) / gridH) + 1;
 
-	    for (y = y1;; y += gridH)
-	    {
-		if (y > y2)
-		    y = y2;
+		    if (nIndices + (iw * ih * 4) > w->indexSize)
+		    {
+			if (!moreWindowIndices (w, nIndices + (iw * ih * 4)))
+			    return;
 
-		for (x = x1;; x += gridW)
-		{
-		    if (x > x2)
-			x = x2;
+			i = w->indices + nIndices;
+		    }
 
-		    bezierPatchEvaluate (ww->model,
-					 (x - wx) / width,
-					 (y - wy) / height,
-					 &deformedX,
-					 &deformedY);
+		    iw++;
+		    ih++;
 
-		    if (rect)
+		    for (y = 0; y < ih - 1; y++)
 		    {
-			for (it = 0; it < nMatrix; it++)
+			for (x = 0; x < iw - 1; x++)
 			{
-			    *v++ = COMP_TEX_COORD_X (&matrix[it], x);
-			    *v++ = COMP_TEX_COORD_Y (&matrix[it], y);
+			    *i++ = nVertices + iw * (y + 1) + x;
+			    *i++ = nVertices + iw * (y + 1) + x + 1;
+			    *i++ = nVertices + iw * y + x + 1;
+			    *i++ = nVertices + iw * y + x;
+
+			    nIndices += 4;
 			}
 		    }
-		    else
+
+		    if (((nVertices + iw * ih) * vSize) > w->vertexSize)
 		    {
-			for (it = 0; it < nMatrix; it++)
-			{
-			    *v++ = COMP_TEX_COORD_XY (&matrix[it], x, y);
-			    *v++ = COMP_TEX_COORD_YX (&matrix[it], x, y);
-			}
+			if (!moreWindowVertices (w,
+						 (nVertices + iw * ih) * vSize))
+			    return;
+
+			v = w->vertices + (nVertices * vSize);
 		    }
 
-		    *v++ = deformedX;
-		    *v++ = deformedY;
-		    *v++ = 0.0;
+		    for (y = y1;; y += gridH)
+		    {
+			if (y > y2)
+			    y = y2;
 
-		    nVertices++;
+			for (x = x1;; x += gridW)
+			{
+			    if (x > x2)
+				x = x2;
+
+			    bezierPatchEvaluate (ws->model,
+						 (x - ws->x) / ws->width,
+						 (y - ws->y) / ws->height,
+						 &deformedX,
+						 &deformedY);
+
+			    if (rect)
+			    {
+				for (it = 0; it < nMatrix; it++)
+				{
+				    *v++ = COMP_TEX_COORD_X (&matrix[it], x);
+				    *v++ = COMP_TEX_COORD_Y (&matrix[it], y);
+				}
+			    }
+			    else
+			    {
+				for (it = 0; it < nMatrix; it++)
+				{
+				    *v++ = COMP_TEX_COORD_XY (&matrix[it], x, y);
+				    *v++ = COMP_TEX_COORD_YX (&matrix[it], x, y);
+				}
+			    }
+
+			    *v++ = deformedX;
+			    *v++ = deformedY;
+			    *v++ = 0.0;
+
+			    nVertices++;
+
+			    if (x == x2)
+				break;
+			}
 
-		    if (x == x2)
-			break;
+			if (y == y2)
+			    break;
+		    }
 		}
-
-		if (y == y2)
-		    break;
+		
+		pClip++;
 	    }
 
-	    pClip++;
+	    pBox++;
 	}
 
 	w->vCount	      = nVertices;
@@ -1964,6 +1999,53 @@ wobblyAddWindowGeometry (CompWindow *w,
     }
 }
 
+static void
+wobblyDrawSubWindows (CompWindow          *w,
+		      const CompTransform *transform,
+		      Region              region,
+		      int                 mask)
+{
+    CompWindow *c;
+
+    for (c = w->windows; c; c = c->next)
+    {
+	FragmentAttrib fragment;
+	unsigned int   wMask = mask;
+
+	initFragmentAttrib (&fragment, &c->lastPaint);
+
+	if (c->alpha || fragment.opacity != OPAQUE)
+	    wMask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+	(*w->screen->drawWindow) (c, transform, &fragment, region, wMask);
+
+	if (c->windows)
+	{
+	    Region r;
+
+	    r = XCreateRegion ();
+	    if (r)
+	    {
+		WOBBLY_SCREEN (w->screen);
+
+		XSubtractRegion (region, &emptyRegion, r);
+		XIntersectRegion (r, c->region, r);
+		XOffsetRegion (r, -c->attrib.x, -c->attrib.y);
+
+		ws->x -= c->attrib.x;
+		ws->y -= c->attrib.y;
+
+		wobblyDrawSubWindows (c, transform, r, mask);
+
+		ws->x += c->attrib.x;
+		ws->y += c->attrib.y;
+
+		XDestroyRegion (r);
+	    }
+	}
+    }
+}
+
 static Bool
 wobblyPaintWindow (CompWindow		   *w,
 		   const WindowPaintAttrib *attrib,
@@ -1971,17 +2053,69 @@ wobblyPaintWindow (CompWindow		   *w,
 		   Region		   region,
 		   unsigned int		   mask)
 {
-    Bool status;
+    CompScreen *s = w->screen;
+    Bool       status;
 
-    WOBBLY_SCREEN (w->screen);
+    WOBBLY_SCREEN (s);
     WOBBLY_WINDOW (w);
 
     if (ww->wobbly)
-	mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+    {
+	FragmentAttrib fragment;
+
+	if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+	    return FALSE;
+
+	UNWRAP (ws, s, paintWindow);
+	status = (*s->paintWindow) (w, attrib, transform, region,
+				    mask | PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
+	WRAP (ws, s, paintWindow, wobblyPaintWindow);
+
+	glPushMatrix ();
+	glLoadMatrixf (transform->m);
+
+	ws->model  = ww->model;
+	ws->x      = WIN_X (w);
+	ws->y      = WIN_Y (w);
+	ws->width  = WIN_W (w);
+	ws->height = WIN_H (w);
+
+	initFragmentAttrib (&fragment, &w->lastPaint);
+
+	if (w->alpha || fragment.opacity != OPAQUE)
+	    mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+	(*s->drawWindow) (w,
+			  transform,
+			  &fragment,
+			  region,
+			  mask | PAINT_WINDOW_TRANSFORMED_MASK);
+
+	if (w->windows)
+	{
+	    XOffsetRegion (w->region, -w->attrib.x, -w->attrib.y);
 
-    UNWRAP (ws, w->screen, paintWindow);
-    status = (*w->screen->paintWindow) (w, attrib, transform, region, mask);
-    WRAP (ws, w->screen, paintWindow, wobblyPaintWindow);
+	    ws->x -= w->attrib.x;
+	    ws->y -= w->attrib.y;
+	    
+	    wobblyDrawSubWindows (w,
+				  transform,
+				  w->region,
+				  PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
+
+	    XOffsetRegion (w->region, w->attrib.x, w->attrib.y);
+	}
+
+	ws->model = NULL;
+
+	glPopMatrix ();
+    }
+    else
+    {
+	UNWRAP (ws, s, paintWindow);
+	status = (*s->paintWindow) (w, attrib, transform, region, mask);
+	WRAP (ws, s, paintWindow, wobblyPaintWindow);
+    }
 
     return status;
 }
@@ -2000,12 +2134,27 @@ wobblyEnableSnapping (CompDisplay     *d,
 
     for (s = d->screens; s; s = s->next)
     {
-	for (w = s->windows; w; w = w->next)
+	w = s->root.windows;
+	for (;;)
 	{
 	    WOBBLY_WINDOW (w);
 
 	    if (ww->grabbed && ww->model)
 		modelUpdateSnapping (w, ww->model);
+
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+		w = w->parent;
+
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
 	}
     }
 
@@ -2031,7 +2180,8 @@ wobblyDisableSnapping (CompDisplay     *d,
 
     for (s = d->screens; s; s = s->next)
     {
-	for (w = s->windows; w; w = w->next)
+	w = s->root.windows;
+	for (;;)
 	{
 	    WOBBLY_WINDOW (w);
 
@@ -2047,6 +2197,20 @@ wobblyDisableSnapping (CompDisplay     *d,
 		    damagePendingOnScreen (w->screen);
 		}
 	    }
+
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+		w = w->parent;
+
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
 	}
     }
 
@@ -2678,7 +2842,8 @@ wobblyInitDisplay (CompPlugin  *p,
 {
     WobblyDisplay *wd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     wd = malloc (sizeof (WobblyDisplay));
@@ -2763,6 +2928,8 @@ wobblyInitScreen (CompPlugin *p,
     ws->grabWindow = NULL;
     ws->moveWindow = FALSE;
 
+    ws->model = NULL;
+
     WRAP (ws, s, preparePaintScreen, wobblyPreparePaintScreen);
     WRAP (ws, s, donePaintScreen, wobblyDonePaintScreen);
     WRAP (ws, s, paintOutput, wobblyPaintOutput);
diff --git a/plugins/zoom.c b/plugins/zoom.c
index 8996c1c..4c3b881 100644
--- a/plugins/zoom.c
+++ b/plugins/zoom.c
@@ -163,7 +163,7 @@ zoomInEvent (CompScreen *s)
 
     o[0].type    = CompOptionTypeInt;
     o[0].name    = "root";
-    o[0].value.i = s->root;
+    o[0].value.i = s->root.id;
 
     o[1].type    = CompOptionTypeInt;
     o[1].name    = "output";
@@ -197,7 +197,7 @@ zoomOutEvent (CompScreen *s)
 
     o[0].type    = CompOptionTypeInt;
     o[0].name    = "root";
-    o[0].value.i = s->root;
+    o[0].value.i = s->root.id;
 
     o[1].type    = CompOptionTypeInt;
     o[1].name    = "output";
@@ -694,7 +694,7 @@ zoomTerminate (CompDisplay     *d,
     {
 	ZOOM_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (zs->grab)
@@ -719,7 +719,7 @@ zoomTerminate (CompDisplay     *d,
 
 	    o.type    = CompOptionTypeInt;
 	    o.name    = "root";
-	    o.value.i = s->root;
+	    o.value.i = s->root.id;
 
 	    zoomOut (d, action, state, &o, 1);
 	}
@@ -787,7 +787,7 @@ zoomTerminatePan (CompDisplay     *d,
     {
 	ZOOM_SCREEN (s);
 
-	if (xid && s->root != xid)
+	if (xid && s->root.id != xid)
 	    continue;
 
 	if (zs->panGrabIndex)
@@ -970,7 +970,8 @@ zoomInitDisplay (CompPlugin  *p,
 {
     ZoomDisplay *zd;
 
-    if (!checkPluginABI ("core", CORE_ABIVERSION))
+    if (!checkPluginABI ("core", CORE_ABIVERSION) ||
+	!checkPluginABI ("glx",  CORE_ABIVERSION))
 	return FALSE;
 
     zd = malloc (sizeof (ZoomDisplay));
diff --git a/src/display.c b/src/display.c
index 23b0ba1..881996f 100644
--- a/src/display.c
+++ b/src/display.c
@@ -195,8 +195,8 @@ mainMenu (CompDisplay     *d,
 
     s = findScreenAtDisplay (d, xid);
     if (s && !s->maxGrab)
-	toolkitAction (s, s->display->toolkitActionMainMenuAtom, time, s->root,
-		       0, 0, 0);
+	toolkitAction (s, s->display->toolkitActionMainMenuAtom, time,
+		       s->root.id, 0, 0, 0);
 
     return TRUE;
 }
@@ -217,8 +217,8 @@ runDialog (CompDisplay     *d,
 
     s = findScreenAtDisplay (d, xid);
     if (s && !s->maxGrab)
-	toolkitAction (s, s->display->toolkitActionRunDialogAtom, time, s->root,
-		       0, 0, 0);
+	toolkitAction (s, s->display->toolkitActionRunDialogAtom, time,
+		       s->root.id, 0, 0, 0);
 
     return TRUE;
 }
@@ -725,7 +725,7 @@ pingTimeout (void *closure)
 
     for (s = d->screens; s; s = s->next)
     {
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    if (w->attrib.map_state != IsViewable)
 		continue;
@@ -841,7 +841,7 @@ setDisplayOption (CompPlugin	  *plugin,
     return FALSE;
 }
 
-static void
+void
 updatePlugins (CompDisplay *d)
 {
     CompOption *o;
@@ -1349,7 +1349,7 @@ doPoll (int timeout)
     return rv;
 }
 
-static void
+void
 handleTimeouts (struct timeval *tv)
 {
     CompTimeout *t;
@@ -1545,13 +1545,20 @@ eventLoop (void)
 	{
 	    for (s = d->screens; s; s = s->next)
 	    {
-		if (s->damageMask)
+		if (manualCompositeManagement)
 		{
-		    finishScreenDrawing (s);
+		    if (s->damageMask)
+		    {
+			finishScreenDrawing (s);
+		    }
+		    else
+		    {
+			s->idle = TRUE;
+		    }
 		}
 		else
 		{
-		    s->idle = TRUE;
+		    s->damageMask = 0;
 		}
 	    }
 	}
@@ -1624,7 +1631,7 @@ eventLoop (void)
 			/* substract top most overlay window region */
 			if (s->overlayWindowCount)
 			{
-			    for (w = s->reverseWindows; w; w = w->prev)
+			    for (w = s->root.reverseWindows; w; w = w->prev)
 			    {
 				if (w->destroyed || w->invisible)
 				    continue;
@@ -1748,24 +1755,6 @@ eventLoop (void)
 
 			(*s->donePaintScreen) (s);
 
-			/* remove destroyed windows */
-			while (s->pendingDestroys)
-			{
-			    CompWindow *w;
-
-			    for (w = s->windows; w; w = w->next)
-			    {
-				if (w->destroyed)
-				{
-				    addWindowDamage (w);
-				    removeWindow (w);
-				    break;
-				}
-			    }
-
-			    s->pendingDestroys--;
-			}
-
 			s->idle = FALSE;
 		    }
 		}
@@ -1797,6 +1786,45 @@ eventLoop (void)
 		doPoll (-1);
 	    }
 	}
+
+	for (d = core.displays; d; d = d->next)
+	{
+	    for (s = d->screens; s; s = s->next)
+	    {
+		/* remove destroyed windows */
+		while (s->pendingDestroys)
+		{
+		    CompWindow *w;
+
+		    w = s->root.windows;
+		    for (;;)
+		    {
+			if (w->destroyed)
+			{
+			    addWindowDamage (w);
+			    removeWindow (w);
+			    break;
+			}
+
+			if (w->windows)
+			{
+			    w = w->windows;
+			    continue;
+			}
+
+			while (!w->next && (w != &s->root))
+			    w = w->parent;
+	    
+			if (w == &s->root)
+			    break;
+
+			w = w->next;
+		    }
+
+		    s->pendingDestroys--;
+		}
+	    }
+	}
     }
 
     for (d = core.displays; d; d = d->next)
@@ -1864,7 +1892,8 @@ compCheckForError (Display *dpy)
 static void
 addScreenActions (CompScreen *s)
 {
-    int i;
+    CompPlugin *p;
+    int        i;
 
     for (i = 0; i < COMP_DISPLAY_OPTION_NUM; i++)
     {
@@ -1874,6 +1903,27 @@ addScreenActions (CompScreen *s)
 	if (s->display->opt[i].value.action.state & CompActionStateAutoGrab)
 	    addScreenAction (s, &s->display->opt[i].value.action);
     }
+
+    for (p = getPlugins (); p; p = p->next)
+    {
+	CompOption *option;
+	int	   nOption;
+
+	if (!p->vTable->getObjectOptions)
+	    continue;
+
+	option = (*p->vTable->getObjectOptions) (p,
+						 &s->display->base,
+						 &nOption);
+	for (i = 0; i < nOption; i++)
+	{
+	    if (!isActionOption (&option[i]))
+		continue;
+
+	    if (option[i].value.action.state & CompActionStateAutoGrab)
+		addScreenAction (s, &option[i].value.action);
+	}
+    }
 }
 
 void
@@ -1920,12 +1970,10 @@ addDisplay (const char *name)
     CompDisplay *d;
     CompPrivate	*privates;
     Display     *dpy;
-    Window	focus;
-    int		revertTo, i;
     int		compositeMajor, compositeMinor;
     int		fixesMinor;
     int		xkbOpcode;
-    int		firstScreen, lastScreen;
+    int		i;
 
     d = malloc (sizeof (CompDisplay));
     if (!d)
@@ -2198,6 +2246,8 @@ addDisplay (const char *name)
 
     d->startupIdAtom = XInternAtom (dpy, "_NET_STARTUP_ID", 0);
 
+    d->syncStateAtom = XInternAtom (dpy, "_COMPIZ_SYNC_STATE", 0);
+
     d->snDisplay = sn_display_new (dpy, NULL, NULL);
     if (!d->snDisplay)
 	return FALSE;
@@ -2288,7 +2338,7 @@ addDisplay (const char *name)
 						   &d->xineramaEvent,
 						   &d->xineramaError);
 
-    if (d->xineramaExtension)
+    if (d->xineramaExtension && XineramaIsActive (dpy))
 	d->screenInfo = XineramaQueryScreens (dpy, &d->nScreenInfo);
 
     d->escapeKeyCode = XKeysymToKeycode (dpy, XStringToKeysym ("Escape"));
@@ -2301,6 +2351,49 @@ addDisplay (const char *name)
 
     (*core.objectAdd) (&core.base, &d->base);
 
+    return TRUE;
+}
+
+void
+removeDisplay (CompDisplay *d)
+{
+    CompDisplay *p;
+
+    for (p = core.displays; p; p = p->next)
+	if (p->next == d)
+	    break;
+
+    if (p)
+	p->next = d->next;
+    else
+	core.displays = NULL;
+
+    while (d->screens)
+	removeScreen (d->screens);
+
+    (*core.objectRemove) (&core.base, &d->base);
+
+    objectFiniPlugins (&d->base);
+
+    compRemoveTimeout (d->pingHandle);
+
+    if (d->snDisplay)
+	sn_display_unref (d->snDisplay);
+
+    XSync (d->display, False);
+    XCloseDisplay (d->display);
+
+    freeDisplay (d);
+}
+
+Bool
+manageDisplay (CompDisplay *d)
+{
+    Display *dpy = d->display;
+    Window  focus;
+    int     revertTo, i;
+    int     firstScreen, lastScreen;
+
     if (onlyCurrentScreen)
     {
 	firstScreen = DefaultScreen (dpy);
@@ -2319,7 +2412,7 @@ addDisplay (const char *name)
 	Time		     wmSnTimestamp = 0;
 	XEvent		     event;
 	XSetWindowAttributes attr;
-	Window		     currentWmSnOwner, currentCmSnOwner;
+	Window		     currentWmSnOwner = None, currentCmSnOwner;
 	char		     buf[128];
 	Window		     rootDummy, childDummy;
 	unsigned int	     uDummy;
@@ -2328,7 +2421,8 @@ addDisplay (const char *name)
 	sprintf (buf, "WM_S%d", i);
 	wmSnAtom = XInternAtom (dpy, buf, 0);
 
-	currentWmSnOwner = XGetSelectionOwner (dpy, wmSnAtom);
+	if (windowManagement)
+	    currentWmSnOwner = XGetSelectionOwner (dpy, wmSnAtom);
 
 	if (currentWmSnOwner != None)
 	{
@@ -2366,6 +2460,9 @@ addDisplay (const char *name)
 
 		continue;
 	    }
+
+	    XSelectInput (dpy, currentCmSnOwner,
+			  StructureNotifyMask);
 	}
 
 	attr.override_redirect = TRUE;
@@ -2379,48 +2476,51 @@ addDisplay (const char *name)
 			   CWOverrideRedirect | CWEventMask,
 			   &attr);
 
-	XChangeProperty (dpy,
-			 newWmSnOwner,
-			 d->wmNameAtom,
-			 d->utf8StringAtom, 8,
-			 PropModeReplace,
-			 (unsigned char *) PACKAGE,
-			 strlen (PACKAGE));
-
-	XWindowEvent (dpy,
-		      newWmSnOwner,
-		      PropertyChangeMask,
-		      &event);
+	if (windowManagement)
+	{
+	    XChangeProperty (dpy,
+			     newWmSnOwner,
+			     d->wmNameAtom,
+			     d->utf8StringAtom, 8,
+			     PropModeReplace,
+			     (unsigned char *) PACKAGE,
+			     strlen (PACKAGE));
 
-	wmSnTimestamp = event.xproperty.time;
+	    XWindowEvent (dpy,
+			  newWmSnOwner,
+			  PropertyChangeMask,
+			  &event);
 
-	XSetSelectionOwner (dpy, wmSnAtom, newWmSnOwner, wmSnTimestamp);
+	    wmSnTimestamp = event.xproperty.time;
 
-	if (XGetSelectionOwner (dpy, wmSnAtom) != newWmSnOwner)
-	{
-	    compLogMessage ("core", CompLogLevelError,
-			    "Could not acquire window manager "
-			    "selection on screen %d display \"%s\"",
-			    i, DisplayString (dpy));
+	    XSetSelectionOwner (dpy, wmSnAtom, newWmSnOwner, wmSnTimestamp);
 
-	    XDestroyWindow (dpy, newWmSnOwner);
+	    if (XGetSelectionOwner (dpy, wmSnAtom) != newWmSnOwner)
+	    {
+		compLogMessage ("core", CompLogLevelError,
+				"Could not acquire window manager "
+				"selection on screen %d display \"%s\"",
+				i, DisplayString (dpy));
 
-	    continue;
-	}
+		XDestroyWindow (dpy, newWmSnOwner);
 
-	/* Send client message indicating that we are now the WM */
-	event.xclient.type	   = ClientMessage;
-	event.xclient.window       = XRootWindow (dpy, i);
-	event.xclient.message_type = d->managerAtom;
-	event.xclient.format       = 32;
-	event.xclient.data.l[0]    = wmSnTimestamp;
-	event.xclient.data.l[1]    = wmSnAtom;
-	event.xclient.data.l[2]    = 0;
-	event.xclient.data.l[3]    = 0;
-	event.xclient.data.l[4]    = 0;
+		continue;
+	    }
 
-	XSendEvent (dpy, XRootWindow (dpy, i), FALSE,
-		    StructureNotifyMask, &event);
+	    /* Send client message indicating that we are now the WM */
+	    event.xclient.type	       = ClientMessage;
+	    event.xclient.window       = XRootWindow (dpy, i);
+	    event.xclient.message_type = d->managerAtom;
+	    event.xclient.format       = 32;
+	    event.xclient.data.l[0]    = wmSnTimestamp;
+	    event.xclient.data.l[1]    = wmSnAtom;
+	    event.xclient.data.l[2]    = 0;
+	    event.xclient.data.l[3]    = 0;
+	    event.xclient.data.l[4]    = 0;
+
+	    XSendEvent (dpy, XRootWindow (dpy, i), FALSE,
+			StructureNotifyMask, &event);
+	}
 
 	/* Wait for old window manager to go away */
 	if (currentWmSnOwner != None)
@@ -2431,18 +2531,35 @@ addDisplay (const char *name)
 	    } while (event.type != DestroyNotify);
 	}
 
-	compCheckForError (dpy);
+	/* Wait for old compositing manager to go away */
+	if (currentCmSnOwner != None && currentCmSnOwner != currentWmSnOwner)
+	{
+	    do {
+		XWindowEvent (dpy, currentCmSnOwner,
+			      StructureNotifyMask, &event);
+	    } while (event.type != DestroyNotify);
+	}
 
-	XCompositeRedirectSubwindows (dpy, XRootWindow (dpy, i),
-				      CompositeRedirectManual);
+	compCheckForError (dpy);
 
-	if (compCheckForError (dpy))
+	if (manualCompositeManagement)
 	{
-	    compLogMessage ("core", CompLogLevelError,
-			    "Another composite manager is already "
-			    "running on screen: %d", i);
+	    XCompositeRedirectSubwindows (dpy, XRootWindow (dpy, i),
+					  CompositeRedirectManual);
 
-	    continue;
+	    if (compCheckForError (dpy))
+	    {
+		compLogMessage ("core", CompLogLevelError,
+				"Another composite manager is already "
+				"running on screen: %d", i);
+
+		continue;
+	    }
+	}
+	else
+	{
+	    XCompositeRedirectSubwindows (dpy, XRootWindow (dpy, i),
+					  CompositeRedirectAutomatic);
 	}
 
 	XSetSelectionOwner (dpy, cmSnAtom, newCmSnOwner, wmSnTimestamp);
@@ -2459,28 +2576,39 @@ addDisplay (const char *name)
 
 	XGrabServer (dpy);
 
-	XSelectInput (dpy, XRootWindow (dpy, i),
-		      SubstructureRedirectMask |
-		      SubstructureNotifyMask   |
-		      StructureNotifyMask      |
-		      PropertyChangeMask       |
-		      LeaveWindowMask	       |
-		      EnterWindowMask	       |
-		      KeyPressMask	       |
-		      KeyReleaseMask	       |
-		      ButtonPressMask	       |
-		      ButtonReleaseMask	       |
-		      FocusChangeMask	       |
-		      ExposureMask);
-
-	if (compCheckForError (dpy))
+	if (windowManagement)
 	{
-	    compLogMessage ("core", CompLogLevelError,
-			    "Another window manager is "
-			    "already running on screen: %d", i);
+	    XSelectInput (dpy, XRootWindow (dpy, i),
+			  SubstructureRedirectMask |
+			  SubstructureNotifyMask   |
+			  StructureNotifyMask      |
+			  PropertyChangeMask       |
+			  LeaveWindowMask          |
+			  EnterWindowMask          |
+			  KeyPressMask             |
+			  KeyReleaseMask           |
+			  ButtonPressMask          |
+			  ButtonReleaseMask        |
+			  FocusChangeMask          |
+			  ExposureMask);
+   
+	    if (compCheckForError (dpy))
+	    {
+		compLogMessage ("core", CompLogLevelError,
+				"Another window manager is "
+				"already running on screen: %d", i);
 
-	    XUngrabServer (dpy);
-	    continue;
+		XUngrabServer (dpy);
+		continue;
+	    }
+	}
+	else
+	{
+	    XSelectInput (dpy, XRootWindow (dpy, i),
+			  SubstructureNotifyMask   |
+			  StructureNotifyMask      |
+			  PropertyChangeMask       |
+			  ExposureMask);
 	}
 
 	if (!addScreen (d, i, newWmSnOwner, wmSnAtom, wmSnTimestamp))
@@ -2503,74 +2631,50 @@ addDisplay (const char *name)
     if (!d->screens)
     {
 	compLogMessage ("core", CompLogLevelFatal,
-			"No manageable screens found on display %s",
-			XDisplayName (name));
+			"No manageable screens found on display");
 	return FALSE;
     }
 
     setAudibleBell (d, d->opt[COMP_DISPLAY_OPTION_AUDIBLE_BELL].value.b);
 
-    XGetInputFocus (dpy, &focus, &revertTo);
-
-    /* move input focus to root window so that we get a FocusIn event when
-       moving it to the default window */
-    XSetInputFocus (dpy, d->screens->root, RevertToPointerRoot, CurrentTime);
-
-    if (focus == None || focus == PointerRoot)
-    {
-	focusDefaultWindow (d->screens);
-    }
-    else
+    if (windowManagement)
     {
-	CompWindow *w;
+	XGetInputFocus (dpy, &focus, &revertTo);
 
-	w = findWindowAtDisplay (d, focus);
-	if (w)
+	/* move input focus to root window so that we get a FocusIn event when
+	   moving it to the default window */
+	XSetInputFocus (dpy, d->screens->root.id, RevertToPointerRoot,
+			CurrentTime);
+
+	if (focus == None || focus == PointerRoot)
 	{
-	    moveInputFocusToWindow (w);
+	    focusDefaultWindow (d->screens);
 	}
 	else
-	    focusDefaultWindow (d->screens);
-    }
-
-    d->pingHandle =
-	compAddTimeout (d->opt[COMP_DISPLAY_OPTION_PING_DELAY].value.i,
-			d->opt[COMP_DISPLAY_OPTION_PING_DELAY].value.i + 500,
-			pingTimeout, d);
-
-    return TRUE;
-}
-
-void
-removeDisplay (CompDisplay *d)
-{
-    CompDisplay *p;
+	{
+	    CompWindow *w;
 
-    for (p = core.displays; p; p = p->next)
-	if (p->next == d)
-	    break;
+	    w = findWindowAtDisplay (d, focus);
+	    if (w)
+	    {
+		moveInputFocusToWindow (w);
+	    }
+	    else
+		focusDefaultWindow (d->screens);
+	}
 
-    if (p)
-	p->next = d->next;
+	d->pingHandle =
+	    compAddTimeout (d->opt[COMP_DISPLAY_OPTION_PING_DELAY].value.i,
+			    d->opt[COMP_DISPLAY_OPTION_PING_DELAY].value.i +
+			    500, pingTimeout, d);
+    }
     else
-	core.displays = NULL;
-
-    while (d->screens)
-	removeScreen (d->screens);
-
-    (*core.objectRemove) (&core.base, &d->base);
-
-    objectFiniPlugins (&d->base);
-
-    compRemoveTimeout (d->pingHandle);
-
-    if (d->snDisplay)
-	sn_display_unref (d->snDisplay);
-
-    XSync (d->display, False);
-    XCloseDisplay (d->display);
+    {
+	d->activeWindow = d->screens->root.activeChild =
+	    getActiveWindow (d, d->screens->root.id);
+    }
 
-    freeDisplay (d);
+    return TRUE;
 }
 
 Time
@@ -2596,7 +2700,7 @@ findScreenAtDisplay (CompDisplay *d,
 
     for (s = d->screens; s; s = s->next)
     {
-	if (s->root == root)
+	if (s->root.id == root)
 	    return s;
     }
 
@@ -2632,6 +2736,23 @@ findWindowAtDisplay (CompDisplay *d,
 }
 
 CompWindow *
+findClientWindowAtDisplay (CompDisplay *d,
+			   Window      id)
+{
+    CompScreen *s;
+    CompWindow *w;
+
+    for (s = d->screens; s; s = s->next)
+    {
+	w = findClientWindowAtScreen (s, id);
+	if (w)
+	    return w;
+    }
+
+    return 0;
+}
+
+CompWindow *
 findTopLevelWindowAtDisplay (CompDisplay *d,
 			     Window      id)
 {
@@ -2823,7 +2944,7 @@ warpPointer (CompScreen *s,
 	pointerY = 0;
 
     XWarpPointer (display->display,
-		  None, s->root,
+		  None, s->root.id,
 		  0, 0, 0, 0,
 		  pointerX, pointerY);
 
diff --git a/src/event.c b/src/event.c
index ac61749..f0f8461 100644
--- a/src/event.c
+++ b/src/event.c
@@ -45,37 +45,46 @@ handleWindowDamageRect (CompWindow *w,
 			int	   height)
 {
     REGION region;
-    Bool   initial = FALSE;
+    Bool   status = TRUE;
 
     if (!w->redirected || w->bindFailed)
 	return;
 
-    if (!w->damaged)
-    {
-	w->damaged = initial = TRUE;
-	w->invisible = WINDOW_INVISIBLE (w);
-    }
-
     region.extents.x1 = x;
     region.extents.y1 = y;
     region.extents.x2 = region.extents.x1 + width;
     region.extents.y2 = region.extents.y1 + height;
 
-    if (!(*w->screen->damageWindowRect) (w, initial, &region.extents))
+    while (w != &w->screen->root)
     {
+	Bool initial = FALSE;
+
+	if (!w->damaged)
+	{
+	    w->damaged = initial = TRUE;
+	    w->invisible = WINDOW_INVISIBLE (w);
+	}
+
+	status &= (*w->screen->damageWindowRect) (w, initial, &region.extents);
+
+	if (initial)
+	    damageWindowOutputExtents (w);
+
 	region.extents.x1 += w->attrib.x + w->attrib.border_width;
 	region.extents.y1 += w->attrib.y + w->attrib.border_width;
 	region.extents.x2 += w->attrib.x + w->attrib.border_width;
 	region.extents.y2 += w->attrib.y + w->attrib.border_width;
 
+	w = w->parent;
+    }
+
+    if (!status)
+    {
 	region.rects = &region.extents;
 	region.numRects = region.size = 1;
 
 	damageScreenRegion (w->screen, &region);
     }
-
-    if (initial)
-	damageWindowOutputExtents (w);
 }
 
 void
@@ -99,6 +108,9 @@ handleSyncAlarm (CompWindow *w)
 	    XRectangle *rects;
 	    int	       nDamage;
 
+	    if (w->parent->substructureRedirect)
+		leaveSyncWaitState (w);
+
 	    nDamage = w->nDamage;
 	    rects   = w->damageRects;
 	    while (nDamage--)
@@ -130,7 +142,7 @@ moveInputFocusToOtherWindow (CompWindow *w)
     {
 	CompWindow *ancestor;
 
-	if (w->transientFor && w->transientFor != w->screen->root)
+	if (w->transientFor && w->transientFor != w->screen->root.id)
 	{
 	    ancestor = findWindowAtDisplay (display, w->transientFor);
 	    if (ancestor && !(ancestor->type & (CompWindowTypeDesktopMask |
@@ -146,7 +158,7 @@ moveInputFocusToOtherWindow (CompWindow *w)
 	{
 	    CompWindow *a, *focus = NULL;
 
-	    for (a = w->screen->reverseWindows; a; a = a->prev)
+	    for (a = w->screen->root.reverseWindows; a; a = a->prev)
 	    {
 		if (a->clientLeader == w->clientLeader)
 		{
@@ -277,7 +289,7 @@ triggerButtonPressBindings (CompDisplay  *d,
 
 	if (event->window != edgeWindow)
 	{
-	    if (!s->maxGrab || event->window != s->root)
+	    if (!s->maxGrab || event->window != s->root.id)
 		return FALSE;
 	}
 
@@ -1064,7 +1076,7 @@ handleActionEvent (CompDisplay *d,
 			if (event->xclient.window == s->screenEdge[i].id)
 			{
 			    edge = 1 << i;
-			    root = s->root;
+			    root = s->root.id;
 			    break;
 			}
 		    }
@@ -1115,7 +1127,7 @@ handleActionEvent (CompDisplay *d,
 			if (xdndWindow == s->screenEdge[i].id)
 			{
 			    edge = 1 << i;
-			    root = s->root;
+			    root = s->root.id;
 			    break;
 			}
 		    }
@@ -1307,32 +1319,29 @@ handleEvent (CompDisplay *d,
     case ConfigureNotify:
 	w = findWindowAtDisplay (d, event->xconfigure.window);
 	if (w)
-	{
 	    configureWindow (w, &event->xconfigure);
-	}
-	else
-	{
-	    s = findScreenAtDisplay (d, event->xconfigure.window);
-	    if (s)
-		configureScreen (s, &event->xconfigure);
-	}
 	break;
     case CreateNotify:
-	s = findScreenAtDisplay (d, event->xcreatewindow.parent);
-	if (s)
+	w = findWindowAtDisplay (d, event->xcreatewindow.parent);
+	if (w)
 	{
 	    /* The first time some client asks for the composite
 	     * overlay window, the X server creates it, which causes
 	     * an errorneous CreateNotify event.  We catch it and
 	     * ignore it. */
-	    if (s->overlay != event->xcreatewindow.window)
-		addWindow (s, event->xcreatewindow.window, getTopWindow (s));
+	    if (w->screen->overlay != event->xcreatewindow.window)
+		addWindow (w,
+			   event->xcreatewindow.window,
+			   getTopWindow (w));
 	}
 	break;
     case DestroyNotify:
 	w = findWindowAtDisplay (d, event->xdestroywindow.window);
 	if (w)
 	{
+	    if (w->parent->supportingWmCheckWindow == w->id)
+		getSupportingWmCheck (w->parent);
+
 	    moveInputFocusToOtherWindow (w);
 	    destroyWindow (w);
 	}
@@ -1341,11 +1350,8 @@ handleEvent (CompDisplay *d,
 	w = findWindowAtDisplay (d, event->xmap.window);
 	if (w)
 	{
-	    if (w->pendingMaps)
-		w->managed = TRUE;
-
 	    /* been shaded */
-	    if (w->height == 0)
+	    if (w->managed && w->height == 0)
 	    {
 		if (w->id == d->activeWindow)
 		    moveInputFocusToWindow (w);
@@ -1364,7 +1370,7 @@ handleEvent (CompDisplay *d,
 		setWmState (d, IconicState, w->id);
 		w->pendingUnmaps--;
 	    }
-	    else /* X -> Withdrawn */
+	    else if (w->managed) /* X -> Withdrawn */
 	    {
 		/* Iconic -> Withdrawn */
 		if (w->state & CompWindowStateHiddenMask)
@@ -1392,12 +1398,7 @@ handleEvent (CompDisplay *d,
 	break;
     case ReparentNotify:
 	w = findWindowAtDisplay (d, event->xreparent.window);
-	s = findScreenAtDisplay (d, event->xreparent.parent);
-	if (s && !w)
-	{
-	    addWindow (s, event->xreparent.window, getTopWindow (s));
-	}
-	else if (w)
+	if (w)
 	{
 	    /* This is the only case where a window is removed but not
 	       destroyed. We must remove our event mask and all passive
@@ -1410,6 +1411,11 @@ handleEvent (CompDisplay *d,
 
 	    destroyWindow (w);
 	}
+
+	w = findWindowAtDisplay (d, event->xreparent.parent);
+	if (w)
+	    addWindow (w, event->xreparent.window, getTopWindow (w));
+
 	break;
     case CirculateNotify:
 	w = findWindowAtDisplay (d, event->xcirculate.window);
@@ -1456,9 +1462,9 @@ handleEvent (CompDisplay *d,
 		    if (w->attrib.map_state == IsViewable)
 		    {
 			if (w->type == CompWindowTypeDesktopMask)
-			    w->screen->desktopWindowCount--;
+			    w->parent->desktopWindowCount--;
 			else if (type == CompWindowTypeDesktopMask)
-			    w->screen->desktopWindowCount++;
+			    w->parent->desktopWindowCount++;
 		    }
 
 		    w->wmType = type;
@@ -1533,6 +1539,12 @@ handleEvent (CompDisplay *d,
 	    if (w)
 		w->clientLeader = getClientLeader (w);
 	}
+	else if (event->xproperty.atom == d->frameWindowAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w && w->parent && !w->parent->substructureRedirect)
+		w->frame = getFrameWindow (w);
+	}
 	else if (event->xproperty.atom == d->wmIconGeometryAtom)
 	{
 	    w = findWindowAtDisplay (d, event->xproperty.window);
@@ -1681,10 +1693,67 @@ handleEvent (CompDisplay *d,
 	    if (w)
 		updateWindowClassHints (w);
 	}
+	else if (event->xproperty.atom == d->supportingWmCheckAtom ||
+		 event->xproperty.atom == d->supportedAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w && !w->substructureRedirect)
+		getSupportingWmCheck (w);
+	}
+	else if (event->xproperty.atom == d->syncStateAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w && w->parent)
+	    {	
+		if (!w->parent->substructureRedirect)
+		{
+		    if (event->xproperty.state == PropertyDelete)
+		    {
+			if (w->parent->syncStateSupport)
+			    syncWait (w);
+		    }
+		    else
+			handleSyncAlarm (w);
+		}
+	    }
+	}
+	else if (event->xproperty.atom == d->winActiveAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w)
+	    {	
+		if (!w->substructureRedirect)
+		{
+		    Window activeChild;
+		    
+		    activeChild = getActiveWindow (d, w->id);
+		    if (activeChild != w->activeChild)
+		    {
+			w->previousActiveChild = w->activeChild;
+			w->activeChild = activeChild;
+		    }
+
+		    if (!w->parent)
+			d->activeWindow = activeChild;
+		}
+	    }
+	}
+	else if (event->xproperty.atom == d->desktopViewportAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w && !w->parent)
+	    {
+		if (!w->substructureRedirect)
+		    getDesktopHints (w->screen);
+	    }
+	}
 	break;
     case MotionNotify:
 	break;
     case ClientMessage:
+	if (!windowManagement)
+	    break;
+
 	if (event->xclient.message_type == d->winActiveAtom)
 	{
 	    w = findWindowAtDisplay (d, event->xclient.window);
@@ -1932,7 +2001,7 @@ handleEvent (CompDisplay *d,
 	{
 	    for (s = d->screens; s; s = s->next)
 	    {
-		if (event->xclient.window == s->root ||
+		if (event->xclient.window == s->root.id ||
 		    event->xclient.window == None)
 		{
 		    if (event->xclient.data.l[0])
@@ -1968,6 +2037,17 @@ handleEvent (CompDisplay *d,
 	    if (w)
 		setDesktopForWindow (w, event->xclient.data.l[0]);
 	}
+	else if (event->xclient.message_type == d->desktopViewportAtom)
+	{
+	    s = findScreenAtDisplay (d, event->xclient.window);
+	    if (s)
+		moveScreenViewport (s,
+				    s->x -
+				    (event->xclient.data.l[0] / s->width),
+				    s->y -
+				    (event->xclient.data.l[1] / s->height),
+				    TRUE);
+	}
 	break;
     case MappingNotify:
 	updateModifierMappings (d);
@@ -2026,7 +2106,7 @@ handleEvent (CompDisplay *d,
 
 		    xwcm = adjustConfigureRequestForGravity (w, &xwc,
 							     CWX | CWY,
-							     gravity);
+							     gravity, 1);
 
 		    if ((*w->screen->placeWindow) (w, xwc.x, xwc.y,
 						   &newX, &newY))
@@ -2061,6 +2141,15 @@ handleEvent (CompDisplay *d,
 
 		if (!(w->state & CompWindowStateHiddenMask))
 		{
+		    /* predict that input will be moved to window. this
+		       makes it look like the window became active just
+		       before it got mapped to external applications */
+		    if (w->inputHint && allowFocus)
+			XChangeProperty (d->display, w->screen->root.id,
+					 d->winActiveAtom,
+					 XA_WINDOW, 32, PropModeReplace,
+					 (unsigned char *) &w->id, 1);
+			
 		    w->pendingMaps++;
 		    XMapWindow (d->display, w->id);
 		}
@@ -2165,14 +2254,19 @@ handleEvent (CompDisplay *d,
 	    {
 		unsigned int state = w->state;
 
-		if (w->id != d->activeWindow)
+		if (w->id != w->parent->activeChild)
 		{
-		    d->activeWindow = w->id;
+		    w->parent->previousActiveChild = w->parent->activeChild; 
+		    w->parent->activeChild = w->id;
+
+		    if (w->parent == &w->screen->root)
+			d->activeWindow = w->id;
+
 		    w->activeNum = w->screen->activeNum++;
 
 		    addToCurrentActiveWindowHistory (w->screen, w->id);
 
-		    XChangeProperty (d->display, w->screen->root,
+		    XChangeProperty (d->display, w->screen->root.id,
 				     d->winActiveAtom,
 				     XA_WINDOW, 32, PropModeReplace,
 				     (unsigned char *) &w->id, 1);
@@ -2324,7 +2418,7 @@ handleEvent (CompDisplay *d,
 
 	    for (s = d->screens; s; s = s->next)
 	    {
-		for (w = s->windows; w; w = w->next)
+		for (w = s->root.windows; w; w = w->next)
 		{
 		    if (w->syncAlarm == sa->alarm)
 			break;
diff --git a/src/main.c b/src/main.c
index ff8328d..ec76311 100644
--- a/src/main.c
+++ b/src/main.c
@@ -68,6 +68,9 @@ Bool onlyCurrentScreen = FALSE;
 Bool useCow = TRUE;
 #endif
 
+Bool windowManagement = FALSE;
+Bool manualCompositeManagement = FALSE;
+
 CompMetadata coreMetadata;
 
 static void
@@ -435,6 +438,15 @@ main (int argc, char **argv)
     if (!addDisplay (displayName))
 	return 1;
 
+    while (core.displays->dirtyPluginList)
+    {
+	updatePlugins (core.displays);
+	handleTimeouts (&core.lastTimeout);
+    }
+
+    if (!manageDisplay (core.displays))
+	return 1;
+
     eventLoop ();
 
     if (!disableSm)
diff --git a/src/paint.c b/src/paint.c
index a2051fa..1c32b4b 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
+#include <assert.h>
 
 #include <compiz-core.h>
 
@@ -157,7 +158,7 @@ paintBackground (CompScreen   *s,
     if (!nBox)
 	return;
 
-    if (s->desktopWindowCount)
+    if (s->root.desktopWindowCount)
     {
 	if (bg->name)
 	{
@@ -251,167 +252,52 @@ paintOutputRegion (CompScreen	       *screen,
 		   CompOutput	       *output,
 		   unsigned int	       mask)
 {
-    static Region tmpRegion = NULL;
-    CompWindow    *w;
-    CompCursor	  *c;
-    int		  count, windowMask, odMask, i;
-    CompWindow	  *fullscreenWindow = NULL;
-    CompWalker    walk;
-    Bool          status;
-    Bool          withOffset = FALSE;
-    CompTransform vTransform;
-    int           offX, offY;
-    Region        clip = region;
-
-    if (!tmpRegion)
-    {
-	tmpRegion = XCreateRegion ();
-	if (!tmpRegion)
-	    return;
-    }
+    Region      r = XCreateRegion ();
+    CompPainter painter;
+    CompCursor	*c;
+    int		windowMask = 0;
+
+    assert (r);
+
+    (*screen->initObjectPainter) (screen, &painter);
 
     if (mask & PAINT_SCREEN_TRANSFORMED_MASK)
-    {
-	windowMask     = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
-	count	       = 1;
-    }
-    else
-    {
-	windowMask     = 0;
-	count	       = 0;
-    }
+    	windowMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
 
-    XSubtractRegion (region, &emptyRegion, tmpRegion);
+    if (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
+    	windowMask |= PAINT_WINDOW_WITH_TRANSFORMED_CHILD_MASK;
 
-    (*screen->initWindowWalker) (screen, &walk);
+    XSubtractRegion (region, &emptyRegion, r);
 
     if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
     {
-	/* detect occlusions */
-	for (w = (*walk.last) (screen); w; w = (*walk.prev) (w))
-	{
-	    if (w->destroyed)
-		continue;
-
-	    if (!w->shaded)
-	    {
-		if (w->attrib.map_state != IsViewable || !w->damaged)
-		    continue;
-	    }
-
-	    /* copy region */
-	    XSubtractRegion (tmpRegion, &emptyRegion, w->clip);
-
-	    odMask = PAINT_WINDOW_OCCLUSION_DETECTION_MASK;
-		
-	    if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) &&
-		!windowOnAllViewports (w))
-	    {
-		withOffset = TRUE;
-
-		getWindowMovementForOffset (w, screen->windowOffsetX,
-					    screen->windowOffsetY,
-					    &offX, &offY);
-
-		vTransform = *transform;
-		matrixTranslate (&vTransform, offX, offY, 0);
-	 
-		XOffsetRegion (w->clip, -offX, -offY);
-
-		odMask |= PAINT_WINDOW_WITH_OFFSET_MASK;
-		status = (*screen->paintWindow) (w, &w->paint, &vTransform,
-						 tmpRegion, odMask);
-	    }
-	    else
-	    {
-		withOffset = FALSE;
-		status = (*screen->paintWindow) (w, &w->paint, transform, tmpRegion,
-						 odMask);
-	    }
-
-	    if (status)
-	    {
-		if (withOffset)
-		{
-		    XOffsetRegion (w->region, offX, offY);
-		    XSubtractRegion (tmpRegion, w->region, tmpRegion);
-		    XOffsetRegion (w->region, -offX, -offY);
-		}
-		else
-		    XSubtractRegion (tmpRegion, w->region, tmpRegion);
-
-		/* unredirect top most fullscreen windows. */
-		if (count == 0 &&
-		    screen->opt[COMP_SCREEN_OPTION_UNREDIRECT_FS].value.b)
-		{
-		    if (XEqualRegion (w->region, &screen->region) &&
-			!REGION_NOT_EMPTY (tmpRegion))
-		    {
-			fullscreenWindow = w;
-		    }
-		    else
-		    {
-			for (i = 0; i < screen->nOutputDev; i++)
-			    if (XEqualRegion (w->region,
-					      &screen->outputDev[i].region))
-				fullscreenWindow = w;
-		    }
-		}
-	    }
-
-	    count++;
-	}
+	if ((*painter.paintObject) (&screen->root,
+				    &screen->root.paint,
+				    transform,
+				    r,
+				    PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
+	    XSubtractRegion (r, screen->root.region, r);
+
+	windowMask |= PAINT_WINDOW_CLIP_MASK;
     }
 
-    if (fullscreenWindow)
-	unredirectWindow (fullscreenWindow);
-
     if (!(mask & PAINT_SCREEN_NO_BACKGROUND_MASK))
-	paintBackground (screen, tmpRegion,
-			 (mask & PAINT_SCREEN_TRANSFORMED_MASK));
-
-    /* paint all windows from bottom to top */
-    for (w = (*walk.first) (screen); w; w = (*walk.next) (w))
-    {
-	if (w->destroyed)
-	    continue;
-
-	if (w == fullscreenWindow)
-	    continue;
-
-	if (!w->shaded)
-	{
-	    if (w->attrib.map_state != IsViewable || !w->damaged)
-		continue;
-	}
-
-	if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
-	    clip = w->clip;
-
-	if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) &&
-	    !windowOnAllViewports (w))
-	{
-	    getWindowMovementForOffset (w, screen->windowOffsetX,
-					screen->windowOffsetY, &offX, &offY);
+	paintBackground (screen, r, (mask & PAINT_SCREEN_TRANSFORMED_MASK));
 
-	    vTransform = *transform;
-	    matrixTranslate (&vTransform, offX, offY, 0);
-	    (*screen->paintWindow) (w, &w->paint, &vTransform, clip,
-				    windowMask | PAINT_WINDOW_WITH_OFFSET_MASK);
-	}
-	else
-	{
-	    (*screen->paintWindow) (w, &w->paint, transform, clip,
-				    windowMask);
-	}
-    }
+    (*painter.paintObject) (&screen->root,
+			    &screen->root.paint,
+			    transform,
+			    r,
+			    windowMask);
 
-    if (walk.fini)
-	(*walk.fini) (screen, &walk);
+    if (painter.fini)
+	(*painter.fini) (screen, &painter);
 
     /* paint cursors */
     for (c = screen->cursors; c; c = c->next)
-	(*screen->paintCursor) (c, transform, tmpRegion, 0);
+	(*screen->paintCursor) (c, transform, r, 0);
+
+    XDestroyRegion (r);
 }
 
 void
@@ -420,21 +306,15 @@ enableOutputClipping (CompScreen 	  *screen,
 		      Region		  region,
 		      CompOutput 	  *output)
 {
-    GLdouble h = screen->height;
-
-    GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
-    GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
-
-    GLdouble halfW = output->width / 2.0;
-    GLdouble halfH = output->height / 2.0;
-
-    GLdouble cx = output->region.extents.x1 + halfW;
-    GLdouble cy = (h - output->region.extents.y2) + halfH;
+    GLdouble x1 = region->extents.x1 > 0 ? 1.0 / region->extents.x1 : MAXSHORT;
+    GLdouble y1 = region->extents.y1 > 0 ? 1.0 / region->extents.y1 : MAXSHORT;
+    GLdouble x2 = region->extents.x2 > 0 ? 1.0 / region->extents.x2 : MAXSHORT;
+    GLdouble y2 = region->extents.y2 > 0 ? 1.0 / region->extents.y2 : MAXSHORT;
 
-    GLdouble top[4]    = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
-    GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
-    GLdouble left[4]   = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
-    GLdouble right[4]  = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
+    GLdouble top[4]    = { 0.0,  y1, 0.0, -1.0 };
+    GLdouble bottom[4] = { 0.0, -y2, 0.0,  1.0 };
+    GLdouble left[4]   = {  x1, 0.0, 0.0, -1.0 };
+    GLdouble right[4]  = { -x2, 0.0, 0.0,  1.0 };
 
     glPushMatrix ();
     glLoadMatrixf (transform->m);
@@ -461,9 +341,6 @@ disableOutputClipping (CompScreen *screen)
     glDisable (GL_CLIP_PLANE3);
 }
 
-#define CLIP_PLANE_MASK (PAINT_SCREEN_TRANSFORMED_MASK | \
-			 PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
-
 void
 paintTransformedOutput (CompScreen		*screen,
 			const ScreenPaintAttrib *sAttrib,
@@ -481,34 +358,14 @@ paintTransformedOutput (CompScreen		*screen,
 
     (*screen->applyScreenTransform) (screen, sAttrib, output, &sTransform);
 
-    if ((mask & CLIP_PLANE_MASK) == CLIP_PLANE_MASK)
-    {
-	screen->enableOutputClipping (screen, &sTransform, region, output);
-
-	transformToScreenSpace (screen, output, -sAttrib->zTranslate,
-				&sTransform);
-
-	glPushMatrix ();
-	glLoadMatrixf (sTransform.m);
-
-	paintOutputRegion (screen, &sTransform, region, output, mask);
-
-	glPopMatrix ();
-
-	screen->disableOutputClipping (screen);
-    }
-    else
-    {
-	transformToScreenSpace (screen, output, -sAttrib->zTranslate,
-				&sTransform);
+    transformToScreenSpace (screen, output, -sAttrib->zTranslate, &sTransform);
 
-	glPushMatrix ();
-	glLoadMatrixf (sTransform.m);
+    glPushMatrix ();
+    glLoadMatrixf (sTransform.m);
 
-	paintOutputRegion (screen, &sTransform, region, output, mask);
+    paintOutputRegion (screen, &sTransform, region, output, mask);
 
-	glPopMatrix ();
-    }
+    glPopMatrix ();
 }
 
 Bool
@@ -1194,7 +1051,13 @@ drawWindow (CompWindow		 *w,
 	return TRUE;
 
     if (w->attrib.map_state != IsViewable)
-	return TRUE;
+	return FALSE;
+
+    if (!w->damaged)
+	return FALSE;
+
+    if (!w->parent || !w->parent->redirectSubwindows)
+	return FALSE;
 
     if (!w->texture->pixmap && !bindWindow (w))
 	return FALSE;
@@ -1217,8 +1080,10 @@ paintWindow (CompWindow		     *w,
 	     Region		     region,
 	     unsigned int	     mask)
 {
-    FragmentAttrib fragment;
-    Bool	   status;
+    CompWindow  *c;
+    CompWalker  walk;
+    CompPainter painter;
+    Bool	status;
 
     w->lastPaint = *attrib;
 
@@ -1229,38 +1094,401 @@ paintWindow (CompWindow		     *w,
 
     if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
     {
-	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
-	    return FALSE;
+	Bool occlude = TRUE;
 
 	if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
-	    return FALSE;
+	    occlude = FALSE;
+
+	if (w->shaded)
+	    occlude = FALSE;
+
+	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+	    occlude = FALSE;
 
 	if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
-	    return FALSE;
+	    occlude = FALSE;
 
-	if (w->shaded)
-	    return FALSE;
+	if (w->attrib.map_state != IsViewable)
+	    occlude = FALSE;
 
-	return TRUE;
+	if (!w->redirected || !w->damaged)
+	    occlude = FALSE;
+
+	(*w->screen->initWindowWalker) (w->screen, w, &walk);
+	(*w->screen->initObjectPainter) (w->screen, &painter);
+
+	c = (*walk.last) (w);
+	if (c)
+	{
+	    Region        r = XCreateRegion ();
+	    CompTransform wTransform = *transform;
+	    int		  count = 0;
+	    CompWindow	  *fullscreenWindow = NULL;
+
+	    assert (r);
+
+	    XIntersectRegion (region, w->region, r);
+
+	    if (w->attrib.x || w->attrib.y)
+	    {
+		matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0);
+		XOffsetRegion (r, -w->attrib.x, -w->attrib.y);
+		mask |= PAINT_WINDOW_WITH_OFFSET_MASK;
+	    }
+	
+	    for (; c; c = (*walk.prev) (c))
+	    {
+		CompTransform     cTransform = wTransform;
+		WindowPaintAttrib cPaint = c->paint;
+		int               viewportOffsetX = 0;
+		int               viewportOffsetY = 0;
+		int               offsetMask = 0;
+		
+		if (c->destroyed)
+		    continue;
+
+		cPaint.opacity = MULTIPLY_USHORT (cPaint.opacity,
+						  attrib->opacity);
+		cPaint.brightness = MULTIPLY_USHORT (cPaint.brightness,
+						     attrib->brightness);
+		cPaint.saturation = MULTIPLY_USHORT (cPaint.saturation,
+						     attrib->saturation);
+
+		if (!windowOnAllViewports (c))
+		{
+		    if (w->viewportOffsetX || w->viewportOffsetY)
+		    {
+			getWindowMovementForOffset (w,
+						    w->viewportOffsetX,
+						    w->viewportOffsetY,
+						    &viewportOffsetX,
+						    &viewportOffsetY);
+			
+			matrixTranslate (&cTransform,
+					 viewportOffsetX,
+					 viewportOffsetY,
+					 0);
+
+			XOffsetRegion (r,
+				       -viewportOffsetX,
+				       -viewportOffsetY);
+
+			offsetMask = PAINT_WINDOW_WITH_OFFSET_MASK;
+		    }
+		}
+
+		/* copy region */
+		XSubtractRegion (r, &emptyRegion, c->clip);
+
+		if ((*painter.paintObject) (c,
+					    &cPaint,
+					    &cTransform,
+					    r,
+					    mask | offsetMask) && !occlude)
+		    XSubtractRegion (r, c->region, r);
+
+		if (viewportOffsetX || viewportOffsetY)
+		    XOffsetRegion (r,
+				   viewportOffsetX,
+				   viewportOffsetY);
+
+		/* unredirect top most top-level fullscreen windows. */
+		if (!w->parent &&
+		    count == 0 &&
+		    w->screen->opt[COMP_SCREEN_OPTION_UNREDIRECT_FS].value.b)
+		{
+		    if (XEqualRegion (c->region, &w->screen->region) &&
+			!REGION_NOT_EMPTY (r))
+		    {
+			fullscreenWindow = c;
+		    }
+		    else
+		    {
+			int i;
+
+			for (i = 0; i < w->screen->nOutputDev; i++)
+			    if (XEqualRegion (c->region,
+					      &w->screen->outputDev[i].region))
+				fullscreenWindow = c;
+		    }
+		}
+
+		count++;
+	    }
+
+	    if (fullscreenWindow)
+		unredirectWindow (fullscreenWindow);
+
+	    if (!occlude)
+	    {
+		if (w->attrib.x || w->attrib.y)
+		    XOffsetRegion (r, w->attrib.x, w->attrib.y);
+
+		XSubtractRegion (region, w->region, region);
+		XUnionRegion (region, r, region);
+	    }
+
+	    XDestroyRegion (r);
+	}
+
+	if (painter.fini)
+	    (*painter.fini) (w->screen, &painter);
+	if (walk.fini)
+	    (*walk.fini) (w->screen, &walk);
+
+	return occlude;
     }
 
     if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
-	return TRUE;
+    {
+	status = TRUE;
+    }
+    else
+    {
+	FragmentAttrib fragment;
 
-    initFragmentAttrib (&fragment, attrib);
+	initFragmentAttrib (&fragment, attrib);
 
-    if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
-        mask & PAINT_WINDOW_WITH_OFFSET_MASK)
-    {
-	glPushMatrix ();
-	glLoadMatrixf (transform->m);
+	if (mask & (PAINT_WINDOW_TRANSFORMED_MASK |
+		    PAINT_WINDOW_WITH_OFFSET_MASK))
+	{
+	    glPushMatrix ();
+	    glLoadMatrixf (transform->m);
+	}
+
+	status = (*w->screen->drawWindow) (w, transform, &fragment, region, mask);
+
+	if (mask & (PAINT_WINDOW_TRANSFORMED_MASK |
+		    PAINT_WINDOW_WITH_OFFSET_MASK))
+	    glPopMatrix ();
     }
 
-    status = (*w->screen->drawWindow) (w, transform, &fragment, region, mask);
+    (*w->screen->initWindowWalker) (w->screen, w, &walk);
+    (*w->screen->initObjectPainter) (w->screen, &painter);
+
+    c = (*walk.first) (w);
+    if (c)
+    {
+	Region        clip = NULL;
+	CompTransform wTransform = *transform;
+	unsigned int  clipMask = PAINT_WINDOW_WITH_TRANSFORMED_CHILD_MASK;
+
+	if (!(mask & PAINT_WINDOW_CLIP_MASK))
+	{
+	    clip = XCreateRegion ();
+	    assert (clip);
+	    XIntersectRegion (region, w->region, clip);
+	}
+
+	if (w->attrib.x || w->attrib.y)
+	{
+	    matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0);
+
+	    mask |= PAINT_WINDOW_WITH_OFFSET_MASK;
+
+	    if (clip)
+		XOffsetRegion (clip, -w->attrib.x, -w->attrib.y);
+	}
+
+	if (w->redirectSubwindows)
+	{
+	    /* root only need clip planes when transformed */
+	    if (!w->parent)
+		clipMask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+
+	    if ((mask & clipMask) == clipMask)
+	    {
+		glPushAttrib (GL_TRANSFORM_BIT);
+
+		if (mask & PAINT_WINDOW_CLIP_MASK)
+		{
+		    REGION reg;
+
+		    reg.rects    = &reg.extents;
+		    reg.numRects = reg.size = 1;
+		    reg.extents  = w->clip->extents;
+
+		    if (reg.extents.x1 < w->region->extents.x1)
+			reg.extents.x1 = w->region->extents.x1;
+		    if (reg.extents.y1 < w->region->extents.y1)
+			reg.extents.y1 = w->region->extents.y1;
+		    if (reg.extents.x2 > w->region->extents.x2)
+			reg.extents.x2 = w->region->extents.x2;
+		    if (reg.extents.y2 > w->region->extents.y2)
+			reg.extents.y2 = w->region->extents.y2;
+
+		    reg.extents.x1 -= w->attrib.x;
+		    reg.extents.y1 -= w->attrib.y;
+		    reg.extents.x2 -= w->attrib.x;
+		    reg.extents.y2 -= w->attrib.y;
+
+		    (*w->screen->enableOutputClipping) (w->screen,
+							&wTransform,
+							&reg,
+							0);
+		}
+		else
+		    (*w->screen->enableOutputClipping) (w->screen,
+							&wTransform,
+							clip,
+							0);
+	    }
+	}
+
+	/* paint all sub-windows from bottom to top */
+	for (; c; c = (*walk.next) (c))
+	{
+	    CompTransform     cTransform = wTransform;
+	    WindowPaintAttrib cPaint = c->paint;
+	    int               viewportOffsetX = 0;
+	    int               viewportOffsetY = 0;
+	    int               offsetMask = 0;
+
+	    if (c->destroyed)
+		continue;
+
+	    cPaint.opacity = MULTIPLY_USHORT (cPaint.opacity,
+					      attrib->opacity);
+	    cPaint.brightness = MULTIPLY_USHORT (cPaint.brightness,
+						 attrib->brightness);
+	    cPaint.saturation = MULTIPLY_USHORT (cPaint.saturation,
+						 attrib->saturation);
 
-    if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
-        mask & PAINT_WINDOW_WITH_OFFSET_MASK)
-	glPopMatrix ();
+	    if (mask & PAINT_WINDOW_CLIP_MASK)
+		clip = c->clip;
+
+	    if (!windowOnAllViewports (c))
+	    {
+		if (w->viewportOffsetX || w->viewportOffsetY)
+		{
+		    getWindowMovementForOffset (w,
+						w->viewportOffsetX,
+						w->viewportOffsetY,
+						&viewportOffsetX,
+						&viewportOffsetY);
+
+		    matrixTranslate (&cTransform,
+				     viewportOffsetX,
+				     viewportOffsetY,
+				     0);
+
+		    if (clip != c->clip)
+			XOffsetRegion (clip,
+				       -viewportOffsetX,
+				       -viewportOffsetY);
+
+		    offsetMask = PAINT_WINDOW_WITH_OFFSET_MASK;
+		}
+	    }
+
+	    (*painter.paintObject) (c,
+				    &cPaint,
+				    &cTransform,
+				    clip,
+				    mask | offsetMask);
+
+	    if (clip != c->clip && (viewportOffsetX || viewportOffsetY))
+		XOffsetRegion (clip,
+			       viewportOffsetX,
+			       viewportOffsetY);
+	}
+
+	if (w->redirectSubwindows)
+	{
+	    if ((mask & clipMask) == clipMask)
+		glPopAttrib ();
+	}
+
+	if (!(mask & PAINT_WINDOW_CLIP_MASK))
+	    XDestroyRegion (clip);
+    }
+
+    if (painter.fini)
+	(*painter.fini) (w->screen, &painter);
+    if (walk.fini)
+	(*walk.fini) (w->screen, &walk);
 
     return status;
 }
+
+static void
+drawWindowAndChildren (CompWindow              *w,
+		       const WindowPaintAttrib *attrib,
+		       const CompTransform     *transform,
+		       Region                  region)
+{
+    FragmentAttrib fragment;
+    unsigned int   wMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+
+    if (attrib)
+	initFragmentAttrib (&fragment, attrib);
+    else
+	initFragmentAttrib (&fragment, &w->lastPaint);
+
+    if (w->alpha || fragment.opacity != OPAQUE)
+	wMask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+    (*w->screen->drawWindow) (w, transform, &fragment, region, wMask);
+
+    if (w->windows)
+    {
+	Region r;
+
+	r = XCreateRegion ();
+	if (r)
+	{
+	    CompWindow *c;
+
+	    XSubtractRegion (region, &emptyRegion, r);
+	    XIntersectRegion (r, w->region, r);
+	    XOffsetRegion (r, -w->attrib.x, -w->attrib.y);
+
+	    glTranslatef (w->attrib.x, w->attrib.y, 0);
+
+	    for (c = w->windows; c; c = c->next)
+		drawWindowAndChildren (c, attrib, transform, r);
+
+	    glTranslatef (-w->attrib.x, -w->attrib.y, 0);
+
+	    XDestroyRegion (r);
+	}
+    }
+}
+
+void
+drawTransformedWindowWithChildren (CompWindow              *w,
+				   const WindowPaintAttrib *attrib,
+				   const CompTransform     *transform)
+{
+    FragmentAttrib fragment;
+    unsigned int   wMask = PAINT_WINDOW_TRANSFORMED_MASK;
+
+    if (attrib)
+	initFragmentAttrib (&fragment, attrib);
+    else
+	initFragmentAttrib (&fragment, &w->lastPaint);
+
+    if (w->alpha || fragment.opacity != OPAQUE)
+	wMask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+    glPushMatrix ();
+    glLoadMatrixf (transform->m);
+
+    (*w->screen->drawWindow) (w, transform, &fragment, &infiniteRegion, wMask);
+
+    if (w->windows)
+    {
+	CompWindow *c;
+
+	XOffsetRegion (w->region, -w->attrib.x, -w->attrib.y);
+	glTranslatef (w->attrib.x, w->attrib.y, 0);
+
+	for (c = w->windows; c; c = c->next)
+	    drawWindowAndChildren (c, attrib, transform, w->region);
+
+	glTranslatef (-w->attrib.x, -w->attrib.y, 0);
+	XOffsetRegion (w->region, w->attrib.x, w->attrib.y);
+    }
+
+    glPopMatrix ();
+}
diff --git a/src/screen.c b/src/screen.c
index 33cb3cc..7f00f23 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -184,6 +184,9 @@ setDesktopHints (CompScreen *s)
     unsigned long *data;
     int		  size, offset, hintSize, i;
 
+    if (!s->root.substructureRedirect)
+	return;
+
     size = s->nDesktop * 2 + s->nDesktop * 2 + s->nDesktop * 4 + 1;
 
     data = malloc (sizeof (unsigned long) * size);
@@ -200,7 +203,7 @@ setDesktopHints (CompScreen *s)
     }
 
     if (!desktopHintEqual (s, data, size, offset, hintSize))
-	XChangeProperty (d->display, s->root, d->desktopViewportAtom,
+	XChangeProperty (d->display, s->root.id, d->desktopViewportAtom,
 			 XA_CARDINAL, 32, PropModeReplace,
 			 (unsigned char *) &data[offset], hintSize);
 
@@ -213,7 +216,7 @@ setDesktopHints (CompScreen *s)
     }
 
     if (!desktopHintEqual (s, data, size, offset, hintSize))
-	XChangeProperty (d->display, s->root, d->desktopGeometryAtom,
+	XChangeProperty (d->display, s->root.id, d->desktopGeometryAtom,
 			 XA_CARDINAL, 32, PropModeReplace,
 			 (unsigned char *) &data[offset], hintSize);
 
@@ -229,7 +232,7 @@ setDesktopHints (CompScreen *s)
     }
 
     if (!desktopHintEqual (s, data, size, offset, hintSize))
-	XChangeProperty (d->display, s->root, d->workareaAtom,
+	XChangeProperty (d->display, s->root.id, d->workareaAtom,
 			 XA_CARDINAL, 32, PropModeReplace,
 			 (unsigned char *) &data[offset], hintSize);
 
@@ -239,7 +242,7 @@ setDesktopHints (CompScreen *s)
     hintSize = 1;
 
     if (!desktopHintEqual (s, data, size, offset, hintSize))
-	XChangeProperty (d->display, s->root, d->numberOfDesktopsAtom,
+	XChangeProperty (d->display, s->root.id, d->numberOfDesktopsAtom,
 			 XA_CARDINAL, 32, PropModeReplace,
 			 (unsigned char *) &data[offset], hintSize);
 
@@ -375,8 +378,11 @@ updateOutputDevices (CompScreen	*s)
 
     updateWorkareaForScreen (s);
 
-    setDefaultViewport (s);
-    damageScreen (s);
+    if (manualCompositeManagement)
+    {
+	setDefaultViewport (s);
+	damageScreen (s);
+    }
 
     region = XCreateRegion ();
     if (region)
@@ -644,9 +650,9 @@ static void
 updateStartupFeedback (CompScreen *s)
 {
     if (s->startupSequences)
-	XDefineCursor (s->display->display, s->root, s->busyCursor);
+	XDefineCursor (s->display->display, s->root.id, s->busyCursor);
     else
-	XDefineCursor (s->display->display, s->root, s->normalCursor);
+	XDefineCursor (s->display->display, s->root.id, s->normalCursor);
 }
 
 #define STARTUP_TIMEOUT_DELAY 15000
@@ -853,11 +859,12 @@ reshape (CompScreen *s,
 {
 
 #ifdef USE_COW
-    if (useCow)
+    if (useCow && manualCompositeManagement)
 	XMoveResizeWindow (s->display->display, s->overlay, 0, 0, w, h);
 #endif
 
-    if (s->display->xineramaExtension)
+    if (s->display->xineramaExtension &&
+	XineramaIsActive (s->display->display))
     {
 	CompDisplay *d = s->display;
 
@@ -971,7 +978,7 @@ updateScreenBackground (CompScreen  *screen,
 
     for (i = 0; pixmap == 0 && i < 2; i++)
     {
-	status = XGetWindowProperty (dpy, screen->root,
+	status = XGetWindowProperty (dpy, screen->root.id,
 				     screen->display->xBackgroundAtom[i],
 				     0, 4, FALSE, AnyPropertyType,
 				     &actualType, &actualFormat, &nItems,
@@ -1054,7 +1061,7 @@ detectRefreshRateOfScreen (CompScreen *s)
 	{
 	    XRRScreenConfiguration *config;
 
-	    config  = XRRGetScreenInfo (s->display->display, s->root);
+	    config  = XRRGetScreenInfo (s->display->display, s->root.id);
 	    value.i = (int) XRRConfigCurrentRate (config);
 
 	    XRRFreeScreenConfigInfo (config);
@@ -1081,6 +1088,8 @@ setSupportingWmCheck (CompScreen *s)
 {
     CompDisplay *d = s->display;
 
+    s->root.supportingWmCheckWindow = s->grabWindow;
+
     XChangeProperty (d->display, s->grabWindow, d->supportingWmCheckAtom,
 		     XA_WINDOW, 32, PropModeReplace,
 		     (unsigned char *) &s->grabWindow, 1);
@@ -1098,7 +1107,7 @@ setSupportingWmCheck (CompScreen *s)
 		     XA_ATOM, 32, PropModeAppend,
 		     (unsigned char *) &d->winStateHiddenAtom, 1);
 
-    XChangeProperty (d->display, s->root, d->supportingWmCheckAtom,
+    XChangeProperty (d->display, s->root.id, d->supportingWmCheckAtom,
 		     XA_WINDOW, 32, PropModeReplace,
 		     (unsigned char *) &s->grabWindow, 1);
 }
@@ -1199,11 +1208,66 @@ setSupported (CompScreen *s)
     data[i++] = d->moveResizeWindowAtom;
     data[i++] = d->restackWindowAtom;
 
-    XChangeProperty (d->display, s->root, d->supportedAtom, XA_ATOM, 32,
+    data[i++] = d->syncStateAtom;
+
+    XChangeProperty (d->display, s->root.id, d->supportedAtom, XA_ATOM, 32,
 		     PropModeReplace, (unsigned char *) data, i);
 }
 
-static void
+void
+getSupportingWmCheck (CompWindow *w)
+{
+    CompDisplay   *d = w->screen->display;
+    Atom	  actual;
+    int		  result, format;
+    unsigned long n, left;
+    unsigned char *propData;
+
+    w->supportingWmCheckWindow = None;
+    w->syncStateSupport        = FALSE;
+
+    result = XGetWindowProperty (d->display, w->id,
+				 d->supportingWmCheckAtom, 0L, 1L, FALSE,
+				 XA_WINDOW, &actual, &format,
+				 &n, &left, &propData);
+    if (result == Success && n && propData)
+    {
+	Window wmCheckWindow = *((unsigned long *) propData);
+
+	XFree (propData);
+
+	result = XGetWindowProperty (d->display,
+				     wmCheckWindow,
+				     d->supportingWmCheckAtom, 0L, 1L, FALSE,
+				     XA_WINDOW, &actual, &format,
+				     &n, &left, &propData);
+	if (result == Success && n && propData)
+	{
+	    XFree (propData);
+
+	    w->supportingWmCheckWindow = wmCheckWindow;
+
+	    result = XGetWindowProperty (d->display,
+					 w->id,
+					 d->supportedAtom, 0L, 4096L,
+					 FALSE, XA_ATOM, &actual, &format,
+					 &n, &left, &propData);
+	    if (result == Success && n && propData)
+	    {
+		unsigned long *data = (unsigned long *) propData;
+		int           i;
+
+		for (i = 0; i < n; i++)
+		    if ((Atom) data[i] == d->syncStateAtom)
+			w->syncStateSupport = TRUE;
+
+		XFree (propData);
+	    }
+	}
+    }
+}
+
+void
 getDesktopHints (CompScreen *s)
 {
     CompDisplay   *d = s->display;
@@ -1215,7 +1279,7 @@ getDesktopHints (CompScreen *s)
 
     if (useDesktopHints)
     {
-	result = XGetWindowProperty (s->display->display, s->root,
+	result = XGetWindowProperty (s->display->display, s->root.id,
 				     d->numberOfDesktopsAtom, 0L, 1L, FALSE,
 				     XA_CARDINAL, &actual, &format,
 				     &n, &left, &propData);
@@ -1229,7 +1293,7 @@ getDesktopHints (CompScreen *s)
 		s->nDesktop = data[0];
 	}
 
-	result = XGetWindowProperty (s->display->display, s->root,
+	result = XGetWindowProperty (s->display->display, s->root.id,
 				     d->currentDesktopAtom, 0L, 1L, FALSE,
 				     XA_CARDINAL, &actual, &format,
 				     &n, &left, &propData);
@@ -1244,7 +1308,7 @@ getDesktopHints (CompScreen *s)
 	}
     }
 
-    result = XGetWindowProperty (s->display->display, s->root,
+    result = XGetWindowProperty (s->display->display, s->root.id,
 				 d->desktopViewportAtom, 0L, 2L,
 				 FALSE, XA_CARDINAL, &actual, &format,
 				 &n, &left, &propData);
@@ -1265,7 +1329,7 @@ getDesktopHints (CompScreen *s)
 	XFree (propData);
     }
 
-    result = XGetWindowProperty (s->display->display, s->root,
+    result = XGetWindowProperty (s->display->display, s->root.id,
 				 d->showingDesktopAtom, 0L, 1L, FALSE,
 				 XA_CARDINAL, &actual, &format,
 				 &n, &left, &propData);
@@ -1279,17 +1343,20 @@ getDesktopHints (CompScreen *s)
 	    (*s->enterShowDesktopMode) (s);
     }
 
-    data[0] = s->currentDesktop;
+    if (s->root.substructureRedirect)
+    {
+	data[0] = s->currentDesktop;
 
-    XChangeProperty (d->display, s->root, d->currentDesktopAtom,
-		     XA_CARDINAL, 32, PropModeReplace,
-		     (unsigned char *) data, 1);
+	XChangeProperty (d->display, s->root.id, d->currentDesktopAtom,
+			 XA_CARDINAL, 32, PropModeReplace,
+			 (unsigned char *) data, 1);
 
-    data[0] = s->showingDesktopMask ? TRUE : FALSE;
+	data[0] = s->showingDesktopMask ? TRUE : FALSE;
 
-    XChangeProperty (d->display, s->root, d->showingDesktopAtom,
-		     XA_CARDINAL, 32, PropModeReplace,
-		     (unsigned char *) data, 1);
+	XChangeProperty (d->display, s->root.id, d->showingDesktopAtom,
+			 XA_CARDINAL, 32, PropModeReplace,
+			 (unsigned char *) data, 1);
+    }
 }
 
 void
@@ -1297,7 +1364,7 @@ showOutputWindow (CompScreen *s)
 {
 
 #ifdef USE_COW
-    if (useCow)
+    if (useCow && manualCompositeManagement)
     {
 	Display       *dpy = s->display->display;
 	XserverRegion region;
@@ -1326,7 +1393,7 @@ hideOutputWindow (CompScreen *s)
 {
 
 #ifdef USE_COW
-    if (useCow)
+    if (useCow && manualCompositeManagement)
     {
 	Display       *dpy = s->display->display;
 	XserverRegion region;
@@ -1349,7 +1416,7 @@ updateOutputWindow (CompScreen *s)
 {
 
 #ifdef USE_COW
-    if (useCow)
+    if (useCow && manualCompositeManagement)
     {
 	Display       *dpy = s->display->display;
 	XserverRegion region;
@@ -1365,7 +1432,7 @@ updateOutputWindow (CompScreen *s)
 
 	XSubtractRegion (&s->region, &emptyRegion, tmpRegion);
 
-	for (w = s->reverseWindows; w; w = w->prev)
+	for (w = s->root.reverseWindows; w; w = w->prev)
 	    if (w->overlayWindow)
 	    {
 		XSubtractRegion (tmpRegion, w->region, tmpRegion);
@@ -1393,9 +1460,10 @@ makeOutputWindow (CompScreen *s)
 {
 
 #ifdef USE_COW
-    if (useCow)
+    if (useCow && manualCompositeManagement)
     {
-	s->overlay = XCompositeGetOverlayWindow (s->display->display, s->root);
+	s->overlay = XCompositeGetOverlayWindow (s->display->display,
+						 s->root.id);
 	s->output  = s->overlay;
 
 	XSelectInput (s->display->display, s->output, ExposureMask);
@@ -1403,7 +1471,7 @@ makeOutputWindow (CompScreen *s)
     else
 #endif
 
-	s->output = s->overlay = s->root;
+	s->output = s->overlay = s->root.id;
 
     showOutputWindow (s);
 }
@@ -1417,10 +1485,13 @@ enterShowDesktopMode (CompScreen *s)
     int		  count = 0;
     CompOption    *st = &d->opt[COMP_DISPLAY_OPTION_HIDE_SKIP_TASKBAR_WINDOWS];
 
+    if (!s->root.substructureRedirect)
+	return;
+
     s->showingDesktopMask = ~(CompWindowTypeDesktopMask |
 			      CompWindowTypeDockMask);
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if ((s->showingDesktopMask & w->wmType) &&
 	    (!(w->state & CompWindowStateSkipTaskbarMask) || st->value.b))
@@ -1443,7 +1514,7 @@ enterShowDesktopMode (CompScreen *s)
 	data = 0;
     }
 
-    XChangeProperty (s->display->display, s->root,
+    XChangeProperty (s->display->display, s->root.id,
 		     s->display->showingDesktopAtom,
 		     XA_CARDINAL, 32, PropModeReplace,
 		     (unsigned char *) &data, 1);
@@ -1456,6 +1527,9 @@ leaveShowDesktopMode (CompScreen *s,
     CompWindow    *w;
     unsigned long data = 0;
 
+    if (!s->root.substructureRedirect)
+	return;
+
     if (window)
     {
 	if (!window->inShowDesktopMode)
@@ -1465,7 +1539,7 @@ leaveShowDesktopMode (CompScreen *s,
 	showWindow (window);
 
 	/* return if some other window is still in show desktop mode */
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    if (w->inShowDesktopMode)
 		return;
 
@@ -1475,7 +1549,7 @@ leaveShowDesktopMode (CompScreen *s,
     {
 	s->showingDesktopMask = 0;
 
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	{
 	    if (!w->inShowDesktopMode)
 		continue;
@@ -1489,22 +1563,22 @@ leaveShowDesktopMode (CompScreen *s,
 	focusDefaultWindow (s);
     }
 
-    XChangeProperty (s->display->display, s->root,
+    XChangeProperty (s->display->display, s->root.id,
 		     s->display->showingDesktopAtom,
 		     XA_CARDINAL, 32, PropModeReplace,
 		     (unsigned char *) &data, 1);
 }
 
 static CompWindow *
-walkFirst (CompScreen *s)
+walkFirst (CompWindow *parent)
 {
-    return s->windows;
+    return parent->windows;
 }
 
 static CompWindow *
-walkLast (CompScreen *s)
+walkLast (CompWindow *parent)
 {
-    return s->reverseWindows;
+    return parent->reverseWindows;
 }
 
 static CompWindow *
@@ -1521,6 +1595,7 @@ walkPrev (CompWindow *w)
 
 static void
 initWindowWalker (CompScreen *screen,
+		  CompWindow *window,
 		  CompWalker *walker)
 {
     walker->fini  = NULL;
@@ -1530,6 +1605,42 @@ initWindowWalker (CompScreen *screen,
     walker->prev  = walkPrev;
 }
 
+static Bool
+paintObject (CompWindow		     *w,
+	     const WindowPaintAttrib *attrib,
+	     const CompTransform     *transform,
+	     Region		     region,
+	     unsigned int	     mask)
+{
+    PaintWindowProc paint = w->screen->paintWindow;
+    Bool            status;
+
+    if (w->parent)
+	w->paintWindowStack = w->parent->paintWindowStack;
+    else
+	w->paintWindowStack = paint;
+
+    status = (*w->paintWindowStack) (w, attrib, transform, region, mask);
+
+    w->screen->paintWindow = paint;
+
+    return status;
+}
+
+static void
+initObjectPainter (CompScreen  *screen,
+		   CompPainter *painter)
+{
+    painter->fini        = NULL;
+    painter->paintObject = paintObject;
+}
+
+static FuncPtr
+dummyGetProcAddress (const GLubyte *procName)
+{
+    return NULL;
+}
+
 static void
 freeScreen (CompScreen *s)
 {
@@ -1652,9 +1763,6 @@ addScreen (CompDisplay *display,
     s->hsize = s->opt[COMP_SCREEN_OPTION_HSIZE].value.i;
     s->vsize = s->opt[COMP_SCREEN_OPTION_VSIZE].value.i;
 
-    s->windowOffsetX = 0;
-    s->windowOffsetY = 0;
-
     s->nDesktop	      = 1;
     s->currentDesktop = 0;
 
@@ -1680,7 +1788,8 @@ addScreen (CompDisplay *display,
 
     s->screenNum = screenNum;
     s->colormap  = DefaultColormap (dpy, screenNum);
-    s->root	 = XRootWindow (dpy, screenNum);
+
+    initRootWindow (s, &s->root);
 
     s->mapNum    = 1;
     s->activeNum = 1;
@@ -1712,9 +1821,6 @@ addScreen (CompDisplay *display,
     s->nOutputDev	= 0;
     s->currentOutputDev = 0;
 
-    s->windows = 0;
-    s->reverseWindows = 0;
-
     s->nextRedraw  = 0;
     s->frameStatus = 0;
     s->timeMult    = 1;
@@ -1781,11 +1887,12 @@ addScreen (CompDisplay *display,
 
     s->outputChangeNotify = outputChangeNotify;
 
-    s->initWindowWalker = initWindowWalker;
+    s->initWindowWalker  = initWindowWalker;
+    s->initObjectPainter = initObjectPainter;
 
-    s->getProcAddress = 0;
+    s->getProcAddress = dummyGetProcAddress;
 
-    if (!XGetWindowAttributes (dpy, s->root, &s->attrib))
+    if (!XGetWindowAttributes (dpy, s->root.id, &s->attrib))
 	return FALSE;
 
     s->workArea.x      = 0;
@@ -1818,7 +1925,7 @@ addScreen (CompDisplay *display,
 	return FALSE;
     }
 
-    bitmap = XCreateBitmapFromData (dpy, s->root, &data, 1, 1);
+    bitmap = XCreateBitmapFromData (dpy, s->root.id, &data, 1, 1);
     if (!bitmap)
     {
 	compLogMessage ("core", CompLogLevelFatal, "Couldn't create bitmap");
@@ -1839,383 +1946,423 @@ addScreen (CompDisplay *display,
     XFreePixmap (dpy, bitmap);
     XFreeColors (dpy, s->colormap, &black.pixel, 1, 0);
 
-    glXGetConfig (dpy, visinfo, GLX_USE_GL, &value);
-    if (!value)
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"Root visual is not a GL visual");
-	XFree (visinfo);
-	return FALSE;
-    }
-
-    glXGetConfig (dpy, visinfo, GLX_DOUBLEBUFFER, &value);
-    if (!value)
+    if (s->root.redirectSubwindows)
     {
-	compLogMessage ("core", CompLogLevelFatal,
-			"Root visual is not a double buffered GL visual");
-	XFree (visinfo);
-	return FALSE;
-    }
+	glXGetConfig (dpy, visinfo, GLX_USE_GL, &value);
+	if (!value)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "Root visual is not a GL visual");
+	    XFree (visinfo);
+	    return FALSE;
+	}
 
-    s->ctx = glXCreateContext (dpy, visinfo, NULL, !indirectRendering);
-    if (!s->ctx)
-    {
-	compLogMessage ("core", CompLogLevelFatal, "glXCreateContext failed");
-	XFree (visinfo);
+	glXGetConfig (dpy, visinfo, GLX_DOUBLEBUFFER, &value);
+	if (!value)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "Root visual is not a double buffered GL visual");
+	    XFree (visinfo);
+	    return FALSE;
+	}
 
-	return FALSE;
-    }
+	s->ctx = glXCreateContext (dpy, visinfo, NULL, !indirectRendering);
+	if (!s->ctx)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "glXCreateContext failed");
+	    XFree (visinfo);
 
-    glxExtensions = glXQueryExtensionsString (dpy, screenNum);
-    if (!strstr (glxExtensions, "GLX_EXT_texture_from_pixmap"))
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"GLX_EXT_texture_from_pixmap is missing");
-	XFree (visinfo);
+	    return FALSE;
+	}
 
-	return FALSE;
-    }
+	glxExtensions = glXQueryExtensionsString (dpy, screenNum);
+	if (!strstr (glxExtensions, "GLX_EXT_texture_from_pixmap"))
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "GLX_EXT_texture_from_pixmap is missing");
+	    XFree (visinfo);
 
-    XFree (visinfo);
+	    return FALSE;
+	}
 
-    if (!strstr (glxExtensions, "GLX_SGIX_fbconfig"))
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"GLX_SGIX_fbconfig is missing");
-	return FALSE;
-    }
+	XFree (visinfo);
 
-    s->getProcAddress = (GLXGetProcAddressProc)
-	getProcAddress (s, "glXGetProcAddressARB");
-    s->bindTexImage = (GLXBindTexImageProc)
-	getProcAddress (s, "glXBindTexImageEXT");
-    s->releaseTexImage = (GLXReleaseTexImageProc)
-	getProcAddress (s, "glXReleaseTexImageEXT");
-    s->queryDrawable = (GLXQueryDrawableProc)
-	getProcAddress (s, "glXQueryDrawable");
-    s->getFBConfigs = (GLXGetFBConfigsProc)
-	getProcAddress (s, "glXGetFBConfigs");
-    s->getFBConfigAttrib = (GLXGetFBConfigAttribProc)
-	getProcAddress (s, "glXGetFBConfigAttrib");
-    s->createPixmap = (GLXCreatePixmapProc)
-	getProcAddress (s, "glXCreatePixmap");
-
-    if (!s->bindTexImage)
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"glXBindTexImageEXT is missing");
-	return FALSE;
-    }
+	if (!strstr (glxExtensions, "GLX_SGIX_fbconfig"))
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "GLX_SGIX_fbconfig is missing");
+	    return FALSE;
+	}
 
-    if (!s->releaseTexImage)
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"glXReleaseTexImageEXT is missing");
-	return FALSE;
-    }
+	s->getProcAddress = (GLXGetProcAddressProc)
+	    getProcAddress (s, "glXGetProcAddressARB");
+	s->bindTexImage = (GLXBindTexImageProc)
+	    getProcAddress (s, "glXBindTexImageEXT");
+	s->releaseTexImage = (GLXReleaseTexImageProc)
+	    getProcAddress (s, "glXReleaseTexImageEXT");
+	s->queryDrawable = (GLXQueryDrawableProc)
+	    getProcAddress (s, "glXQueryDrawable");
+	s->getFBConfigs = (GLXGetFBConfigsProc)
+	    getProcAddress (s, "glXGetFBConfigs");
+	s->getFBConfigAttrib = (GLXGetFBConfigAttribProc)
+	    getProcAddress (s, "glXGetFBConfigAttrib");
+	s->createPixmap = (GLXCreatePixmapProc)
+	    getProcAddress (s, "glXCreatePixmap");
+
+	if (!s->bindTexImage)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "glXBindTexImageEXT is missing");
+	    return FALSE;
+	}
 
-    if (!s->queryDrawable     ||
-	!s->getFBConfigs      ||
-	!s->getFBConfigAttrib ||
-	!s->createPixmap)
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"fbconfig functions missing");
-	return FALSE;
-    }
+	if (!s->releaseTexImage)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "glXReleaseTexImageEXT is missing");
+	    return FALSE;
+	}
 
-    s->copySubBuffer = NULL;
-    if (strstr (glxExtensions, "GLX_MESA_copy_sub_buffer"))
-	s->copySubBuffer = (GLXCopySubBufferProc)
-	    getProcAddress (s, "glXCopySubBufferMESA");
+	if (!s->queryDrawable     ||
+	    !s->getFBConfigs      ||
+	    !s->getFBConfigAttrib ||
+	    !s->createPixmap)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "fbconfig functions missing");
+	    return FALSE;
+	}
 
-    s->getVideoSync = NULL;
-    s->waitVideoSync = NULL;
-    if (strstr (glxExtensions, "GLX_SGI_video_sync"))
-    {
-	s->getVideoSync = (GLXGetVideoSyncProc)
-	    getProcAddress (s, "glXGetVideoSyncSGI");
+	s->copySubBuffer = NULL;
+	if (strstr (glxExtensions, "GLX_MESA_copy_sub_buffer"))
+	    s->copySubBuffer = (GLXCopySubBufferProc)
+		getProcAddress (s, "glXCopySubBufferMESA");
 
-	s->waitVideoSync = (GLXWaitVideoSyncProc)
-	    getProcAddress (s, "glXWaitVideoSyncSGI");
-    }
+	s->getVideoSync = NULL;
+	s->waitVideoSync = NULL;
+	if (strstr (glxExtensions, "GLX_SGI_video_sync"))
+	{
+	    s->getVideoSync = (GLXGetVideoSyncProc)
+		getProcAddress (s, "glXGetVideoSyncSGI");
 
-    glXMakeCurrent (dpy, s->output, s->ctx);
-    currentRoot = s->root;
+	    s->waitVideoSync = (GLXWaitVideoSyncProc)
+		getProcAddress (s, "glXWaitVideoSyncSGI");
+	}
 
-    glExtensions = (const char *) glGetString (GL_EXTENSIONS);
-    if (!glExtensions)
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"No valid GL extensions string found.");
-	return FALSE;
-    }
+	glXMakeCurrent (dpy, s->output, s->ctx);
+	currentRoot = s->root.id;
 
-    s->textureNonPowerOfTwo = 0;
-    if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
-	s->textureNonPowerOfTwo = 1;
+	glExtensions = (const char *) glGetString (GL_EXTENSIONS);
+	if (!glExtensions)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "No valid GL extensions string found.");
+	    return FALSE;
+	}
 
-    glGetIntegerv (GL_MAX_TEXTURE_SIZE, &s->maxTextureSize);
+	s->textureNonPowerOfTwo = 0;
+	if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
+	    s->textureNonPowerOfTwo = 1;
 
-    s->textureRectangle = 0;
-    if (strstr (glExtensions, "GL_NV_texture_rectangle")  ||
-	strstr (glExtensions, "GL_EXT_texture_rectangle") ||
-	strstr (glExtensions, "GL_ARB_texture_rectangle"))
-    {
-	s->textureRectangle = 1;
+	glGetIntegerv (GL_MAX_TEXTURE_SIZE, &s->maxTextureSize);
 
-	if (!s->textureNonPowerOfTwo)
+	s->textureRectangle = 0;
+	if (strstr (glExtensions, "GL_NV_texture_rectangle")  ||
+	    strstr (glExtensions, "GL_EXT_texture_rectangle") ||
+	    strstr (glExtensions, "GL_ARB_texture_rectangle"))
 	{
-	    GLint maxTextureSize;
+	    s->textureRectangle = 1;
 
-	    glGetIntegerv (GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &maxTextureSize);
-	    if (maxTextureSize > s->maxTextureSize)
-		s->maxTextureSize = maxTextureSize;
-	}
-    }
+	    if (!s->textureNonPowerOfTwo)
+	    {
+		GLint maxTextureSize;
 
-    if (!(s->textureRectangle || s->textureNonPowerOfTwo))
-    {
-	compLogMessage ("core", CompLogLevelFatal,
-			"Support for non power of two textures missing");
-	return FALSE;
-    }
+		glGetIntegerv (GL_MAX_RECTANGLE_TEXTURE_SIZE_NV,
+			       &maxTextureSize);
+		if (maxTextureSize > s->maxTextureSize)
+		    s->maxTextureSize = maxTextureSize;
+	    }
+	}
 
-    s->textureEnvCombine = s->textureEnvCrossbar = 0;
-    if (strstr (glExtensions, "GL_ARB_texture_env_combine"))
-    {
-	s->textureEnvCombine = 1;
+	if (!(s->textureRectangle || s->textureNonPowerOfTwo))
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "Support for non power of two textures missing");
+	    return FALSE;
+	}
 
-	/* XXX: GL_NV_texture_env_combine4 need special code but it seams to
-	   be working anyway for now... */
-	if (strstr (glExtensions, "GL_ARB_texture_env_crossbar") ||
-	    strstr (glExtensions, "GL_NV_texture_env_combine4"))
-	    s->textureEnvCrossbar = 1;
-    }
+	s->textureEnvCombine = s->textureEnvCrossbar = 0;
+	if (strstr (glExtensions, "GL_ARB_texture_env_combine"))
+	{
+	    s->textureEnvCombine = 1;
 
-    s->textureBorderClamp = 0;
-    if (strstr (glExtensions, "GL_ARB_texture_border_clamp") ||
-	strstr (glExtensions, "GL_SGIS_texture_border_clamp"))
-	s->textureBorderClamp = 1;
+	    /* XXX: GL_NV_texture_env_combine4 need special code but it
+	       seems to be working anyway for now... */
+	    if (strstr (glExtensions, "GL_ARB_texture_env_crossbar") ||
+		strstr (glExtensions, "GL_NV_texture_env_combine4"))
+		s->textureEnvCrossbar = 1;
+	}
 
-    s->maxTextureUnits = 1;
-    if (strstr (glExtensions, "GL_ARB_multitexture"))
-    {
-	s->activeTexture = (GLActiveTextureProc)
-	    getProcAddress (s, "glActiveTexture");
-	s->clientActiveTexture = (GLClientActiveTextureProc)
-	    getProcAddress (s, "glClientActiveTexture");
-	s->multiTexCoord2f = (GLMultiTexCoord2fProc)
-	    getProcAddress (s, "glMultiTexCoord2f");
-
-	if (s->activeTexture && s->clientActiveTexture && s->multiTexCoord2f)
-	    glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &s->maxTextureUnits);
-    }
+	s->textureBorderClamp = 0;
+	if (strstr (glExtensions, "GL_ARB_texture_border_clamp") ||
+	    strstr (glExtensions, "GL_SGIS_texture_border_clamp"))
+	    s->textureBorderClamp = 1;
 
-    s->fragmentProgram = 0;
-    if (strstr (glExtensions, "GL_ARB_fragment_program"))
-    {
-	s->genPrograms = (GLGenProgramsProc)
-	    getProcAddress (s, "glGenProgramsARB");
-	s->deletePrograms = (GLDeleteProgramsProc)
-	    getProcAddress (s, "glDeleteProgramsARB");
-	s->bindProgram = (GLBindProgramProc)
-	    getProcAddress (s, "glBindProgramARB");
-	s->programString = (GLProgramStringProc)
-	    getProcAddress (s, "glProgramStringARB");
-	s->programEnvParameter4f = (GLProgramParameter4fProc)
-	    getProcAddress (s, "glProgramEnvParameter4fARB");
-	s->programLocalParameter4f = (GLProgramParameter4fProc)
-	    getProcAddress (s, "glProgramLocalParameter4fARB");
-	s->getProgramiv = (GLGetProgramivProc)
-	    getProcAddress (s, "glGetProgramivARB");
-
-	if (s->genPrograms	       &&
-	    s->deletePrograms	       &&
-	    s->bindProgram	       &&
-	    s->programString	       &&
-	    s->programEnvParameter4f   &&
-	    s->programLocalParameter4f &&
-	    s->getProgramiv)
-	    s->fragmentProgram = 1;
-    }
+	s->maxTextureUnits = 1;
+	if (strstr (glExtensions, "GL_ARB_multitexture"))
+	{
+	    s->activeTexture = (GLActiveTextureProc)
+		getProcAddress (s, "glActiveTexture");
+	    s->clientActiveTexture = (GLClientActiveTextureProc)
+		getProcAddress (s, "glClientActiveTexture");
+	    s->multiTexCoord2f = (GLMultiTexCoord2fProc)
+		getProcAddress (s, "glMultiTexCoord2f");
+
+	    if (s->activeTexture       &&
+		s->clientActiveTexture &&
+		s->multiTexCoord2f)
+		glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &s->maxTextureUnits);
+	}
 
-    s->fbo = 0;
-    if (strstr (glExtensions, "GL_EXT_framebuffer_object"))
-    {
-	s->genFramebuffers = (GLGenFramebuffersProc)
-	    getProcAddress (s, "glGenFramebuffersEXT");
-	s->deleteFramebuffers = (GLDeleteFramebuffersProc)
-	    getProcAddress (s, "glDeleteFramebuffersEXT");
-	s->bindFramebuffer = (GLBindFramebufferProc)
-	    getProcAddress (s, "glBindFramebufferEXT");
-	s->checkFramebufferStatus = (GLCheckFramebufferStatusProc)
-	    getProcAddress (s, "glCheckFramebufferStatusEXT");
-	s->framebufferTexture2D = (GLFramebufferTexture2DProc)
-	    getProcAddress (s, "glFramebufferTexture2DEXT");
-	s->generateMipmap = (GLGenerateMipmapProc)
-	    getProcAddress (s, "glGenerateMipmapEXT");
-
-	if (s->genFramebuffers	      &&
-	    s->deleteFramebuffers     &&
-	    s->bindFramebuffer	      &&
-	    s->checkFramebufferStatus &&
-	    s->framebufferTexture2D   &&
-	    s->generateMipmap)
-	    s->fbo = 1;
-    }
+	s->fragmentProgram = 0;
+	if (strstr (glExtensions, "GL_ARB_fragment_program"))
+	{
+	    s->genPrograms = (GLGenProgramsProc)
+		getProcAddress (s, "glGenProgramsARB");
+	    s->deletePrograms = (GLDeleteProgramsProc)
+		getProcAddress (s, "glDeleteProgramsARB");
+	    s->bindProgram = (GLBindProgramProc)
+		getProcAddress (s, "glBindProgramARB");
+	    s->programString = (GLProgramStringProc)
+		getProcAddress (s, "glProgramStringARB");
+	    s->programEnvParameter4f = (GLProgramParameter4fProc)
+		getProcAddress (s, "glProgramEnvParameter4fARB");
+	    s->programLocalParameter4f = (GLProgramParameter4fProc)
+		getProcAddress (s, "glProgramLocalParameter4fARB");
+	    s->getProgramiv = (GLGetProgramivProc)
+		getProcAddress (s, "glGetProgramivARB");
+
+	    if (s->genPrograms	           &&
+		s->deletePrograms	   &&
+		s->bindProgram	           &&
+		s->programString	   &&
+		s->programEnvParameter4f   &&
+		s->programLocalParameter4f &&
+		s->getProgramiv)
+		s->fragmentProgram = 1;
+	}
 
-    s->textureCompression = 0;
-    if (strstr (glExtensions, "GL_ARB_texture_compression"))
-	s->textureCompression = 1;
+	s->fbo = 0;
+	if (strstr (glExtensions, "GL_EXT_framebuffer_object"))
+	{
+	    s->genFramebuffers = (GLGenFramebuffersProc)
+		getProcAddress (s, "glGenFramebuffersEXT");
+	    s->deleteFramebuffers = (GLDeleteFramebuffersProc)
+		getProcAddress (s, "glDeleteFramebuffersEXT");
+	    s->bindFramebuffer = (GLBindFramebufferProc)
+		getProcAddress (s, "glBindFramebufferEXT");
+	    s->checkFramebufferStatus = (GLCheckFramebufferStatusProc)
+		getProcAddress (s, "glCheckFramebufferStatusEXT");
+	    s->framebufferTexture2D = (GLFramebufferTexture2DProc)
+		getProcAddress (s, "glFramebufferTexture2DEXT");
+	    s->generateMipmap = (GLGenerateMipmapProc)
+		getProcAddress (s, "glGenerateMipmapEXT");
+
+	    if (s->genFramebuffers	  &&
+		s->deleteFramebuffers     &&
+		s->bindFramebuffer	  &&
+		s->checkFramebufferStatus &&
+		s->framebufferTexture2D   &&
+		s->generateMipmap)
+		s->fbo = 1;
+	}
 
-    fbConfigs = (*s->getFBConfigs) (dpy,
-				    screenNum,
-				    &nElements);
+	s->textureCompression = 0;
+	if (strstr (glExtensions, "GL_ARB_texture_compression"))
+	    s->textureCompression = 1;
 
-    for (i = 0; i <= MAX_DEPTH; i++)
-    {
-	int j, db, stencil, depth, alpha, mipmap, rgba;
+	fbConfigs = (*s->getFBConfigs) (dpy,
+					screenNum,
+					&nElements);
 
-	s->glxPixmapFBConfigs[i].fbConfig       = NULL;
-	s->glxPixmapFBConfigs[i].mipmap         = 0;
-	s->glxPixmapFBConfigs[i].yInverted      = 0;
-	s->glxPixmapFBConfigs[i].textureFormat  = 0;
-	s->glxPixmapFBConfigs[i].textureTargets = 0;
+	for (i = 0; i <= MAX_DEPTH; i++)
+	{
+	    int j, db, stencil, depth, alpha, mipmap, rgba;
 
-	db      = MAXSHORT;
-	stencil = MAXSHORT;
-	depth   = MAXSHORT;
-	mipmap  = 0;
-	rgba    = 0;
+	    s->glxPixmapFBConfigs[i].fbConfig       = NULL;
+	    s->glxPixmapFBConfigs[i].mipmap         = 0;
+	    s->glxPixmapFBConfigs[i].yInverted      = 0;
+	    s->glxPixmapFBConfigs[i].textureFormat  = 0;
+	    s->glxPixmapFBConfigs[i].textureTargets = 0;
 
-	for (j = 0; j < nElements; j++)
-	{
-	    XVisualInfo *vi;
-	    int		visualDepth;
+	    db      = MAXSHORT;
+	    stencil = MAXSHORT;
+	    depth   = MAXSHORT;
+	    mipmap  = 0;
+	    rgba    = 0;
 
-	    vi = glXGetVisualFromFBConfig (dpy, fbConfigs[j]);
-	    if (vi == NULL)
-		continue;
+	    for (j = 0; j < nElements; j++)
+	    {
+		XVisualInfo *vi;
+		int		visualDepth;
 
-	    visualDepth = vi->depth;
+		vi = glXGetVisualFromFBConfig (dpy, fbConfigs[j]);
+		if (vi == NULL)
+		    continue;
 
-	    XFree (vi);
+		visualDepth = vi->depth;
 
-	    if (visualDepth != i)
-		continue;
+		XFree (vi);
 
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_ALPHA_SIZE,
-				     &alpha);
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_BUFFER_SIZE,
-				     &value);
-	    if (value != i && (value - alpha) != i)
-		continue;
+		if (visualDepth != i)
+		    continue;
 
-	    value = 0;
-	    if (i == 32)
-	    {
 		(*s->getFBConfigAttrib) (dpy,
 					 fbConfigs[j],
-					 GLX_BIND_TO_TEXTURE_RGBA_EXT,
+					 GLX_ALPHA_SIZE,
+					 &alpha);
+		(*s->getFBConfigAttrib) (dpy,
+					 fbConfigs[j],
+					 GLX_BUFFER_SIZE,
 					 &value);
+		if (value != i && (value - alpha) != i)
+		    continue;
+
+		value = 0;
+		if (i == 32)
+		{
+		    (*s->getFBConfigAttrib) (dpy,
+					     fbConfigs[j],
+					     GLX_BIND_TO_TEXTURE_RGBA_EXT,
+					     &value);
+
+		    if (value)
+		    {
+			rgba = 1;
 
-		if (value)
+			s->glxPixmapFBConfigs[i].textureFormat =
+			    GLX_TEXTURE_FORMAT_RGBA_EXT;
+		    }
+		}
+
+		if (!value)
 		{
-		    rgba = 1;
+		    if (rgba)
+			continue;
+
+		    (*s->getFBConfigAttrib) (dpy,
+					     fbConfigs[j],
+					     GLX_BIND_TO_TEXTURE_RGB_EXT,
+					     &value);
+		    if (!value)
+			continue;
 
 		    s->glxPixmapFBConfigs[i].textureFormat =
-			GLX_TEXTURE_FORMAT_RGBA_EXT;
+			GLX_TEXTURE_FORMAT_RGB_EXT;
 		}
-	    }
 
-	    if (!value)
-	    {
-		if (rgba)
+		(*s->getFBConfigAttrib) (dpy,
+					 fbConfigs[j],
+					 GLX_DOUBLEBUFFER,
+					 &value);
+		if (value > db)
 		    continue;
 
+		db = value;
+
 		(*s->getFBConfigAttrib) (dpy,
 					 fbConfigs[j],
-					 GLX_BIND_TO_TEXTURE_RGB_EXT,
+					 GLX_STENCIL_SIZE,
 					 &value);
-		if (!value)
+		if (value > stencil)
 		    continue;
 
-		s->glxPixmapFBConfigs[i].textureFormat =
-		    GLX_TEXTURE_FORMAT_RGB_EXT;
-	    }
-
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_DOUBLEBUFFER,
-				     &value);
-	    if (value > db)
-		continue;
+		stencil = value;
 
-	    db = value;
+		(*s->getFBConfigAttrib) (dpy,
+					 fbConfigs[j],
+					 GLX_DEPTH_SIZE,
+					 &value);
+		if (value > depth)
+		    continue;
 
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_STENCIL_SIZE,
-				     &value);
-	    if (value > stencil)
-		continue;
+		depth = value;
 
-	    stencil = value;
+		if (s->fbo)
+		{
+		    (*s->getFBConfigAttrib) (dpy,
+					     fbConfigs[j],
+					     GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+					     &value);
+		    if (value < mipmap)
+			continue;
+
+		    mipmap = value;
+		}
 
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_DEPTH_SIZE,
-				     &value);
-	    if (value > depth)
-		continue;
+		(*s->getFBConfigAttrib) (dpy,
+					 fbConfigs[j],
+					 GLX_Y_INVERTED_EXT,
+					 &value);
 
-	    depth = value;
+		s->glxPixmapFBConfigs[i].yInverted = value;
 
-	    if (s->fbo)
-	    {
 		(*s->getFBConfigAttrib) (dpy,
 					 fbConfigs[j],
-					 GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+					 GLX_BIND_TO_TEXTURE_TARGETS_EXT,
 					 &value);
-		if (value < mipmap)
-		    continue;
 
-		mipmap = value;
+		s->glxPixmapFBConfigs[i].textureTargets = value;
+
+		s->glxPixmapFBConfigs[i].fbConfig = fbConfigs[j];
+		s->glxPixmapFBConfigs[i].mipmap   = mipmap;
 	    }
+	}
 
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_Y_INVERTED_EXT,
-				     &value);
+	if (nElements)
+	    XFree (fbConfigs);
 
-	    s->glxPixmapFBConfigs[i].yInverted = value;
+	if (!s->glxPixmapFBConfigs[defaultDepth].fbConfig)
+	{
+	    compLogMessage ("core", CompLogLevelFatal,
+			    "No GLXFBConfig for default depth, "
+			    "this isn't going to work.");
+	    return FALSE;
+	}
 
-	    (*s->getFBConfigAttrib) (dpy,
-				     fbConfigs[j],
-				     GLX_BIND_TO_TEXTURE_TARGETS_EXT,
-				     &value);
+	glClearColor (0.0, 0.0, 0.0, 1.0);
+	glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	glEnable (GL_CULL_FACE);
+	glDisable (GL_BLEND);
+	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+	glColor4usv (defaultColor);
+	glEnableClientState (GL_VERTEX_ARRAY);
+	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+	s->canDoSaturated = s->canDoSlightlySaturated = FALSE;
+	if (s->textureEnvCombine && s->maxTextureUnits >= 2)
+	{
+	    s->canDoSaturated = TRUE;
+	    if (s->textureEnvCrossbar && s->maxTextureUnits >= 4)
+		s->canDoSlightlySaturated = TRUE;
+	}
 
-	    s->glxPixmapFBConfigs[i].textureTargets = value;
+	glLightModelfv (GL_LIGHT_MODEL_AMBIENT, globalAmbient);
 
-	    s->glxPixmapFBConfigs[i].fbConfig = fbConfigs[j];
-	    s->glxPixmapFBConfigs[i].mipmap   = mipmap;
-	}
-    }
+	glEnable (GL_LIGHT0);
+	glLightfv (GL_LIGHT0, GL_AMBIENT, ambientLight);
+	glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuseLight);
+	glLightfv (GL_LIGHT0, GL_POSITION, light0Position);
 
-    if (nElements)
-	XFree (fbConfigs);
+	glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
 
-    if (!s->glxPixmapFBConfigs[defaultDepth].fbConfig)
+	glNormal3f (0.0f, 0.0f, -1.0f);
+    }
+    else
     {
-	compLogMessage ("core", CompLogLevelFatal,
-			"No GLXFBConfig for default depth, "
-			"this isn't going to work.");
-	return FALSE;
+	s->maxTextureSize = SHRT_MAX;
+	s->canDoSaturated = s->canDoSlightlySaturated = FALSE;
     }
 
     initTexture (s, &s->backgroundTexture);
@@ -2223,25 +2370,6 @@ addScreen (CompDisplay *display,
 
     s->defaultIcon = NULL;
 
-    s->desktopWindowCount = 0;
-
-    glClearColor (0.0, 0.0, 0.0, 1.0);
-    glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    glEnable (GL_CULL_FACE);
-    glDisable (GL_BLEND);
-    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-    glColor4usv (defaultColor);
-    glEnableClientState (GL_VERTEX_ARRAY);
-    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-
-    s->canDoSaturated = s->canDoSlightlySaturated = FALSE;
-    if (s->textureEnvCombine && s->maxTextureUnits >= 2)
-    {
-	s->canDoSaturated = TRUE;
-	if (s->textureEnvCrossbar && s->maxTextureUnits >= 4)
-	    s->canDoSlightlySaturated = TRUE;
-    }
-
     s->redrawTime = 1000 / defaultRefreshRate;
     s->optimalRedrawTime = s->redrawTime;
 
@@ -2251,17 +2379,6 @@ addScreen (CompDisplay *display,
     detectOutputDevices (s);
     updateOutputDevices (s);
 
-    glLightModelfv (GL_LIGHT_MODEL_AMBIENT, globalAmbient);
-
-    glEnable (GL_LIGHT0);
-    glLightfv (GL_LIGHT0, GL_AMBIENT, ambientLight);
-    glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuseLight);
-    glLightfv (GL_LIGHT0, GL_POSITION, light0Position);
-
-    glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
-
-    glNormal3f (0.0f, 0.0f, -1.0f);
-
     s->lighting	      = FALSE;
     s->slowAnimations = FALSE;
 
@@ -2269,34 +2386,10 @@ addScreen (CompDisplay *display,
 
     getDesktopHints (s);
 
-    /* TODO: bailout properly when objectInitPlugins fails */
-    assert (objectInitPlugins (&s->base));
-
-    (*core.objectAdd) (&display->base, &s->base);
-
-    XQueryTree (dpy, s->root,
-		&rootReturn, &parentReturn,
-		&children, &nchildren);
-
-    for (i = 0; i < nchildren; i++)
-	addWindow (s, children[i], i ? children[i - 1] : 0);
-
-    for (w = s->windows; w; w = w->next)
-    {
-	if (w->attrib.map_state == IsViewable)
-	{
-	    w->activeNum = s->activeNum++;
-	    w->damaged   = TRUE;
-	    w->invisible = WINDOW_INVISIBLE (w);
-	}
-    }
-
-    XFree (children);
-
     attrib.override_redirect = 1;
     attrib.event_mask	     = PropertyChangeMask;
 
-    s->grabWindow = XCreateWindow (dpy, s->root, -100, -100, 1, 1, 0,
+    s->grabWindow = XCreateWindow (dpy, s->root.id, -100, -100, 1, 1, 0,
 				   CopyFromParent, InputOnly, CopyFromParent,
 				   CWOverrideRedirect | CWEventMask,
 				   &attrib);
@@ -2306,9 +2399,13 @@ addScreen (CompDisplay *display,
     {
 	long xdndVersion = 3;
 
-	s->screenEdge[i].id = XCreateWindow (dpy, s->root, -100, -100, 1, 1, 0,
-					     CopyFromParent, InputOnly,
-					     CopyFromParent, CWOverrideRedirect,
+	s->screenEdge[i].id = XCreateWindow (dpy,
+					     s->root.id,
+					     -100, -100, 1, 1, 0,
+					     CopyFromParent,
+					     InputOnly,
+					     CopyFromParent,
+					     CWOverrideRedirect,
 					     &attrib);
 
 	XChangeProperty (dpy, s->screenEdge[i].id, display->xdndAwareAtom,
@@ -2325,19 +2422,52 @@ addScreen (CompDisplay *display,
 
     updateScreenEdges (s);
 
-    setDesktopHints (s);
-    setSupportingWmCheck (s);
-    setSupported (s);
-
     s->normalCursor = XCreateFontCursor (dpy, XC_left_ptr);
     s->busyCursor   = XCreateFontCursor (dpy, XC_watch);
 
-    XDefineCursor (dpy, s->root, s->normalCursor);
+    if (s->root.substructureRedirect)
+    {
+	setDesktopHints (s);
+	setSupportingWmCheck (s);
+	setSupported (s);
+
+	XDefineCursor (dpy, s->root.id, s->normalCursor);
+    }
+    else
+    {
+	getSupportingWmCheck (&s->root);
+    }
 
     s->filter[NOTHING_TRANS_FILTER] = COMP_TEXTURE_FILTER_FAST;
     s->filter[SCREEN_TRANS_FILTER]  = COMP_TEXTURE_FILTER_GOOD;
     s->filter[WINDOW_TRANS_FILTER]  = COMP_TEXTURE_FILTER_GOOD;
 
+    /* TODO: bailout properly when objectInitPlugins fails */
+    assert (objectInitPlugins (&s->base));
+    (*core.objectAdd) (&display->base, &s->base);
+
+    assert (objectInitPlugins (&s->root.base));
+    (*core.objectAdd) (&s->base, &s->root.base);
+
+    XQueryTree (dpy, s->root.id,
+		&rootReturn, &parentReturn,
+		&children, &nchildren);
+
+    for (i = 0; i < nchildren; i++)
+	addWindow (&s->root, children[i], i ? children[i - 1] : 0);
+
+    for (w = s->root.windows; w; w = w->next)
+    {
+	if (w->attrib.map_state == IsViewable)
+	{
+	    w->activeNum = s->activeNum++;
+	    w->damaged   = TRUE;
+	    w->invisible = WINDOW_INVISIBLE (w);
+	}
+    }
+
+    XFree (children);
+
     return TRUE;
 }
 
@@ -2357,14 +2487,14 @@ removeScreen (CompScreen *s)
     else
 	d->screens = NULL;
 
-    while (s->windows)
-	removeWindow (s->windows);
+    while (s->root.windows)
+	removeWindow (s->root.windows);
 
     (*core.objectRemove) (&d->base, &s->base);
 
     objectFiniPlugins (&s->base);
 
-    XUngrabKey (d->display, AnyKey, AnyModifier, s->root);
+    XUngrabKey (d->display, AnyKey, AnyModifier, s->root.id);
 
     for (i = 0; i < SCREEN_EDGE_NUM; i++)
 	XDestroyWindow (d->display, s->screenEdge[i].id);
@@ -2379,13 +2509,14 @@ removeScreen (CompScreen *s)
 	free (s->defaultIcon);
     }
 
-    glXDestroyContext (d->display, s->ctx);
+    if (manualCompositeManagement)
+	glXDestroyContext (d->display, s->ctx);
 
     XFreeCursor (d->display, s->invisibleCursor);
 
 #ifdef USE_COW
-    if (useCow)
-	XCompositeReleaseOverlayWindow (s->display->display, s->root);
+    if (useCow && manualCompositeManagement)
+	XCompositeReleaseOverlayWindow (s->display->display, s->root.id);
 #endif
 
     freeScreen (s);
@@ -2430,7 +2561,7 @@ forEachWindowOnScreen (CompScreen	 *screen,
 {
     CompWindow *w;
 
-    for (w = screen->windows; w; w = w->next)
+    for (w = screen->root.windows; w; w = w->next)
 	(*proc) (w, closure);
 }
 
@@ -2441,6 +2572,9 @@ focusDefaultWindow (CompScreen *s)
     CompWindow  *w;
     CompWindow  *focus = NULL;
 
+    if (!s->root.substructureRedirect)
+	return;
+
     if (!d->opt[COMP_DISPLAY_OPTION_CLICK_TO_FOCUS].value.b)
     {
 	w = findTopLevelWindowAtDisplay (d, d->below);
@@ -2461,11 +2595,11 @@ focusDefaultWindow (CompScreen *s)
 	    /* huh, we didn't find d->below ... perhaps it's out of date;
 	       try grabbing it through the server */
 
-	    status = XQueryPointer (d->display, s->root, &rootReturn,
+	    status = XQueryPointer (d->display, s->root.id, &rootReturn,
 				    &childReturn, &dummyInt, &dummyInt,
 				    &dummyInt, &dummyInt, &dummyUInt);
 
-	    if (status && rootReturn == s->root)
+	    if (status && rootReturn == s->root.id)
 	    {
 		w = findTopLevelWindowAtDisplay (d, childReturn);
 
@@ -2481,7 +2615,7 @@ focusDefaultWindow (CompScreen *s)
 
     if (!focus)
     {
-	for (w = s->reverseWindows; w; w = w->prev)
+	for (w = s->root.reverseWindows; w; w = w->prev)
 	{
 	    if (w->type & CompWindowTypeDockMask)
 		continue;
@@ -2511,7 +2645,7 @@ focusDefaultWindow (CompScreen *s)
     }
     else
     {
-	XSetInputFocus (d->display, s->root, RevertToPointerRoot,
+	XSetInputFocus (d->display, s->root.id, RevertToPointerRoot,
 			CurrentTime);
     }
 }
@@ -2526,19 +2660,35 @@ findWindowAtScreen (CompScreen *s,
     }
     else
     {
-	CompWindow *w;
+	CompWindow *w = &s->root;
 
-	for (w = s->windows; w; w = w->next)
+	for (;;)
+	{
 	    if (w->id == id)
 		return (lastFoundWindow = w);
+
+	    if (w->windows)
+	    {
+		w = w->windows;
+		continue;
+	    }
+
+	    while (!w->next && (w != &s->root))
+	    	w = w->parent;
+	    
+	    if (w == &s->root)
+		break;
+
+	    w = w->next;
+	}
     }
 
-    return 0;
+    return NULL;
 }
 
 CompWindow *
-findTopLevelWindowAtScreen (CompScreen *s,
-			    Window     id)
+findClientWindowAtScreen (CompScreen *s,
+			  Window     id)
 {
     CompWindow *w;
 
@@ -2548,120 +2698,29 @@ findTopLevelWindowAtScreen (CompScreen *s,
 
     if (w->attrib.override_redirect)
     {
-	/* likely a frame window */
-	if (w->attrib.class == InputOnly)
-	{
-	    for (w = s->windows; w; w = w->next)
-		if (w->frame == id)
-		    return w;
-	}
+	if (!w->parent || w->attrib.class != InputOnly)
+	    return NULL;
 
-	return NULL;
+	/* likely a frame window */
+	for (w = w->parent->windows; w; w = w->next)
+	    if (w->frame == id)
+		break;
     }
 
     return w;
 }
 
-void
-insertWindowIntoScreen (CompScreen *s,
-			CompWindow *w,
-			Window	   aboveId)
-{
-    CompWindow *p;
-
-    if (s->windows)
-    {
-	if (!aboveId)
-	{
-	    w->next = s->windows;
-	    w->prev = NULL;
-	    s->windows->prev = w;
-	    s->windows = w;
-	}
-	else
-	{
-	    for (p = s->windows; p; p = p->next)
-	    {
-		if (p->id == aboveId)
-		{
-		    if (p->next)
-		    {
-			w->next = p->next;
-			w->prev = p;
-			p->next->prev = w;
-			p->next = w;
-		    }
-		    else
-		    {
-			p->next = w;
-			w->next = NULL;
-			w->prev = p;
-			s->reverseWindows = w;
-		    }
-		    break;
-		}
-	    }
-
-#ifdef DEBUG
-	    if (!p)
-		abort ();
-#endif
-
-	}
-    }
-    else
-    {
-	s->reverseWindows = s->windows = w;
-	w->prev = w->next = NULL;
-    }
-}
-
-void
-unhookWindowFromScreen (CompScreen *s,
-			CompWindow *w)
+CompWindow *
+findTopLevelWindowAtScreen (CompScreen *s,
+			    Window     id)
 {
-    CompWindow *next, *prev;
-
-    next = w->next;
-    prev = w->prev;
-
-    if (next || prev)
-    {
-	if (next)
-	{
-	    if (prev)
-	    {
-		next->prev = prev;
-	    }
-	    else
-	    {
-		s->windows = next;
-		next->prev = NULL;
-	    }
-	}
+    CompWindow *w;
 
-	if (prev)
-	{
-	    if (next)
-	    {
-		prev->next = next;
-	    }
-	    else
-	    {
-		s->reverseWindows = prev;
-		prev->next = NULL;
-	    }
-	}
-    }
-    else
-    {
-	s->windows = s->reverseWindows = NULL;
-    }
+    w = findClientWindowAtScreen (s, id);
+    if (w && w->managed)
+	return w;
 
-    if (w == lastFoundWindow)
-	lastFoundWindow = NULL;
-    if (w == lastDamagedWindow)
-	lastDamagedWindow = NULL;
+    return NULL;
 }
 
 #define POINTER_GRAB_MASK (ButtonReleaseMask | \
@@ -2679,7 +2738,7 @@ pushScreenGrab (CompScreen *s,
 	status = XGrabPointer (s->display->display, s->grabWindow, TRUE,
 			       POINTER_GRAB_MASK,
 			       GrabModeAsync, GrabModeAsync,
-			       s->root, cursor,
+			       s->root.id, cursor,
 			       CurrentTime);
 
 	if (status == GrabSuccess)
@@ -2831,7 +2890,7 @@ grabUngrabOneKey (CompScreen   *s,
 	XGrabKey (s->display->display,
 		  keycode,
 		  modifiers,
-		  s->root,
+		  s->root.id,
 		  TRUE,
 		  GrabModeAsync,
 		  GrabModeAsync);
@@ -2841,7 +2900,7 @@ grabUngrabOneKey (CompScreen   *s,
 	XUngrabKey (s->display->display,
 		    keycode,
 		    modifiers,
-		    s->root);
+		    s->root.id);
     }
 }
 
@@ -2971,7 +3030,7 @@ updatePassiveKeyGrabs (CompScreen *s)
 {
     int i;
 
-    XUngrabKey (s->display->display, AnyKey, AnyModifier, s->root);
+    XUngrabKey (s->display->display, AnyKey, AnyModifier, s->root.id);
 
     for (i = 0; i < s->nKeyGrab; i++)
     {
@@ -3127,7 +3186,7 @@ computeWorkareaForBox (CompScreen *s,
 
     XUnionRegion (&r, region, region);
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if (!w->mapNum)
 	    continue;
@@ -3241,7 +3300,7 @@ updateWorkareaForScreen (CompScreen *s)
 
 	/* as work area changed, update all maximized windows on this
 	   screen to snap to the new work area */
-	for (w = s->windows; w; w = w->next)
+	for (w = s->root.windows; w; w = w->next)
 	    updateWindowSize (w);
     }
 }
@@ -3308,6 +3367,9 @@ updateClientListForScreen (CompScreen *s)
     Bool   updateClientListStacking = FALSE;
     int	   i, n = 0;
 
+    if (!s->root.substructureRedirect)
+	return;
+
     forEachWindowOnScreen (s, countClientListWindow, (void *) &n);
 
     if (n == 0)
@@ -3319,11 +3381,11 @@ updateClientListForScreen (CompScreen *s)
 	    s->clientList  = NULL;
 	    s->nClientList = 0;
 
-	    XChangeProperty (s->display->display, s->root,
+	    XChangeProperty (s->display->display, s->root.id,
 			     s->display->clientListAtom,
 			     XA_WINDOW, 32, PropModeReplace,
 			     (unsigned char *) &s->grabWindow, 1);
-	    XChangeProperty (s->display->display, s->root,
+	    XChangeProperty (s->display->display, s->root.id,
 			     s->display->clientListStackingAtom,
 			     XA_WINDOW, 32, PropModeReplace,
 			     (unsigned char *) &s->grabWindow, 1);
@@ -3379,13 +3441,13 @@ updateClientListForScreen (CompScreen *s)
     }
 
     if (updateClientList)
-	XChangeProperty (s->display->display, s->root,
+	XChangeProperty (s->display->display, s->root.id,
 			 s->display->clientListAtom,
 			 XA_WINDOW, 32, PropModeReplace,
 			 (unsigned char *) clientList, s->nClientList);
 
     if (updateClientListStacking)
-	XChangeProperty (s->display->display, s->root,
+	XChangeProperty (s->display->display, s->root.id,
 			 s->display->clientListStackingAtom,
 			 XA_WINDOW, 32, PropModeReplace,
 			 (unsigned char *) clientListStacking, s->nClientList);
@@ -3439,7 +3501,8 @@ toolkitAction (CompScreen *s,
     XUngrabPointer (s->display->display, CurrentTime);
     XUngrabKeyboard (s->display->display, CurrentTime);
 
-    XSendEvent (s->display->display, s->root, FALSE, StructureNotifyMask, &ev);
+    XSendEvent (s->display->display, s->root.id, FALSE, StructureNotifyMask,
+		&ev);
 }
 
 void
@@ -3510,7 +3573,7 @@ moveScreenViewport (CompScreen *s,
     tx *= -s->width;
     ty *= -s->height;
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if (windowOnAllViewports (w))
 	    continue;
@@ -3581,7 +3644,7 @@ moveWindowToViewportPosition (CompWindow *w,
     {
 	int m, wx, wy;
 
-	if (!w->managed)
+	if (w->attrib.override_redirect)
 	    return;
 
 	if (w->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
@@ -3752,7 +3815,7 @@ sendWindowActivationRequest (CompScreen *s,
     xev.xclient.data.l[4] = 0;
 
     XSendEvent (s->display->display,
-		s->root,
+		s->root.id,
 		FALSE,
 		SubstructureRedirectMask | SubstructureNotifyMask,
 		&xev);
@@ -3813,12 +3876,12 @@ disableScreenEdge (CompScreen *s,
 }
 
 Window
-getTopWindow (CompScreen *s)
+getTopWindow (CompWindow *parent)
 {
     CompWindow *w;
 
     /* return first window that has not been destroyed */
-    for (w = s->reverseWindows; w; w = w->prev)
+    for (w = parent->reverseWindows; w; w = w->prev)
     {
 	if (w->id > 1)
 	    return w->id;
@@ -3830,24 +3893,30 @@ getTopWindow (CompScreen *s)
 void
 makeScreenCurrent (CompScreen *s)
 {
-    if (currentRoot != s->root)
+    if (manualCompositeManagement)
     {
-	glXMakeCurrent (s->display->display, s->output, s->ctx);
-	currentRoot = s->root;
-    }
+	if (currentRoot != s->root.id)
+	{
+	    glXMakeCurrent (s->display->display, s->output, s->ctx);
+	    currentRoot = s->root.id;
+	}
 
-    s->pendingCommands = TRUE;
+	s->pendingCommands = TRUE;
+    }
 }
 
 void
 finishScreenDrawing (CompScreen *s)
 {
-    if (s->pendingCommands)
+    if (manualCompositeManagement)
     {
-	makeScreenCurrent (s);
-	glFinish ();
+	if (s->pendingCommands)
+	{
+	    makeScreenCurrent (s);
+	    glFinish ();
 
-	s->pendingCommands = FALSE;
+	    s->pendingCommands = FALSE;
+	}
     }
 }
 
@@ -3894,7 +3963,7 @@ setNumberOfDesktops (CompScreen   *s,
     if (s->currentDesktop >= nDesktop)
 	s->currentDesktop = nDesktop - 1;
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if (w->desktop == 0xffffffff)
 	    continue;
@@ -3915,6 +3984,9 @@ setCurrentDesktop (CompScreen   *s,
     unsigned long data;
     CompWindow    *w;
 
+    if (!s->root.substructureRedirect)
+	return;
+
     if (desktop >= s->nDesktop)
 	return;
 
@@ -3923,7 +3995,7 @@ setCurrentDesktop (CompScreen   *s,
 
     s->currentDesktop = desktop;
 
-    for (w = s->windows; w; w = w->next)
+    for (w = s->root.windows; w; w = w->next)
     {
 	if (w->desktop == 0xffffffff)
 	    continue;
@@ -3936,7 +4008,7 @@ setCurrentDesktop (CompScreen   *s,
 
     data = desktop;
 
-    XChangeProperty (s->display->display, s->root,
+    XChangeProperty (s->display->display, s->root.id,
 		     s->display->currentDesktopAtom,
 		     XA_CARDINAL, 32, PropModeReplace,
 		     (unsigned char *) &data, 1);
@@ -4292,6 +4364,6 @@ setWindowPaintOffset (CompScreen *s,
 		      int        x,
 		      int        y)
 {
-    s->windowOffsetX = x;
-    s->windowOffsetY = y;
+    s->root.viewportOffsetX = x;
+    s->root.viewportOffsetY = y;
 }
diff --git a/src/window.c b/src/window.c
index 881bbd5..3302957 100644
--- a/src/window.c
+++ b/src/window.c
@@ -53,18 +53,18 @@ static int
 reallocWindowPrivates (int  size,
 		       void *closure)
 {
-    CompScreen *s = (CompScreen *) closure;
-    CompWindow *w;
+    CompWindow *c, *w = (CompWindow *) closure;
     void       *privates;
 
-    for (w = s->windows; w; w = w->next)
-    {
-	privates = realloc (w->base.privates, size * sizeof (CompPrivate));
-	if (!privates)
-	    return FALSE;
+    privates = realloc (w->base.privates, size * sizeof (CompPrivate));
+    if (!privates)
+	return FALSE;
 
-	w->base.privates = (CompPrivate *) privates;
-    }
+    w->base.privates = (CompPrivate *) privates;
+
+    for (c = w->windows; c; c = c->next)
+	if (!reallocWindowPrivates (size, (void *) c))
+	    return FALSE;
 
     return TRUE;
 }
@@ -77,7 +77,7 @@ allocWindowObjectPrivateIndex (CompObject *parent)
     return allocatePrivateIndex (&screen->windowPrivateLen,
 				 &screen->windowPrivateIndices,
 				 reallocWindowPrivates,
-				 (void *) screen);
+				 (void *) &screen->root);
 }
 
 void
@@ -98,15 +98,16 @@ forEachWindowObject (CompObject	        *parent,
 {
     if (parent->type == COMP_OBJECT_TYPE_SCREEN)
     {
-	CompWindow *w;
-
-	CORE_SCREEN (parent);
+	if (!(*proc) (&GET_CORE_SCREEN (parent)->root.base, closure))
+	    return FALSE;
+    }
+    else if (parent->type == COMP_OBJECT_TYPE_WINDOW)
+    {
+	CompWindow *c;
 
-	for (w = s->windows; w; w = w->next)
-	{
-	    if (!(*proc) (&w->base, closure))
+	for (c = GET_CORE_WINDOW (parent)->windows; c; c = c->next)
+	    if (!(*proc) (&c->base, closure))
 		return FALSE;
-	}
     }
 
     return TRUE;
@@ -130,14 +131,23 @@ findWindowObject (CompObject *parent,
 {
     if (parent->type == COMP_OBJECT_TYPE_SCREEN)
     {
-	CompWindow *w;
-	Window	   id = atoi (name);
+	Window id = atoi (name);
 
 	CORE_SCREEN (parent);
 
-	for (w = s->windows; w; w = w->next)
-	    if (w->id == id)
-		return &w->base;
+	if (s->root.id == id)
+	    return &s->root.base;
+    }
+    else if (parent->type == COMP_OBJECT_TYPE_WINDOW)
+    {
+	CompWindow *c;
+	Window	   id = atoi (name);
+
+	CORE_WINDOW (parent);
+
+	for (c = w->windows; c; c = c->next)
+	    if (c->id == id)
+		return &c->base;
     }
 
     return NULL;
@@ -1153,6 +1163,33 @@ setWindowProp32 (CompDisplay    *display,
 		     (unsigned char *) &value32, 1);
 }
 
+Window
+getFrameWindow (CompWindow *w)
+{
+    Atom	  actual;
+    int		  result, format;
+    unsigned long n, left;
+    unsigned char *data;
+
+    result = XGetWindowProperty (w->screen->display->display, w->id,
+				 w->screen->display->frameWindowAtom,
+				 0L, 1L, False, XA_WINDOW, &actual, &format,
+				 &n, &left, &data);
+
+    if (result == Success && n && data)
+    {
+	Window win;
+
+	memcpy (&win, data, sizeof (Window));
+	XFree ((void *) data);
+
+	if (win)
+	    return win;
+    }
+
+    return None;
+}
+
 static void
 updateFrameWindow (CompWindow *w)
 {
@@ -1181,7 +1218,7 @@ updateFrameWindow (CompWindow *w)
 	    attr.event_mask	   = 0;
 	    attr.override_redirect = TRUE;
 
-	    w->frame = XCreateWindow (d->display, w->screen->root,
+	    w->frame = XCreateWindow (d->display, w->parent->id,
 				      x, y, width, height, 0,
 				      CopyFromParent,
 				      InputOnly,
@@ -1281,14 +1318,17 @@ setWindowFrameExtents (CompWindow	 *w,
 	data[2] = input->top;
 	data[3] = input->bottom;
 
-	updateWindowSize (w);
-	updateFrameWindow (w);
-	recalcWindowActions (w);
-
-	XChangeProperty (w->screen->display->display, w->id,
-			 w->screen->display->frameExtentsAtom,
-			 XA_CARDINAL, 32, PropModeReplace,
-			 (unsigned char *) data, 4);
+	if (w->parent->substructureRedirect)
+	{
+	    updateWindowSize (w);
+	    updateFrameWindow (w);
+	    recalcWindowActions (w);
+
+	    XChangeProperty (w->screen->display->display, w->id,
+			     w->screen->display->frameExtentsAtom,
+			     XA_CARDINAL, 32, PropModeReplace,
+			     (unsigned char *) data, 4);
+	}
     }
 }
 
@@ -1397,7 +1437,7 @@ freeWindow (CompWindow *w)
 
     destroyTexture (w->screen, w->texture);
 
-    if (w->frame)
+    if (w->frame && w->parent->substructureRedirect)
 	XDestroyWindow (w->screen->display->display, w->frame);
 
     if (w->clip)
@@ -1446,9 +1486,6 @@ damageTransformedWindowRect (CompWindow *w,
 {
     REGION reg;
 
-    reg.rects    = &reg.extents;
-    reg.numRects = 1;
-
     reg.extents.x1 = (rect->x1 * xScale) - 1;
     reg.extents.y1 = (rect->y1 * yScale) - 1;
     reg.extents.x2 = (rect->x2 * xScale + 0.5f) + 1;
@@ -1461,10 +1498,17 @@ damageTransformedWindowRect (CompWindow *w,
 
     if (reg.extents.x2 > reg.extents.x1 && reg.extents.y2 > reg.extents.y1)
     {
-	reg.extents.x1 += w->attrib.x + w->attrib.border_width;
-	reg.extents.y1 += w->attrib.y + w->attrib.border_width;
-	reg.extents.x2 += w->attrib.x + w->attrib.border_width;
-	reg.extents.y2 += w->attrib.y + w->attrib.border_width;
+	CompWindow *p = w;
+
+	do {
+	    reg.extents.x1 += p->attrib.x + p->attrib.border_width;
+	    reg.extents.y1 += p->attrib.y + p->attrib.border_width;
+	    reg.extents.x2 += p->attrib.x + p->attrib.border_width;
+	    reg.extents.y2 += p->attrib.y + p->attrib.border_width;
+	} while ((p = p->parent));
+
+	reg.rects    = &reg.extents;
+	reg.numRects = reg.size = 1;
 
 	damageScreenRegion (w->screen, &reg);
     }
@@ -1527,19 +1571,27 @@ addWindowDamageRect (CompWindow *w,
 		     BoxPtr     rect)
 {
     REGION region;
+    Bool   status = TRUE;
 
     if (w->screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
 	return;
 
     region.extents = *rect;
 
-    if (!(*w->screen->damageWindowRect) (w, FALSE, &region.extents))
+    while (w != &w->screen->root)
     {
+	status &= (*w->screen->damageWindowRect) (w, FALSE, &region.extents);
+
 	region.extents.x1 += w->attrib.x + w->attrib.border_width;
 	region.extents.y1 += w->attrib.y + w->attrib.border_width;
 	region.extents.x2 += w->attrib.x + w->attrib.border_width;
 	region.extents.y2 += w->attrib.y + w->attrib.border_width;
 
+	w = w->parent;
+    }
+
+    if (!status)
+    {
 	region.rects = &region.extents;
 	region.numRects = region.size = 1;
 
@@ -1882,21 +1934,121 @@ setDefaultWindowAttributes (XWindowAttributes *wa)
 }
 
 void
-addWindow (CompScreen *screen,
+initRootWindow (CompScreen *s,
+		CompWindow *root)
+{
+    CompWindow  *w = root;
+    CompPrivate	*privates;
+    CompDisplay *d = s->display;
+    REGION      rect;
+
+    memset (w, 0, sizeof (*w));
+
+    w->id     = XRootWindow (d->display, s->screenNum);
+    w->screen = s;
+
+    w->bindFailed = TRUE;
+    w->alive      = TRUE;
+
+    w->paint.opacity    = OPAQUE;
+    w->paint.brightness = BRIGHT;
+    w->paint.saturation = COLOR;
+    w->paint.xScale	= 1.0f;
+    w->paint.yScale	= 1.0f;
+    w->paint.xTranslate	= 0.0f;
+    w->paint.yTranslate	= 0.0f;
+
+    w->lastPaint = w->paint;
+
+    if (s->windowPrivateLen)
+    {
+	privates = malloc (s->windowPrivateLen * sizeof (CompPrivate));
+	assert (privates);
+    }
+    else
+	privates = 0;
+
+    compObjectInit (&w->base, privates, COMP_OBJECT_TYPE_WINDOW);
+
+    w->clip   = XCreateRegion ();
+    w->region = XCreateRegion ();
+
+    assert (w->clip && w->region);
+
+    if (!XGetWindowAttributes (d->display, w->id, &w->attrib))
+	setDefaultWindowAttributes (&w->attrib);
+
+    w->attrib.override_redirect = TRUE;
+
+    w->serverWidth	 = w->attrib.width;
+    w->serverHeight	 = w->attrib.height;
+    w->serverBorderWidth = w->attrib.border_width;
+
+    w->width  = w->attrib.width  + w->attrib.border_width * 2;
+    w->height = w->attrib.height + w->attrib.border_width * 2;
+
+    w->serverX = w->attrib.x;
+    w->serverY = w->attrib.y;
+
+    w->syncWait	       = FALSE;
+    w->syncX	       = w->attrib.x;
+    w->syncY	       = w->attrib.y;
+    w->syncWidth       = w->attrib.width;
+    w->syncHeight      = w->attrib.height;
+    w->syncBorderWidth = w->attrib.border_width;
+
+    w->alpha = (w->attrib.depth == 32);
+    w->type  = CompWindowTypeUnknownMask;
+
+    w->invisible = TRUE;
+
+    rect.rects = &rect.extents;
+    rect.numRects = rect.size = 1;
+
+    rect.extents.x1 = w->attrib.x;
+    rect.extents.y1 = w->attrib.y;
+    rect.extents.x2 = w->attrib.x + w->width;
+    rect.extents.y2 = w->attrib.y + w->height;
+
+    XUnionRegion (&rect, w->region, w->region);
+
+    w->substructureRedirect = windowManagement;
+    w->redirectSubwindows   = manualCompositeManagement;
+}
+
+void
+addWindow (CompWindow *parent,
 	   Window     id,
 	   Window     aboveId)
 {
     CompWindow  *w;
     CompPrivate	*privates;
+    CompScreen  *screen = parent->screen;
     CompDisplay *d = screen->display;
 
     w = (CompWindow *) malloc (sizeof (CompWindow));
     if (!w)
 	return;
 
+    w->parent = parent;
+
+    w->windows        = 0;
+    w->reverseWindows = 0;
+
     w->next = NULL;
     w->prev = NULL;
 
+    w->substructureRedirect = FALSE;
+    w->redirectSubwindows   = FALSE;
+
+    w->supportingWmCheckWindow = None;
+    w->syncStateSupport        = FALSE;
+    w->activeChild             = None;
+    w->previousActiveChild     = None;
+
+    w->viewportOffsetX = 0;
+    w->viewportOffsetY = 0;
+    
     w->mapNum	 = 0;
     w->activeNum = 0;
 
@@ -1935,9 +2087,18 @@ addWindow (CompScreen *screen,
     w->pixmap     = None;
     w->destroyed  = FALSE;
     w->damaged    = FALSE;
-    w->redirected = TRUE;
     w->managed    = FALSE;
-    w->bindFailed = FALSE;
+
+    if (parent->redirectSubwindows)
+    {
+	w->redirected = TRUE;
+	w->bindFailed = FALSE;
+    }
+    else
+    {
+	w->redirected = FALSE;
+	w->bindFailed = TRUE;
+    }
 
     w->destroyRefCnt = 1;
     w->unmapRefCnt   = 1;
@@ -1996,11 +2157,15 @@ addWindow (CompScreen *screen,
     w->syncCounter    = 0;
     w->syncWaitHandle = 0;
 
+    XSyncIntToValue (&w->syncValue, 0);
+
     w->closeRequests	    = 0;
     w->lastCloseRequestTime = 0;
 
     w->overlayWindow = FALSE;
 
+    w->desktopWindowCount = 0;
+
     if (screen->windowPrivateLen)
     {
 	privates = malloc (screen->windowPrivateLen * sizeof (CompPrivate));
@@ -2063,10 +2228,23 @@ addWindow (CompScreen *screen,
 
     w->saveMask = 0;
 
-    XSelectInput (d->display, id,
-		  PropertyChangeMask |
-		  EnterWindowMask    |
-		  FocusChangeMask);
+    if (w->parent->substructureRedirect)
+    {
+	XSelectInput (d->display, id,
+		      PropertyChangeMask |
+		      EnterWindowMask    |
+		      FocusChangeMask);
+    }
+    else if (w->parent->redirectSubwindows)
+    {
+	XSelectInput (d->display, id, PropertyChangeMask);
+
+	if (w->parent->syncStateSupport)
+	{
+	    if (!getWindowProp (d, w->id, d->syncStateAtom, 0))
+		syncWait (w);
+	}
+    }
 
     w->id = id;
 
@@ -2083,10 +2261,10 @@ addWindow (CompScreen *screen,
     w->type      = CompWindowTypeUnknownMask;
     w->lastPong  = d->lastPing;
 
-    if (d->shapeExtension)
+    if (d->shapeExtension && parent->redirectSubwindows)
 	XShapeSelectInput (d->display, id, ShapeNotifyMask);
 
-    insertWindowIntoScreen (screen, w, aboveId);
+    insertWindow (parent, w, aboveId);
 
     EMPTY_REGION (w->region);
 
@@ -2104,8 +2282,9 @@ addWindow (CompScreen *screen,
 
 	XUnionRegion (&rect, w->region, w->region);
 
-	w->damage = XDamageCreate (d->display, id,
-				   XDamageReportRawRectangles);
+	if (parent->redirectSubwindows)
+	    w->damage = XDamageCreate (d->display, id,
+				       XDamageReportRawRectangles);
 
 	/* need to check for DisplayModal state on all windows */
 	w->state = getWindowState (d, w->id);
@@ -2115,7 +2294,6 @@ addWindow (CompScreen *screen,
     else
     {
 	w->damage = None;
-	w->attrib.map_state = IsUnmapped;
     }
 
     w->invisible = TRUE;
@@ -2134,6 +2312,9 @@ addWindow (CompScreen *screen,
 	if (!w->clientLeader)
 	    w->startupId = getStartupId (w);
 
+	if (w->parent && !w->parent->substructureRedirect)
+	    w->frame = getFrameWindow (w);
+
 	recalcWindowType (w);
 
 	getMwmHints (d, w->id, &w->mwmFunc, &w->mwmDecor);
@@ -2175,28 +2356,32 @@ addWindow (CompScreen *screen,
 
 	if (!w->attrib.override_redirect)
 	{
-	    w->managed = TRUE;
-
-	    if (getWmState (d, w->id) == IconicState)
+	    if (w->parent->substructureRedirect)
 	    {
-		if (w->state & CompWindowStateShadedMask)
-		    w->shaded = TRUE;
-		else
-		    w->minimized = TRUE;
-	    }
-	    else
-	    {
-		if (w->wmType & (CompWindowTypeDockMask |
-				 CompWindowTypeDesktopMask))
+		w->managed = TRUE;
+
+		if (getWmState (d, w->id) == IconicState)
 		{
-		    setDesktopForWindow (w, 0xffffffff);
+		    if (w->state & CompWindowStateShadedMask)
+			w->shaded = TRUE;
+		    else
+			w->minimized = TRUE;
 		}
 		else
 		{
-		    if (w->desktop != 0xffffffff)
-			w->desktop = screen->currentDesktop;
+		    if (w->wmType & (CompWindowTypeDockMask |
+				     CompWindowTypeDesktopMask))
+		    {
+			setDesktopForWindow (w, 0xffffffff);
+		    }
+		    else
+		    {
+			if (w->desktop != 0xffffffff)
+			    w->desktop = screen->currentDesktop;
 
-		    setWindowProp (d, w->id, d->winDesktopAtom, w->desktop);
+			setWindowProp (d, w->id, d->winDesktopAtom,
+				       w->desktop);
+		    }
 		}
 	    }
 	}
@@ -2239,7 +2424,7 @@ addWindow (CompScreen *screen,
     /* TODO: bailout properly when objectInitPlugins fails */
     assert (objectInitPlugins (&w->base));
 
-    (*core.objectAdd) (&screen->base, &w->base);
+    (*core.objectAdd) (&parent->base, &w->base);
 
     recalcWindowActions (w);
     updateIconGeometry (w);
@@ -2254,7 +2439,10 @@ addWindow (CompScreen *screen,
 void
 removeWindow (CompWindow *w)
 {
-    unhookWindowFromScreen (w->screen, w);
+    while (w->windows)
+	removeWindow (w->windows);
+
+    unhookWindow (w->parent, w);
 
     if (!w->destroyed)
     {
@@ -2276,7 +2464,7 @@ removeWindow (CompWindow *w)
 	if (w->damage)
 	    XDamageDestroy (d->display, w->damage);
 
-	if (d->shapeExtension)
+	if (d->shapeExtension && w->parent->redirectSubwindows)
 	    XShapeSelectInput (d->display, w->id, NoEventMask);
 
 	XSelectInput (d->display, w->id, NoEventMask);
@@ -2287,7 +2475,7 @@ removeWindow (CompWindow *w)
     if (w->attrib.map_state == IsViewable && w->damaged)
     {
 	if (w->type == CompWindowTypeDesktopMask)
-	    w->screen->desktopWindowCount--;
+	    w->parent->desktopWindowCount--;
 
 	if (w->destroyed && w->struts)
 	    updateWorkareaForScreen (w->screen);
@@ -2296,7 +2484,7 @@ removeWindow (CompWindow *w)
     if (w->destroyed)
 	updateClientListForScreen (w->screen);
 
-    if (!w->redirected)
+    if (w->parent->redirectSubwindows && !w->redirected)
     {
 	w->screen->overlayWindowCount--;
 
@@ -2304,7 +2492,7 @@ removeWindow (CompWindow *w)
 	    showOutputWindow (w->screen);
     }
 
-    (*core.objectRemove) (&w->screen->base, &w->base);
+    (*core.objectRemove) (&w->parent->base, &w->base);
 
     objectFiniPlugins (&w->base);
 
@@ -2384,9 +2572,17 @@ sendConfigureNotify (CompWindow *w)
 void
 mapWindow (CompWindow *w)
 {
+    CompWindow *c;
+
     if (w->attrib.map_state == IsViewable)
 	return;
 
+    if (w->parent->attrib.map_state != IsViewable)
+    {
+	w->attrib.map_state = IsUnviewable;
+	return;
+    }
+
     if (w->pendingMaps > 0)
 	w->pendingMaps--;
 
@@ -2402,7 +2598,7 @@ mapWindow (CompWindow *w)
 
     w->attrib.map_state = IsViewable;
 
-    if (!w->attrib.override_redirect)
+    if (w->managed)
 	setWmState (w->screen->display, NormalState, w->id);
 
     w->invisible  = TRUE;
@@ -2415,21 +2611,28 @@ mapWindow (CompWindow *w)
     updateWindowRegion (w);
     updateWindowSize (w);
 
-    if (w->frame)
+    if (w->frame && w->parent->substructureRedirect)
 	XMapWindow (w->screen->display->display, w->frame);
 
     updateClientListForScreen (w->screen);
 
     if (w->type & CompWindowTypeDesktopMask)
-	w->screen->desktopWindowCount++;
+	w->parent->desktopWindowCount++;
 
-    if (w->protocols & CompWindowProtocolSyncRequestMask)
+    if (w->parent->substructureRedirect)
     {
-	sendSyncRequest (w);
-	sendConfigureNotify (w);
+	if (w->protocols & CompWindowProtocolSyncRequestMask)
+	{
+	    sendSyncRequest (w);
+	    sendConfigureNotify (w);
+	}
+	else
+	{
+	    leaveSyncWaitState (w);
+	}
     }
 
-    if (!w->attrib.override_redirect)
+    if (w->managed)
     {
 	/* been shaded */
 	if (!w->height)
@@ -2438,35 +2641,31 @@ mapWindow (CompWindow *w)
 			  w->attrib.width, ++w->attrib.height - 1,
 			  w->attrib.border_width);
     }
+
+    for (c = w->windows; c; c = c->next)
+	if (c->attrib.map_state == IsUnviewable)
+	    mapWindow (c);
 }
 
-void
-unmapWindow (CompWindow *w)
+static void
+withdrawWindowToState (CompWindow *w,
+		       int        state)
 {
-    if (w->mapNum)
-    {
-	if (w->frame && !w->shaded)
-	    XUnmapWindow (w->screen->display->display, w->frame);
-
-	w->mapNum = 0;
-    }
-
-    w->unmapRefCnt--;
-    if (w->unmapRefCnt > 0)
-	return;
+    CompWindow *c;
 
     if (w->struts)
 	updateWorkareaForScreen (w->screen);
 
-    if (w->attrib.map_state != IsViewable)
+    if (w->attrib.map_state == state)
 	return;
 
     if (w->type == CompWindowTypeDesktopMask)
-	w->screen->desktopWindowCount--;
+	w->parent->desktopWindowCount--;
 
-    addWindowDamage (w);
+    if (w->attrib.map_state == IsViewable)
+	addWindowDamage (w);
 
-    w->attrib.map_state = IsUnmapped;
+    w->attrib.map_state = state;
 
     w->invisible = TRUE;
 
@@ -2482,6 +2681,31 @@ unmapWindow (CompWindow *w)
 
     if (!w->redirected)
 	redirectWindow (w);
+
+    for (c = w->windows; c; c = c->next)
+	if (c->attrib.map_state == IsViewable)
+	    withdrawWindowToState (c, IsUnviewable);
+}
+
+void
+unmapWindow (CompWindow *w)
+{
+    if (w->mapNum)
+    {
+	if (w->frame && w->parent->substructureRedirect && !w->shaded)
+	    XUnmapWindow (w->screen->display->display, w->frame);
+
+	if (w->parent->substructureRedirect)
+	    enterSyncWaitState (w);
+
+	w->mapNum = 0;
+    }
+
+    w->unmapRefCnt--;
+    if (w->unmapRefCnt > 0)
+	return;
+
+    withdrawWindowToState (w, IsUnmapped);
 }
 
 static int
@@ -2496,8 +2720,8 @@ restackWindow (CompWindow *w,
     else if (aboveId == None && !w->next)
 	return 0;
 
-    unhookWindowFromScreen (w->screen, w);
-    insertWindowIntoScreen (w->screen, w, aboveId);
+    unhookWindow (w->parent, w);
+    insertWindow (w->parent, w, aboveId);
 
     updateClientListForScreen (w->screen);
 
@@ -2575,7 +2799,8 @@ resizeWindow (CompWindow *w,
 
 	w->invisible = WINDOW_INVISIBLE (w);
 
-	updateFrameWindow (w);
+	if (w->parent && w->parent->substructureRedirect)
+	    updateFrameWindow (w);
     }
     else if (w->attrib.x != x || w->attrib.y != y)
     {
@@ -2586,7 +2811,7 @@ resizeWindow (CompWindow *w,
 
 	moveWindow (w, dx, dy, TRUE, TRUE);
 
-	if (w->frame)
+	if (w->frame && w->parent->substructureRedirect)
 	    XMoveWindow (w->screen->display->display, w->frame,
 			 w->attrib.x - w->input.left,
 			 w->attrib.y - w->input.top);
@@ -2614,6 +2839,9 @@ initializeSyncCounter (CompWindow *w)
     unsigned long	 n, left;
     unsigned char	 *data;
 
+    if (!w->parent->substructureRedirect)
+	return FALSE;
+
     if (w->syncCounter)
 	return w->syncAlarm != None;
 
@@ -2633,7 +2861,6 @@ initializeSyncCounter (CompWindow *w)
 
 	XFree (data);
 
-	XSyncIntsToValue (&w->syncValue, (unsigned int) rand (), 0);
 	XSyncSetCounter (w->screen->display->display,
 			 w->syncCounter,
 			 w->syncValue);
@@ -2689,6 +2916,20 @@ syncWaitTimeout (void *closure)
 }
 
 void
+syncWait (CompWindow *w)
+{
+    w->syncWait	       = TRUE;
+    w->syncX	       = w->serverX;
+    w->syncY	       = w->serverY;
+    w->syncWidth       = w->serverWidth;
+    w->syncHeight      = w->serverHeight;
+    w->syncBorderWidth = w->serverBorderWidth;
+
+    if (!w->syncWaitHandle)
+	w->syncWaitHandle = compAddTimeout (1000, 1200, syncWaitTimeout, w);
+}
+
+void
 sendSyncRequest (CompWindow *w)
 {
     XClientMessageEvent xev;
@@ -2697,7 +2938,10 @@ sendSyncRequest (CompWindow *w)
 	return;
 
     if (!initializeSyncCounter (w))
+    {
+	leaveSyncWaitState (w);
 	return;
+    }
 
     xev.type	     = ClientMessage;
     xev.window	     = w->id;
@@ -2711,23 +2955,26 @@ sendSyncRequest (CompWindow *w)
 
     syncValueIncrement (&w->syncValue);
 
-    XSendEvent (w->screen->display->display, w->id, FALSE, 0, (XEvent *) &xev);
+    enterSyncWaitState (w);
 
-    w->syncWait	       = TRUE;
-    w->syncX	       = w->serverX;
-    w->syncY	       = w->serverY;
-    w->syncWidth       = w->serverWidth;
-    w->syncHeight      = w->serverHeight;
-    w->syncBorderWidth = w->serverBorderWidth;
+    XSendEvent (w->screen->display->display, w->id, FALSE, 0, (XEvent *) &xev);
 
-    if (!w->syncWaitHandle)
-	w->syncWaitHandle = compAddTimeout (1000, 1200, syncWaitTimeout, w);
+    syncWait (w);
 }
 
 void
 configureWindow (CompWindow	 *w,
 		 XConfigureEvent *ce)
 {
+    if (!w->managed)
+    {
+	w->serverX	     = ce->x;
+	w->serverY	     = ce->y;
+	w->serverWidth       = ce->width;
+	w->serverHeight      = ce->height;
+	w->serverBorderWidth = ce->border_width;
+    }
+
     if (w->syncWait)
     {
 	w->syncX	   = ce->x;
@@ -2738,15 +2985,6 @@ configureWindow (CompWindow	 *w,
     }
     else
     {
-	if (ce->override_redirect)
-	{
-	    w->serverX		 = ce->x;
-	    w->serverY		 = ce->y;
-	    w->serverWidth       = ce->width;
-	    w->serverHeight      = ce->height;
-	    w->serverBorderWidth = ce->border_width;
-	}
-
 	resizeWindow (w, ce->x, ce->y, ce->width, ce->height,
 		      ce->border_width);
     }
@@ -2755,6 +2993,9 @@ configureWindow (CompWindow	 *w,
 
     if (restackWindow (w, ce->above))
 	addWindowDamage (w);
+
+    if (!w->parent)
+	configureScreen (w->screen, ce);
 }
 
 void
@@ -2764,7 +3005,7 @@ circulateWindow (CompWindow	 *w,
     Window newAboveId;
 
     if (ce->place == PlaceOnTop)
-	newAboveId = getTopWindow (w->screen);
+	newAboveId = getTopWindow (w->parent);
     else
 	newAboveId = 0;
 
@@ -2800,29 +3041,12 @@ moveWindow (CompWindow *w,
     }
 }
 
-void
-syncWindowPosition (CompWindow *w)
-{
-    w->serverX = w->attrib.x;
-    w->serverY = w->attrib.y;
-
-    XMoveWindow (w->screen->display->display, w->id, w->attrib.x, w->attrib.y);
-
-    if (w->frame)
-	XMoveWindow (w->screen->display->display, w->frame,
-		     w->serverX - w->input.left,
-		     w->serverY - w->input.top);
-}
-
 Bool
 focusWindow (CompWindow *w)
 {
     if (w->attrib.override_redirect)
 	return FALSE;
 
-    if (!w->managed)
-	return FALSE;
-
     if (!onCurrentDesktop (w))
 	return FALSE;
 
@@ -2902,7 +3126,8 @@ isGroupTransient (CompWindow *w,
     if (!clientLeader)
 	return FALSE;
 
-    if (w->transientFor == None || w->transientFor == w->screen->root)
+    if (w->transientFor == None ||
+	(w->parent && w->transientFor == w->parent->id))
     {
 	if (w->type & (CompWindowTypeDialogMask |
 		       CompWindowTypeModalDialogMask))
@@ -2922,7 +3147,7 @@ getModalTransient (CompWindow *window)
 
     modalTransient = window;
 
-    for (w = window->screen->reverseWindows; w; w = w->prev)
+    for (w = window->parent->reverseWindows; w; w = w->prev)
     {
 	if (w == modalTransient || w->mapNum == 0)
 	    continue;
@@ -2932,7 +3157,7 @@ getModalTransient (CompWindow *window)
 	    if (w->state & CompWindowStateModalMask)
 	    {
 		modalTransient = w;
-		w = window->screen->reverseWindows;
+		w = window->parent->reverseWindows;
 	    }
 	}
     }
@@ -2944,7 +3169,7 @@ getModalTransient (CompWindow *window)
 	if (window->state & CompWindowStateModalMask)
 	    return NULL;
 
-	for (w = window->screen->reverseWindows; w; w = w->prev)
+	for (w = window->parent->reverseWindows; w; w = w->prev)
 	{
 	    if (w == modalTransient || w->mapNum == 0)
 		continue;
@@ -2980,14 +3205,18 @@ moveInputFocusToWindow (CompWindow *w)
     CompDisplay *d = s->display;
     CompWindow  *modalTransient;
 
+    if (!w->managed)
+	return;
+
     modalTransient = getModalTransient (w);
     if (modalTransient)
 	w = modalTransient;
 
     if (w->state & CompWindowStateHiddenMask)
     {
-	XSetInputFocus (d->display, w->frame, RevertToPointerRoot, CurrentTime);
-	XChangeProperty (d->display, s->root, d->winActiveAtom,
+	XSetInputFocus (d->display, w->frame, RevertToPointerRoot,
+			CurrentTime);
+	XChangeProperty (d->display, w->parent->id, d->winActiveAtom,
 			 XA_WINDOW, 32, PropModeReplace,
 			 (unsigned char *) &w->id, 1);
     }
@@ -3027,7 +3256,9 @@ moveInputFocusToWindow (CompWindow *w)
 	    CompWindow *ancestor;
 
 	    /* move input to closest ancestor */
-	    for (ancestor = s->windows; ancestor; ancestor = ancestor->next)
+	    for (ancestor = w->parent->windows;
+		 ancestor;
+		 ancestor = ancestor->next)
 	    {
 		if (isAncestorTo (w, ancestor))
 		{
@@ -3111,7 +3342,7 @@ findSiblingBelow (CompWindow *w,
     if (w->transientFor || isGroupTransient (w, clientLeader))
 	clientLeader = None;
 
-    for (below = w->screen->reverseWindows; below; below = below->prev)
+    for (below = w->parent->reverseWindows; below; below = below->prev)
     {
 	if (below == w || avoidStackingRelativeTo (below))
 	    continue;
@@ -3157,7 +3388,7 @@ findSiblingBelow (CompWindow *w,
 static CompWindow *
 findLowestSiblingBelow (CompWindow *w)
 {
-    CompWindow   *below, *lowest = w->screen->reverseWindows;
+    CompWindow   *below, *lowest = w->parent->reverseWindows;
     Window	 clientLeader = w->clientLeader;
     unsigned int type = w->type;
 
@@ -3169,7 +3400,7 @@ findLowestSiblingBelow (CompWindow *w)
     if (w->transientFor || isGroupTransient (w, clientLeader))
 	clientLeader = None;
 
-    for (below = w->screen->reverseWindows; below; below = below->prev)
+    for (below = w->parent->reverseWindows; below; below = below->prev)
     {
 	if (below == w || avoidStackingRelativeTo (below))
 	    continue;
@@ -3366,11 +3597,41 @@ reconfigureXWindow (CompWindow	   *w,
     if (valueMask & CWBorderWidth)
 	w->serverBorderWidth = xwc->border_width;
 
+    if (!w->parent->substructureRedirect)
+	valueMask |=
+	    adjustConfigureRequestForGravity (w,
+					      xwc, valueMask,
+					      w->sizeHints.win_gravity,
+					      -1);
+
     XConfigureWindow (w->screen->display->display, w->id, valueMask, xwc);
 
-    if (w->frame && (valueMask & (CWSibling | CWStackMode)))
+    if (w->frame && w->parent->substructureRedirect &&
+	(valueMask & (CWSibling | CWStackMode | CWX | CWY)))
+    {
+	XWindowChanges wc = *xwc;
+
+	wc.x -= w->input.left;
+	wc.y -= w->input.top;
+	    
 	XConfigureWindow (w->screen->display->display, w->frame,
-			  valueMask & (CWSibling | CWStackMode), xwc);
+			  valueMask & (CWSibling | CWStackMode | CWX | CWY),
+			  &wc);
+
+    }
+}
+
+void
+syncWindowPosition (CompWindow *w)
+{
+    XWindowChanges xwc;
+
+    xwc.x      = w->attrib.x;
+    xwc.y      = w->attrib.y;
+    xwc.width  = w->serverWidth;
+    xwc.height = w->serverHeight;
+
+    reconfigureXWindow (w, CWX | CWY, &xwc);
 }
 
 static Bool
@@ -3384,7 +3645,7 @@ stackTransients (CompWindow	*w,
     if (w->transientFor || isGroupTransient (w, clientLeader))
 	clientLeader = None;
 
-    for (t = w->screen->reverseWindows; t; t = t->prev)
+    for (t = w->parent->reverseWindows; t; t = t->prev)
     {
 	if (t == w || t == avoid)
 	    continue;
@@ -3442,7 +3703,7 @@ stackAncestors (CompWindow     *w,
     {
 	CompWindow *a;
 
-	for (a = w->screen->reverseWindows; a; a = a->prev)
+	for (a = w->parent->reverseWindows; a; a = a->prev)
 	{
 	    if (a->clientLeader == w->clientLeader &&
 		a->transientFor == None		   &&
@@ -3709,7 +3970,8 @@ unsigned int
 adjustConfigureRequestForGravity (CompWindow     *w,
 				  XWindowChanges *xwc,
 				  unsigned int   xwcm,
-				  int            gravity)
+				  int            gravity,
+				  int		 direction)
 {
     int          newX, newY;
     unsigned int mask = 0;
@@ -3724,23 +3986,23 @@ adjustConfigureRequestForGravity (CompWindow     *w,
 	case WestGravity:
 	case SouthWestGravity:
 	    if (xwcm & CWX)
-		newX += w->input.left;
+		newX += w->input.left * direction;
 	    break;
 
 	case NorthGravity:
 	case CenterGravity:
 	case SouthGravity:
 	    if (!(xwcm & CWX))
-		newX += (w->serverWidth - xwc->width) / 2;
+		newX += ((w->serverWidth - xwc->width) / 2) * direction;
 	    break;
 
 	case NorthEastGravity:
 	case EastGravity:
 	case SouthEastGravity:
 	    if (xwcm & CWX)
-		newX -= w->input.right;
+		newX -= w->input.right * direction;
 	    else
-		newX += w->serverWidth - xwc->width;
+		newX += (w->serverWidth - xwc->width) * direction;
 	    break;
 
 	case StaticGravity:
@@ -3756,23 +4018,23 @@ adjustConfigureRequestForGravity (CompWindow     *w,
 	case NorthGravity:
 	case NorthEastGravity:
 	    if (xwcm & CWY)
-		newY += w->input.top;
+		newY += w->input.top * direction;
 	    break;
 
 	case WestGravity:
 	case CenterGravity:
 	case EastGravity:
 	    if (!(xwcm & CWY))
-		newY += (w->serverHeight - xwc->height) / 2;
+		newY += ((w->serverHeight - xwc->height) / 2) * direction;
 	    break;
 
 	case SouthWestGravity:
 	case SouthGravity:
 	case SouthEastGravity:
 	    if (xwcm & CWY)
-		newY -= w->input.bottom;
+		newY -= w->input.bottom * direction;
 	    else
-		newY += w->serverHeight - xwc->height;
+		newY += (w->serverHeight - xwc->height) * direction;
 	    break;
 
 	case StaticGravity:
@@ -3838,7 +4100,7 @@ moveResizeWindow (CompWindow     *w,
 	}
     }
 
-    xwcm |= adjustConfigureRequestForGravity (w, xwc, xwcm, gravity);
+    xwcm |= adjustConfigureRequestForGravity (w, xwc, xwcm, gravity, 1);
 
     if (!(w->type & (CompWindowTypeDockMask       |
 		     CompWindowTypeFullscreenMask |
@@ -3975,7 +4237,7 @@ addWindowStackChanges (CompWindow     *w,
 	    if (!sibling)
 	    {
 		XLowerWindow (w->screen->display->display, w->id);
-		if (w->frame)
+		if (w->frame && w->parent->substructureRedirect)
 		    XLowerWindow (w->screen->display->display, w->frame);
 	    }
 	    else if (sibling->id != w->prev->id)
@@ -4008,7 +4270,7 @@ addWindowStackChanges (CompWindow     *w,
 	{
 	    CompWindow *dw;
 
-	    for (dw = w->screen->reverseWindows; dw; dw = dw->prev)
+	    for (dw = w->parent->reverseWindows; dw; dw = dw->prev)
 		if (dw == sibling)
 		    break;
 
@@ -4073,7 +4335,7 @@ findValidStackSiblingBelow (CompWindow *w,
     lowest = last = findLowestSiblingBelow (w);
 
     /* walk from bottom up */
-    for (p = w->screen->windows; p; p = p->next)
+    for (p = w->parent->windows; p; p = p->next)
     {
 	/* stop walking when we reach the sibling we should try to stack
 	   below */
@@ -4122,7 +4384,7 @@ updateWindowAttributes (CompWindow             *w,
     XWindowChanges xwc;
     int		   mask = 0;
 
-    if (w->attrib.override_redirect || !w->managed)
+    if (!w->managed)
 	return;
 
     if (w->state & CompWindowStateShadedMask)
@@ -4200,7 +4462,7 @@ ensureWindowVisibility (CompWindow *w)
     int dx = 0;
     int dy = 0;
 
-    if (w->struts || w->attrib.override_redirect)
+    if (w->struts || !w->managed)
 	return;
 
     if (w->type & (CompWindowTypeDockMask	|
@@ -4259,6 +4521,30 @@ revealAncestors (CompWindow *w,
 void
 activateWindow (CompWindow *w)
 {
+    if (!w->parent->substructureRedirect)
+    {
+	XEvent xev;
+
+	xev.xclient.type    = ClientMessage;
+	xev.xclient.display = w->screen->display->display;
+	xev.xclient.format  = 32;
+
+	xev.xclient.message_type = w->screen->display->winActiveAtom;
+	xev.xclient.window	 = w->id;
+
+	xev.xclient.data.l[0] = 2; /* pretend to be a pager */
+	xev.xclient.data.l[1] = 0;
+	xev.xclient.data.l[2] = 0;
+	xev.xclient.data.l[3] = 0;
+	xev.xclient.data.l[4] = 0;
+
+	XSendEvent (w->screen->display->display, w->parent->id, FALSE,
+		    SubstructureRedirectMask | SubstructureNotifyMask,
+		    &xev);
+
+	return;
+    }
+
     setCurrentDesktop (w->screen, w->desktop);
 
     forEachWindowOnScreen (w->screen, revealAncestors, (void *) w);
@@ -4511,7 +4797,8 @@ hideWindow (CompWindow *w)
 
 	w->shaded = FALSE;
 
-	if ((w->state & CompWindowStateShadedMask) && w->frame)
+	if ((w->state & CompWindowStateShadedMask) &&
+	    w->frame && w->parent->substructureRedirect)
 	    XUnmapWindow (w->screen->display->display, w->frame);
     }
 
@@ -4551,7 +4838,7 @@ showWindow (CompWindow *w)
     {
 	w->shaded = TRUE;
 
-	if (w->frame)
+	if (w->frame && w->parent->substructureRedirect)
 	    XMapWindow (w->screen->display->display, w->frame);
 
 	if (w->height)
@@ -4633,7 +4920,7 @@ void
 maximizeWindow (CompWindow *w,
 		int	   state)
 {
-    if (w->attrib.override_redirect)
+    if (!w->managed)
 	return;
 
     state = constrainWindowState (state, w->actions);
@@ -4880,7 +5167,7 @@ unredirectWindow (CompWindow *w)
 void
 redirectWindow (CompWindow *w)
 {
-    if (w->redirected)
+    if (!w->parent || !w->parent->redirectSubwindows || w->redirected)
 	return;
 
     XCompositeRedirectWindow (w->screen->display->display, w->id,
@@ -5199,3 +5486,127 @@ getWindowMovementForOffset (CompWindow *w,
     }
 
 }
+
+void
+enterSyncWaitState (CompWindow *w)
+{
+    XDeleteProperty (w->screen->display->display,
+		     w->id,
+		     w->screen->display->syncStateAtom);
+}
+
+void
+leaveSyncWaitState (CompWindow *w)
+{
+    unsigned long data = XSyncValueLow32 (w->syncValue);
+
+    XChangeProperty (w->screen->display->display,
+		     w->id,
+		     w->screen->display->syncStateAtom,
+		     XA_CARDINAL,
+		     32,
+		     PropModeReplace,
+		     (unsigned char *) &data, 1);
+}
+
+void
+insertWindow (CompWindow *parent,
+	      CompWindow *w,
+	      Window	 aboveId)
+{
+    CompWindow *p;
+
+    if (parent->windows)
+    {
+	if (!aboveId)
+	{
+	    w->next = parent->windows;
+	    w->prev = NULL;
+	    parent->windows->prev = w;
+	    parent->windows = w;
+	}
+	else
+	{
+	    for (p = parent->windows; p; p = p->next)
+	    {
+		if (p->id == aboveId)
+		{
+		    if (p->next)
+		    {
+			w->next = p->next;
+			w->prev = p;
+			p->next->prev = w;
+			p->next = w;
+		    }
+		    else
+		    {
+			p->next = w;
+			w->next = NULL;
+			w->prev = p;
+			parent->reverseWindows = w;
+		    }
+		    break;
+		}
+	    }
+
+#ifdef DEBUG
+	    if (!p)
+		abort ();
+#endif
+
+	}
+    }
+    else
+    {
+	parent->reverseWindows = parent->windows = w;
+	w->prev = w->next = NULL;
+    }
+}
+
+void
+unhookWindow (CompWindow *parent,
+	      CompWindow *w)
+{
+    CompWindow *next, *prev;
+
+    next = w->next;
+    prev = w->prev;
+
+    if (next || prev)
+    {
+	if (next)
+	{
+	    if (prev)
+	    {
+		next->prev = prev;
+	    }
+	    else
+	    {
+		parent->windows = next;
+		next->prev = NULL;
+	    }
+	}
+
+	if (prev)
+	{
+	    if (next)
+	    {
+		prev->next = next;
+	    }
+	    else
+	    {
+		parent->reverseWindows = prev;
+		prev->next = NULL;
+	    }
+	}
+    }
+    else
+    {
+	parent->windows = parent->reverseWindows = NULL;
+    }
+
+    if (w == lastFoundWindow)
+	lastFoundWindow = NULL;
+    if (w == lastDamagedWindow)
+	lastDamagedWindow = NULL;
+}
openSUSE Build Service is sponsored by