New compositor patch



Hi,

Here is a new patch that takes care of most of the previous comments.
I'd really like to get something committed to HEAD. This patch should
be minimally intrusive to a non-compositing metacity.


Soren

? birnan
? blah
? mergediff
? newattempt
? newattempt.patch
? non-working-comp.c
Index: compositor.c
===================================================================
RCS file: /cvs/gnome/metacity/src/compositor.c,v
retrieving revision 1.14
diff -u -p -u -r1.14 compositor.c
--- compositor.c	14 Dec 2005 12:47:35 -0000	1.14
+++ compositor.c	12 Jan 2006 23:39:16 -0000
@@ -1,5 +1,3 @@
-/* Metacity compositing manager */
-
 /* 
  * Copyright (C) 2003, 2004 Red Hat, Inc.
  * Copyright (C) 2003 Keith Packard
@@ -26,117 +24,66 @@
 #include "errors.h"
 #include "window.h"
 #include "frame.h"
+#include "workspace.h"
+
+#include <math.h>
+
+#include <cm/node.h>
+#include <cm/drawable-node.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <X11/extensions/shape.h>
+
+#include <cm/ws.h>
+#include <cm/wsint.h>
+
 
 #ifdef HAVE_COMPOSITE_EXTENSIONS
 #include <X11/extensions/Xcomposite.h>
 #include <X11/extensions/Xdamage.h>
 #include <X11/extensions/Xrender.h>
 
-#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
-#define HAVE_NAME_WINDOW_PIXMAP 1
-#endif
-
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
-#define SHADOW_OFFSET 3
 #define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
 
-/* Unlike MetaWindow, there's one of these for _all_ toplevel windows,
- * override redirect or not. We also track unmapped windows as
- * otherwise on window map we'd have to determine where the
- * newly-mapped window was in the stack. A MetaCompositorWindow may
- * correspond to a metacity window frame rather than an application
- * window.
- */
+/* Screen specific information */
 typedef struct
 {
-  Window xwindow;
-  
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-  MetaCompositor *compositor;
-
-  int x;
-  int y;
-  int width;
-  int height;
-  int border_width;
-  
-  Damage          damage;
-  XserverRegion   last_painted_extents;
-  
-  Picture         picture;
-  XserverRegion   border_size;
-
-#if HAVE_NAME_WINDOW_PIXMAP
-  Pixmap          pixmap;
-#endif
-  
-  unsigned int managed : 1;
-  unsigned int damaged : 1;
-  unsigned int viewable : 1;
-
-  unsigned int screen_index : 8;
-
-#endif  
-} MetaCompositorWindow;
+  /* top of stack is first in list */
+  GList *compositor_windows;
+  WsWindow *glw;
+} ScreenInfo;
 
 struct MetaCompositor
 {
   MetaDisplay *display;
-
-  int composite_error_base;
-  int composite_event_base;
-  int damage_error_base;
-  int damage_event_base;
-  int fixes_error_base;
-  int fixes_event_base;
+  
+  Ws *ws;
   
   GHashTable *window_hash;
-
+  
   guint repair_idle;
-  guint repair_timeout;
   
   guint enabled : 1;
   guint have_composite : 1;
   guint have_damage : 1;
   guint have_fixes : 1;
-#ifdef HAVE_NAME_WINDOW_PIXMAP
   guint have_name_window_pixmap : 1;
-#endif
-};
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-meta_compositor_window_free (MetaCompositorWindow *cwindow)
-{
-  g_assert (cwindow->damage != None);
+  guint debug_updates : 1;
   
-  meta_error_trap_push (cwindow->compositor->display);
-  /* This seems to cause an error if the window
-   * is destroyed?
-   */
-  XDamageDestroy (cwindow->compositor->display->xdisplay,
-                  cwindow->damage);
-
-#if HAVE_NAME_WINDOW_PIXMAP
-  /* Free our window pixmap name */
-  if (cwindow->pixmap != None)
-    XFreePixmap (cwindow->compositor->display->xdisplay,
-                 cwindow->pixmap);
-#endif
-  meta_error_trap_pop (cwindow->compositor->display, FALSE);
-  
-  g_free (cwindow);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+  GList *ignored_damage;
+};
 
 #ifdef HAVE_COMPOSITE_EXTENSIONS
 static void
 free_window_hash_value (void *v)
 {
-  MetaCompositorWindow *cwindow = v;
-
-  meta_compositor_window_free (cwindow);
+  DrawableNode *drawable_node = v;
+  
+  drawable_node_unref (drawable_node);
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
@@ -145,81 +92,20 @@ meta_compositor_new (MetaDisplay *displa
 {
 #ifdef HAVE_COMPOSITE_EXTENSIONS
   MetaCompositor *compositor;
-
+  
   compositor = g_new0 (MetaCompositor, 1);
-
-  compositor->display = display;
   
-  if (!XCompositeQueryExtension (display->xdisplay,
-                                 &compositor->composite_event_base,
-                                 &compositor->composite_error_base))
-    {
-      compositor->composite_event_base = 0;
-      compositor->composite_error_base = 0;
-    }
-  else
-    {
-      int composite_major, composite_minor;
-      
-      compositor->have_composite = TRUE;
-
-#if HAVE_NAME_WINDOW_PIXMAP
-      XCompositeQueryVersion (display->xdisplay,
-                              &composite_major, &composite_minor);
-
-#if 0
-      if (composite_major > 0 || composite_minor >= 2)
-	compositor->have_name_window_pixmap = TRUE;
-#endif
-#endif
-    }
-
-  meta_topic (META_DEBUG_COMPOSITOR, "Composite extension event base %d error base %d\n",
-              compositor->composite_event_base,
-              compositor->composite_error_base);
-
-  if (!XDamageQueryExtension (display->xdisplay,
-                              &compositor->damage_event_base,
-                              &compositor->damage_error_base))
-    {
-      compositor->damage_event_base = 0;
-      compositor->damage_error_base = 0;
-    }
-  else
-    compositor->have_damage = TRUE;
-
-  meta_topic (META_DEBUG_COMPOSITOR, "Damage extension event base %d error base %d\n",
-              compositor->damage_event_base,
-              compositor->damage_error_base);
-  
-  if (!XFixesQueryExtension (display->xdisplay,
-                             &compositor->fixes_event_base,
-                             &compositor->fixes_error_base))
-    {
-      compositor->fixes_event_base = 0;
-      compositor->fixes_error_base = 0;
-    }
-  else
-    compositor->have_fixes = TRUE;
-
-  meta_topic (META_DEBUG_COMPOSITOR, "Fixes extension event base %d error base %d\n",
-              compositor->fixes_event_base,
-              compositor->fixes_error_base);
-  
-  if (!(compositor->have_composite &&
-        compositor->have_fixes &&
-        compositor->have_damage &&
-        META_DISPLAY_HAS_RENDER (compositor->display)))
-    {
-      meta_topic (META_DEBUG_COMPOSITOR, "Failed to find all extensions needed for compositing manager, disabling compositing manager\n");
-      g_assert (!compositor->enabled);
-      return compositor;
-    }
+  compositor->ws = ws_new (NULL);
+  
+  ws_init_test (compositor->ws);
+  ws_set_ignore_grabs (compositor->ws, TRUE);
+  
+  compositor->display = display;
   
   compositor->window_hash = g_hash_table_new_full (meta_unsigned_long_hash,
-                                                   meta_unsigned_long_equal,
-                                                   NULL,
-                                                   free_window_hash_value);
+						   meta_unsigned_long_equal,
+						   NULL,
+						   free_window_hash_value);
   
   compositor->enabled = TRUE;
   
@@ -229,24 +115,24 @@ meta_compositor_new (MetaDisplay *displa
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 }
 
+void
+meta_compositor_set_debug_updates (MetaCompositor *compositor,
+				   gboolean	   debug_updates)
+{
+  compositor->debug_updates = !!debug_updates;
+}
+
 #ifdef HAVE_COMPOSITE_EXTENSIONS
 static void
 remove_repair_idle (MetaCompositor *compositor)
 {
-  if (compositor->repair_idle || compositor->repair_timeout)
-    meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
-  
-  if (compositor->repair_idle != 0)
+  if (compositor->repair_idle)
     {
+      meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
+      
       g_source_remove (compositor->repair_idle);
       compositor->repair_idle = 0;
     }
-
-  if (compositor->repair_timeout != 0)
-    {
-      g_source_remove (compositor->repair_timeout);
-      compositor->repair_timeout = 0;
-    }
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
@@ -258,7 +144,7 @@ meta_compositor_unref (MetaCompositor *c
    * there's no ref()
    */
   remove_repair_idle (compositor);
-
+  
   if (compositor->window_hash)
     g_hash_table_destroy (compositor->window_hash);
   
@@ -267,500 +153,102 @@ meta_compositor_unref (MetaCompositor *c
 }
 
 #ifdef HAVE_COMPOSITE_EXTENSIONS
-static XserverRegion
-window_extents (MetaCompositorWindow *cwindow)
-{
-  XRectangle r;
-
-  r.x = cwindow->x;
-  r.y = cwindow->y;
-  r.width = cwindow->width;
-  r.height = cwindow->height;
-
-  r.width += SHADOW_OFFSET;
-  r.height += SHADOW_OFFSET;
-  
-  return XFixesCreateRegion (cwindow->compositor->display->xdisplay, &r, 1);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-window_get_paint_bounds (MetaCompositorWindow *cwindow,
-                         int *x,
-                         int *y,
-                         int *w,
-                         int *h)
-{
-#ifdef HAVE_NAME_WINDOW_PIXMAP
-  if (cwindow->pixmap != None)
-    {
-      *x = cwindow->x;
-      *y = cwindow->y;
-      *w = cwindow->width + cwindow->border_width * 2;
-      *h = cwindow->height + cwindow->border_width * 2;
-    }
-  else
-#endif
-    {
-      *x = cwindow->x + cwindow->border_width;
-      *y = cwindow->y + cwindow->border_width;
-      *w = cwindow->width;
-      *h = cwindow->height;
-    }
-}
-
 static void
-paint_screen (MetaCompositor *compositor,
-              MetaScreen     *screen,
-              XserverRegion   damage_region)
+draw_windows (MetaScreen *screen,
+	      GList      *list)
 {
-  XserverRegion region;
-  Picture buffer_picture;
-  Pixmap buffer_pixmap;
-  Display *xdisplay;
-  XRenderPictFormat *format;
-  GList *tmp;
-  GC gc;
-
-  meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n",
-              screen->number, screen->xroot);
-
-  /* meta_display_grab (screen->display); */
+  Node *node;
   
-  xdisplay = screen->display->xdisplay;
+  if (!list)
+    return;
   
-  if (damage_region == None)
-    {
-      XRectangle  r;
-
-      r.x = 0;
-      r.y = 0;
-      r.width = screen->rect.width;
-      r.height = screen->rect.height;
-      
-      region = XFixesCreateRegion (xdisplay, &r, 1);
-    }
-  else
-    {
-      region = XFixesCreateRegion (xdisplay, NULL, 0);
-      
-      XFixesCopyRegion (compositor->display->xdisplay,
-                        region,
-                        damage_region);
-    }
-
-  buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot,
-                                 screen->rect.width,
-                                 screen->rect.height,
-                                 DefaultDepth (xdisplay,
-                                               screen->number));
-
-  gc = XCreateGC (xdisplay, buffer_pixmap, 0, NULL);
-  XSetForeground (xdisplay, gc, WhitePixel (xdisplay, screen->number));
-  XFixesSetGCClipRegion (xdisplay, gc, 0, 0, region);
-  XFillRectangle (xdisplay, buffer_pixmap, gc, 0, 0,
-                  screen->rect.width, screen->rect.height);
-  
-  format = XRenderFindVisualFormat (xdisplay,
-                                    DefaultVisual (xdisplay,
-                                                   screen->number));
-  
-  buffer_picture = XRenderCreatePicture (xdisplay,
-                                         buffer_pixmap,
-                                         format,
-                                         0, 0);
-
-  /* set clip */          
-  XFixesSetPictureClipRegion (xdisplay,
-                              buffer_picture, 0, 0,
-                              region);
-
-  /* draw windows from bottom to top */
-  
-  meta_error_trap_push (compositor->display);
-  tmp = g_list_last (screen->compositor_windows);
-  while (tmp != NULL)
-    {
-      MetaCompositorWindow *cwindow = tmp->data;
-      XRenderColor shadow_color;
-      MetaWindow *window;
-
-      shadow_color.red = 0;
-      shadow_color.green = 0;
-      shadow_color.blue = 0;
-      shadow_color.alpha = 0x90c0;
-
-      if (cwindow->picture == None) /* InputOnly */
-        goto next;
-
-      if (!cwindow->viewable)
-        goto next; /* not viewable */
-      
-      if (cwindow->last_painted_extents)
-        XFixesDestroyRegion (xdisplay,
-                             cwindow->last_painted_extents);
-
-      cwindow->last_painted_extents = window_extents (cwindow);
-      
-      /* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */
-
-      meta_topic (META_DEBUG_COMPOSITOR, "  Compositing window 0x%lx %d,%d %dx%d\n",
-                  cwindow->xwindow,
-                  cwindow->x, cwindow->y,
-                  cwindow->width, cwindow->height);
-      
-      window = meta_display_lookup_x_window (compositor->display,
-                                             cwindow->xwindow);
-      if (window != NULL &&
-          window == compositor->display->grab_window &&
-          (meta_grab_op_is_resizing (compositor->display->grab_op) ||
-           meta_grab_op_is_moving (compositor->display->grab_op)))
-        {
-          /* Draw window transparent while resizing */
-          int x, y, w, h;
-
-          window_get_paint_bounds (cwindow, &x, &y, &w, &h);
-          
-          XRenderComposite (xdisplay,
-                            PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
-                            cwindow->picture,
-                            screen->trans_picture,
-                            buffer_picture,
-                            0, 0, 0, 0,
-                            x, y, w, h);
-        }
-      else
-        {
-          /* Draw window normally */
-          int x, y, w, h;
-          
-          window_get_paint_bounds (cwindow, &x, &y, &w, &h);
-          
-          /* superlame drop shadow */
-          XRenderFillRectangle (xdisplay, PictOpOver,
-                                buffer_picture,
-                                &shadow_color,
-                                cwindow->x + SHADOW_OFFSET,
-                                cwindow->y + SHADOW_OFFSET,
-                                cwindow->width, cwindow->height);
-
-          XRenderComposite (xdisplay,
-                            PictOpSrc, /* PictOpOver for alpha, PictOpSrc without */
-                            cwindow->picture,
-                            None,
-                            buffer_picture,
-                            0, 0, 0, 0,
-                            x, y, w, h);
-        }
-
-    next:
-      tmp = tmp->prev;
-    }
-  meta_error_trap_pop (compositor->display, FALSE);
-
-  /* Copy buffer to root window */
-  meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n",
-              screen->xroot, screen->root_picture);
-
-#if 1
-  XFixesSetPictureClipRegion (xdisplay,
-                              screen->root_picture,
-                              0, 0, region);
-#endif
+  node = list->data;
   
-  /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
-  XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None,
-                    screen->root_picture,
-                    0, 0, 0, 0, 0, 0,
-                    screen->rect.width, screen->rect.height);
-  
-  XFixesDestroyRegion (xdisplay, region);
-  XFreePixmap (xdisplay, buffer_pixmap);
-  XRenderFreePicture (xdisplay, buffer_picture);
-  XFreeGC (xdisplay, gc);
-
-  /* meta_display_ungrab (screen->display); */
-
-  XSync (screen->display->xdisplay, False);
+  draw_windows (screen, list->next);
+  node->render (node);
 }
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+#endif
 
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-do_repair (MetaCompositor *compositor)
+static MetaScreen *
+node_get_screen (Display *dpy,
+		 DrawableNode *node)
 {
-  GSList *tmp;
+  /* FIXME: we should probably have a reverse mapping
+   * from nodes to screens
+   */
   
-  tmp = compositor->display->screens;
-  while (tmp != NULL)
-    {
-      MetaScreen *s = tmp->data;
-
-      if (s->damage_region != None)
-        {
-          paint_screen (compositor, s,
-                        s->damage_region);
-          XFixesDestroyRegion (s->display->xdisplay,
-                               s->damage_region);
-          s->damage_region = None;
-        }
-      
-      tmp = tmp->next;
-    }
-
-  remove_repair_idle (compositor);
+  Screen *screen = XDefaultScreenOfDisplay (dpy);
+  return meta_screen_for_x_screen (screen);
 }
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
 
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static gboolean
-repair_idle_func (void *data)
+static void
+handle_restacking (MetaCompositor *compositor,
+		   DrawableNode *node,
+		   DrawableNode *above)
 {
-  MetaCompositor *compositor = data;
-
-  compositor->repair_idle = 0;
-  do_repair (compositor);
+  GList *window_link, *above_link;
+  MetaScreen *screen;
+  ScreenInfo *scr_info;
   
-  return FALSE;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static gboolean
-repair_timeout_func (void *data)
-{
-  MetaCompositor *compositor = data;
-
-  compositor->repair_timeout = 0;
-  do_repair (compositor);
+  screen = node_get_screen (compositor->display->xdisplay, node);
+  scr_info = screen->compositor_data;
   
-  return FALSE;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static MetaScreen*
-meta_compositor_window_get_screen (MetaCompositorWindow *cwindow)
-{
-  MetaScreen *screen;
-  GSList *tmp;
+  window_link = g_list_find (scr_info->compositor_windows, node);
+  above_link  = g_list_find (scr_info->compositor_windows, above);
   
-  screen = NULL;
-  tmp = cwindow->compositor->display->screens;
-  while (tmp != NULL)
-    {
-      MetaScreen *s = tmp->data;
-
-      if (s->number == cwindow->screen_index)
-        {
-          screen = s;
-          break;
-        }
-      
-      tmp = tmp->next;
-    }
-  g_assert (screen != NULL);
-
-  return screen;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-ensure_repair_idle (MetaCompositor *compositor)
-{
-  if (compositor->repair_idle != 0)
+  if (!window_link || !above_link)
     return;
-
-  compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE,
-                                             repair_idle_func, compositor, NULL);
-  compositor->repair_timeout = g_timeout_add (FRAME_INTERVAL_MILLISECONDS,
-                                              repair_timeout_func, compositor);
-
-  meta_topic (META_DEBUG_COMPOSITOR, "Damage idle queued\n");
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-merge_and_destroy_damage_region (MetaCompositor *compositor,
-                                 MetaScreen     *screen,
-                                 XserverRegion   region)
-{
-  if (screen->damage_region != None)
-    {
-      XFixesUnionRegion (compositor->display->xdisplay,
-                         screen->damage_region,
-                         region, screen->damage_region);
-      XFixesDestroyRegion (compositor->display->xdisplay,
-                           region);
-    }
-  else
+  
+  if (window_link == above_link)
     {
-      screen->damage_region = region;
+      /* This can happen if the topmost window is raise above
+       * the GL window
+       */
+      return;
     }
-
-  ensure_repair_idle (compositor);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-merge_damage_region (MetaCompositor *compositor,
-                     MetaScreen     *screen,
-                     XserverRegion   region)
-{
-  if (screen->damage_region == None)
-    screen->damage_region =
-      XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
-
-  meta_topic (META_DEBUG_COMPOSITOR,
-              "(Merging damage region)\n");
-  
-  XFixesUnionRegion (compositor->display->xdisplay,
-                     screen->damage_region,
-                     region, screen->damage_region);
-
-  ensure_repair_idle (compositor);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-process_damage_notify (MetaCompositor     *compositor,
-                       XDamageNotifyEvent *event)
-{
-  MetaCompositorWindow *cwindow;
-  XserverRegion region;
-  MetaScreen *screen;
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &event->drawable);
-  if (cwindow == NULL)
-    return;
-
-  region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
-
-  /* translate region to screen; can error if window of damage is
-   * destroyed
-   */
-  meta_error_trap_push (compositor->display);
-  XDamageSubtract (compositor->display->xdisplay,
-                   cwindow->damage, None, region);
-  meta_error_trap_pop (compositor->display, FALSE);
-
-  XFixesTranslateRegion (compositor->display->xdisplay,
-                         region,
-                         cwindow->x,
-                         cwindow->y);
-
-  screen = meta_compositor_window_get_screen (cwindow);
-  
-  merge_and_destroy_damage_region (compositor, screen, region);
+  if (window_link->next != above_link)
+    {
+      ScreenInfo *scr_info = screen->compositor_data;
+      
+      scr_info->compositor_windows =
+	g_list_delete_link (scr_info->compositor_windows, window_link);
+      scr_info->compositor_windows =
+	g_list_insert_before (scr_info->compositor_windows, above_link, node);
+    }
 }
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
 
 #ifdef HAVE_COMPOSITE_EXTENSIONS
 static void
 process_configure_notify (MetaCompositor  *compositor,
                           XConfigureEvent *event)
 {
-  MetaCompositorWindow *cwindow;
+  WsWindow *above_window;
+  DrawableNode *node = g_hash_table_lookup (compositor->window_hash,
+					    &event->window);
+  DrawableNode *above_node;
   MetaScreen *screen;
-  GList *link;
-  Window above;
-  XserverRegion region;
-  
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &event->window);
-  if (cwindow == NULL)
+  ScreenInfo *scr_info;
+  
+  if (!node)
     return;
-
-  screen = meta_compositor_window_get_screen (cwindow);
-
-  g_assert (screen != NULL);
-
-  if (screen->xroot != event->event)
-    {
-      meta_topic (META_DEBUG_COMPOSITOR,
-                  "ConfigureNotify for 0x%lx received by 0x%lx not using\n",
-                  event->window, event->event);
-      return; /* ignore ConfigureNotify not received on root window */
-    }
-
-  meta_topic (META_DEBUG_COMPOSITOR,
-              "ConfigureNotify for 0x%lx received by 0x%lx  %d,%d %dx%d\n",
-              event->window, event->event,
-              event->x, event->y, event->width, event->height);
   
-  if (cwindow->last_painted_extents)
+  screen = node_get_screen (compositor->display->xdisplay, node);
+  scr_info = screen->compositor_data;
+  
+  above_window = ws_window_lookup (node->drawable->ws, event->above);
+  
+  if (above_window == scr_info->glw)
     {
-      merge_and_destroy_damage_region (compositor,
-                                       screen,
-                                       cwindow->last_painted_extents);
-      cwindow->last_painted_extents = None;
+      above_node = scr_info->compositor_windows->data;
     }
-  
-  cwindow->x = event->x;
-  cwindow->y = event->y;
-  cwindow->width = event->width;
-  cwindow->height = event->height;
-  cwindow->border_width = event->border_width;
-
-  link = g_list_find (screen->compositor_windows,
-                      cwindow);
-
-  g_assert (link != NULL);
-
-  if (link->next)
-    above = ((MetaCompositorWindow*) link->next)->xwindow;
   else
-    above = None;
-  
-  if (above != event->above)
     {
-      GList *tmp;
-      
-      screen->compositor_windows =
-        g_list_delete_link (screen->compositor_windows,
-                            link);
-      link = NULL;
-
-      /* Note that event->above is None if our window is on the bottom */
-      tmp = screen->compositor_windows;
-      while (tmp != NULL)
-        {
-          MetaCompositorWindow *t = tmp->data;
-          
-          if (t->xwindow == event->above)
-            {
-              /* We are above this window, i.e. earlier in list */
-              break;
-            }
-          
-          tmp = tmp->next;
-        }
-
-      if (tmp != NULL)
-        {
-          screen->compositor_windows =
-            g_list_insert_before (screen->compositor_windows,
-                                  tmp,
-                                  cwindow);
-        }
-      else
-        screen->compositor_windows =
-          g_list_prepend (screen->compositor_windows,
-                          cwindow);
+      above_node = g_hash_table_lookup (compositor->window_hash,
+					&event->above);
     }
-
-  region = window_extents (cwindow);
-  merge_damage_region (compositor,
-                       screen,
-                       region);
-  XFixesDestroyRegion (compositor->display->xdisplay, region);
+  
+  handle_restacking (compositor, node, above_node);
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
@@ -770,24 +258,9 @@ static void
 process_expose (MetaCompositor     *compositor,
                 XExposeEvent       *event)
 {
-  XserverRegion region;
-  MetaScreen *screen;
-  XRectangle r;
-
-  screen = meta_display_screen_for_root (compositor->display,
-                                         event->window);
-
-  if (screen == NULL || screen->root_picture == None)
-    return;
-
-  r.x = 0;
-  r.y = 0;
-  r.width = screen->rect.width;
-  r.height = screen->rect.height;
-  region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
-  
-  merge_and_destroy_damage_region (compositor, screen, region);
+  /* FIXME: queue repaint */
 }
+
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
 #ifdef HAVE_COMPOSITE_EXTENSIONS
@@ -795,49 +268,52 @@ static void
 process_map (MetaCompositor     *compositor,
              XMapEvent          *event)
 {
-  MetaCompositorWindow *cwindow;
+  DrawableNode *node;
   MetaScreen *screen;
-
+  
   /* See if window was mapped as child of root */
   screen = meta_display_screen_for_root (compositor->display,
-                                         event->event);
-
-  if (screen == NULL || screen->root_picture == None)
+					 event->event);
+  
+  if (screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "MapNotify received on non-root 0x%lx for 0x%lx\n",
-                  event->event, event->window);
+		  "MapNotify received on non-root 0x%lx for 0x%lx\n",
+		  event->event, event->window);
       return; /* MapNotify wasn't for a child of the root */
     }
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &event->window);
-  if (cwindow == NULL)
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &event->window);
+  if (node == NULL)
     {
       XWindowAttributes attrs;
       
       meta_error_trap_push_with_return (compositor->display);
       
       XGetWindowAttributes (compositor->display->xdisplay,
-                            event->window, &attrs);
+			    event->window, &attrs);
       
       if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
         {
-          meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
-                      event->window);
+	  meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
+		      event->window);
         }
       else
