The X server can re-use window ids once a window has been destroyed.
However, window ids persist in xcompmgr until the window has finished
fading out.  As a result, xcompmgr can have multiple win structures
with the same window id.

If a window is destroyed and a new window with the same id is added
and subsequently mapped before the first window fades out, xcompmgr
finds the wrong win structure and tries to map the destroyed window,
failing due to X errors.  The new window is never mapped and never
appears.

This patch fixes this problem by adding a "destroyed" field to the win
structure and only considering non-destroyed windows when matching wins
on window id.

Signed-off-by: Forest Bond <for...@alittletooquiet.net>
---
 xcompmgr.c |   99 ++++++++++++++++++++++++++++++++----------------------------
 1 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/xcompmgr.c b/xcompmgr.c
index a345bbe..c5a7dea 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;
@@ -753,7 +754,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;
 }
@@ -1456,7 +1457,7 @@ add_win (Display *dpy, Window id, Window prev)
     if (prev)
     {
        for (p = &list; *p; p = &(*p)->next)
-           if ((*p)->id == prev)
+           if ((!(*p)->destroyed) && ((*p)->id == prev))
                break;
     }
     else
@@ -1471,6 +1472,7 @@ add_win (Display *dpy, Window id, Window prev)
 #endif
        return;
     }
+    new->destroyed = 0;
     new->damaged = 0;
 #if CAN_DO_USABLE
     new->usable = False;
@@ -1537,7 +1539,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;
@@ -1628,58 +1630,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;
 
 #if DEBUG_WINDOWS
-    printf ("finish_destroy_win: 0x%x\n", id);
+    printf ("finish_destroy_win: 0x%x\n", w->id);
 #endif
 
-    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);
+    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
 
@@ -1690,13 +1695,14 @@ destroy_win (Display *dpy, Window id, Bool gone, Bool 
fade)
 #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);
     }
 }
 
@@ -1704,8 +1710,9 @@ destroy_win (Display *dpy, Window id, Bool gone, Bool 
fade)
 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)" : "");
 }
 
 
-- 
1.7.0.4

Attachment: signature.asc
Description: Digital signature

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to