[mutter] Separate source and header files for MutterWindow



commit c60d4c2bc43d374269f3148bc752a48b6033376a
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Fri Jun 26 15:33:20 2009 -0400

    Separate source and header files for MutterWindow
    
    compositor.c: Move MutterWindow code to mutter-window.c;
     rename map_win() to mutter_window_map(), etc.
    
    mutter-window-private.h: New private header file for
     MutterWindow functions used internally to the compositor.
    
    compositor-mutter.h: Move MutterWindow declarations to
     mutter-window.h; move a couple of private functions to
     compositor-private.h
    
    compositor-private.h: Move MetaCompScreen declaration to here:
     Conceptually it's private to compositor.c, but MutterWindow
     manipulates some of the lists directly for now.
    
    mutter-plugin.c compositor.c: Don't call mutter_window_effect_completed()
     for MUTTER_PLUGIN_SWITCH_WORKSPACE, but use a new
     mutter_switch_workspace_completed(), since the window is
     just used to identify a screen.
    
    http://bugzilla.gnome.org/show_bug.cgi?id=587251

 src/Makefile.am                        |    6 +-
 src/compositor/compositor-private.h    |   30 +
 src/compositor/compositor.c            | 1580 +-------------------------------
 src/compositor/mutter-plugin.c         |   15 +-
 src/compositor/mutter-window-private.h |   39 +
 src/compositor/mutter-window.c         | 1528 ++++++++++++++++++++++++++++++
 src/include/compositor-mutter.h        |   50 +-
 src/include/mutter-window.h            |   71 ++
 8 files changed, 1727 insertions(+), 1592 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index d46a73a..e3a7c5c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,8 @@ mutter_SOURCES= 				\
 	compositor/mutter-plugin-manager.c	\
 	compositor/mutter-plugin-manager.h	\
 	compositor/mutter-shaped-texture.c	\
+	compositor/mutter-window.c		\
+	compositor/mutter-window-private.h	\
 	compositor/shadow.c			\
 	compositor/shadow.h			\
 	compositor/mutter-shaped-texture.h	\
@@ -36,6 +38,7 @@ mutter_SOURCES= 				\
 	compositor/tidy/tidy-texture-frame.h	\
 	include/compositor.h			\
 	include/mutter-plugin.h			\
+	include/mutter-window.h			\
 	include/compositor-mutter.h 		\
 	core/constraints.c			\
 	core/constraints.h			\
@@ -162,7 +165,8 @@ libmutterinclude_base_headers =		\
 	include/display.h			\
 	include/group.h				\
 	include/keybindings.h			\
-	include/mutter-plugin.h
+	include/mutter-plugin.h			\
+	include/mutter-window.h
 
 # Excluded from scanning for introspection but installed
 libmutterinclude_extra_headers =		\
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 6611761..986c570 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -3,10 +3,15 @@
 #ifndef META_COMPOSITOR_PRIVATE_H
 #define META_COMPOSITOR_PRIVATE_H
 
+#include <X11/extensions/Xfixes.h>
+
 #include "compositor.h"
 #include "display.h"
+#include "mutter-plugin-manager.h"
 #include <clutter/clutter.h>
 
+typedef struct _MetaCompScreen MetaCompScreen;
+
 struct _MetaCompositor
 {
   MetaDisplay    *display;
@@ -22,4 +27,29 @@ struct _MetaCompositor
   gboolean        no_mipmaps  : 1;
 };
 
+struct _MetaCompScreen
+{
+  MetaScreen            *screen;
+
+  ClutterActor          *stage, *window_group, *overlay_group;
+  ClutterActor		*hidden_group;
+  GList                 *windows;
+  GHashTable            *windows_by_xid;
+  MetaWindow            *focus_window;
+  Window                 output;
+  GSList                *dock_windows;
+
+  /* Before we create the output window */
+  XserverRegion     pending_input_region;
+
+  gint                   switch_workspace_in_progress;
+
+  MutterPluginManager *plugin_mgr;
+};
+
+void mutter_switch_workspace_completed (MetaScreen    *screen);
+void mutter_set_stage_input_region     (MetaScreen    *screen,
+                                        XserverRegion  region);
+void mutter_empty_stage_input_region   (MetaScreen    *screen);
+
 #endif /* META_COMPOSITOR_PRIVATE_H */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 5a70bb9..0950fa2 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -2,91 +2,24 @@
 
 #include <config.h>
 
-#include <string.h>
-#include <unistd.h>
-
-#include <gdk/gdk.h>
+#include <clutter/x11/clutter-x11.h>
 
-#include "../core/window-private.h"
 #include "screen.h"
-#include "frame.h"
 #include "errors.h"
 #include "window.h"
 #include "compositor-private.h"
 #include "compositor-mutter.h"
-#include "mutter-plugin-manager.h"
 #include "xprops.h"
 #include "prefs.h"
-#include "shadow.h"
-#include "mutter-shaped-texture.h"
-#include <X11/Xatom.h>
-#include <X11/Xlibint.h>
+#include "mutter-window-private.h"
+#include "../core/window-private.h" /* to check window->hidden */
+#include "../core/display-private.h" /* for meta_display_lookup_x_window() */
 #include <X11/extensions/shape.h>
 #include <X11/extensions/Xcomposite.h>
-#include <X11/extensions/Xdamage.h>
-#include <X11/extensions/Xfixes.h>
-#include <X11/extensions/Xrender.h>
-
-#include <clutter/x11/clutter-x11.h>
-
-#define CHECK_LIST_INTEGRITY_START(list)	\
-  {int len2__; int len__ = g_list_length(list);
-
-#define CHECK_LIST_INTEGRITY_END(list)			    \
-  len2__ = g_list_length(list);				    \
-  if (len__ != len2__)					    \
-    g_warning ("Integrity check of list failed at %s:%d\n", \
-	       __FILE__, __LINE__); }
 
 /* #define DEBUG_TRACE g_print */
 #define DEBUG_TRACE(X)
 
-/*
- * Register GType wrapper for XWindowAttributes, so we do not have to
- * query window attributes in the MutterWindow constructor but can pass
- * them as a property to the constructor (so we can gracefully handle the case
- * where no attributes can be retrieved).
- *
- * NB -- we only need a subset of the attributes; at some point we might want
- * to just store the relevant values rather than the whole struct.
- */
-#define META_TYPE_XATTRS (meta_xattrs_get_type ())
-
-GType meta_xattrs_get_type   (void) G_GNUC_CONST;
-
-static XWindowAttributes *
-meta_xattrs_copy (const XWindowAttributes *attrs)
-{
-  XWindowAttributes *result;
-
-  g_return_val_if_fail (attrs != NULL, NULL);
-
-  result = (XWindowAttributes*) Xmalloc (sizeof (XWindowAttributes));
-  *result = *attrs;
-
-  return result;
-}
-
-static void
-meta_xattrs_free (XWindowAttributes *attrs)
-{
-  g_return_if_fail (attrs != NULL);
-
-  XFree (attrs);
-}
-
-GType
-meta_xattrs_get_type (void)
-{
-  static GType our_type = 0;
-
-  if (!our_type)
-    our_type = g_boxed_type_register_static ("XWindowAttributes",
-		                     (GBoxedCopyFunc) meta_xattrs_copy,
-				     (GBoxedFreeFunc) meta_xattrs_free);
-  return our_type;
-}
-
 static inline gboolean
 composite_at_least_version (MetaDisplay *display, int maj, int min)
 {
@@ -99,493 +32,6 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
   return (major > maj || (major == maj && minor >= min));
 }
 