-        {
-          meta_topic (META_DEBUG_COMPOSITOR,
-                      "Map window 0x%lx\n", event->window);
-          meta_compositor_add_window (compositor,
-                                      event->window, &attrs);
+	{
+	  meta_compositor_add_window (compositor,
+				      event->window, &attrs);
         }
     }
   else
     {
-      cwindow->viewable = TRUE;
+      drawable_node_set_viewable (node, TRUE);
     }
+  
+  /* We don't actually need to invalidate anything, because we will
+   * get damage events as the server fills the background and the client
+   * draws the window
+   */
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 
@@ -846,34 +322,26 @@ static void
 process_unmap (MetaCompositor     *compositor,
                XUnmapEvent        *event)
 {
-  MetaCompositorWindow *cwindow;
+  DrawableNode *node;
   MetaScreen *screen;
-
+  
   /* See if window was unmapped as child of root */
   screen = meta_display_screen_for_root (compositor->display,
-                                         event->event);
-
-  if (screen == NULL || screen->root_picture == None)
+					 event->event);
+  
+  if (screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "UnmapNotify received on non-root 0x%lx for 0x%lx\n",
-                  event->event, event->window);
+		  "UnmapNotify received on non-root 0x%lx for 0x%lx\n",
+		  event->event, event->window);
       return; /* UnmapNotify wasn't for a child of the root */
     }
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &event->window);
-  if (cwindow != NULL)
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &event->window);
+  if (node != NULL)
     {
-      cwindow->viewable = FALSE;
-
-      if (cwindow->last_painted_extents)
-        {
-          merge_and_destroy_damage_region (compositor,
-                                           screen,
-                                           cwindow->last_painted_extents);
-          cwindow->last_painted_extents = None;
-        }
+      drawable_node_set_viewable (node, FALSE);
     }
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -885,34 +353,35 @@ process_create (MetaCompositor     *comp
 {
   MetaScreen *screen;
   XWindowAttributes attrs;
-      
+  
   screen = meta_display_screen_for_root (compositor->display,
-                                         event->parent);
-
-  if (screen == NULL || screen->root_picture == None)
+					 event->parent);
+  
+  if (screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "CreateNotify received on non-root 0x%lx for 0x%lx\n",
-                  event->parent, event->window);
+		  "CreateNotify received on non-root 0x%lx for 0x%lx\n",
+		  event->parent, event->window);
       return;
     }
