[PATCH 3/3] xcompmgr: fix window adding with re-used window ids

Forest Bond forest.bond at outpostembedded.com
Sat Jun 12 15:39:59 PDT 2010


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 <forest at alittletooquiet.net>
---
 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.x.org/archives/xorg-devel/attachments/20100612/7e66d05e/attachment.pgp>


More information about the xorg-devel mailing list