-typedef struct _MetaCompScreen
-{
-  MetaScreen            *screen;
-
-  ClutterActor          *stage, *window_group, *overlay_group;
-  ClutterActor		*hidden_group;
-  GList                 *windows;
-  GHashTable            *windows_by_xid;
-  MetaWindow            *focus_window;
-  Window                 output;
-  GSList                *dock_windows;
-
-  /* Before we create the output window */
-  XserverRegion     pending_input_region;
-
-  gint                   switch_workspace_in_progress;
-
-  MutterPluginManager *plugin_mgr;
-} MetaCompScreen;
-
-/*
- * MutterWindow implementation
- */
-struct _MutterWindowPrivate
-{
-  XWindowAttributes attrs;
-
-  MetaWindow       *window;
-  Window            xwindow;
-  MetaScreen       *screen;
-
-  ClutterActor     *actor;
-  ClutterActor     *shadow;
-  Pixmap            back_pixmap;
-
-  MetaCompWindowType  type;
-  Damage            damage;
-
-  guint8            opacity;
-
-  gchar *           desc;
-
-  /*
-   * These need to be counters rather than flags, since more plugins
-   * can implement same effect; the practicality of stacking effects
-   * might be dubious, but we have to at least handle it correctly.
-   */
-  gint              minimize_in_progress;
-  gint              maximize_in_progress;
-  gint              unmaximize_in_progress;
-  gint              map_in_progress;
-  gint              destroy_in_progress;
-
-  guint		    shaped                 : 1;
-  guint		    destroy_pending        : 1;
-  guint		    argb32                 : 1;
-  guint		    disposed               : 1;
-  guint		    is_minimized           : 1;
-  guint		    hide_after_effect      : 1;
-  guint             redecorating           : 1;
-
-  /* Desktop switching flags */
-  guint		    needs_map              : 1;
-  guint		    needs_unmap            : 1;
-  guint		    needs_repair           : 1;
-
-  guint		    needs_destroy	   : 1;
-
-  guint             no_shadow              : 1;
-
-  guint             no_more_x_calls        : 1;
-};
-
-enum
-{
-  PROP_MCW_META_WINDOW = 1,
-  PROP_MCW_META_SCREEN,
-  PROP_MCW_X_WINDOW,
-  PROP_MCW_X_WINDOW_ATTRIBUTES,
-  PROP_MCW_NO_SHADOW,
-};
-
-static void mutter_window_class_init (MutterWindowClass *klass);
-static void mutter_window_init       (MutterWindow *self);
-static void mutter_window_dispose    (GObject *object);
-static void mutter_window_finalize   (GObject *object);
-static void mutter_window_constructed (GObject *object);
-static void mutter_window_set_property (GObject       *object,
-					   guint         prop_id,
-					   const GValue *value,
-					   GParamSpec   *pspec);
-static void mutter_window_get_property (GObject      *object,
-					   guint         prop_id,
-					   GValue       *value,
-					   GParamSpec   *pspec);
-static void mutter_window_query_window_type (MutterWindow *self);
-static void mutter_window_detach (MutterWindow *self);
-
-G_DEFINE_TYPE (MutterWindow, mutter_window, CLUTTER_TYPE_GROUP);
-
-static void
-mutter_window_class_init (MutterWindowClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GParamSpec   *pspec;
-
-  g_type_class_add_private (klass, sizeof (MutterWindowPrivate));
-
-  object_class->dispose      = mutter_window_dispose;
-  object_class->finalize     = mutter_window_finalize;
-  object_class->set_property = mutter_window_set_property;
-  object_class->get_property = mutter_window_get_property;
-  object_class->constructed  = mutter_window_constructed;
-
-  pspec = g_param_spec_object ("meta-window",
-                               "MetaWindow",
-                               "The displayed MetaWindow",
-                               META_TYPE_WINDOW,
-                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  g_object_class_install_property (object_class,
-                                   PROP_MCW_META_WINDOW,
-                                   pspec);
-
-  pspec = g_param_spec_pointer ("meta-screen",
-				"MetaScreen",
-				"MetaScreen",
-				G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  g_object_class_install_property (object_class,
-                                   PROP_MCW_META_SCREEN,
-                                   pspec);
-
-  pspec = g_param_spec_ulong ("x-window",
-			      "Window",
-			      "Window",
-			      0,
-			      G_MAXULONG,
-			      0,
-			      G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  g_object_class_install_property (object_class,
-                                   PROP_MCW_X_WINDOW,
-                                   pspec);
-
-  pspec = g_param_spec_boxed ("x-window-attributes",
-			      "XWindowAttributes",
-			      "XWindowAttributes",
-			      META_TYPE_XATTRS,
-			      G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  g_object_class_install_property (object_class,
-                                   PROP_MCW_X_WINDOW_ATTRIBUTES,
-                                   pspec);
-
-  pspec = g_param_spec_boolean ("no-shadow",
-                                "No shadow",
-                                "Do not add shaddow to this window",
-                                FALSE,
-                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  g_object_class_install_property (object_class,
-                                   PROP_MCW_NO_SHADOW,
-                                   pspec);
-}
-
-static void
-mutter_window_init (MutterWindow *self)
-{
-  MutterWindowPrivate *priv;
-
-  priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
-						   MUTTER_TYPE_COMP_WINDOW,
-						   MutterWindowPrivate);
-  priv->opacity = 0xff;
-}
-
-static gboolean is_shaped (MetaDisplay *display, Window xwindow);
-static gboolean mutter_window_has_shadow (MutterWindow *self);
-static void update_shape (MetaCompositor *compositor,
-                          MutterWindow   *cw);
-
-static void
-mutter_meta_window_decorated_notify (MetaWindow *mw,
-                                     GParamSpec *arg1,
-                                     gpointer    data)
-{
-  MutterWindow        *mcw      = MUTTER_WINDOW (data);
-  MutterWindowPrivate *priv     = mcw->priv;
-  MetaFrame           *frame    = meta_window_get_frame (mw);
-  MetaScreen          *screen   = priv->screen;
-  MetaDisplay         *display  = meta_screen_get_display (screen);
-  Display             *xdisplay = meta_display_get_xdisplay (display);
-  Window               new_xwindow;
-  MetaCompScreen      *info;
-  XWindowAttributes    attrs;
-
-  /*
-   * Basically, we have to reconstruct the the internals of this object
-   * from scratch, as everything has changed.
-   */
-  priv->redecorating = TRUE;
-
-  if (frame)
-    new_xwindow = meta_frame_get_xwindow (frame);
-  else
-    new_xwindow = meta_window_get_xwindow (mw);
-
-  mutter_window_detach (mcw);
-
-  info = meta_screen_get_compositor_data (screen);
-
-  /*
-   * First of all, clean up any resources we are currently using and will
-   * be replacing.
-   */
-  if (priv->damage != None)
-    {
-      meta_error_trap_push (display);
-      XDamageDestroy (xdisplay, priv->damage);
-      meta_error_trap_pop (display, FALSE);
-      priv->damage = None;
-    }
-
-  g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
-  g_hash_table_insert (info->windows_by_xid, (gpointer) new_xwindow, mcw);
-
-  g_free (priv->desc);
-  priv->desc = NULL;
-
-  priv->xwindow = new_xwindow;
-
-  if (!XGetWindowAttributes (xdisplay, new_xwindow, &attrs))
-    {
-      g_warning ("Could not obtain attributes for window 0x%x after "
-                 "decoration change",
-                 (guint) new_xwindow);
-      return;
-    }
-
-  g_object_set (mcw, "x-window-attributes", &attrs, NULL);
-
-  if (priv->shadow)
-    {
-      ClutterActor *p = clutter_actor_get_parent (priv->shadow);
-
-      if (CLUTTER_IS_CONTAINER (p))
-        clutter_container_remove_actor (CLUTTER_CONTAINER (p), priv->shadow);
-      else
-        clutter_actor_unparent (priv->shadow);
-
-      priv->shadow = NULL;
-    }
-
-  /*
-   * Recreate the contents.
-   */
-  mutter_window_constructed (G_OBJECT (mcw));
-}
-
-static void
-mutter_window_constructed (GObject *object)
-{
-  MutterWindow        *self     = MUTTER_WINDOW (object);
-  MutterWindowPrivate *priv     = self->priv;
-  MetaScreen          *screen   = priv->screen;
-  MetaDisplay         *display  = meta_screen_get_display (screen);
-  Window               xwindow  = priv->xwindow;
-  Display             *xdisplay = meta_display_get_xdisplay (display);
-  XRenderPictFormat   *format;
-  gulong               value;
-  MetaCompositor      *compositor;
-  Window               xwin_child;
-
-  compositor = meta_display_get_compositor (display);
-  xwin_child = meta_window_get_xwindow (priv->window);
-
-  mutter_window_query_window_type (self);
-
-#ifdef HAVE_SHAPE
-  /* Listen for ShapeNotify events on the window */
-  if (meta_display_has_shape (display))
-    XShapeSelectInput (xdisplay, xwindow, ShapeNotifyMask);
-#endif
-
-  priv->shaped = is_shaped (display, xwindow);
-
-  if (priv->attrs.class == InputOnly)
-    priv->damage = None;
-  else
-    priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty);
-
-  format = XRenderFindVisualFormat (xdisplay, priv->attrs.visual);
-
-  if (format && format->type == PictTypeDirect && format->direct.alphaMask)
-    priv->argb32 = TRUE;
-
-  if (meta_prop_get_cardinal (display, xwin_child,
-                              compositor->atom_net_wm_window_opacity,
-                              &value))
-    {
-      guint8 opacity;
-
-      opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
-
-      priv->opacity = opacity;
-      clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity);
-    }
-
-  if (mutter_window_has_shadow (self))
-    {
-      priv->shadow = mutter_create_shadow_frame (compositor);
-
-      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
-    }
-
-  if (!priv->actor)
-    {
-      priv->actor = mutter_shaped_texture_new ();
-
-      if (!clutter_glx_texture_pixmap_using_extension (
-                                  CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
-        g_warning ("NOTE: Not using GLX TFP!\n");
-
-      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
-
-      g_signal_connect (priv->window, "notify::decorated",
-                        G_CALLBACK (mutter_meta_window_decorated_notify), self);
-    }
-  else
-    {
-      /*
-       * This is the case where existing window is gaining/loosing frame.
-       * Just ensure the actor is top most (i.e., above shadow).
-       */
-      clutter_actor_raise_top (priv->actor);
-    }
-
-
-  update_shape (compositor, self);
-}
-
-static void
-mutter_window_dispose (GObject *object)
-{
-  MutterWindow        *self = MUTTER_WINDOW (object);
-  MutterWindowPrivate *priv = self->priv;
-  MetaScreen            *screen;
-  MetaDisplay           *display;
-  Display               *xdisplay;
-  MetaCompScreen        *info;
-
-  if (priv->disposed)
-    return;
-
-  priv->disposed = TRUE;
-
-  screen   = priv->screen;
-  display  = meta_screen_get_display (screen);
-  xdisplay = meta_display_get_xdisplay (display);
-  info     = meta_screen_get_compositor_data (screen);
-
-  mutter_window_detach (self);
-
-  if (priv->damage != None)
-    {
-      meta_error_trap_push (display);
-      XDamageDestroy (xdisplay, priv->damage);
-      meta_error_trap_pop (display, FALSE);
-
-      priv->damage = None;
-    }
-
-  /*
-   * Check we are not in the dock list -- FIXME (do this in a cleaner way)
-   */
-  if (priv->type == META_COMP_WINDOW_DOCK)
-    info->dock_windows = g_slist_remove (info->dock_windows, self);
-
-  info->windows = g_list_remove (info->windows, (gconstpointer) self);
-  g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
-
-  g_free (priv->desc);
-
-  G_OBJECT_CLASS (mutter_window_parent_class)->dispose (object);
-}
-
-static void
-mutter_window_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (mutter_window_parent_class)->finalize (object);
-}
-
-static void
-mutter_window_set_property (GObject      *object,
-                            guint         prop_id,
-                            const GValue *value,
-                            GParamSpec   *pspec)
-{
-  MutterWindow        *mw   = MUTTER_WINDOW (object);
-  MutterWindowPrivate *priv = mw->priv;
-
-  switch (prop_id)
-    {
-    case PROP_MCW_META_WINDOW:
-      priv->window = g_value_get_object (value);
-      break;
-    case PROP_MCW_META_SCREEN:
-      priv->screen = g_value_get_pointer (value);
-      break;
-    case PROP_MCW_X_WINDOW:
-      priv->xwindow = g_value_get_ulong (value);
-      break;
-    case PROP_MCW_X_WINDOW_ATTRIBUTES:
-      priv->attrs = *((XWindowAttributes*)g_value_get_boxed (value));
-      break;
-    case PROP_MCW_NO_SHADOW:
-      {
-        gboolean oldv = priv->no_shadow ? TRUE : FALSE;
-        gboolean newv = g_value_get_boolean (value);
-
-        if (oldv == newv)
-          return;
-
-        priv->no_shadow = newv;
-
-        if (newv && priv->shadow)
-          {
-            clutter_container_remove_actor (CLUTTER_CONTAINER (object),
-                                            priv->shadow);
-            priv->shadow = NULL;
-          }
-        else if (!newv && !priv->shadow && mutter_window_has_shadow (mw))
-          {
-            gfloat       w, h;
-            MetaDisplay *display = meta_screen_get_display (priv->screen);
-            MetaCompositor *compositor;
-
-            compositor = meta_display_get_compositor (display);
-
-            clutter_actor_get_size (CLUTTER_ACTOR (mw), &w, &h);
-
-            priv->shadow = mutter_create_shadow_frame (compositor);
-
-            clutter_actor_set_size (priv->shadow, w, h);
-
-            clutter_container_add_actor (CLUTTER_CONTAINER (mw), priv->shadow);
-          }
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-mutter_window_get_property (GObject      *object,
-			       guint         prop_id,
-			       GValue       *value,
-			       GParamSpec   *pspec)
-{
-  MutterWindowPrivate *priv = MUTTER_WINDOW (object)->priv;
-
-  switch (prop_id)
-    {
-    case PROP_MCW_META_WINDOW:
-      g_value_set_object (value, priv->window);
-      break;
-    case PROP_MCW_META_SCREEN:
-      g_value_set_pointer (value, priv->screen);
-      break;
-    case PROP_MCW_X_WINDOW:
-      g_value_set_ulong (value, priv->xwindow);
-      break;
-    case PROP_MCW_X_WINDOW_ATTRIBUTES:
-      g_value_set_boxed (value, &priv->attrs);
-      break;
-    case PROP_MCW_NO_SHADOW:
-      g_value_set_boolean (value, priv->no_shadow);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
 static MutterWindow*
 find_window_for_screen (MetaScreen *screen, Window xwindow)
 {
@@ -594,7 +40,8 @@ find_window_for_screen (MetaScreen *screen, Window xwindow)
   if (info == NULL)
     return NULL;
 
-  return g_hash_table_lookup (info->windows_by_xid, (gpointer) xwindow);
+  return g_hash_table_lookup (info->windows_by_xid,
+                              (gpointer) xwindow);
 }
 
 static MutterWindow *
@@ -638,229 +85,6 @@ find_window_for_child_window_in_display (MetaDisplay *display, Window xwindow)
   return NULL;
 }
 
-static void
-mutter_window_query_window_type (MutterWindow *self)
-{
-  MutterWindowPrivate *priv = self->priv;
-  priv->type = (MetaCompWindowType) meta_window_get_window_type (priv->window);
-}
-
-static gboolean
-is_shaped (MetaDisplay *display, Window xwindow)
-{
-  Display *xdisplay = meta_display_get_xdisplay (display);
-  gint     xws, yws, xbs, ybs;
-  guint    wws, hws, wbs, hbs;
-  gint     bounding_shaped, clip_shaped;
-
-  if (meta_display_has_shape (display))
-    {
-      XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
-                          &xws, &yws, &wws, &hws, &clip_shaped,
-                          &xbs, &ybs, &wbs, &hbs);
-      return (bounding_shaped != 0);
-    }
-
-  return FALSE;
-}
-
-static gboolean
-mutter_window_has_shadow (MutterWindow *self)
-{
-  MutterWindowPrivate * priv = self->priv;
-
-  if (priv->no_shadow)
-    return FALSE;
-
-  /*
-   * Always put a shadow around windows with a frame - This should override
-   * the restriction about not putting a shadow around shaped windows
-   * as the frame might be the reason the window is shaped
-   */
-  if (priv->window)
-    {
-      if (meta_window_get_frame (priv->window))
-	{
-	  meta_verbose ("Window 0x%x has shadow because it has a frame\n",
-			(guint)priv->xwindow);
-	  return TRUE;
-	}
-    }
-
-  /*
-   * Do not add shadows to ARGB windows (since they are probably transparent)
-   */
-  if (priv->argb32 || priv->opacity != 0xff)
-    {
-      meta_verbose ("Window 0x%x has no shadow as it is ARGB\n",
-		    (guint)priv->xwindow);
-      return FALSE;
-    }
-
-  /*
-   * Never put a shadow around shaped windows
-   */
-  if (priv->shaped)
-    {
-      meta_verbose ("Window 0x%x has no shadow as it is shaped\n",
-		    (guint)priv->xwindow);
-      return FALSE;
-    }
-
-  /*
-   * Add shadows to override redirect windows (e.g., Gtk menus).
-   * This must have lower priority than window shape test.
-   */
-  if (priv->attrs.override_redirect)
-    {
-      meta_verbose ("Window 0x%x has shadow because it is override redirect.\n",
-		    (guint)priv->xwindow);
-      return TRUE;
-    }
-
-  /*
-   * Don't put shadow around DND icon windows
-   */
-  if (priv->type == META_COMP_WINDOW_DND ||
-      priv->type == META_COMP_WINDOW_DESKTOP)
-    {
-      meta_verbose ("Window 0x%x has no shadow as it is DND or Desktop\n",
-		    (guint)priv->xwindow);
-      return FALSE;
-    }
-
-  if (priv->type == META_COMP_WINDOW_MENU
-#if 0
-      || priv->type == META_COMP_WINDOW_DROPDOWN_MENU
-#endif
-      )
-    {
-      meta_verbose ("Window 0x%x has shadow as it is a menu\n",
-		    (guint)priv->xwindow);
-      return TRUE;
-    }
-
-#if 0
-  if (priv->type == META_COMP_WINDOW_TOOLTIP)
-    {
-      meta_verbose ("Window 0x%x has shadow as it is a tooltip\n",
-		    (guint)priv->xwindow);
-      return TRUE;
-    }
-#endif
-
-  meta_verbose ("Window 0x%x has no shadow as it fell through\n",
-		(guint)priv->xwindow);
-  return FALSE;
-}
-
-Window
-mutter_window_get_x_window (MutterWindow *mcw)
-{
-  if (!mcw)
-    return None;
-
-  return mcw->priv->xwindow;
-}
-
-/**
- * mutter_window_get_meta_window:
- *
- * Gets the MetaWindow object that the the MutterWindow is displaying
- *
- * Return value: (transfer none): the displayed MetaWindow
- */
-MetaWindow *
-mutter_window_get_meta_window (MutterWindow *mcw)
-{
-  return mcw->priv->window;
-}
-
-/**
- * mutter_window_get_texture:
- *
- * Gets the ClutterActor that is used to display the contents of the window
- *
- * Return value: (transfer none): the ClutterActor for the contents
- */
-ClutterActor *
-mutter_window_get_texture (MutterWindow *mcw)
-{
-  return mcw->priv->actor;
-}
-
-MetaCompWindowType
-mutter_window_get_window_type (MutterWindow *mcw)
-{
-  if (!mcw)
-    return 0;
-
-  return mcw->priv->type;
-}
-
-gboolean
-mutter_window_is_override_redirect (MutterWindow *mcw)
-{
-  if (mcw->priv->window->override_redirect)
-    return TRUE;
-
-  return FALSE;
-}
-
-const char *mutter_window_get_description (MutterWindow *mcw)
-{
-  /*
-   * For windows managed by the WM, we just defer to the WM for the window
-   * description. For override-redirect windows, we create the description
-   * ourselves, but only on demand.
-   */
-  if (mcw->priv->window)
-    return meta_window_get_description (mcw->priv->window);
-
-  if (G_UNLIKELY (mcw->priv->desc == NULL))
-    {
-      mcw->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
-                                         (guint) mcw->priv->xwindow);
-    }
-
-  return mcw->priv->desc;
-}
-
-gint
-mutter_window_get_workspace (MutterWindow *mcw)
-{
-  MutterWindowPrivate *priv;
-  MetaWorkspace       *workspace;
-
-  if (!mcw)
-    return -1;
-
-  priv = mcw->priv;
-
-  if (!priv->window || meta_window_is_on_all_workspaces (priv->window))
-    return -1;
-
-  workspace = meta_window_get_workspace (priv->window);
-
-  return meta_workspace_index (workspace);
-}
-
-gboolean
-mutter_window_showing_on_its_workspace (MutterWindow *mcw)
-{
-  if (!mcw)
-    return FALSE;
-
-  /* If override redirect: */
-  if (!mcw->priv->window)
-    return TRUE;
-
-  return meta_window_showing_on_its_workspace (mcw->priv->window);
-}
-
-static void repair_win (MutterWindow *cw);
-static void map_win    (MutterWindow *cw);
-static void unmap_win  (MutterWindow *cw);
 static void sync_actor_stacking (GList *windows);
 
 static void
@@ -882,18 +106,7 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
 
       while (l)
 	{
-	  MutterWindow        *cw   = l->data;
-	  MutterWindowPrivate *priv = cw->priv;
-
-	  if (priv->needs_map && !priv->needs_unmap)
-	    {
-	      map_win (cw);
-	    }
-
-	  if (priv->needs_unmap)
-	    {
-	      unmap_win (cw);
-	    }
+          mutter_window_finish_workspace_switch (l->data);
 
 	  l = l->prev;
 	}
@@ -909,676 +122,50 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
 
 }
 
-static gboolean
-effect_in_progress (MutterWindow *cw, gboolean include_destroy)
-{
-  return (cw->priv->minimize_in_progress ||
-	  cw->priv->maximize_in_progress ||
-	  cw->priv->unmaximize_in_progress ||
-	  cw->priv->map_in_progress ||
-	  (include_destroy && cw->priv->destroy_in_progress));
-}
-
-void
-mutter_window_effect_completed (MutterWindow *cw, gulong event)
-{
-  MutterWindowPrivate *priv   = cw->priv;
-  MetaScreen          *screen = priv->screen;
-  MetaCompScreen      *info   = meta_screen_get_compositor_data (screen);
-  ClutterActor        *actor  = CLUTTER_ACTOR (cw);
-  gboolean             effect_done = FALSE;
-
-  /* NB: Keep in mind that when effects get completed it possible
-   * that the corresponding MetaWindow may have be been destroyed.
-   * In this case priv->window will == NULL */
-
-  switch (event)
-  {
-  case MUTTER_PLUGIN_MINIMIZE:
-    {
-      ClutterActor *a = CLUTTER_ACTOR (cw);
-
-      priv->minimize_in_progress--;
-      if (priv->minimize_in_progress < 0)
-	{
-	  g_warning ("Error in minimize accounting.");
-	  priv->minimize_in_progress = 0;
-	}
-
-      if (!priv->minimize_in_progress)
-	{
-	  priv->is_minimized = TRUE;
-
-	  /*
-	   * We must ensure that the minimized actor is pushed down the stack
-	   * (the XConfigureEvent has 'above' semantics, i.e., when a window
-	   * is lowered, we get a bunch of 'raise' notifications, but might
-	   * not get any notification for the window that has been lowered.
-	   */
-	  clutter_actor_lower_bottom (a);
-
-	  /* Make sure that after the effect finishes, the actor is
-	   * made visible for sake of live previews.
-	   */
-	  clutter_actor_show (a);
-
-	  effect_done = TRUE;
-	}
-    }
-    break;
-  case MUTTER_PLUGIN_MAP:
-    /*
-     * Make sure that the actor is at the correct place in case
-     * the plugin fscked.
-     */
-    priv->map_in_progress--;
-
-    if (priv->map_in_progress < 0)
-      {
-	g_warning ("Error in map accounting.");
-	priv->map_in_progress = 0;
-      }
-
-    if (!priv->map_in_progress && priv->window && !priv->no_more_x_calls)
-      {
-	MetaRectangle rect;
-	meta_window_get_outer_rect (priv->window, &rect);
-	priv->is_minimized = FALSE;
-	clutter_actor_set_anchor_point (actor, 0, 0);
-	clutter_actor_set_position (actor, rect.x, rect.y);
-	clutter_actor_show_all (actor);
-	effect_done = TRUE;
-      }
-    break;
-  case MUTTER_PLUGIN_DESTROY:
-    priv->destroy_in_progress--;
-
-    if (priv->destroy_in_progress < 0)
-      {
-	g_warning ("Error in destroy accounting.");
-	priv->destroy_in_progress = 0;
-      }
-
-    if (!priv->destroy_in_progress)
-      {
-	priv->needs_destroy = TRUE;
-	effect_done = TRUE;
-      }
-    break;
-  case MUTTER_PLUGIN_UNMAXIMIZE:
-    priv->unmaximize_in_progress--;
-    if (priv->unmaximize_in_progress < 0)
-      {
-	g_warning ("Error in unmaximize accounting.");
-	priv->unmaximize_in_progress = 0;
-      }
-
-    if (!priv->unmaximize_in_progress && priv->window && !priv->no_more_x_calls)
-      {
-	MetaRectangle rect;
-	meta_window_get_outer_rect (priv->window, &rect);
-	clutter_actor_set_position (actor, rect.x, rect.y);
-	mutter_window_detach (cw);
-	repair_win (cw);
-        effect_done = TRUE;
-      }
-    break;
-  case MUTTER_PLUGIN_MAXIMIZE:
-    priv->maximize_in_progress--;
-    if (priv->maximize_in_progress < 0)
-      {
-	g_warning ("Error in maximize accounting.");
-	priv->maximize_in_progress = 0;
-      }
-
-    if (!priv->maximize_in_progress && priv->window && !priv->no_more_x_calls)
-      {
-	MetaRectangle rect;
-	meta_window_get_outer_rect (priv->window, &rect);
-	clutter_actor_set_position (actor, rect.x, rect.y);
-	mutter_window_detach (cw);
-	repair_win (cw);
-        effect_done = TRUE;
-      }
-    break;
-  case MUTTER_PLUGIN_SWITCH_WORKSPACE:
-    /* FIXME -- must redo stacking order */
-    info->switch_workspace_in_progress--;
-    if (info->switch_workspace_in_progress < 0)
-      {
-	g_warning ("Error in workspace_switch accounting!");
-	info->switch_workspace_in_progress = 0;
-      }
-
-    if (!info->switch_workspace_in_progress)
-      mutter_finish_workspace_switch (info);
-    break;
-  default:
-    break;
-  }
-
-  switch (event)
-  {
-  case MUTTER_PLUGIN_MINIMIZE:
-  case MUTTER_PLUGIN_MAP:
-  case MUTTER_PLUGIN_DESTROY:
-  case MUTTER_PLUGIN_UNMAXIMIZE:
-  case MUTTER_PLUGIN_MAXIMIZE:
-
-    if (effect_done &&
-	priv->hide_after_effect &&
-	effect_in_progress (cw, TRUE) == FALSE)
-      {
-	if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group)
-	  {
-	    clutter_actor_reparent (CLUTTER_ACTOR (cw),
-				    info->hidden_group);
-	  }
-	priv->hide_after_effect = FALSE;
-      }
-
-    if (priv->needs_destroy && effect_in_progress (cw, TRUE) == FALSE)
-      {
-	clutter_actor_destroy (CLUTTER_ACTOR (cw));
-	return;
-      }
-
-  default:
-    break;
-  }
-}
-
-
 void
-meta_compositor_destroy (MetaCompositor *compositor)
-{
-}
-
-static void
-mutter_window_detach (MutterWindow *self)
+mutter_switch_workspace_completed (MetaScreen *screen)
 {
-  MutterWindowPrivate *priv     = self->priv;
-  MetaScreen            *screen   = priv->screen;
-  MetaDisplay           *display  = meta_screen_get_display (screen);
-  Display               *xdisplay = meta_display_get_xdisplay (display);
-
-  if (!priv->back_pixmap)
-    return;
-
-  XFreePixmap (xdisplay, priv->back_pixmap);
-  priv->back_pixmap = None;
-}
-
-static void
-destroy_win (MutterWindow *cw)
-{
-  MetaWindow	      *window;
-  MetaCompScreen      *info;
-  MutterWindowPrivate *priv;
-
-  priv = cw->priv;
-
-  window = priv->window;
-  meta_window_set_compositor_private (window, NULL);
-
-  /*
-   * We remove the window from internal lookup hashes and thus any other
-   * unmap events etc fail
-   */
-  info = meta_screen_get_compositor_data (priv->screen);
-  info->windows = g_list_remove (info->windows, (gconstpointer) cw);
-  g_hash_table_remove (info->windows_by_xid, (gpointer)priv->xwindow);
-
-  if (priv->type == META_COMP_WINDOW_DROPDOWN_MENU ||
-      priv->type == META_COMP_WINDOW_POPUP_MENU ||
-      priv->type == META_COMP_WINDOW_TOOLTIP ||
-      priv->type == META_COMP_WINDOW_NOTIFICATION ||
-      priv->type == META_COMP_WINDOW_COMBO ||
-      priv->type == META_COMP_WINDOW_DND ||
-      priv->type == META_COMP_WINDOW_OVERRIDE_OTHER)
-    {
-      /*
-       * No effects, just kill it.
-       */
-      clutter_actor_destroy (CLUTTER_ACTOR (cw));
-      return;
-    }
-
-  /*
-   * If a plugin manager is present, try to run an effect; if no effect of this
-   * type is present, destroy the actor.
-   */
-  priv->destroy_in_progress++;
-
-  /*
-   * Once the window destruction is initiated we can no longer perform any
-   * furter X-based operations. For example, if we have a Map effect running,
-   * we cannot query the window geometry once the effect completes. So, flag
-   * this.
-   */
-  priv->no_more_x_calls = TRUE;
+  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 
-  if (!info->plugin_mgr ||
-      !mutter_plugin_manager_event_simple (info->plugin_mgr,
-					   cw,
-					   MUTTER_PLUGIN_DESTROY))
+  /* FIXME -- must redo stacking order */
+  info->switch_workspace_in_progress--;
+  if (info->switch_workspace_in_progress < 0)
     {
-      priv->destroy_in_progress--;
-
-      if (effect_in_progress (cw, FALSE))
-	{
-	  priv->needs_destroy = TRUE;
-	}
-      else
-	clutter_actor_destroy (CLUTTER_ACTOR (cw));
+      g_warning ("Error in workspace_switch accounting!");
+      info->switch_workspace_in_progress = 0;
     }
-}
-
-static void
-sync_actor_position (MutterWindow *cw)
-{
-  MutterWindowPrivate *priv = cw->priv;
-  MetaRectangle window_rect;
 
-  meta_window_get_outer_rect (priv->window, &window_rect);
-
-  if (priv->attrs.width != window_rect.width ||
-      priv->attrs.height != window_rect.height)
-    mutter_window_detach (cw);
-
-  /* XXX deprecated: please use meta_window_get_outer_rect instead */
-  priv->attrs.width = window_rect.width;
-  priv->attrs.height = window_rect.height;
-  priv->attrs.x = window_rect.x;
-  priv->attrs.y = window_rect.y;
-
-  if (effect_in_progress (cw, FALSE))
-    return;
-
-  clutter_actor_set_position (CLUTTER_ACTOR (cw),
-			      window_rect.x, window_rect.y);
-}
-
-static void
-map_win (MutterWindow *cw)
-{
-  MutterWindowPrivate *priv;
-  MetaCompScreen      *info;
-
-  if (!cw)
-    return;
-
-  priv = cw->priv;
-  info = meta_screen_get_compositor_data (priv->screen);
-
-  if (priv->attrs.map_state == IsViewable)
-    return;
-
-  priv->attrs.map_state = IsViewable;
-
-  /*
-   * Now repair the window; this ensures that the actor is correctly sized
-   * before we run any effects on it.
-   */
-  priv->needs_map = FALSE;
-  mutter_window_detach (cw);
-  repair_win (cw);
-
-  /*
-   * Make sure the position is set correctly (we might have got moved while
-   * unmapped.
-   */
   if (!info->switch_workspace_in_progress)
-    {
-      MetaRectangle rect;
-      meta_window_get_outer_rect (priv->window, &rect);
-      clutter_actor_set_anchor_point (CLUTTER_ACTOR (cw), 0, 0);
-      clutter_actor_set_position (CLUTTER_ACTOR (cw), rect.x, rect.y);
-    }
-
-  priv->map_in_progress++;
-
-  /*
-   * If a plugin manager is present, try to run an effect; if no effect of this
-   * type is present, destroy the actor.
-   */
-  if (priv->redecorating ||
-      info->switch_workspace_in_progress || !info->plugin_mgr ||
-      !mutter_plugin_manager_event_simple (info->plugin_mgr,
-				cw,
-                                MUTTER_PLUGIN_MAP))
-    {
-      clutter_actor_show_all (CLUTTER_ACTOR (cw));
-      priv->map_in_progress--;
-      priv->is_minimized = FALSE;
-      priv->redecorating = FALSE;
-    }
+    mutter_finish_workspace_switch (info);
 }
 
-static void
-unmap_win (MutterWindow *cw)
+void
+meta_compositor_destroy (MetaCompositor *compositor)
 {
-  MutterWindowPrivate *priv;
-  MetaCompScreen      *info;
-
-  if (!cw)
-    return;
-
-  priv = cw->priv;
-  info = meta_screen_get_compositor_data (priv->screen);
-
-  /*
-   * If the needs_unmap flag is set, we carry on even if the winow is
-   * already marked as unmapped; this is necessary so windows temporarily
-   * shown during an effect (like desktop switch) are properly hidden again.
-   */
-  if (priv->attrs.map_state == IsUnmapped && !priv->needs_unmap)
-    return;
-
-  if (priv->window && priv->window == info->focus_window)
-    info->focus_window = NULL;
-
-  if (info->switch_workspace_in_progress)
-    {
-      /*
-       * Cannot unmap windows while switching desktops effect is in progress.
-       */
-      priv->needs_unmap = TRUE;
-      return;
-    }
-
-  priv->attrs.map_state = IsUnmapped;
-  priv->needs_unmap = FALSE;
-  priv->needs_map   = FALSE;
-
-  if (!priv->minimize_in_progress &&
-      (!meta_prefs_get_live_hidden_windows () ||
-       priv->type == META_COMP_WINDOW_DROPDOWN_MENU ||
-       priv->type == META_COMP_WINDOW_POPUP_MENU ||
-       priv->type == META_COMP_WINDOW_TOOLTIP ||
-       priv->type == META_COMP_WINDOW_NOTIFICATION ||
-       priv->type == META_COMP_WINDOW_COMBO ||
-       priv->type == META_COMP_WINDOW_DND ||
-       priv->type == META_COMP_WINDOW_OVERRIDE_OTHER))
-    {
-      clutter_actor_hide (CLUTTER_ACTOR (cw));
-    }
 }
 
 static void
 add_win (MetaWindow *window)
 {
   MetaScreen		*screen = meta_window_get_screen (window);
-  MetaDisplay           *display = meta_screen_get_display (screen);
   MetaCompScreen        *info = meta_screen_get_compositor_data (screen);
-  MutterWindow          *cw;
-  MutterWindowPrivate   *priv;
-  MetaFrame		*frame;
-  Window		 top_window;
-  XWindowAttributes	 attrs;
 
   g_return_if_fail (info != NULL);
 
-  frame = meta_window_get_frame (window);
-  if (frame)
-    top_window = meta_frame_get_xwindow (frame);
-  else
-    top_window = meta_window_get_xwindow (window);
-
-  meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
-
-  /* FIXME: Remove the redundant data we store in cw->priv->attrs, and
-   * simply query metacity core for the data. */
-  if (!XGetWindowAttributes (display->xdisplay, top_window, &attrs))
-    return;
-
-  cw = g_object_new (MUTTER_TYPE_COMP_WINDOW,
-		     "meta-window",         window,
-		     "x-window",            top_window,
-		     "meta-screen",         screen,
-		     "x-window-attributes", &attrs,
-		     NULL);
-
-  priv = cw->priv;
-
-  clutter_actor_set_position (CLUTTER_ACTOR (cw),
-			      priv->attrs.x, priv->attrs.y);
-
-  clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group),
-			       CLUTTER_ACTOR (cw));
-  clutter_actor_hide (CLUTTER_ACTOR (cw));
-
-  if (priv->type == META_COMP_WINDOW_DOCK)
-    {
-      meta_verbose ("Appending 0x%x to dock windows\n", (guint)top_window);
-      info->dock_windows = g_slist_append (info->dock_windows, cw);
-    }
-
-  meta_verbose ("added 0x%x (%p) type:", (guint)top_window, cw);
-
-  /* Hang our compositor window state off the MetaWindow for fast retrieval */
-  meta_window_set_compositor_private (window, G_OBJECT (cw));
-
-  /*
-   * Add this to the list at the top of the stack before it is mapped so that
-   * map_win can find it again
-   */
-  info->windows = g_list_append (info->windows, cw);
-  g_hash_table_insert (info->windows_by_xid, (gpointer) top_window, cw);
-
-  if (priv->attrs.map_state == IsViewable)
-    {
-      /* Need to reset the map_state for map_win() to work */
-      priv->attrs.map_state = IsUnmapped;
-      map_win (cw);
-    }
+  mutter_window_new (window);
 
   sync_actor_stacking (info->windows);
 }
 
 static void
-repair_win (MutterWindow *cw)
-{
-  MutterWindowPrivate *priv     = cw->priv;
-  MetaScreen          *screen   = priv->screen;
-  MetaDisplay         *display  = meta_screen_get_display (screen);
-  Display             *xdisplay = meta_display_get_xdisplay (display);
-  MetaCompScreen      *info     = meta_screen_get_compositor_data (screen);
-  MetaCompositor      *compositor;
-  Window               xwindow  = priv->xwindow;
-  gboolean             full     = FALSE;
-
-  if (xwindow == meta_screen_get_xroot (screen) ||
-      xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
-    return;
-
-  compositor = meta_display_get_compositor (display);
-
-  meta_error_trap_push (display);
-
-  if (priv->back_pixmap == None)
-    {
-      gint pxm_width, pxm_height;
-
-      meta_error_trap_push (display);
-
-      priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
-
-      if (meta_error_trap_pop_with_return (display, FALSE) != Success)
-        {
-          /* Probably a BadMatch if the window isn't viewable; we could
-           * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
-           * to avoid this, but there's no reason to take two round trips
-           * when one will do. (We need that Sync if we want to handle failures
-           * for any reason other than !viewable. That's unlikely, but maybe
-           * we'll BadAlloc or something.)
-           */
-          priv->back_pixmap = None;
-        }
-
-      if (priv->back_pixmap == None)
-        {
-          meta_verbose ("Unable to get named pixmap for %p\n", cw);
-          return;
-        }
-
-      /* MUST call before setting pixmap or serious performance issues
-       * seemingly caused by cogl_texture_set_filters() in set_filter
-       * Not sure if that call is actually needed.
-       */
-      if (!compositor->no_mipmaps)
-        clutter_texture_set_filter_quality (CLUTTER_TEXTURE (priv->actor),
-                                            CLUTTER_TEXTURE_QUALITY_HIGH );
-
-      clutter_x11_texture_pixmap_set_pixmap
-                       (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
-                        priv->back_pixmap);
-
-      g_object_get (priv->actor,
-                    "pixmap-width", &pxm_width,
-                    "pixmap-height", &pxm_height,
-                    NULL);
-
-      clutter_actor_set_size (priv->actor, pxm_width, pxm_height);
-
-      if (priv->shadow)
-        clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
-
-      full = TRUE;
-    }
-
- /*
-   * TODO -- on some gfx hardware updating the whole texture instead of
-   * the individual rectangles is actually quicker, so we might want to
-   * make this a configurable option (on desktop HW with multiple pipelines
-   * it is usually quicker to just update the damaged parts).
-   *
-   * If we are using TFP we update the whole texture (this simply trigers
-   * the texture rebind).
-   */
-  if (full
-#ifdef HAVE_GLX_TEXTURE_PIXMAP
-      || (CLUTTER_GLX_IS_TEXTURE_PIXMAP (priv->actor) &&
-          clutter_glx_texture_pixmap_using_extension
-                  (CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
-#endif /* HAVE_GLX_TEXTURE_PIXMAP */
-      )
-    {
-      XDamageSubtract (xdisplay, priv->damage, None, None);
-
-      clutter_x11_texture_pixmap_update_area
-	(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
-	 0,
-	 0,
-	 clutter_actor_get_width (priv->actor),
-	 clutter_actor_get_height (priv->actor));
-    }
-  else
-    {
-      XRectangle   *r_damage;
-      XRectangle    r_bounds;
-      XserverRegion parts;
-      int           i, r_count;
-
-      parts = XFixesCreateRegion (xdisplay, 0, 0);
-      XDamageSubtract (xdisplay, priv->damage, None, parts);
-
-      r_damage = XFixesFetchRegionAndBounds (xdisplay,
-					     parts,
-					     &r_count,
-					     &r_bounds);
-
-      if (r_damage)
-	{
-	  for (i = 0; i < r_count; ++i)
-	    {
-	      clutter_x11_texture_pixmap_update_area
-		(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
-		 r_damage[i].x,
-		 r_damage[i].y,
-		 r_damage[i].width,
-		 r_damage[i].height);
-	    }
-	}
-
-      XFree (r_damage);
-      XFixesDestroyRegion (xdisplay, parts);
-    }
-
-  meta_error_trap_pop (display, FALSE);
-
-  priv->needs_repair = FALSE;
-}
-
-static void
 process_damage (MetaCompositor     *compositor,
                 XDamageNotifyEvent *event)
 {
-  XEvent   next;
-  Display *dpy = event->display;
-  Drawable drawable = event->drawable;
-  MutterWindowPrivate *priv;
-  MutterWindow *cw = find_window_in_display (compositor->display, drawable);
-
-  if (!cw)
+  MutterWindow *cw = find_window_in_display (compositor->display, event->drawable);
+  if (cw == NULL)
     return;
 
-  priv = cw->priv;
-
-  if (priv->destroy_pending        ||
-      priv->maximize_in_progress   ||
-      priv->unmaximize_in_progress)
-    {
-      priv->needs_repair = TRUE;
-      return;
-    }
-
-  /*
-   * Check if the event queue does not already contain DetstroyNotify for this
-   * window -- if it does, we need to stop updating the pixmap (to avoid damage
-   * notifications that come from the window teardown), and process the destroy
-   * immediately.
-   */
-  if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
-    {
-      priv->destroy_pending = TRUE;
-      destroy_win (cw);
-      return;
-    }
-
-  repair_win (cw);
-}
-
-static void
-update_shape (MetaCompositor *compositor,
-              MutterWindow   *cw)
-{
-  MutterWindowPrivate *priv = cw->priv;
-
-  mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
-
-#ifdef HAVE_SHAPE
-  if (priv->shaped)
-    {
-      Display *xdisplay = meta_display_get_xdisplay (compositor->display);
-      XRectangle *rects;
-      int n_rects, ordering;
-
-      rects = XShapeGetRectangles (xdisplay,
-                                   priv->xwindow,
-                                   ShapeBounding,
-                                   &n_rects,
-                                   &ordering);
-
-      if (rects)
-        {
-          mutter_shaped_texture_add_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor),
-                                              n_rects, rects);
-
-          XFree (rects);
-        }
-    }
-#endif
+  mutter_window_process_damage (cw, event);
 }
 
 #ifdef HAVE_SHAPE
@@ -1588,17 +175,12 @@ process_shape (MetaCompositor *compositor,
 {
   MutterWindow *cw = find_window_in_display (compositor->display,
                                              event->window);
-  MutterWindowPrivate *priv;
-
   if (cw == NULL)
     return;
 
-  priv = cw->priv;
-
   if (event->kind == ShapeBounding)
     {
-      priv->shaped = event->shaped;
-      update_shape (compositor, cw);
+      mutter_window_update_shape (cw, event->shaped);
     }
 }
 #endif
@@ -1613,7 +195,6 @@ process_property_notify (MetaCompositor	*compositor,
   if (event->atom == compositor->atom_net_wm_window_opacity)
     {
       MutterWindow *cw = find_window_in_display (display, event->window);
-      gulong        value;
 
       if (!cw)
         {
@@ -1630,19 +211,7 @@ process_property_notify (MetaCompositor	*compositor,
 	  return;
 	}
 
-      if (meta_prop_get_cardinal (display, event->window,
-                                  compositor->atom_net_wm_window_opacity,
-                                  &value))
-	{
-	  guint8 opacity;
-
-	  opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
-
-	  cw->priv->opacity = opacity;
-	  clutter_actor_set_opacity (CLUTTER_ACTOR (cw), opacity);
-	}
-
-      return;
+      mutter_window_update_opacity (cw);
     }
   else if (event->atom == meta_display_get_atom (display,
 					       META_ATOM__NET_WM_WINDOW_TYPE))
@@ -1655,7 +224,7 @@ process_property_notify (MetaCompositor	*compositor,
 	  return;
 	}
 
-      mutter_window_query_window_type (cw);
+      mutter_window_update_window_type (cw);
       DEBUG_TRACE ("process_property_notify: net_wm_type\n");
       return;
     }
@@ -1951,7 +520,7 @@ meta_compositor_remove_window (MetaCompositor *compositor,
   if (!cw)
     return;
 
-  destroy_win (cw);
+  mutter_window_destroy (cw);
 }
 
 void
@@ -2056,7 +625,7 @@ meta_compositor_map_window (MetaCompositor *compositor,
   if (!cw)
     return;
 
-  map_win (cw);
+  mutter_window_map (cw);
 }
 
 void
@@ -2068,7 +637,7 @@ meta_compositor_unmap_window (MetaCompositor *compositor,
   if (!cw)
     return;
 
-  unmap_win (cw);
+  mutter_window_unmap (cw);
 }
 
 void
@@ -2088,20 +657,7 @@ meta_compositor_minimize_window (MetaCompositor *compositor,
   if (!cw)
     return;
 
-  /*
-   * If there is a plugin manager, try to run an effect; if no effect is
-   * executed, hide the actor.
-   */
-  cw->priv->minimize_in_progress++;
-
-  if (!info->plugin_mgr ||
-      !mutter_plugin_manager_event_simple (info->plugin_mgr,
-					   cw,
-					   MUTTER_PLUGIN_MINIMIZE))
-    {
-      cw->priv->is_minimized = TRUE;
-      cw->priv->minimize_in_progress--;
-    }
+  mutter_window_minimize (cw);
 }
 
 void
@@ -2140,7 +696,7 @@ meta_compositor_unminimize_window (MetaCompositor    *compositor,
   if (!cw)
     return;
 
-  map_win (cw);
+  mutter_window_map (cw);
 #endif
 }
 
@@ -2151,26 +707,11 @@ meta_compositor_maximize_window (MetaCompositor    *compositor,
 				 MetaRectangle	   *window_rect)
 {
   MutterWindow	 *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
-  MetaScreen	 *screen = meta_window_get_screen (window);
-  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
-
   DEBUG_TRACE ("clutter_cmp_maximize_window\n");
-  g_return_if_fail (info);
-
   if (!cw)
     return;
 
-  cw->priv->maximize_in_progress++;
-
-  if (!info->plugin_mgr ||
-      !mutter_plugin_manager_event_maximize (info->plugin_mgr,
-					     cw,
-					     MUTTER_PLUGIN_MAXIMIZE,
-					     window_rect->x, window_rect->y,
-					     window_rect->width, window_rect->height))
-    {
-      cw->priv->maximize_in_progress--;
-    }
+  mutter_window_maximize (cw, window_rect);
 }
 
 void
@@ -2179,26 +720,11 @@ meta_compositor_unmaximize_window (MetaCompositor    *compositor,
 				   MetaRectangle     *window_rect)
 {
   MutterWindow	 *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
-  MetaScreen	 *screen = meta_window_get_screen (window);
-  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
-
-  g_return_if_fail (info);
-
   DEBUG_TRACE ("clutter_cmp_unmaximize_window\n");
   if (!cw)
     return;
 
-  cw->priv->unmaximize_in_progress++;
-
-  if (!info->plugin_mgr ||
-      !mutter_plugin_manager_event_maximize (info->plugin_mgr,
-					     cw,
-					     MUTTER_PLUGIN_UNMAXIMIZE,
-					     window_rect->x, window_rect->y,
-					     window_rect->width, window_rect->height))
-    {
-      cw->priv->unmaximize_in_progress--;
-    }
+  mutter_window_unmaximize (cw, window_rect);
 }
 
 void
@@ -2253,7 +779,7 @@ meta_compositor_switch_workspace (MetaCompositor     *compositor,
       for (l = info->windows; l != NULL; l = l->next)
 	{
 	  MutterWindow *cw = l->data;
-	  MetaWindow   *mw = cw->priv->window;
+	  MetaWindow   *mw = mutter_window_get_meta_window (cw);
 	  gboolean      sticky;
 	  gint          workspace = -1;
 
@@ -2263,22 +789,14 @@ meta_compositor_switch_workspace (MetaCompositor     *compositor,
 	    {
 	      MetaWorkspace *w;
 
-	      w = meta_window_get_workspace (cw->priv->window);
+	      w = meta_window_get_workspace (mw);
 	      workspace = meta_workspace_index (w);
 
 	      /*
 	       * If the window is not on the target workspace, mark it for
 	       * unmap.
 	       */
-	      if (to_indx != workspace)
-		{
-		  cw->priv->needs_unmap = TRUE;
-		}
-	      else
-		{
-		  cw->priv->needs_map = TRUE;
-		  cw->priv->needs_unmap = FALSE;
-		}
+              mutter_window_queue_map_change (cw, to_indx == workspace);
 	    }
 	}
     }
@@ -2352,7 +870,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
           old_window = mutter_window_get_meta_window (old_actor);
 
           if (old_window->hidden &&
-              !effect_in_progress (old_actor, TRUE))
+              !mutter_window_effect_in_progress (old_actor, TRUE))
             old_stack = g_list_delete_link (old_stack, old_stack);
           else
             break;
@@ -2414,35 +932,13 @@ meta_compositor_set_window_hidden (MetaCompositor *compositor,
 				   gboolean	   hidden)
 {
   MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
-  MutterWindowPrivate *priv = cw->priv;
-  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 
   DEBUG_TRACE ("clutter_cmp_set_window_hidden\n");
+  
   if (!cw)
     return;
 
-  if (hidden)
-    {
-      if (effect_in_progress (cw, TRUE))
-	{
-	  priv->hide_after_effect = TRUE;
-	}
-      else
-	{
-	  if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group)
-	    {
-	      clutter_actor_reparent (CLUTTER_ACTOR (cw),
-				      info->hidden_group);
-	    }
-	}
-    }
-  else
-    {
-      priv->hide_after_effect = FALSE;
-      if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->window_group)
-	clutter_actor_reparent (CLUTTER_ACTOR (cw),
-				info->window_group);
-    }
+  mutter_window_set_hidden (cw, hidden);
 }
 
 void
@@ -2459,7 +955,7 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
   if (!cw)
     return;
 
-  sync_actor_position (cw);
+  mutter_window_sync_actor_position (cw);
 }
 
 void
diff --git a/src/compositor/mutter-plugin.c b/src/compositor/mutter-plugin.c
index 7714344..18763da 100644
--- a/src/compositor/mutter-plugin.c
+++ b/src/compositor/mutter-plugin.c
@@ -31,6 +31,9 @@
 #include <X11/extensions/shape.h>
 #include <clutter/x11/clutter-x11.h>
 
+#include "compositor-private.h"
+#include "mutter-window-private.h"
+
 G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
 
 #define MUTTER_PLUGIN_GET_PRIVATE(obj) \
@@ -389,7 +392,17 @@ mutter_plugin_effect_completed (MutterPlugin *plugin,
                  name ? name : "unknown");
     }
 