-      
+  
   meta_error_trap_push_with_return (compositor->display);
   
   XGetWindowAttributes (compositor->display->xdisplay,
-                        event->window, &attrs);
+			event->window, &attrs);
   
   if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
     {
       meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
-                  event->window);
+		  event->window);
     }
   else
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "Create window 0x%lx, adding\n", event->window);
+		  "Create window 0x%lx, adding\n", event->window);
+      
       meta_compositor_add_window (compositor,
-                                  event->window, &attrs);
+				  event->window, &attrs);
     }
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -923,20 +392,20 @@ process_destroy (MetaCompositor      *co
                  XDestroyWindowEvent *event)
 {
   MetaScreen *screen;
-
+  
   screen = meta_display_screen_for_root (compositor->display,
-                                         event->event);
-
-  if (screen == NULL || screen->root_picture == None)
+					 event->event);
+  
+  if (screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "DestroyNotify received on non-root 0x%lx for 0x%lx\n",
-                  event->event, event->window);
+		  "DestroyNotify received on non-root 0x%lx for 0x%lx\n",
+		  event->event, event->window);
       return;
     }
-
+  
   meta_topic (META_DEBUG_COMPOSITOR,
-              "Destroy window 0x%lx\n", event->window);
+	      "Destroy window 0x%lx\n", event->window);
   meta_compositor_remove_window (compositor, event->window);
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -952,65 +421,56 @@ process_reparent (MetaCompositor      *c
    */
   MetaScreen *event_screen;
   MetaScreen *parent_screen;
-  MetaCompositorWindow *cwindow;
+  DrawableNode *node;
   XWindowAttributes attrs;
   
   event_screen = meta_display_screen_for_root (compositor->display,
-                                               event->event);
-
-  if (event_screen == NULL || event_screen->root_picture == None)
+					       event->event);
+  
+  if (event_screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "ReparentNotify received on non-root 0x%lx for 0x%lx\n",
-                  event->event, event->window);
+		  "ReparentNotify received on non-root 0x%lx for 0x%lx\n",
+		  event->event, event->window);
       return;
     }
