The X server can re-use window ids once a window has been destroyed.
However, xcompmgr does not forget about window ids until after the
window has finished fading out.  If a window is destroyed and a new
window with the same id is added before the first window fades out,
the new window never appears because xcompmgr has two win structures
with the same window id and chooses the wrong one to map.  This patch
fixes this problem by tracking which windows have been destroyed and
looking only at windows that have not been destroyed when matching
window ids from the server.

Signed-off-by: Forest Bond <[email protected]>
---
 xcompmgr.c |  150 +++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 99 insertions(+), 51 deletions(-)

diff --git a/xcompmgr.c b/xcompmgr.c
index 47f5667..d25323d 100644
--- a/xcompmgr.c
+++ b/xcompmgr.c
@@ -67,6 +67,7 @@ typedef struct _win {
     Bool               usable;             /* mapped and all damaged at one 
point */
     XRectangle         damage_bounds;      /* bounds of damage */
 #endif
+    int                        destroyed;
     int                        mode;
     int                        damaged;
     Damage             damage;
@@ -156,6 +157,7 @@ static conv         *gaussianMap;
 
 #define TRANS_OPACITY  0.75
 
+#define DEBUG_WINDWS 0
 #define DEBUG_REPAINT 0
 #define DEBUG_EVENTS 0
 #define MONITOR_REPAINT 0
@@ -751,7 +753,7 @@ find_win (Display *dpy, Window id)
     win        *w;
 
     for (w = list; w; w = w->next)
-       if (w->id == id)
+       if ((!w->destroyed) && (w->id == id))
            return w;
     return NULL;
 }
@@ -948,12 +950,20 @@ paint_all (Display *dpy, XserverRegion region)
            continue;
 #endif
        /* never painted, ignore it */
-       if ((!screen_damaged) && (!w->damaged))
+       if ((!screen_damaged) && (!w->damaged)) {
+#if DEBUG_REPAINT
+           printf(" [not damaged: 0x%x]", w->id);
+#endif
            continue;
+       }
        /* if invisible, ignore it */
        if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
-           || w->a.x >= root_width || w->a.y >= root_height)
+           || w->a.x >= root_width || w->a.y >= root_height) {
+#if DEBUG_REPAINT
+           printf(" [invisible: 0x%x]", w->id);
+#endif
            continue;
+       }
        if (!w->picture)
        {
            XRenderPictureAttributes    pa;
@@ -974,7 +984,7 @@ paint_all (Display *dpy, XserverRegion region)
                                               &pa);
        }
 #if DEBUG_REPAINT
