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