-
+  
   meta_topic (META_DEBUG_COMPOSITOR,
-              "Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n",
-              event->window, event->parent, event->event);
-
+	      "Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n",
+	      event->window, event->parent, event->event);
+  
   parent_screen = meta_display_screen_for_root (compositor->display,
-                                                event->parent);
+						event->parent);
   
   if (parent_screen == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
-                  event->window, event->parent);
+		  "ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
+		  event->window, event->parent);
       meta_compositor_remove_window (compositor, event->window);
       return;
     }
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &event->window);
-  if (cwindow != NULL)
-    {
-      meta_topic (META_DEBUG_COMPOSITOR,
-                  "Window reparented to new screen at %d,%d\n",
-                  event->x, event->y);
-      cwindow->x = event->x;
-      cwindow->y = event->y;
-      return;
-    }
-
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &event->window);
+  
   meta_error_trap_push_with_return (compositor->display);
   
   XGetWindowAttributes (compositor->display->xdisplay,
-                        event->window, &attrs);
+			event->window, &attrs);
   
   if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
     {
       meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
-                  event->window);
+		  event->window);
     }
   else
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "Reparent window 0x%lx into screen 0x%lx, adding\n",
-                  event->window, event->parent);
+		  "Reparent window 0x%lx into screen 0x%lx, adding\n",
+		  event->window, event->parent);
       meta_compositor_add_window (compositor,
-                                  event->window, &attrs);
+				  event->window, &attrs);
     }
 }
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -1023,53 +483,65 @@ meta_compositor_process_event (MetaCompo
 #ifdef HAVE_COMPOSITE_EXTENSIONS
   if (!compositor->enabled)
     return; /* no extension */
-
+  
   /* FIXME support CirculateNotify */
   
-  if (event->type == (compositor->damage_event_base + XDamageNotify))
-    {
-      process_damage_notify (compositor,
-                             (XDamageNotifyEvent*) event);
-    }
-  else if (event->type == ConfigureNotify)
+  if (event->type == ConfigureNotify)
     {
       process_configure_notify (compositor,
-                                (XConfigureEvent*) event);
+				(XConfigureEvent*) event);
     }
   else if (event->type == Expose)
     {
       process_expose (compositor,
-                      (XExposeEvent*) event);
+		      (XExposeEvent*) event);
     }
   else if (event->type == UnmapNotify)
     {
       process_unmap (compositor,
-                     (XUnmapEvent*) event);
+		     (XUnmapEvent*) event);
     }
   else if (event->type == MapNotify)
     {
       process_map (compositor,
-                   (XMapEvent*) event);
+		   (XMapEvent*) event);
     }
   else if (event->type == ReparentNotify)
     {
       process_reparent (compositor,
-                        (XReparentEvent*) event);
+			(XReparentEvent*) event);
     }
   else if (event->type == CreateNotify)
     {
       process_create (compositor,
-                      (XCreateWindowEvent*) event);
+		      (XCreateWindowEvent*) event);
     }
   else if (event->type == DestroyNotify)
     {
       process_destroy (compositor,
-                       (XDestroyWindowEvent*) event);
+		       (XDestroyWindowEvent*) event);
     }
   
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 }
 