-       printf (" 0x%x", w->id);
+       printf (" [painting 0x%x]", w->id);
 #endif
        if (clipChanged)
        {
@@ -1177,6 +1187,10 @@ map_win (Display *dpy, Window id, unsigned long 
sequence, Bool fade)
 {
     win                *w = find_win (dpy, id);
 
+#if DEBUG_WINDOWS
+    printf("map_win: 0x%x\n", w->id);
+#endif
+
     if (!w)
        return;
 
@@ -1202,6 +1216,9 @@ map_win (Display *dpy, Window id, unsigned long sequence, 
Bool fade)
 static void
 finish_unmap_win (Display *dpy, win *w)
 {
+#if DEBUG_WINDOWS
+    printf("finish_unmap_win: 0x%x\n", w->id);
+#endif
     w->damaged = 0;
 #if CAN_DO_USABLE
     w->usable = False;
@@ -1263,6 +1280,11 @@ static void
 unmap_win (Display *dpy, Window id, Bool fade)
 {
     win *w = find_win (dpy, id);
+
+#if DEBUG_WINDOWS
+    printf("unmap_win: 0x%x\n", w->id);
+#endif
+
     if (!w)
        return;
     w->a.map_state = IsUnmapped;
@@ -1427,12 +1449,16 @@ add_win (Display *dpy, Window id, Window prev)
     win                                *new = malloc (sizeof (win));
     win                                **p;
     
+#if DEBUG_WINDOWS
+    printf("add_win: 0x%x\n", id);
+#endif
+
     if (!new)
        return;
     if (prev)
     {
        for (p = &list; *p; p = &(*p)->next)
-           if ((*p)->id == prev)
+           if ((!(*p)->destroyed) && ((*p)->id == prev))
                break;
     }
     else
@@ -1442,8 +1468,12 @@ add_win (Display *dpy, Window id, Window prev)
     if (!XGetWindowAttributes (dpy, id, &new->a))
     {
        free (new);
+#if DEBUG_WINDOWS
+       printf("not adding 0x%x: failed to get attributes\n", new->id);
+#endif
        return;
     }
+    new->destroyed = 0;
     new->damaged = 0;
 #if CAN_DO_USABLE
     new->usable = False;
@@ -1489,6 +1519,10 @@ restack_win (Display *dpy, win *w, Window new_above)
 {
     Window  old_above;
     
+#if DEBUG_WINDOWS
+    printf("restack_win: 0x%x\n", w->id);
+#endif
+
     if (w->next)
        old_above = w->next->id;
     else
@@ -1506,7 +1540,7 @@ restack_win (Display *dpy, win *w, Window new_above)
        /* rehook */
        for (prev = &list; *prev; prev = &(*prev)->next)
        {
-           if ((*prev)->id == new_above)
+           if ((!(*prev)->destroyed) && ((*prev)->id == new_above))
                break;
        }
        w->next = *prev;
@@ -1597,54 +1631,61 @@ circulate_win (Display *dpy, XCirculateEvent *ce)
 }
 
 static void
-finish_destroy_win (Display *dpy, Window id, Bool gone)
+finish_destroy_win (Display *dpy, win *w, Bool gone)
 {
-    win        **prev, *w;
+    win *prev;
 
-    for (prev = &list; (w = *prev); prev = &w->next)
-       if (w->id == id)
-       {
-           if (gone)
-               finish_unmap_win (dpy, w);
-           *prev = w->next;
-           if (w->picture)
-           {
-               set_ignore (dpy, NextRequest (dpy));
-               XRenderFreePicture (dpy, w->picture);
-               w->picture = None;
-           }
-           if (w->alphaPict)
-           {
-               XRenderFreePicture (dpy, w->alphaPict);
-               w->alphaPict = None;
-           }
-           if (w->shadowPict)
-           {
-               XRenderFreePicture (dpy, w->shadowPict);
-               w->shadowPict = None;
-           }
-           if (w->shadow)
-           {
-               XRenderFreePicture (dpy, w->shadow);
-               w->shadow = None;
-           }
-           if (w->damage != None)
-           {
-               set_ignore (dpy, NextRequest (dpy));
-               XDamageDestroy (dpy, w->damage);
-               w->damage = None;
-           }
-           cleanup_fade (dpy, w);
-           free (w);
+#if DEBUG_WINDOWS
+    printf("finish_destroy_win: 0x%x\n", w->id);
+#endif
+
+    for (prev = list; prev; prev = prev->next)
+       if (prev->next == w)
            break;
-       }
+
+    if (! prev)
+       /* Couldn't find the window? */
+       return;
+
+    if (gone)
+       finish_unmap_win (dpy, w);
+    prev->next = w->next;
+    if (w->picture)
+    {
+       set_ignore (dpy, NextRequest (dpy));
+       XRenderFreePicture (dpy, w->picture);
+       w->picture = None;
+    }
+    if (w->alphaPict)
+    {
+       XRenderFreePicture (dpy, w->alphaPict);
+       w->alphaPict = None;
+    }
+    if (w->shadowPict)
+    {
+       XRenderFreePicture (dpy, w->shadowPict);
+       w->shadowPict = None;
+    }
+    if (w->shadow)
+    {
+       XRenderFreePicture (dpy, w->shadow);
+       w->shadow = None;
+    }
+    if (w->damage != None)
+    {
+       set_ignore (dpy, NextRequest (dpy));
+       XDamageDestroy (dpy, w->damage);
+       w->damage = None;
+    }
+    cleanup_fade (dpy, w);
+    free (w);
 }
 
 #if HAS_NAME_WINDOW_PIXMAP
 static void
 destroy_callback (Display *dpy, win *w, Bool gone)
 {
-    finish_destroy_win (dpy, w->id, gone);
+    finish_destroy_win (dpy, w, gone);
 }
 #endif
 
@@ -1652,22 +1693,27 @@ static void
 destroy_win (Display *dpy, Window id, Bool gone, Bool fade)
 {
     win *w = find_win (dpy, id);
+#if DEBUG_WINDOWS
+    printf("destroy_win: 0x%x\n", w->id);
+#endif
+    w->destroyed = 1;
 #if HAS_NAME_WINDOW_PIXMAP
     if (w && w->pixmap && fade && fadeWindows)
        set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, 
destroy_callback, gone, False, True);
     else
 #endif
     {
-       finish_destroy_win (dpy, id, gone);
+       finish_destroy_win (dpy, w, gone);
     }
 }
 
-/*
+#if DEBUG_WINDOWS
 static void
 dump_win (win *w)
 {
-    printf ("\t%08lx: %d x %d + %d + %d (%d)\n", w->id,
-           w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width);
+    printf ("\t%08lx: %d x %d + %d + %d (%d)%s\n", w->id,
+           w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width,
+           w->destroyed ? " (destroyed)" : "");
 }
 
 
@@ -1680,7 +1726,7 @@ dump_wins (void)
     for (w = list; w; w = w->next)
        dump_win (w);
 }
-*/
+#endif
 
 static void
 damage_win (Display *dpy, XDamageNotifyEvent *de)
@@ -2128,7 +2174,9 @@ main (int argc, char **argv)
        paint_all (dpy, None);
     for (;;)
     {
-       /*      dump_wins (); */
+#if DEBUG_WINDOWS
+       dump_wins ();
+#endif
        do {
            if (autoRedirect)
                XFlush (dpy);
-- 
1.7.0.4

Attachment: signature.asc
Description: Digital signature

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to