[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