+static void
+wavy (double time,
+      double in_x, double in_y,
+      double *out_x, double *out_y,
+      gpointer data)
+{
+  static int m;
+  time = time * 5;
+  double dx = 0.0025 * sin (time + 35 * in_y);
+  double dy = 0.0025 * cos (time + 35 * in_x);
+  
+  *out_x = in_x + dx;
+  *out_y = in_y + dy;
+  
+  m++;
+}
+
 /* This is called when metacity does its XQueryTree() on startup
  * and when a new window is mapped.
  */
@@ -1079,106 +551,55 @@ meta_compositor_add_window (MetaComposit
                             XWindowAttributes *attrs)
 {
 #ifdef HAVE_COMPOSITE_EXTENSIONS
-  MetaCompositorWindow *cwindow;
+  DrawableNode *node;
   MetaScreen *screen;
-  Damage damage;
-  XRenderPictFormat *format;
-  XRenderPictureAttributes pa;
-  XserverRegion region;
+  WsDrawable *drawable;
+  ScreenInfo *scr_info;
   
   if (!compositor->enabled)
     return; /* no extension */
-
+  
   screen = meta_screen_for_x_screen (attrs->screen);
   g_assert (screen != NULL);
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &xwindow);
-
-  if (cwindow != NULL)
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &xwindow);
+  
+  if (node != NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "Window 0x%lx already added\n", xwindow);
+		  "Window 0x%lx already added\n", xwindow);
       return;
     }
-
-  meta_topic (META_DEBUG_COMPOSITOR,
-              "Adding window 0x%lx (%s) to compositor\n",
-              xwindow,
-              attrs->map_state == IsViewable ?
-              "mapped" : "unmapped");
-  
-  /* Create Damage object to monitor window damage */
-  meta_error_trap_push (compositor->display);
-  damage = XDamageCreate (compositor->display->xdisplay,
-                          xwindow, XDamageReportNonEmpty);
-  meta_error_trap_pop (compositor->display, FALSE);
-
-  if (damage == None)
-    return;
   
-  cwindow = g_new0 (MetaCompositorWindow, 1);
+  drawable = (WsDrawable *)ws_window_lookup (compositor->ws, xwindow);
 
-  cwindow->compositor = compositor;
-  cwindow->xwindow = xwindow;
-  cwindow->screen_index = screen->number;
-  cwindow->damage = damage;
-  cwindow->x = attrs->x;
-  cwindow->y = attrs->y;
-  cwindow->width = attrs->width;
-  cwindow->height = attrs->height;
-  cwindow->border_width = attrs->border_width;
-
-#if HAVE_NAME_WINDOW_PIXMAP
-  if (compositor->have_name_window_pixmap)
-    {
-      meta_error_trap_push (compositor->display);
-      cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay,
-                                                    cwindow->xwindow);
-      meta_error_trap_pop (compositor->display, FALSE);
-    }
-#endif
+  scr_info = screen->compositor_data;
+
+  g_assert (scr_info);
   
-  /* viewable == mapped for the root window, since root can't be unmapped */
-  cwindow->viewable = (attrs->map_state == IsViewable);
-  /* FIXME this assertion can fail somehow... */
-  g_assert (attrs->map_state != IsUnviewable);
-  
-  pa.subwindow_mode = IncludeInferiors;
-
-  if (attrs->class != InputOnly)
-    {      
-      format = XRenderFindVisualFormat (compositor->display->xdisplay,
-                                        attrs->visual);
-      cwindow->picture = XRenderCreatePicture (compositor->display->xdisplay,
-#if HAVE_NAME_WINDOW_PIXMAP
-                                               cwindow->pixmap != None ?
-                                               cwindow->pixmap :
-                                               cwindow->xwindow,
-#else
-                                               cwindow->xwindow,
-#endif
-                                               format,
-                                               CPSubwindowMode,
-                                               &pa);
+  if (ws_window_query_input_only ((WsWindow *)drawable) ||
+      drawable == (WsDrawable *)scr_info->glw)
+    {
+      return;
     }
   else
     {
-      cwindow->picture = None;
+      node = drawable_node_new (drawable);
+      
+      drawable_node_set_deformation_func (node, wavy, NULL);
     }
   
+  /* FIXME: we should probably just store xid's directly */
   g_hash_table_insert (compositor->window_hash,
-                       &cwindow->xwindow, cwindow);
-
+		       &(node->drawable->xid), node);
+  
   /* assume cwindow is at the top of the stack as it was either just
    * created or just reparented to the root window
    */