-  mutter_window_effect_completed (actor, event);
+  if (event == MUTTER_PLUGIN_SWITCH_WORKSPACE)
+    {
+      /* The window is just used to identify the screen */
+      MetaWindow *window = mutter_window_get_meta_window (actor);
+      MetaScreen *screen = meta_window_get_screen (window);
+      mutter_switch_workspace_completed (screen);
+    }
+    else
+    {
+      mutter_window_effect_completed (actor, event);
+    }
 }
 
 void
diff --git a/src/compositor/mutter-window-private.h b/src/compositor/mutter-window-private.h
new file mode 100644
index 0000000..68be514
--- /dev/null
+++ b/src/compositor/mutter-window-private.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#ifndef MUTTER_WINDOW_PRIVATE_H
+#define MUTTER_WINDOW_PRIVATE_H
+
+#include <X11/extensions/Xdamage.h>
+#include "compositor-mutter.h"
+
+MutterWindow *mutter_window_new (MetaWindow *window);
+
+void mutter_window_map      (MutterWindow *cw);
+void mutter_window_unmap    (MutterWindow *cw);
+void mutter_window_minimize (MutterWindow *cw);
+void mutter_window_destroy  (MutterWindow *cw);
+
+void mutter_window_maximize   (MutterWindow  *cw,
+                               MetaRectangle *window_rect);
+void mutter_window_unmaximize (MutterWindow  *cw,
+                               MetaRectangle *window_rect);
+
+void     mutter_window_process_damage          (MutterWindow       *cw,
+                                                XDamageNotifyEvent *event);
+gboolean mutter_window_effect_in_progress      (MutterWindow       *cw,
+                                                gboolean            include_destroy);
+void     mutter_window_sync_actor_position     (MutterWindow       *cw);
+void     mutter_window_finish_workspace_switch (MutterWindow       *cw);
+void     mutter_window_update_window_type      (MutterWindow       *cw);
+void     mutter_window_update_shape            (MutterWindow       *cw,
+                                                gboolean            shaped);
+void     mutter_window_update_opacity          (MutterWindow       *cw);
+void     mutter_window_set_hidden              (MutterWindow       *cw,
+                                                gboolean            hidden);
+void     mutter_window_queue_map_change        (MutterWindow       *cw,
+                                                gboolean            should_be_mapped);
+
+void mutter_window_effect_completed (MutterWindow *actor,
+                                     gulong        event);
+
+#endif /* MUTTER_WINDOW_PRIVATE_H */
diff --git a/src/compositor/mutter-window.c b/src/compositor/mutter-window.c
new file mode 100644
index 0000000..3a95067
--- /dev/null
+++ b/src/compositor/mutter-window.c
@@ -0,0 +1,1528 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#include <X11/extensions/shape.h>
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xrender.h>
+
+#include <clutter/x11/clutter-x11.h>
+
+#include "../core/window-private.h" /* FIXME: add meta_window_is_override_redirect */
+#include "display.h"
+#include "errors.h"
+#include "frame.h"
+#include "window.h"
+#include "xprops.h"
+
+#include "compositor-private.h"
+#include "mutter-shaped-texture.h"
+#include "mutter-window-private.h"
+#include "shadow.h"
+
+struct _MutterWindowPrivate
+{
+  XWindowAttributes attrs;
+
+  MetaWindow       *window;
+  Window            xwindow;
+  MetaScreen       *screen;
+
+  ClutterActor     *actor;
+  ClutterActor     *shadow;
+  Pixmap            back_pixmap;
+
+  MetaCompWindowType  type;
+  Damage            damage;
+
+  guint8            opacity;
+
+  gchar *           desc;
+
+  /*
+   * These need to be counters rather than flags, since more plugins
+   * can implement same effect; the practicality of stacking effects
+   * might be dubious, but we have to at least handle it correctly.
+   */
+  gint              minimize_in_progress;
+  gint              maximize_in_progress;
+  gint              unmaximize_in_progress;
+  gint              map_in_progress;
+  gint              destroy_in_progress;
+
+  guint		    shaped                 : 1;
+  guint		    destroy_pending        : 1;
+  guint		    argb32                 : 1;
+  guint		    disposed               : 1;
+  guint		    is_minimized           : 1;
+  guint		    hide_after_effect      : 1;
+  guint             redecorating           : 1;
+
+  /* Desktop switching flags */
+  guint		    needs_map              : 1;
+  guint		    needs_unmap            : 1;
+  guint		    needs_repair           : 1;
+
+  guint		    needs_destroy	   : 1;
+
+  guint             no_shadow              : 1;
+
+  guint             no_more_x_calls        : 1;
+};
+
+enum
+{
+  PROP_MCW_META_WINDOW = 1,
+  PROP_MCW_META_SCREEN,
+  PROP_MCW_X_WINDOW,
+  PROP_MCW_X_WINDOW_ATTRIBUTES,
+  PROP_MCW_NO_SHADOW,
+};
+
+static void mutter_window_dispose    (GObject *object);
+static void mutter_window_finalize   (GObject *object);
+static void mutter_window_constructed (GObject *object);
+static void mutter_window_set_property (GObject       *object,
+					   guint         prop_id,
+					   const GValue *value,
+					   GParamSpec   *pspec);
+static void mutter_window_get_property (GObject      *object,
+					   guint         prop_id,
+					   GValue       *value,
+					   GParamSpec   *pspec);
+
+static void     mutter_window_detach     (MutterWindow *self);
+static gboolean mutter_window_has_shadow (MutterWindow *self);
+
+
+static void     repair_win               (MutterWindow *self);
+static gboolean is_shaped                (MetaDisplay  *display,
+                                          Window        xwindow);
+/*
+ * Register GType wrapper for XWindowAttributes, so we do not have to
+ * query window attributes in the MutterWindow constructor but can pass
+ * them as a property to the constructor (so we can gracefully handle the case
+ * where no attributes can be retrieved).
+ *
+ * NB -- we only need a subset of the attributes; at some point we might want
+ * to just store the relevant values rather than the whole struct.
+ */
+#define META_TYPE_XATTRS (meta_xattrs_get_type ())
+
+static GType meta_xattrs_get_type   (void) G_GNUC_CONST;
+
+static XWindowAttributes *
+meta_xattrs_copy (const XWindowAttributes *attrs)
+{
+  XWindowAttributes *result;
+
+  g_return_val_if_fail (attrs != NULL, NULL);
+
+  result = (XWindowAttributes*) g_malloc (sizeof (XWindowAttributes));
+  *result = *attrs;
+
+  return result;
+}
+
+static void
+meta_xattrs_free (XWindowAttributes *attrs)
+{
+  g_return_if_fail (attrs != NULL);
+
+  g_free (attrs);
+}
+
+static GType
+meta_xattrs_get_type (void)
+{
+  static GType our_type = 0;
+
+  if (!our_type)
+    our_type = g_boxed_type_register_static ("XWindowAttributes",
+		                     (GBoxedCopyFunc) meta_xattrs_copy,
+				     (GBoxedFreeFunc) meta_xattrs_free);
+  return our_type;
+}
+
+G_DEFINE_TYPE (MutterWindow, mutter_window, CLUTTER_TYPE_GROUP);
+
+static void
+mutter_window_class_init (MutterWindowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GParamSpec   *pspec;
+
+  g_type_class_add_private (klass, sizeof (MutterWindowPrivate));
+
+  object_class->dispose      = mutter_window_dispose;
+  object_class->finalize     = mutter_window_finalize;
+  object_class->set_property = mutter_window_set_property;
+  object_class->get_property = mutter_window_get_property;
+  object_class->constructed  = mutter_window_constructed;
+
+  pspec = g_param_spec_object ("meta-window",
+                               "MetaWindow",
+                               "The displayed MetaWindow",
+                               META_TYPE_WINDOW,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MCW_META_WINDOW,
+                                   pspec);
+
+  pspec = g_param_spec_pointer ("meta-screen",
+				"MetaScreen",
+				"MetaScreen",
+				G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MCW_META_SCREEN,
+                                   pspec);
+
+  pspec = g_param_spec_ulong ("x-window",
+			      "Window",
+			      "Window",
+			      0,
+			      G_MAXULONG,
+			      0,
+			      G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MCW_X_WINDOW,
+                                   pspec);
+
+  pspec = g_param_spec_boxed ("x-window-attributes",
+			      "XWindowAttributes",
+			      "XWindowAttributes",
+			      META_TYPE_XATTRS,
+			      G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MCW_X_WINDOW_ATTRIBUTES,
+                                   pspec);
+
+  pspec = g_param_spec_boolean ("no-shadow",
+                                "No shadow",
+                                "Do not add shaddow to this window",
+                                FALSE,
+                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MCW_NO_SHADOW,
+                                   pspec);
+}
+
+static void
+mutter_window_init (MutterWindow *self)
+{
+  MutterWindowPrivate *priv;
+
+  priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+						   MUTTER_TYPE_COMP_WINDOW,
+						   MutterWindowPrivate);
+  priv->opacity = 0xff;
+}
+
+static void
+mutter_meta_window_decorated_notify (MetaWindow *mw,
+                                     GParamSpec *arg1,
+                                     gpointer    data)
+{
+  MutterWindow        *self     = MUTTER_WINDOW (data);
+  MutterWindowPrivate *priv     = self->priv;
+  MetaFrame           *frame    = meta_window_get_frame (mw);
+  MetaScreen          *screen   = priv->screen;
+  MetaDisplay         *display  = meta_screen_get_display (screen);
+  Display             *xdisplay = meta_display_get_xdisplay (display);
+  Window               new_xwindow;
+  MetaCompScreen      *info;
+  XWindowAttributes    attrs;
+
+  /*
+   * Basically, we have to reconstruct the the internals of this object
+   * from scratch, as everything has changed.
+   */
+  priv->redecorating = TRUE;
+
+  if (frame)
+    new_xwindow = meta_frame_get_xwindow (frame);
+  else
+    new_xwindow = meta_window_get_xwindow (mw);
+
+  mutter_window_detach (self);
+
+  info = meta_screen_get_compositor_data (screen);
+
+  /*
+   * First of all, clean up any resources we are currently using and will
+   * be replacing.
+   */
+  if (priv->damage != None)
+    {
+      meta_error_trap_push (display);
+      XDamageDestroy (xdisplay, priv->damage);
+      meta_error_trap_pop (display, FALSE);
+      priv->damage = None;
+    }
+
+  g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
+  g_hash_table_insert (info->windows_by_xid, (gpointer) new_xwindow, self);
+
+  g_free (priv->desc);
+  priv->desc = NULL;
+
+  priv->xwindow = new_xwindow;
+
+  if (!XGetWindowAttributes (xdisplay, new_xwindow, &attrs))
+    {
+      g_warning ("Could not obtain attributes for window 0x%x after "
+                 "decoration change",
+                 (guint) new_xwindow);
+      return;
+    }
+
+  g_object_set (self, "x-window-attributes", &attrs, NULL);
+
+  if (priv->shadow)
+    {
+      ClutterActor *p = clutter_actor_get_parent (priv->shadow);
+
+      if (CLUTTER_IS_CONTAINER (p))
+        clutter_container_remove_actor (CLUTTER_CONTAINER (p), priv->shadow);
+      else
+        clutter_actor_unparent (priv->shadow);
+
+      priv->shadow = NULL;
+    }
+
+  /*
+   * Recreate the contents.
+   */
+  mutter_window_constructed (G_OBJECT (self));
+}
+
+static void
+mutter_window_constructed (GObject *object)
+{
+  MutterWindow        *self     = MUTTER_WINDOW (object);
+  MutterWindowPrivate *priv     = self->priv;
+  MetaScreen          *screen   = priv->screen;
+  MetaDisplay         *display  = meta_screen_get_display (screen);
+  Window               xwindow  = priv->xwindow;
+  Display             *xdisplay = meta_display_get_xdisplay (display);
+  XRenderPictFormat   *format;
+  MetaCompositor      *compositor;
+
+  compositor = meta_display_get_compositor (display);
+
+  mutter_window_update_window_type (self);
+
+#ifdef HAVE_SHAPE
+  /* Listen for ShapeNotify events on the window */
+  if (meta_display_has_shape (display))
+    XShapeSelectInput (xdisplay, xwindow, ShapeNotifyMask);
+#endif
+
+  priv->shaped = is_shaped (display, xwindow);
+
+  if (priv->attrs.class == InputOnly)
+    priv->damage = None;
+  else
+    priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty);
+
+  format = XRenderFindVisualFormat (xdisplay, priv->attrs.visual);
+
+  if (format && format->type == PictTypeDirect && format->direct.alphaMask)
+    priv->argb32 = TRUE;
+
+  mutter_window_update_opacity (self);
+
+  if (mutter_window_has_shadow (self))
+    {
+      priv->shadow = mutter_create_shadow_frame (compositor);
+
+      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
+    }
+
+  if (!priv->actor)
+    {
+      priv->actor = mutter_shaped_texture_new ();
+
+      if (!clutter_glx_texture_pixmap_using_extension (
+                                  CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
+        g_warning ("NOTE: Not using GLX TFP!\n");
+
+      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
+
+      g_signal_connect (priv->window, "notify::decorated",
+                        G_CALLBACK (mutter_meta_window_decorated_notify), self);
+    }
+  else
+    {
+      /*
+       * This is the case where existing window is gaining/loosing frame.
+       * Just ensure the actor is top most (i.e., above shadow).
+       */
+      clutter_actor_raise_top (priv->actor);
+    }
+
+
+  mutter_window_update_shape (self, priv->shaped);
+}
+
+static void
+mutter_window_dispose (GObject *object)
+{
+  MutterWindow        *self = MUTTER_WINDOW (object);
+  MutterWindowPrivate *priv = self->priv;
+  MetaScreen            *screen;
+  MetaDisplay           *display;
+  Display               *xdisplay;
+  MetaCompScreen        *info;
+
+  if (priv->disposed)
+    return;
+
+  priv->disposed = TRUE;
+
+  screen   = priv->screen;
+  display  = meta_screen_get_display (screen);
+  xdisplay = meta_display_get_xdisplay (display);
+  info     = meta_screen_get_compositor_data (screen);
+
+  mutter_window_detach (self);
+
+  if (priv->damage != None)
+    {
+      meta_error_trap_push (display);
+      XDamageDestroy (xdisplay, priv->damage);
+      meta_error_trap_pop (display, FALSE);
+
+      priv->damage = None;
+    }
+
+  /*
+   * Check we are not in the dock list -- FIXME (do this in a cleaner way)
+   */
+  if (priv->type == META_COMP_WINDOW_DOCK)
+    info->dock_windows = g_slist_remove (info->dock_windows, self);
+
+  info->windows = g_list_remove (info->windows, (gconstpointer) self);
+  g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
+
+  g_free (priv->desc);
+
+  G_OBJECT_CLASS (mutter_window_parent_class)->dispose (object);
+}
+
+static void
+mutter_window_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (mutter_window_parent_class)->finalize (object);
+}
+
+static void
+mutter_window_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  MutterWindow        *self   = MUTTER_WINDOW (object);
+  MutterWindowPrivate *priv = self->priv;
+
+  switch (prop_id)
+    {
+    case PROP_MCW_META_WINDOW:
+      priv->window = g_value_get_object (value);
+      break;
+    case PROP_MCW_META_SCREEN:
+      priv->screen = g_value_get_pointer (value);
+      break;
+    case PROP_MCW_X_WINDOW:
+      priv->xwindow = g_value_get_ulong (value);
+      break;
+    case PROP_MCW_X_WINDOW_ATTRIBUTES:
+      priv->attrs = *((XWindowAttributes*)g_value_get_boxed (value));
+      break;
+    case PROP_MCW_NO_SHADOW:
+      {
+        gboolean oldv = priv->no_shadow ? TRUE : FALSE;
+        gboolean newv = g_value_get_boolean (value);
+
+        if (oldv == newv)
+          return;
+
+        priv->no_shadow = newv;
+
+        if (newv && priv->shadow)
+          {
+            clutter_container_remove_actor (CLUTTER_CONTAINER (object),
+                                            priv->shadow);
+            priv->shadow = NULL;
+          }
+        else if (!newv && !priv->shadow && mutter_window_has_shadow (self))
+          {
+            gfloat       w, h;
+            MetaDisplay *display = meta_screen_get_display (priv->screen);
+            MetaCompositor *compositor;
+
+            compositor = meta_display_get_compositor (display);
+
+            clutter_actor_get_size (CLUTTER_ACTOR (self), &w, &h);
+
+            priv->shadow = mutter_create_shadow_frame (compositor);
+
+            clutter_actor_set_size (priv->shadow, w, h);
+
+            clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
+          }
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+mutter_window_get_property (GObject      *object,
+                            guint         prop_id,
+                            GValue       *value,
+                            GParamSpec   *pspec)
+{
+  MutterWindowPrivate *priv = MUTTER_WINDOW (object)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_MCW_META_WINDOW:
+      g_value_set_object (value, priv->window);
+      break;
+    case PROP_MCW_META_SCREEN:
+      g_value_set_pointer (value, priv->screen);
+      break;
+    case PROP_MCW_X_WINDOW:
+      g_value_set_ulong (value, priv->xwindow);
+      break;
+    case PROP_MCW_X_WINDOW_ATTRIBUTES:
+      g_value_set_boxed (value, &priv->attrs);
+      break;
+    case PROP_MCW_NO_SHADOW:
+      g_value_set_boolean (value, priv->no_shadow);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+void
+mutter_window_update_window_type (MutterWindow *self)
+{
+  MutterWindowPrivate *priv = self->priv;
+  priv->type = (MetaCompWindowType) meta_window_get_window_type (priv->window);
+}
+
+static gboolean
+is_shaped (MetaDisplay *display, Window xwindow)
+{
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  gint     xws, yws, xbs, ybs;
+  guint    wws, hws, wbs, hbs;
+  gint     bounding_shaped, clip_shaped;
+
+  if (meta_display_has_shape (display))
+    {
+      XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
+                          &xws, &yws, &wws, &hws, &clip_shaped,
+                          &xbs, &ybs, &wbs, &hbs);
+      return (bounding_shaped != 0);
+    }
+
+  return FALSE;
+}
+
+static gboolean
+mutter_window_has_shadow (MutterWindow *self)
+{
+  MutterWindowPrivate * priv = self->priv;
+
+  if (priv->no_shadow)
+    return FALSE;
+
+  /*
+   * Always put a shadow around windows with a frame - This should override
+   * the restriction about not putting a shadow around shaped windows
+   * as the frame might be the reason the window is shaped
+   */
+  if (priv->window)
+    {
+      if (meta_window_get_frame (priv->window))
+	{
+	  meta_verbose ("Window 0x%x has shadow because it has a frame\n",
+			(guint)priv->xwindow);
+	  return TRUE;
+	}
+    }
+
+  /*
+   * Do not add shadows to ARGB windows (since they are probably transparent)
+   */
+  if (priv->argb32 || priv->opacity != 0xff)
+    {
+      meta_verbose ("Window 0x%x has no shadow as it is ARGB\n",
+		    (guint)priv->xwindow);
+      return FALSE;
+    }
+
+  /*
+   * Never put a shadow around shaped windows
+   */
+  if (priv->shaped)
+    {
+      meta_verbose ("Window 0x%x has no shadow as it is shaped\n",
+		    (guint)priv->xwindow);
+      return FALSE;
+    }
+
+  /*
+   * Add shadows to override redirect windows (e.g., Gtk menus).
+   * This must have lower priority than window shape test.
+   */
+  if (priv->attrs.override_redirect)
+    {
+      meta_verbose ("Window 0x%x has shadow because it is override redirect.\n",
+		    (guint)priv->xwindow);
+      return TRUE;
+    }
+
+  /*
+   * Don't put shadow around DND icon windows
+   */
+  if (priv->type == META_COMP_WINDOW_DND ||
+      priv->type == META_COMP_WINDOW_DESKTOP)
+    {
+      meta_verbose ("Window 0x%x has no shadow as it is DND or Desktop\n",
+		    (guint)priv->xwindow);
+      return FALSE;
+    }
+
+  if (priv->type == META_COMP_WINDOW_MENU
+#if 0
+      || priv->type == META_COMP_WINDOW_DROPDOWN_MENU
+#endif
+      )
+    {
+      meta_verbose ("Window 0x%x has shadow as it is a menu\n",
+		    (guint)priv->xwindow);
+      return TRUE;
+    }
+
+#if 0
+  if (priv->type == META_COMP_WINDOW_TOOLTIP)
+    {
+      meta_verbose ("Window 0x%x has shadow as it is a tooltip\n",
+		    (guint)priv->xwindow);
+      return TRUE;
+    }
+#endif
+
+  meta_verbose ("Window 0x%x has no shadow as it fell through\n",
+		(guint)priv->xwindow);
+  return FALSE;
+}
+
+Window
+mutter_window_get_x_window (MutterWindow *self)
+{
+  if (!self)
+    return None;
+
+  return self->priv->xwindow;
+}
+
+/**
+ * mutter_window_get_meta_window:
+ *
+ * Gets the MetaWindow object that the the MutterWindow is displaying
+ *
+ * Return value: (transfer none): the displayed MetaWindow
+ */
+MetaWindow *
+mutter_window_get_meta_window (MutterWindow *self)
+{
+  return self->priv->window;
+}
+
+/**
+ * mutter_window_get_texture:
+ *
+ * Gets the ClutterActor that is used to display the contents of the window
+ *
+ * Return value: (transfer none): the ClutterActor for the contents
+ */
+ClutterActor *
+mutter_window_get_texture (MutterWindow *self)
+{
+  return self->priv->actor;
+}
+
+MetaCompWindowType
+mutter_window_get_window_type (MutterWindow *self)
+{
+  if (!self)
+    return 0;
+
+  return self->priv->type;
+}
+
+gboolean
+mutter_window_is_override_redirect (MutterWindow *self)
+{
+  if (self->priv->window->override_redirect)
+    return TRUE;
+
+  return FALSE;
+}
+
+const char *mutter_window_get_description (MutterWindow *self)
+{
+  /*
+   * For windows managed by the WM, we just defer to the WM for the window
+   * description. For override-redirect windows, we create the description
+   * ourselves, but only on demand.
+   */
+  if (self->priv->window)
+    return meta_window_get_description (self->priv->window);
+
+  if (G_UNLIKELY (self->priv->desc == NULL))
+    {
+      self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
+                                         (guint) self->priv->xwindow);
+    }
+
+  return self->priv->desc;
+}
+
+gint
+mutter_window_get_workspace (MutterWindow *self)
+{
+  MutterWindowPrivate *priv;
+  MetaWorkspace       *workspace;
+
+  if (!self)
+    return -1;
+
+  priv = self->priv;
+
+  if (!priv->window || meta_window_is_on_all_workspaces (priv->window))
+    return -1;
+
+  workspace = meta_window_get_workspace (priv->window);
+
+  return meta_workspace_index (workspace);
+}
+
+gboolean
+mutter_window_showing_on_its_workspace (MutterWindow *self)
+{
+  if (!self)
+    return FALSE;
+
+  /* If override redirect: */
+  if (!self->priv->window)
+    return TRUE;
+
+  return meta_window_showing_on_its_workspace (self->priv->window);
+}
+
+gboolean
+mutter_window_effect_in_progress (MutterWindow *self,
+				  gboolean      include_destroy)
+{
+  return (self->priv->minimize_in_progress ||
+	  self->priv->maximize_in_progress ||
+	  self->priv->unmaximize_in_progress ||
+	  self->priv->map_in_progress ||
+	  (include_destroy && self->priv->destroy_in_progress));
+}
+
+void
+mutter_window_effect_completed (MutterWindow *self,
+				gulong        event)
+{
+  MutterWindowPrivate *priv   = self->priv;
+  MetaScreen          *screen = priv->screen;
+  MetaCompScreen      *info   = meta_screen_get_compositor_data (screen);
+  ClutterActor        *actor  = CLUTTER_ACTOR (self);
+  gboolean             effect_done = FALSE;
+
+  /* NB: Keep in mind that when effects get completed it possible
+   * that the corresponding MetaWindow may have be been destroyed.
+   * In this case priv->window will == NULL */
+
+  switch (event)
+  {
+  case MUTTER_PLUGIN_MINIMIZE:
+    {
+      ClutterActor *a = CLUTTER_ACTOR (self);
+
+      priv->minimize_in_progress--;
+      if (priv->minimize_in_progress < 0)
+	{
+	  g_warning ("Error in minimize accounting.");
+	  priv->minimize_in_progress = 0;
+	}
+
+      if (!priv->minimize_in_progress)
+	{
+	  priv->is_minimized = TRUE;
+
+	  /*
+	   * We must ensure that the minimized actor is pushed down the stack
+	   * (the XConfigureEvent has 'above' semantics, i.e., when a window
+	   * is lowered, we get a bunch of 'raise' notifications, but might
+	   * not get any notification for the window that has been lowered.
+	   */
+	  clutter_actor_lower_bottom (a);
+
+	  /* Make sure that after the effect finishes, the actor is
+	   * made visible for sake of live previews.
+	   */
+	  clutter_actor_show (a);
+
+	  effect_done = TRUE;
+	}
+    }
+    break;
+  case MUTTER_PLUGIN_MAP:
+    /*
+     * Make sure that the actor is at the correct place in case
+     * the plugin fscked.
+     */
+    priv->map_in_progress--;
+
+    if (priv->map_in_progress < 0)
+      {
+	g_warning ("Error in map accounting.");
+	priv->map_in_progress = 0;
+      }
+
+    if (!priv->map_in_progress && priv->window && !priv->no_more_x_calls)
+      {
+	MetaRectangle rect;
+	meta_window_get_outer_rect (priv->window, &rect);
+	priv->is_minimized = FALSE;
+	clutter_actor_set_anchor_point (actor, 0, 0);
+	clutter_actor_set_position (actor, rect.x, rect.y);
+	clutter_actor_show_all (actor);
+	effect_done = TRUE;
+      }
+    break;
+  case MUTTER_PLUGIN_DESTROY:
+    priv->destroy_in_progress--;
+
+    if (priv->destroy_in_progress < 0)
+      {
+	g_warning ("Error in destroy accounting.");
+	priv->destroy_in_progress = 0;
+      }
+
+    if (!priv->destroy_in_progress)
+      {
+	priv->needs_destroy = TRUE;
+	effect_done = TRUE;
+      }
+    break;
+  case MUTTER_PLUGIN_UNMAXIMIZE:
+    priv->unmaximize_in_progress--;
+    if (priv->unmaximize_in_progress < 0)
+      {
+	g_warning ("Error in unmaximize accounting.");
+	priv->unmaximize_in_progress = 0;
+      }
+
+    if (!priv->unmaximize_in_progress && priv->window && !priv->no_more_x_calls)
+      {
+	MetaRectangle rect;
+	meta_window_get_outer_rect (priv->window, &rect);
+	clutter_actor_set_position (actor, rect.x, rect.y);
+	mutter_window_detach (self);
+	repair_win (self);
+        effect_done = TRUE;
+      }
+    break;
+  case MUTTER_PLUGIN_MAXIMIZE:
+    priv->maximize_in_progress--;
+    if (priv->maximize_in_progress < 0)
+      {
+	g_warning ("Error in maximize accounting.");
+	priv->maximize_in_progress = 0;
+      }
+
+    if (!priv->maximize_in_progress && priv->window && !priv->no_more_x_calls)
+      {
+	MetaRectangle rect;
+	meta_window_get_outer_rect (priv->window, &rect);
+	clutter_actor_set_position (actor, rect.x, rect.y);
+	mutter_window_detach (self);
+	repair_win (self);
+        effect_done = TRUE;
+      }
+    break;
+  case MUTTER_PLUGIN_SWITCH_WORKSPACE:
+    g_assert_not_reached ();
+    break;
+  default:
+    break;
+  }
+
+  switch (event)
+  {
+  case MUTTER_PLUGIN_MINIMIZE:
+  case MUTTER_PLUGIN_MAP:
+  case MUTTER_PLUGIN_DESTROY:
+  case MUTTER_PLUGIN_UNMAXIMIZE:
+  case MUTTER_PLUGIN_MAXIMIZE:
+
+    if (effect_done &&
+	priv->hide_after_effect &&
+	mutter_window_effect_in_progress (self, TRUE) == FALSE)
+      {
+	if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->hidden_group)
+	  {
+	    clutter_actor_reparent (CLUTTER_ACTOR (self),
+				    info->hidden_group);
+	  }
+	priv->hide_after_effect = FALSE;
+      }
+
+    if (priv->needs_destroy && mutter_window_effect_in_progress (self, TRUE) == FALSE)
+      {
+        clutter_actor_destroy (CLUTTER_ACTOR (self));
+	return;
+      }
+
+  default:
+    break;
+  }
+}
+
+static void
+mutter_window_detach (MutterWindow *self)
+{
+  MutterWindowPrivate *priv     = self->priv;
+  MetaScreen            *screen   = priv->screen;
+  MetaDisplay           *display  = meta_screen_get_display (screen);
+  Display               *xdisplay = meta_display_get_xdisplay (display);
+
+  if (!priv->back_pixmap)
+    return;
+
+  XFreePixmap (xdisplay, priv->back_pixmap);
+  priv->back_pixmap = None;
+}
+
+void
+mutter_window_destroy (MutterWindow *self)
+{
+  MetaWindow	      *window;
+  MetaCompScreen      *info;
+  MutterWindowPrivate *priv;
+
+  priv = self->priv;
+
+  window = priv->window;
+  meta_window_set_compositor_private (window, NULL);
+
+  /*
+   * We remove the window from internal lookup hashes and thus any other
+   * unmap events etc fail
+   */
+  info = meta_screen_get_compositor_data (priv->screen);
+  info->windows = g_list_remove (info->windows, (gconstpointer) self);
+  g_hash_table_remove (info->windows_by_xid, (gpointer)priv->xwindow);
+
+  if (priv->type == META_COMP_WINDOW_DROPDOWN_MENU ||
+      priv->type == META_COMP_WINDOW_POPUP_MENU ||
+      priv->type == META_COMP_WINDOW_TOOLTIP ||
+      priv->type == META_COMP_WINDOW_NOTIFICATION ||
+      priv->type == META_COMP_WINDOW_COMBO ||
+      priv->type == META_COMP_WINDOW_DND ||
+      priv->type == META_COMP_WINDOW_OVERRIDE_OTHER)
+    {
+      /*
+       * No effects, just kill it.
+       */
+      clutter_actor_destroy (CLUTTER_ACTOR (self));
+      return;
+    }
+
+  /*
+   * If a plugin manager is present, try to run an effect; if no effect of this
+   * type is present, destroy the actor.
+   */
+  priv->destroy_in_progress++;
+
+  /*
+   * Once the window destruction is initiated we can no longer perform any
+   * furter X-based operations. For example, if we have a Map effect running,
+   * we cannot query the window geometry once the effect completes. So, flag
+   * this.
+   */
+  priv->no_more_x_calls = TRUE;
+
+  if (!info->plugin_mgr ||
+      !mutter_plugin_manager_event_simple (info->plugin_mgr,
+					   self,
+					   MUTTER_PLUGIN_DESTROY))
+    {
+      priv->destroy_in_progress--;
+
+      if (mutter_window_effect_in_progress (self, FALSE))
+	{
+	  priv->needs_destroy = TRUE;
+	}
+      else
+        clutter_actor_destroy (CLUTTER_ACTOR (self));
+    }
+}
+
+void
+mutter_window_sync_actor_position (MutterWindow *self)
+{
+  MutterWindowPrivate *priv = self->priv;
+  MetaRectangle window_rect;
+
+  meta_window_get_outer_rect (priv->window, &window_rect);
+
+  if (priv->attrs.width != window_rect.width ||
+      priv->attrs.height != window_rect.height)
+    mutter_window_detach (self);
+
+  /* XXX deprecated: please use meta_window_get_outer_rect instead */
+  priv->attrs.width = window_rect.width;
+  priv->attrs.height = window_rect.height;
+  priv->attrs.x = window_rect.x;
+  priv->attrs.y = window_rect.y;
+
+  if (mutter_window_effect_in_progress (self, FALSE))
+    return;
+
+  clutter_actor_set_position (CLUTTER_ACTOR (self),
+			      window_rect.x, window_rect.y);
+}
+
+void
+mutter_window_map (MutterWindow *self)
+{
+  MutterWindowPrivate *priv;
+  MetaCompScreen      *info;
+
+  if (!self)
+    return;
+
+  priv = self->priv;
+  info = meta_screen_get_compositor_data (priv->screen);
+
+  if (priv->attrs.map_state == IsViewable)
+    return;
+
+  priv->attrs.map_state = IsViewable;
+
+  /*
+   * Now repair the window; this ensures that the actor is correctly sized
+   * before we run any effects on it.
+   */
+  priv->needs_map = FALSE;
+  mutter_window_detach (self);
+  repair_win (self);
+
+  /*
+   * Make sure the position is set correctly (we might have got moved while
+   * unmapped.
+   */
+  if (!info->switch_workspace_in_progress)
+    {
+      MetaRectangle rect;
+      meta_window_get_outer_rect (priv->window, &rect);
+      clutter_actor_set_anchor_point (CLUTTER_ACTOR (self), 0, 0);
+      clutter_actor_set_position (CLUTTER_ACTOR (self), rect.x, rect.y);
+    }
+
+  priv->map_in_progress++;
+
+  /*
+   * If a plugin manager is present, try to run an effect; if no effect of this
+   * type is present, destroy the actor.
+   */
+  if (priv->redecorating ||
+      info->switch_workspace_in_progress || !info->plugin_mgr ||
+      !mutter_plugin_manager_event_simple (info->plugin_mgr,
+				self,
+                                MUTTER_PLUGIN_MAP))
+    {
+      clutter_actor_show_all (CLUTTER_ACTOR (self));
+      priv->map_in_progress--;
+      priv->is_minimized = FALSE;
+      priv->redecorating = FALSE;
+    }
+}
+
+void
+mutter_window_unmap (MutterWindow *self)
+{
+  MutterWindowPrivate *priv;
+  MetaCompScreen      *info;
+
+  priv = self->priv;
+  info = meta_screen_get_compositor_data (priv->screen);
+
+  /*
+   * If the needs_unmap flag is set, we carry on even if the winow is
+   * already marked as unmapped; this is necessary so windows temporarily
+   * shown during an effect (like desktop switch) are properly hidden again.
+   */
+  if (priv->attrs.map_state == IsUnmapped && !priv->needs_unmap)
+    return;
+
+  if (priv->window && priv->window == info->focus_window)
+    info->focus_window = NULL;
+
+  if (info->switch_workspace_in_progress)
+    {
+      /*
+       * Cannot unmap windows while switching desktops effect is in progress.
+       */
+      priv->needs_unmap = TRUE;
+      return;
+    }
+
+  priv->attrs.map_state = IsUnmapped;
+  priv->needs_unmap = FALSE;
+  priv->needs_map   = FALSE;
+
+  if (!priv->minimize_in_progress &&
+      (!meta_prefs_get_live_hidden_windows () ||
+       priv->type == META_COMP_WINDOW_DROPDOWN_MENU ||
+       priv->type == META_COMP_WINDOW_POPUP_MENU ||
+       priv->type == META_COMP_WINDOW_TOOLTIP ||
+       priv->type == META_COMP_WINDOW_NOTIFICATION ||
+       priv->type == META_COMP_WINDOW_COMBO ||
+       priv->type == META_COMP_WINDOW_DND ||
+       priv->type == META_COMP_WINDOW_OVERRIDE_OTHER))
+    {
+      clutter_actor_hide (CLUTTER_ACTOR (self));
+    }
+}
+
+void
+mutter_window_minimize (MutterWindow *self)
+{
+  MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+  /*
+   * If there is a plugin manager, try to run an effect; if no effect is
+   * executed, hide the actor.
+   */
+  self->priv->minimize_in_progress++;
+
+  if (!info->plugin_mgr ||
+      !mutter_plugin_manager_event_simple (info->plugin_mgr,
+					   self,
+					   MUTTER_PLUGIN_MINIMIZE))
+    {
+      self->priv->is_minimized = TRUE;
+      self->priv->minimize_in_progress--;
+    }
+}
+
+void
+mutter_window_maximize (MutterWindow       *self,
+                        MetaRectangle	   *window_rect)
+{
+  MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+  self->priv->maximize_in_progress++;
+
+  if (!info->plugin_mgr ||
+      !mutter_plugin_manager_event_maximize (info->plugin_mgr,
+					     self,
+					     MUTTER_PLUGIN_MAXIMIZE,
+					     window_rect->x, window_rect->y,
+					     window_rect->width, window_rect->height))
+
+    {
+      self->priv->maximize_in_progress--;
+    }
+}
+
+void
+mutter_window_unmaximize (MutterWindow      *self,
+                          MetaRectangle     *window_rect)
+{
+  MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+  self->priv->unmaximize_in_progress++;
+
+  if (!info->plugin_mgr ||
+      !mutter_plugin_manager_event_maximize (info->plugin_mgr,
+					     self,
+					     MUTTER_PLUGIN_UNMAXIMIZE,
+					     window_rect->x, window_rect->y,
+					     window_rect->width, window_rect->height))
+    {
+      self->priv->unmaximize_in_progress--;
+    }
+}
+
+MutterWindow *
+mutter_window_new (MetaWindow *window)
+{
+  MetaScreen		*screen = meta_window_get_screen (window);
+  MetaDisplay           *display = meta_screen_get_display (screen);
+  MetaCompScreen        *info = meta_screen_get_compositor_data (screen);
+  MutterWindow          *self;
+  MutterWindowPrivate   *priv;
+  MetaFrame		*frame;
+  Window		 top_window;
+  XWindowAttributes	 attrs;
+
+  frame = meta_window_get_frame (window);
+  if (frame)
+    top_window = meta_frame_get_xwindow (frame);
+  else
+    top_window = meta_window_get_xwindow (window);
+
+  meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
+
+  /* FIXME: Remove the redundant data we store in self->priv->attrs, and
+   * simply query metacity core for the data. */
+  if (!XGetWindowAttributes (display->xdisplay, top_window, &attrs))
+    return NULL;
+
+  self = g_object_new (MUTTER_TYPE_COMP_WINDOW,
+		     "meta-window",         window,
+		     "x-window",            top_window,
+		     "meta-screen",         screen,
+		     "x-window-attributes", &attrs,
+		     NULL);
+
+  priv = self->priv;
+
+  clutter_actor_set_position (CLUTTER_ACTOR (self),
+			      priv->attrs.x, priv->attrs.y);
+
+  /* Hang our compositor window state off the MetaWindow for fast retrieval */
+  meta_window_set_compositor_private (window, G_OBJECT (self));
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group),
+			       CLUTTER_ACTOR (self));
+  clutter_actor_hide (CLUTTER_ACTOR (self));
+
+  if (priv->type == META_COMP_WINDOW_DOCK)
+    {
+      meta_verbose ("Appending %s to dock windows\n", meta_window_get_description (window));
+      info->dock_windows = g_slist_append (info->dock_windows, self);
+    }
+
+  /*
+   * Add this to the list at the top of the stack before it is mapped so that
+   * map_win can find it again
+   */
+  info->windows = g_list_append (info->windows, self);
+  g_hash_table_insert (info->windows_by_xid, (gpointer) top_window, self);
+
+  if (priv->attrs.map_state == IsViewable)
+    {
+      /* Need to reset the map_state for map_win() to work */
+      priv->attrs.map_state = IsUnmapped;
+      mutter_window_map (self);
+    }
+
+  return self;
+}
+
+static void
+repair_win (MutterWindow *self)
+{
+  MutterWindowPrivate *priv     = self->priv;
+  MetaScreen          *screen   = priv->screen;
+  MetaDisplay         *display  = meta_screen_get_display (screen);
+  Display             *xdisplay = meta_display_get_xdisplay (display);
+  MetaCompScreen      *info     = meta_screen_get_compositor_data (screen);
+  MetaCompositor      *compositor;
+  Window               xwindow  = priv->xwindow;
+  gboolean             full     = FALSE;
+
+  if (xwindow == meta_screen_get_xroot (screen) ||
+      xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
+    return;
+
+  compositor = meta_display_get_compositor (display);
+
+  meta_error_trap_push (display);
+
+  if (priv->back_pixmap == None)
+    {
+      gint pxm_width, pxm_height;
+
+      meta_error_trap_push (display);
+
+      priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
+
+      if (meta_error_trap_pop_with_return (display, FALSE) != Success)
+        {
+          /* Probably a BadMatch if the window isn't viewable; we could
+           * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
+           * to avoid this, but there's no reason to take two round trips
+           * when one will do. (We need that Sync if we want to handle failures
+           * for any reason other than !viewable. That's unlikely, but maybe
+           * we'll BadAlloc or something.)
+           */
+          priv->back_pixmap = None;
+        }
+
+      if (priv->back_pixmap == None)
+        {
+          meta_verbose ("Unable to get named pixmap for %p\n", self);
+          return;
+        }
+
+      /* MUST call before setting pixmap or serious performance issues
+       * seemingly caused by cogl_texture_set_filters() in set_filter
+       * Not sure if that call is actually needed.
+       */
+      if (!compositor->no_mipmaps)
+        clutter_texture_set_filter_quality (CLUTTER_TEXTURE (priv->actor),
+                                            CLUTTER_TEXTURE_QUALITY_HIGH );
+
+      clutter_x11_texture_pixmap_set_pixmap
+                       (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
+                        priv->back_pixmap);
+
+      g_object_get (priv->actor,
+                    "pixmap-width", &pxm_width,
+                    "pixmap-height", &pxm_height,
+                    NULL);
+
+      clutter_actor_set_size (priv->actor, pxm_width, pxm_height);
+
+      if (priv->shadow)
+        clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
+
+      full = TRUE;
+    }
+
+ /*
+   * TODO -- on some gfx hardware updating the whole texture instead of
+   * the individual rectangles is actually quicker, so we might want to
+   * make this a configurable option (on desktop HW with multiple pipelines
+   * it is usually quicker to just update the damaged parts).
+   *
+   * If we are using TFP we update the whole texture (this simply trigers
+   * the texture rebind).
+   */
+  if (full
+#ifdef HAVE_GLX_TEXTURE_PIXMAP
+      || (CLUTTER_GLX_IS_TEXTURE_PIXMAP (priv->actor) &&
+          clutter_glx_texture_pixmap_using_extension
+                  (CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
+#endif /* HAVE_GLX_TEXTURE_PIXMAP */
+      )
+    {
+      XDamageSubtract (xdisplay, priv->damage, None, None);
+
+      clutter_x11_texture_pixmap_update_area
+	(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
+	 0,
+	 0,
+	 clutter_actor_get_width (priv->actor),
+	 clutter_actor_get_height (priv->actor));
+    }
+  else
+    {
+      XRectangle   *r_damage;
+      XRectangle    r_bounds;
+      XserverRegion parts;
+      int           i, r_count;
+
+      parts = XFixesCreateRegion (xdisplay, 0, 0);
+      XDamageSubtract (xdisplay, priv->damage, None, parts);
+
+      r_damage = XFixesFetchRegionAndBounds (xdisplay,
+					     parts,
+					     &r_count,
+					     &r_bounds);
+
+      if (r_damage)
+	{
+	  for (i = 0; i < r_count; ++i)
+	    {
+	      clutter_x11_texture_pixmap_update_area
+		(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
+		 r_damage[i].x,
+		 r_damage[i].y,
+		 r_damage[i].width,
+		 r_damage[i].height);
+	    }
+	}
+
+      XFree (r_damage);
+      XFixesDestroyRegion (xdisplay, parts);
+    }
+
+  meta_error_trap_pop (display, FALSE);
+
+  priv->needs_repair = FALSE;
+}
+
+void
+mutter_window_process_damage (MutterWindow       *self,
+			      XDamageNotifyEvent *event)
+{
+  MutterWindowPrivate *priv = self->priv;
+  Display *dpy = event->display;
+  Drawable drawable = event->drawable;
+  XEvent   next;
+
+  if (priv->destroy_pending        ||
+      priv->maximize_in_progress   ||
+      priv->unmaximize_in_progress)
+    {
+      priv->needs_repair = TRUE;
+      return;
+    }
+
+  /*
+   * Check if the event queue does not already contain DetstroyNotify for this
+   * window -- if it does, we need to stop updating the pixmap (to avoid damage
+   * notifications that come from the window teardown), and process the destroy
+   * immediately.
+   */
+  if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
+    {
+      priv->destroy_pending = TRUE;
+      mutter_window_destroy (self);
+      return;
+    }
+
+  repair_win (self);
+}
+
+void
+mutter_window_finish_workspace_switch (MutterWindow *self)
+{
+  MutterWindowPrivate *priv = self->priv;
+
+  if (priv->needs_map && !priv->needs_unmap)
+    {
+      mutter_window_map (self);
+    }
+
+  if (priv->needs_unmap)
+    {
+      mutter_window_unmap (self);
+    }
+}
+
+void
+mutter_window_update_shape (MutterWindow   *self,
+                            gboolean        shaped)
+{
+  MutterWindowPrivate *priv = self->priv;
+
+  priv->shaped = shaped;
+
+  mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
+
+#ifdef HAVE_SHAPE
+  if (priv->shaped)
+    {
+      Display *xdisplay = meta_display_get_xdisplay (priv->window->display);
+      XRectangle *rects;
+      int n_rects, ordering;
+
+      rects = XShapeGetRectangles (xdisplay,
+                                   priv->xwindow,
+                                   ShapeBounding,
+                                   &n_rects,
+                                   &ordering);
+
+      if (rects)
+        {
+          mutter_shaped_texture_add_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor),
+                                              n_rects, rects);
+
+          XFree (rects);
+        }
+    }
+#endif
+}
+
+void
+mutter_window_update_opacity (MutterWindow *self)
+{
+  MutterWindowPrivate *priv = self->priv;
+  MetaDisplay *display = meta_screen_get_display (priv->screen);
+  MetaCompositor *compositor = meta_display_get_compositor (display);
+  Window xwin = meta_window_get_xwindow (priv->window);
+  gulong value;
+  guint8 opacity;
+
+  if (meta_prop_get_cardinal (display, xwin,
+                              compositor->atom_net_wm_window_opacity,
+                              &value))
+    {
+      opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
+    }
+  else
+    opacity = 255;
+
+  self->priv->opacity = opacity;
+  clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity);
+}
+
+void
+mutter_window_set_hidden (MutterWindow	  *self,
+                          gboolean	   hidden)
+{
+  MutterWindowPrivate *priv = self->priv;
+  MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
+
+  if (hidden)
+    {
+      if (mutter_window_effect_in_progress (self, TRUE))
+	{
+	  priv->hide_after_effect = TRUE;
+	}
+      else
+	{
+	  if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->hidden_group)
+	    {
+	      clutter_actor_reparent (CLUTTER_ACTOR (self),
+				      info->hidden_group);
+	    }
+	}
+    }
+  else
+    {
+      priv->hide_after_effect = FALSE;
+      if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->window_group)
+	clutter_actor_reparent (CLUTTER_ACTOR (self),
+				info->window_group);
+    }
+}
+
+void
+mutter_window_queue_map_change (MutterWindow *self,
+                                gboolean      should_be_mapped)
+{
+  if (should_be_mapped)
+    {
+      self->priv->needs_map = TRUE;
+      self->priv->needs_unmap = FALSE;
+    }
+  else
+    {
+      self->priv->needs_unmap = TRUE;
+    }
+}
diff --git a/src/include/compositor-mutter.h b/src/include/compositor-mutter.h
index 7ab3511..ba3ab0c 100644
--- a/src/include/compositor-mutter.h
+++ b/src/include/compositor-mutter.h
@@ -26,63 +26,17 @@
 #define MUTTER_H_
 
 #include <clutter/clutter.h>
