Save ConfigureNotify events for unmapped windows until the window maps. If a window...
authorDana Jansens <danakj@orodu.net>
Fri, 15 Feb 2008 05:55:17 +0000 (00:55 -0500)
committerDana Jansens <danakj@orodu.net>
Fri, 15 Feb 2008 16:12:54 +0000 (11:12 -0500)
A window can move/resize while it is fading out.  Even if you don't delete the pixmap in that case, the fade-out will be shown in the wrong place and the wrong area on screen will be marked damaged when the window is gone without this patch.

xcompmgr.c

index 41cc3bd..f9d101c 100644 (file)
@@ -101,6 +101,9 @@ typedef struct _win {
     wintype             windowType;
     unsigned long      damage_sequence;    /* sequence when damage was created */
 
+    Bool                need_configure;
+    XConfigureEvent     queue_configure;
+
     /* for drawing translucent windows */
     XserverRegion      borderClip;
     struct _win                *prev_trans;
@@ -1281,6 +1284,9 @@ static unsigned int
 get_opacity_prop (Display *dpy, win *w, unsigned int def);
 
 static void
+configure_win (Display *dpy, XConfigureEvent *ce);
+
+static void
 map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
 {
     win                *w = find_win (dpy, id);
@@ -1289,19 +1295,18 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
        return;
 
     w->a.map_state = IsViewable;
-    
-    /* This needs to be here or else we lose transparency messages */
-    XSelectInput (dpy, id, PropertyChangeMask);
-
-    /* This needs to be here since we don't get PropertyNotify when unmapped */
-    w->opacity = get_opacity_prop (dpy, w, OPAQUE);
-    determine_mode (dpy, w);
 
     w->windowType = determine_wintype (dpy, w->id, w->id);
 #if 0
     printf("window 0x%x type %s\n", w->id, wintype_name(w->windowType));
 #endif
 
+    /* select before reading the property so that no property changes are lost */
+    XSelectInput (dpy, id, PropertyChangeMask);
+    w->opacity = get_opacity_prop (dpy, w, OPAQUE);
+
+    determine_mode (dpy, w);
+
 #if CAN_DO_USABLE
     w->damage_bounds.x = w->damage_bounds.y = 0;
     w->damage_bounds.width = w->damage_bounds.height = 0;
@@ -1310,6 +1315,11 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
 
     if (fade && winTypeFade[w->windowType])
        set_fade (dpy, w, 0, get_opacity_percent (dpy, w), fade_in_step, 0, True, True);
+
+    /* if any configure events happened while the window was unmapped, then
+       configure the window to its correct place */
+    if (w->need_configure)
+        configure_win (dpy, &w->queue_configure);
 }
 
 static void
@@ -1340,10 +1350,6 @@ finish_unmap_win (Display *dpy, win *w)
        w->picture = None;
     }
 
-    /* don't care about properties anymore */
-    set_ignore (dpy, NextRequest (dpy));
-    XSelectInput(dpy, w->id, 0);
-
     if (w->borderSize)
     {
        set_ignore (dpy, NextRequest (dpy));
@@ -1379,6 +1385,11 @@ unmap_win (Display *dpy, Window id, Bool fade)
     if (!w)
        return;
     w->a.map_state = IsUnmapped;
+
+    /* don't care about properties anymore */
+    set_ignore (dpy, NextRequest (dpy));
+    XSelectInput(dpy, w->id, 0);
+
 #if HAS_NAME_WINDOW_PIXMAP
     if (w->pixmap && fade && winTypeFade[w->windowType])
        set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, True);
@@ -1526,6 +1537,7 @@ add_win (Display *dpy, Window id, Window prev)
     new->shadow_width = 0;
     new->shadow_height = 0;
     new->opacity = OPAQUE;
+    new->need_configure = False;
 
     new->borderClip = None;
     new->prev_trans = 0;
@@ -1586,50 +1598,59 @@ configure_win (Display *dpy, XConfigureEvent *ce)
        }
        return;
     }
+
+    if (w->a.map_state == IsUnmapped) {
+        /* save the configure event for when the window maps */
+        w->need_configure = True;
+        w->queue_configure = *ce;
+    }
+    else {
+        w->need_configure = False;
+
 #if CAN_DO_USABLE
-    if (w->usable)
+        if (w->usable)
 #endif
-    {
-       damage = XFixesCreateRegion (dpy, 0, 0);
-       if (w->extents != None) 
-           XFixesCopyRegion (dpy, damage, w->extents);
-    }
-    w->a.x = ce->x;
-    w->a.y = ce->y;
-    /* Only destroy the pixmap if the window is mapped */
-    if (w->a.map_state != IsUnmapped &&
-        (w->a.width != ce->width || w->a.height != ce->height))
-    {
+        {
+            damage = XFixesCreateRegion (dpy, 0, 0);
+            if (w->extents != None)
+                XFixesCopyRegion (dpy, damage, w->extents);
+        }
+
+        w->a.x = ce->x;
+        w->a.y = ce->y;
+        if (w->a.width != ce->width || w->a.height != ce->height)
+        {
 #if HAS_NAME_WINDOW_PIXMAP
-       if (w->pixmap)
-       {
-           XFreePixmap (dpy, w->pixmap);
-           w->pixmap = None;
-           if (w->picture)
-           {
-               XRenderFreePicture (dpy, w->picture);
-               w->picture = None;
-           }
-       }
+            if (w->pixmap)
+            {
+                XFreePixmap (dpy, w->pixmap);
+                w->pixmap = None;
+                if (w->picture)
+                {
+                    XRenderFreePicture (dpy, w->picture);
+                    w->picture = None;
+                }
+            }
 #endif
-       if (w->shadow)
-       {
-           XRenderFreePicture (dpy, w->shadow);
-           w->shadow = None;
-       }
+            if (w->shadow)
+            {
+                XRenderFreePicture (dpy, w->shadow);
+                w->shadow = None;
+            }
+        }
+        w->a.width = ce->width;
+        w->a.height = ce->height;
+        w->a.border_width = ce->border_width;
+        if (w->a.map_state != IsUnmapped && damage)
+        {
+            XserverRegion      extents = win_extents (dpy, w);
+            XFixesUnionRegion (dpy, damage, damage, extents);
+            XFixesDestroyRegion (dpy, extents);
+            add_damage (dpy, damage);
+        }
     }
-    w->a.width = ce->width;
-    w->a.height = ce->height;
-    w->a.border_width = ce->border_width;
     w->a.override_redirect = ce->override_redirect;
     restack_win (dpy, w, ce->above);
-    if (w->a.map_state != IsUnmapped && damage)
-    {
-       XserverRegion   extents = win_extents (dpy, w);
-       XFixesUnionRegion (dpy, damage, damage, extents);
-       XFixesDestroyRegion (dpy, extents);
-       add_damage (dpy, damage);
-    }
     clipChanged = True;
 }
 
@@ -1676,6 +1697,7 @@ finish_destroy_win (Display *dpy, Window id)
                XDamageDestroy (dpy, w->damage);
                w->damage = None;
            }
+
            cleanup_fade (dpy, w);
            free (w);
            break;
@@ -1694,6 +1716,7 @@ static void
 destroy_win (Display *dpy, Window id, Bool fade)
 {
     win *w = find_win (dpy, id);
+
 #if HAS_NAME_WINDOW_PIXMAP
     if (w && w->pixmap && fade && winTypeFade[w->windowType])
        set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step,