-  screen->compositor_windows = g_list_prepend (screen->compositor_windows,
-                                               cwindow);
-
-  /* schedule paint of the new window */
-  region = window_extents (cwindow);
-  merge_and_destroy_damage_region (compositor, screen, region);
+  scr_info->compositor_windows = g_list_prepend (scr_info->compositor_windows,
+						 node);
+  
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 }
 
@@ -1187,173 +608,293 @@ meta_compositor_remove_window (MetaCompo
                                Window             xwindow)
 {
 #ifdef HAVE_COMPOSITE_EXTENSIONS
-  MetaCompositorWindow *cwindow;
+  DrawableNode *node;
   MetaScreen *screen;
+  ScreenInfo *scr_info;
   
   if (!compositor->enabled)
     return; /* no extension */
   
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &xwindow);
-
-  if (cwindow == NULL)
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &xwindow);
+  
+  if (node == NULL)
     {
       meta_topic (META_DEBUG_COMPOSITOR,
-                  "Window 0x%lx already removed\n", xwindow);
+		  "Window 0x%lx already removed\n", xwindow);
       return;
     }
-
-  meta_topic (META_DEBUG_COMPOSITOR,
-              "Removing window 0x%lx (%s) from compositor\n",
-              xwindow,
-              cwindow->viewable ? "mapped" : "unmapped");
   
-  screen = meta_compositor_window_get_screen (cwindow);
-
-  if (cwindow->last_painted_extents)
-    {
-      merge_and_destroy_damage_region (compositor,
-                                       screen,
-                                       cwindow->last_painted_extents);
-      cwindow->last_painted_extents = None;
-    }
+  screen = node_get_screen (compositor->display->xdisplay, node);
+  scr_info = screen->compositor_data;
   
-  screen->compositor_windows = g_list_remove (screen->compositor_windows,
-                                              cwindow);
+  scr_info->compositor_windows = g_list_remove (scr_info->compositor_windows,
+					      node);
   
-  /* Frees cwindow as side effect */
+  /* Frees node as side effect */
   g_hash_table_remove (compositor->window_hash,
-                       &xwindow);
+		       &xwindow);
   
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 }
 
+typedef struct Info
+{
+  MetaScreen  *screen;
+  WsWindow	*window;
+} Info;
+
+static gboolean
+update (gpointer data)
+{
+  Info *info = data;
+
+  MetaScreen *screen = info->screen;
+  ScreenInfo *scr_info = screen->compositor_data;
+  WsWindow *gl_window = info->window;
+  
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  gluOrtho2D (0, 1.0, 0.0, 1.0);
+  
+  ws_window_raise (gl_window);
+  
+  glClearColor (0.0, 0.5, 0.5, 0.0);
+  glClear (GL_COLOR_BUFFER_BIT);
+  
+  glColor4f (1.0, 0.0, 0.0, 1.0);
+  
+  glDisable (GL_TEXTURE_2D);
+  
+  glBegin (GL_QUADS);
+  
+  glVertex2f (0.2, 0.2);
+  glVertex2f (0.2, 0.4);
+  glVertex2f (0.4, 0.4);
+  glVertex2f (0.4, 0.2);
+  
+  glEnd ();
+  
+  
+  glEnable (GL_TEXTURE_2D);
+  draw_windows (screen, scr_info->compositor_windows);
+  
+  /* FIXME: we should probably grab the server around the raise/swap */
+  
+  ws_window_gl_swap_buffers (gl_window);
+  
+  return TRUE;
+}
+
 void
 meta_compositor_manage_screen (MetaCompositor *compositor,
                                MetaScreen     *screen)
 {
 #ifdef HAVE_COMPOSITE_EXTENSIONS
-  XRenderPictureAttributes pa;
-  XRectangle r;
-  XRenderColor c;
+  ScreenInfo *scr_info = g_new0 (ScreenInfo, 1);
   
-  if (!compositor->enabled)
-    return; /* no extension */
-
-  /* FIXME we need to handle root window resize by recreating the
-   * root_picture
-   */
+  WsScreen *ws_screen =
+      ws_screen_get_from_number (compositor->ws, screen->number);
+  WsWindow *root = ws_screen_get_root_window (ws_screen);
+  Info *info;
+  WsRegion *region;
   
-  g_assert (screen->root_picture == None);
+  scr_info->glw = ws_window_new_gl (root);
+  scr_info->compositor_windows = NULL;
 
-  /* FIXME add flag for whether we're composite-managing each
-   * screen and detect failure here
-   */
-  XCompositeRedirectSubwindows (screen->display->xdisplay,
-                                screen->xroot,
-                                CompositeRedirectManual);
-  meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n");
-  
-  pa.subwindow_mode = IncludeInferiors;
-  
-  screen->root_picture =
-    XRenderCreatePicture (compositor->display->xdisplay,
-                          screen->xroot, 
-                          XRenderFindVisualFormat (compositor->display->xdisplay,
-                                                   DefaultVisual (compositor->display->xdisplay,
-                                                                  screen->number)),
-                          CPSubwindowMode,
-                          &pa);
-
-  g_assert (screen->root_picture != None);
-
-  screen->trans_pixmap = XCreatePixmap (compositor->display->xdisplay,
-                                        screen->xroot, 1, 1, 8);
-
-  pa.repeat = True;
-  screen->trans_picture =
-    XRenderCreatePicture (compositor->display->xdisplay,
-                          screen->trans_pixmap,
-                          XRenderFindStandardFormat (compositor->display->xdisplay,
-                                                     PictStandardA8),
-                          CPRepeat,
-                          &pa);
-  
-  c.red = c.green = c.blue = 0;
-  c.alpha = 0xc0c0;
-  XRenderFillRectangle (compositor->display->xdisplay,
-                        PictOpSrc,
-                        screen->trans_picture, &c, 0, 0, 1, 1);
-  
-  /* Damage the whole screen */
-  r.x = 0;
-  r.y = 0;
-  r.width = screen->rect.width;
-  r.height = screen->rect.height;
-
-  merge_and_destroy_damage_region (compositor,
-                                   screen,
-                                   XFixesCreateRegion (compositor->display->xdisplay,
-                                                       &r, 1));
+  g_print ("setting compositor_data for screen %p to %p\n", screen, scr_info);
+  screen->compositor_data = scr_info;
   
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+  ws_init_composite (compositor->ws);
+  ws_init_damage (compositor->ws);
+  ws_init_fixes (compositor->ws);
+  
+  ws_window_redirect_subwindows (root);
+  ws_window_set_override_redirect (scr_info->glw, TRUE);
+  ws_window_unredirect (scr_info->glw);
+  
+  region = ws_region_new (compositor->ws);
+  ws_window_set_input_shape (scr_info->glw, region);
+  ws_region_unref (region);
+  
+  ws_window_map (scr_info->glw);
+  
+  ws_sync (compositor->ws);
+  
+  info = g_new (Info, 1);
+  info->window = scr_info->glw;
+  info->screen = screen;
+  
+  g_idle_add (update,
+	      info);
+  
+#endif
 }
 
 void
 meta_compositor_unmanage_screen (MetaCompositor *compositor,
                                  MetaScreen     *screen)
 {
+  ScreenInfo *scr_info = screen->compositor_data;
+  
 #ifdef HAVE_COMPOSITE_EXTENSIONS  
   if (!compositor->enabled)
     return; /* no extension */
-
-  XRenderFreePicture (screen->display->xdisplay,
-                      screen->root_picture);
-  screen->root_picture = None;
-  XRenderFreePicture (screen->display->xdisplay,
-                      screen->trans_picture);
-  screen->trans_picture = None;
-  XFreePixmap (screen->display->xdisplay,
-               screen->trans_pixmap);
-  screen->trans_pixmap = None;
   
-  while (screen->compositor_windows != NULL)
+  while (scr_info->compositor_windows != NULL)
     {
-      MetaCompositorWindow *cwindow = screen->compositor_windows->data;
-
-      meta_topic (META_DEBUG_COMPOSITOR,
-                  "Unmanage screen for 0x%lx\n", cwindow->xwindow);
-      meta_compositor_remove_window (compositor, cwindow->xwindow);
+      DrawableNode *node = scr_info->compositor_windows->data;
+      
+      meta_compositor_remove_window (compositor, node->drawable->xid);
     }
+  /* FIXME: free scr_info */
+  
 #endif /* HAVE_COMPOSITE_EXTENSIONS */
 }
 
