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
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