Allow the user to specify offsets for server-side (hard) shadows.
[dana/xcompmgr.git] / xcompmgr.c
index f9d101c..c3a76cb 100644 (file)
@@ -100,6 +100,7 @@ typedef struct _win {
     unsigned int       opacity;
     wintype             windowType;
     unsigned long      damage_sequence;    /* sequence when damage was created */
+    Bool                destroyed;
 
     Bool                need_configure;
     XConfigureEvent     queue_configure;
@@ -312,8 +313,19 @@ set_fade (Display *dpy, win *w, double start, double finish, double step,
     {
        XRenderFreePicture (dpy, w->shadow);
        w->shadow = None;
-       w->extents = win_extents (dpy, w);
+
+        if (w->extents != None)
+            XFixesDestroyRegion (dpy, w->extents);
+
+        /* rebuild the shadow */
+        w->extents = win_extents (dpy, w);
     }
+
+    /* fading windows need to be drawn, mark them as damaged.
+       when a window maps, if it tries to fade in but it already at the right
+       opacity (map/unmap/map fast) then it will never get drawn without this
+       until it repaints */
+    w->damaged = 1;
 }
 
 int
@@ -382,6 +394,11 @@ run_fades (Display *dpy)
        {
            XRenderFreePicture (dpy, w->shadow);
            w->shadow = None;
+
+            if (w->extents != None)
+                XFixesDestroyRegion (dpy, w->extents);
+
+            /* rebuild the shadow */
            w->extents = win_extents(dpy, w);
        }
        /* Must do this last as it might destroy f->w in callbacks */
@@ -763,7 +780,7 @@ find_win (Display *dpy, Window id)
     win        *w;
 
     for (w = list; w; w = w->next)
-       if (w->id == id)
+       if (w->id == id && !w->destroyed)
            return w;
     return 0;
 }
@@ -852,8 +869,8 @@ win_extents (Display *dpy, win *w)
 
            if (compMode == CompServerShadows)
            {
-               w->shadow_dx = 2;
-               w->shadow_dy = 7;
+               w->shadow_dx = shadowOffsetX;
+               w->shadow_dy = shadowOffsetY;
                w->shadow_width = w->a.width;
                w->shadow_height = w->a.height;
            }
@@ -973,8 +990,10 @@ paint_all (Display *dpy, XserverRegion region)
            Drawable                    draw = w->id;
            
 #if HAS_NAME_WINDOW_PIXMAP
-           if (hasNamePixmap && !w->pixmap)
-               w->pixmap = XCompositeNameWindowPixmap (dpy, w->id);
+           if (hasNamePixmap && !w->pixmap) {
+                set_ignore (dpy, NextRequest (dpy));
+                w->pixmap = XCompositeNameWindowPixmap (dpy, w->id);
+            }
            if (w->pixmap)
                draw = w->pixmap;
 #endif
@@ -1497,7 +1516,7 @@ add_win (Display *dpy, Window id, Window prev)
     if (prev)
     {
        for (p = &list; *p; p = &(*p)->next)
-           if ((*p)->id == prev)
+           if ((*p)->id == prev && !(*p)->destroyed)
                break;
     }
     else
@@ -1525,6 +1544,7 @@ add_win (Display *dpy, Window id, Window prev)
     else
     {
        new->damage_sequence = NextRequest (dpy);
+        set_ignore (dpy, NextRequest (dpy));
        new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty);
     }
     new->alphaPict = None;
@@ -1537,6 +1557,7 @@ add_win (Display *dpy, Window id, Window prev)
     new->shadow_width = 0;
     new->shadow_height = 0;
     new->opacity = OPAQUE;
+    new->destroyed = False;
     new->need_configure = False;
 
     new->borderClip = None;
@@ -1570,7 +1591,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)->id == new_above && !(*prev)->destroyed)
                break;
        }
        w->next = *prev;
@@ -1648,10 +1669,12 @@ configure_win (Display *dpy, XConfigureEvent *ce)
             XFixesDestroyRegion (dpy, extents);
             add_damage (dpy, damage);
         }
+
+        clipChanged = True;
     }
+
     w->a.override_redirect = ce->override_redirect;
     restack_win (dpy, w, ce->above);
-    clipChanged = True;
 }
 
 static void
@@ -1677,7 +1700,7 @@ finish_destroy_win (Display *dpy, Window id)
     win        **prev, *w;
 
     for (prev = &list; (w = *prev); prev = &w->next)
-       if (w->id == id)
+       if (w->id == id && w->destroyed)
        {
             finish_unmap_win (dpy, w);
            *prev = w->next;
@@ -1717,10 +1740,12 @@ destroy_win (Display *dpy, Window id, Bool fade)
 {
     win *w = find_win (dpy, id);
 
+    if (w) w->destroyed = True;
+
 #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,
-                  destroy_callback, False, (w->a.map_state != IsUnmapped));
+                  destroy_callback, False, True);
     else
 #endif
     {
@@ -1920,8 +1945,8 @@ usage (char *program)
     fprintf (stderr, "   -d display\n      Specifies which display should be managed.\n");
     fprintf (stderr, "   -r radius\n      Specifies the blur radius for client-side shadows. (default 12)\n");
     fprintf (stderr, "   -o opacity\n      Specifies the translucency for client-side shadows. (default .75)\n");
-    fprintf (stderr, "   -l left-offset\n      Specifies the left offset for client-side shadows. (default -15)\n");
-    fprintf (stderr, "   -t top-offset\n      Specifies the top offset for clinet-side shadows. (default -15)\n");
+    fprintf (stderr, "   -l left-offset\n      Specifies the left offset for shadows. (default -15)\n");
+    fprintf (stderr, "   -t top-offset\n      Specifies the top offset for shadows. (default -15)\n");
     fprintf (stderr, "   -I fade-in-step\n      Specifies the opacity change between steps while fading in. (default 0.028)\n");
     fprintf (stderr, "   -O fade-out-step\n      Specifies the opacity change between steps while fading out. (default 0.03)\n");
     fprintf (stderr, "   -D fade-delta-time\n      Specifies the time between steps in a fade in milliseconds. (default 10)\n");
@@ -2279,12 +2304,17 @@ main (int argc, char **argv)
                                      fade_out_step, 0, True, False);
                        else
                        {
-                       w->opacity = get_opacity_prop(dpy, w, OPAQUE);
-                       determine_mode(dpy, w);
+                            w->opacity = get_opacity_prop(dpy, w, OPAQUE);
+                            determine_mode(dpy, w);
                            if (w->shadow)
                            {
                                XRenderFreePicture (dpy, w->shadow);
                                w->shadow = None;
+
+                                if (w->extents != None)
+                                    XFixesDestroyRegion (dpy, w->extents);
+
+                                /* rebuild the shadow */
                                w->extents = win_extents (dpy, w);
                            }
                        }