-void
-meta_compositor_damage_window (MetaCompositor *compositor,
-                               MetaWindow     *window)
+static DrawableNode *
+window_to_node (MetaCompositor *compositor,
+		MetaWindow *window)
 {
-#ifdef HAVE_COMPOSITE_EXTENSIONS
   Window xwindow;
-  MetaCompositorWindow *cwindow;
-
-  if (!compositor->enabled)
-    return;
-
-  if (window->screen->root_picture == None)
-    return;
+  DrawableNode *node;
   
   if (window->frame)
     xwindow = window->frame->xwindow;
   else
     xwindow = window->xwindow;
+  
+  node = g_hash_table_lookup (compositor->window_hash,
+			      &xwindow);
+  
+  return node;
+}
 
-  cwindow = g_hash_table_lookup (compositor->window_hash,
-                                 &xwindow);
-  if (cwindow == NULL)
-    return;
+typedef struct
+{
+  double x;
+  double y;
+  double width;
+  double height;
+} DoubleRect;
+
+typedef struct
+{
+  MetaWindow *window;
+  DrawableNode *node;
   
-  merge_and_destroy_damage_region (compositor,
-                                   window->screen,
-                                   window_extents (cwindow));
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+  DoubleRect start;
+  DoubleRect target;
+  
+  double start_time;
+  int idle_id;
+
+  MetaMinimizeFinishedFunc finished_func;
+  gpointer		   finished_data;
+} MiniInfo;
+
+static gdouble
+interpolate (gdouble t, gdouble begin, gdouble end, double power)
+{
+  return (begin + (end - begin) * pow (t, power));
+}
+
+static gboolean
+stop_minimize (gpointer data)
+{
+  MiniInfo *info = data;
+  
+  drawable_node_set_deformation_func (info->node, NULL, NULL);
+  
+  if (info->finished_func)
+    info->finished_func (info->finished_data);
+  
+  g_free (info);
+  
+  return FALSE;
+}
+
+static void
+minimize_deformation (gdouble time,
+		      double in_x,
+		      double in_y,
+		      double *out_x,
+		      double *out_y,
+		      gpointer data)
+{
+#define MINIMIZE_TIME 0.5
+  MiniInfo *info = data;
+  gdouble elapsed;
+  gdouble pos;
+  
+  if (info->start_time == -1)
+    info->start_time = time;
+  
+  elapsed = time - info->start_time;
+  pos = elapsed / MINIMIZE_TIME;
+  
+  *out_x = interpolate (pos, in_x, info->target.x + info->target.width * ((in_x - info->start.x)  / info->start.width), 10 * in_y);
+  *out_y = interpolate (pos, in_y, info->target.y + info->target.height * ((in_y - info->start.y)  / info->start.height), 1.0);
+  
+  if (elapsed > MINIMIZE_TIME)
+    {
+      g_assert (info->node);
+      if (!info->idle_id)
+	info->idle_id = g_idle_add (stop_minimize, info);
+    }
+}
+
+static void
+convert (MetaScreen *screen,
+	 int x, int y, int width, int height,
+	 DoubleRect *rect)
+{
+  rect->x = x / (double)screen->rect.width;
+  rect->y = y / (double)screen->rect.height;
+  rect->width = width / (double)screen->rect.width;
+  rect->height = height / (double)screen->rect.height;
+}
+
+void
+meta_compositor_minimize (MetaCompositor           *compositor,
+			  MetaWindow               *window,
+			  int                       x,
+			  int                       y,
+			  int                       width,
+			  int                       height,
+			  MetaMinimizeFinishedFunc  finished,
+			  gpointer                  data)
+{
+  MiniInfo *info = g_new (MiniInfo, 1);
+  DrawableNode *node = window_to_node (compositor, window);
+  WsRectangle start;
+  MetaScreen *screen = window->screen;
+  
+  info->node = node;
+  
+  info->idle_id = 0;
+  
+  ws_drawable_query_geometry (node->drawable, &start);
+  
+  convert (screen, start.x, start.y, start.width, start.height,
+	   &info->start);
+  convert (screen, x, y, width, height,
+	   &info->target);
+  
+  info->window = window;
+  
+  info->target.y = 1 - info->target.y;
+  
+  info->start_time = -1;
+
+  info->finished_func = finished;
+  info->finished_data = data;
+  
+  drawable_node_set_deformation_func (node, minimize_deformation, info);
+}
+
+MetaDisplay *
+meta_compositor_get_display (MetaCompositor *compositor)
+{
+  return compositor->display;
 }
Index: compositor.h
===================================================================
RCS file: /cvs/gnome/metacity/src/compositor.h,v
retrieving revision 1.3
diff -u -p -u -r1.3 compositor.h
--- compositor.h	30 Nov 2003 03:30:27 -0000	1.3
+++ compositor.h	12 Jan 2006 23:39:16 -0000
@@ -25,6 +25,10 @@
 #include "util.h"
 #include "display.h"
 
+#include <X11/extensions/Xfixes.h>
+
+typedef void (* MetaMinimizeFinishedFunc) (gpointer data);
+
 MetaCompositor* meta_compositor_new           (MetaDisplay       *display);
 void            meta_compositor_unref         (MetaCompositor    *compositor);
 void            meta_compositor_process_event (MetaCompositor    *compositor,
@@ -35,22 +39,21 @@ void            meta_compositor_add_wind
                                                XWindowAttributes *attrs);
 void            meta_compositor_remove_window (MetaCompositor    *compositor,
                                                Window             xwindow);
+void		meta_compositor_set_debug_updates (MetaCompositor *compositor,
+						   gboolean	   debug_updates);
 
 void meta_compositor_manage_screen   (MetaCompositor *compositor,
                                       MetaScreen     *screen);
 void meta_compositor_unmanage_screen (MetaCompositor *compositor,
                                       MetaScreen     *screen);
 
-void meta_compositor_damage_window   (MetaCompositor *compositor,
-                                      MetaWindow     *window);
+void meta_compositor_minimize (MetaCompositor           *compositor,
+			       MetaWindow               *window,
+			       int                       x,
+			       int                       y,
+			       int                       width,
+			       int                       height,
+			       MetaMinimizeFinishedFunc  finished_cb,
+			       gpointer                  finished_data);
 
 #endif /* META_COMPOSITOR_H */
-
-
-
-
-
-
-
-
-
Index: display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.269
diff -u -p -u -r1.269 display.c
--- display.c	10 Jan 2006 19:43:21 -0000	1.269
+++ display.c	12 Jan 2006 23:39:16 -0000
@@ -689,7 +689,22 @@ meta_display_open (const char *name)
   tmp = display->screens;
   while (tmp != NULL)
     {
-      meta_screen_manage_all_windows (tmp->data);
+      MetaScreen *screen = tmp->data;
+	
+      /* The compositing manager opens its own connection to the X server
+       * and uses the XTest extension to ignore grabs. However, it also
+       * uses GL which opens yet another connection to the X server. With
+       * this ungrab/grab we would block indefinitely in XOpenDisplay().
+       */
+      meta_display_ungrab (display);
+      
+      meta_compositor_manage_screen (screen->display->compositor,
+				     screen);
+
+      meta_display_grab (display);
+  
+      meta_screen_manage_all_windows (screen);
+
       tmp = tmp->next;
     }
 