-#include <X11/extensions/Xfixes.h>
 #include <X11/Xlib.h>
 
 #include "types.h"
 #include "compositor.h"
+#include "mutter-window.h"
 
-/*
- * MutterWindow object (ClutterGroup sub-class)
- */
-#define MUTTER_TYPE_COMP_WINDOW       (mutter_window_get_type ())
-#define MUTTER_WINDOW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindow))
-#define MUTTER_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
-#define MUTTER_IS_WINDOW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_COMP_WINDOW))
-#define MUTTER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_COMP_WINDOW))
-#define MUTTER_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
-
-typedef struct _MutterWindow        MutterWindow;
-typedef struct _MutterWindowClass   MutterWindowClass;
-typedef struct _MutterWindowPrivate MutterWindowPrivate;
-
-struct _MutterWindowClass
-{
-  ClutterGroupClass parent_class;
-};
-
-struct _MutterWindow
-{
-  ClutterGroup           parent;
-
-  MutterWindowPrivate *priv;
-};
-
-GType mutter_window_get_type (void);
-
-Window             mutter_window_get_x_window         (MutterWindow *mcw);
-MetaCompWindowType mutter_window_get_window_type      (MutterWindow *mcw);
-gint               mutter_window_get_workspace        (MutterWindow *mcw);
-gboolean           mutter_window_is_hidden            (MutterWindow *mcw);
-MetaWindow *       mutter_window_get_meta_window      (MutterWindow *mcw);
-ClutterActor *     mutter_window_get_texture          (MutterWindow *mcw);
-gboolean           mutter_window_is_override_redirect (MutterWindow *mcw);
-const char *       mutter_window_get_description      (MutterWindow *mcw);
-gboolean       mutter_window_showing_on_its_workspace (MutterWindow *mcw);
-
-/* Compositor API */
-MetaCompositor *mutter_new (MetaDisplay *display);
-
-void mutter_window_effect_completed (MutterWindow *actor, gulong event);
-
+/* Public compositor API */
 ClutterActor * mutter_get_stage_for_screen (MetaScreen *screen);
 ClutterActor * mutter_get_overlay_group_for_screen (MetaScreen *screen);
 Window         mutter_get_overlay_window (MetaScreen *screen);
 GList        * mutter_get_windows (MetaScreen *screen);
 ClutterActor * mutter_get_window_group_for_screen (MetaScreen *screen);
 