@@ -811,7 +826,7 @@ void
 meta_display_close (MetaDisplay *display)
 {
   GSList *tmp;
-  
+
   if (display->error_traps > 0)
     meta_bug ("Display closed with error traps pending\n");
 
@@ -3456,12 +3471,6 @@ meta_display_begin_grab_op (MetaDisplay 
   if (display->grab_window)
     {
       meta_window_refresh_resize_popup (display->grab_window);
-
-      /* repaint window in case we draw it differently
-       * when grabbed
-       */
-      meta_compositor_damage_window (display->compositor,
-                                     display->grab_window);
     }
   
   return TRUE;
@@ -3574,13 +3583,6 @@ meta_display_end_grab_op (MetaDisplay *d
       display->grab_sync_request_alarm = None;
     }
 #endif /* HAVE_XSYNC */
-
-  /* repaint window in case the grab op drew it in a
-   * nonstandard way such as transparent or wireframe
-   */
-  if (display->grab_window != NULL)
-    meta_compositor_damage_window (display->compositor,
-                                   display->grab_window);
   
   display->grab_window = NULL;
   display->grab_screen = NULL;
Index: errors.c
===================================================================
RCS file: /cvs/gnome/metacity/src/errors.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 errors.c
--- errors.c	4 Nov 2002 00:56:12 -0000	1.12
+++ errors.c	12 Jan 2006 23:39:16 -0000
@@ -97,7 +97,6 @@ meta_error_trap_pop_internal  (MetaDispl
                                       XErrorEvent *);
 
       restored_error_handler = XSetErrorHandler (x_error_handler);
-      g_assert (restored_error_handler == x_error_handler);
 
       /* remove this */
       display->error_trap_handler = NULL;
@@ -183,8 +182,11 @@ x_error_handler (Display     *xdisplay,
   XGetErrorText (xdisplay, error->error_code, buf, 63);  
 
   display = meta_display_for_x_display (xdisplay);
-  
-  if (display->error_traps > 0)
+
+  /* Display can be NULL here because the compositing manager
+   * has its own Display, but Xlib only has one global error handler
+   */
+  if (display && display->error_traps > 0)
     {
       /* we're in an error trap, chain to the trap handler
        * saved from GDK
Index: screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.149
diff -u -p -u -r1.149 screen.c
--- screen.c	10 Jan 2006 19:43:21 -0000	1.149
+++ screen.c	12 Jan 2006 23:39:16 -0000
@@ -534,13 +534,8 @@ meta_screen_new (MetaDisplay *display,
   screen->columns_of_workspaces = -1;
   screen->vertical_workspaces = FALSE;
   screen->starting_corner = META_SCREEN_TOPLEFT;
+  screen->compositor_data = NULL;
 
-  screen->compositor_windows = NULL;
-  screen->damage_region = None;
-  screen->root_picture = None;
-  screen->trans_pixmap = None;
-  screen->trans_picture = None;
-  
   {
     XFontStruct *font_info;
     XGCValues gc_values;
@@ -652,9 +647,6 @@ meta_screen_new (MetaDisplay *display,
       meta_workspace_activate (space, timestamp);
   }
 
-  meta_compositor_manage_screen (screen->display->compositor,
-                                 screen);
-  
   meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
                 screen->number, screen->screen_name, screen->xroot);
   
Index: screen.h
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.h,v
retrieving revision 1.68
diff -u -p -u -r1.68 screen.h
--- screen.h	10 Jan 2006 19:43:21 -0000	1.68
+++ screen.h	12 Jan 2006 23:39:16 -0000
@@ -116,12 +116,8 @@ struct _MetaScreen
   /* gc for XOR on root window */
   GC root_xor_gc;
 
-  /* Managed by compositor.c; top of stack is first in list */
-  GList *compositor_windows;
-  XID root_picture;
-  XID damage_region;
-  XID trans_pixmap;
-  XID trans_picture;
+  /* Managed by compositor.c */
+  gpointer compositor_data;
 };
 
 MetaScreen*   meta_screen_new                 (MetaDisplay                *display,
Index: window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.409
diff -u -p -u -r1.409 window.c
--- window.c	10 Jan 2006 19:43:21 -0000	1.409
+++ window.c	12 Jan 2006 23:39:17 -0000
@@ -71,7 +71,6 @@ static void     send_configure_notify   
 static gboolean process_property_notify   (MetaWindow     *window,
                                            XPropertyEvent *event);
 static void     meta_window_show          (MetaWindow     *window);
-static void     meta_window_hide          (MetaWindow     *window);
 
 static void     meta_window_save_rect         (MetaWindow    *window);
 
@@ -114,6 +113,7 @@ static void meta_window_update_icon_now 
 void meta_window_unqueue_update_icon    (MetaWindow *window);
 void meta_window_flush_update_icon      (MetaWindow *window);
 
+static void meta_window_hide (MetaWindow *window);
 static gboolean queue_calc_showing_func (MetaWindow *window,
                                          void       *data);
 
@@ -1313,6 +1313,21 @@ meta_window_should_be_showing (MetaWindo
 }
 
 static void
+finish_minimize (gpointer data)
+{
+  MetaWindow *window = data;
+  
+  meta_window_hide (window);
+  if (window->has_focus)
+    {
+      meta_workspace_focus_default_window
+	(window->screen->active_workspace,
+	 window,
+	 meta_display_get_current_time_roundtrip (window->display));
+    }
+}
+
+static void
 implement_showing (MetaWindow *window,
                    gboolean    showing)
 {
@@ -1354,16 +1369,34 @@ implement_showing (MetaWindow *window,
             }
 
           meta_window_get_outer_rect (window, &window_rect);
-          
-          /* Draw a nice cool animation */
-          meta_effects_draw_box_animation (window->screen,
-                                           &window_rect,
-                                           &icon_rect,
-                                           META_MINIMIZE_ANIMATION_LENGTH,
-                                           META_BOX_ANIM_SCALE);
-	}
 
-      meta_window_hide (window);
+	  if (window->display->compositor)
+	    {
+	      /* Draw a nice cool animation */
+	      meta_compositor_minimize (window->display->compositor,
+					window,
+					icon_rect.x,
+					icon_rect.y,
+					icon_rect.width,
+					icon_rect.height,
+					finish_minimize,
+					window);
+	    }
+	  else
+	    {
+	      meta_effects_draw_box_animation (window->screen,
+					       &window_rect,
+					       &icon_rect,
+					       META_MINIMIZE_ANIMATION_LENGTH,
+					       META_BOX_ANIM_SCALE);
+
+	      finish_minimize (window);
+	  }
+	}
+      else
+	{
+	  finish_minimize (window);
+	}
     }
   else
     {
@@ -2000,7 +2033,7 @@ meta_window_show (MetaWindow *window)
     }
 }
 
-void
+static void
 meta_window_hide (MetaWindow *window)
 {
   gboolean did_hide;
@@ -2078,7 +2111,6 @@ meta_window_minimize (MetaWindow  *windo
           meta_topic (META_DEBUG_FOCUS,
                       "Focusing default window due to minimization of focus window %s\n",
                       window->desc);
-          meta_workspace_focus_default_window (window->screen->active_workspace, window, meta_display_get_current_time_roundtrip (window->display));
         }
       else
         {


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