-void mutter_set_stage_input_region   (MetaScreen   *screen,
-                                      XserverRegion region);
-void mutter_empty_stage_input_region (MetaScreen   *screen);
-
 #endif
diff --git a/src/include/mutter-window.h b/src/include/mutter-window.h
new file mode 100644
index 0000000..9ef3794
--- /dev/null
+++ b/src/include/mutter-window.h
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2008 Matthew Allum
+ * Copyright (C) 2007 Iain Holmes
+ * Based on xcompmgr - (c) 2003 Keith Packard
+ *          xfwm4    - (c) 2005-2007 Olivier Fourdan
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef MUTTER_WINDOW_H_
+#define MUTTER_WINDOW_H_
+
+#include <clutter/clutter.h>
+#include <X11/Xlib.h>
+
+#include "compositor.h"
+
+/*
+ * MutterWindow object (ClutterGroup sub-class)
+ */
+#define MUTTER_TYPE_COMP_WINDOW       (mutter_window_get_type ())
+#define MUTTER_WINDOW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindow))
+#define MUTTER_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
+#define MUTTER_IS_WINDOW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_COMP_WINDOW))
+#define MUTTER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_COMP_WINDOW))
+#define MUTTER_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
+
+typedef struct _MutterWindow        MutterWindow;
+typedef struct _MutterWindowClass   MutterWindowClass;
+typedef struct _MutterWindowPrivate MutterWindowPrivate;
+
+struct _MutterWindowClass
+{
+  ClutterGroupClass parent_class;
+};
+
+struct _MutterWindow
+{
+  ClutterGroup           parent;
+
+  MutterWindowPrivate *priv;
+};
+
+GType mutter_window_get_type (void);
+
+Window             mutter_window_get_x_window         (MutterWindow *mcw);
+MetaCompWindowType mutter_window_get_window_type      (MutterWindow *mcw);
+gint               mutter_window_get_workspace        (MutterWindow *mcw);
+gboolean           mutter_window_is_hidden            (MutterWindow *mcw);
+MetaWindow *       mutter_window_get_meta_window      (MutterWindow *mcw);
+ClutterActor *     mutter_window_get_texture          (MutterWindow *mcw);
+gboolean           mutter_window_is_override_redirect (MutterWindow *mcw);
+const char *       mutter_window_get_description      (MutterWindow *mcw);
+gboolean       mutter_window_showing_on_its_workspace (MutterWindow *mcw);
+
+#endif /* MUTTER_WINDOW_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]