More effects, bug fixes, doc updates. XCOMPMGR_1_0
authorAdam Jackson <ajax@nwnk.net>
Fri, 10 Sep 2004 05:55:19 +0000 (05:55 +0000)
committerAdam Jackson <ajax@nwnk.net>
Fri, 10 Sep 2004 05:55:19 +0000 (05:55 +0000)
ChangeLog
Makefile.am
xcompmgr.1 [moved from xcompmgr.man with 62% similarity]
xcompmgr.c

index dfa1cc7..f9abcd0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-09-10  Adam Jackson  <ajax@freedesktop.org>
+
+       * xcompmgr.c:
+       Bug fixes and more pretty effects from Dan Doel.
+       * xcompmgr.1, Makefile.am:
+       More doc, fix the suffix so the man page installs in a sane place.
+
 2004-09-08  Adam Jackson  <ajax@freedesktop.org>
 
        * xcompmgr.man, Makefile.am:
 2004-09-08  Adam Jackson  <ajax@freedesktop.org>
 
        * xcompmgr.man, Makefile.am:
index 96c4dfd..aee1748 100644 (file)
@@ -1,5 +1,5 @@
 bin_PROGRAMS = xcompmgr
 bin_PROGRAMS = xcompmgr
-man_MANS = xcompmgr.man
+man_MANS = xcompmgr.1
 
 xcompmgr_LDADD = @XCOMPMGR_LIBS@ -lm
 
 
 xcompmgr_LDADD = @XCOMPMGR_LIBS@ -lm
 
similarity index 62%
rename from xcompmgr.man
rename to xcompmgr.1
index 9646b5f..d5d43d8 100644 (file)
@@ -4,7 +4,7 @@
 xcompmgr \- sample X compositing manager
 .SH SYNOPSIS
 .nf
 xcompmgr \- sample X compositing manager
 .SH SYNOPSIS
 .nf
-.B xcompmgr [\-acfns]
+.B xcompmgr [\-d display] [\-acfnsCFS]
 .fi
 .SH DESCRIPTION
 .B xcompmgr
 .fi
 .SH DESCRIPTION
 .B xcompmgr
@@ -12,6 +12,9 @@ is a sample compositing manager for X servers supporting the XFIXES, DAMAGE,
 and COMPOSITE extensions.  It enables basic eye-candy effects.
 .SH OPTIONS
 .TP
 and COMPOSITE extensions.  It enables basic eye-candy effects.
 .SH OPTIONS
 .TP
+.BI \-d\ display
+Specifies the display to manage.
+.TP
 .BI \-a
 Automatic server-side compositing.  This instructs the server to use the
 standard composition rules.  Useful for debugging.
 .BI \-a
 Automatic server-side compositing.  This instructs the server to use the
 standard composition rules.  Useful for debugging.
@@ -21,15 +24,25 @@ Client-side compositing with soft shadows and translucency support.
 .TP
 .BI \-f
 When \-c is specified, enables a smooth fade effect for transient windows like
 .TP
 .BI \-f
 When \-c is specified, enables a smooth fade effect for transient windows like
-menus.
+menus, and for all windows on hide and restore events.
 .TP
 .BI \-n
 Simple client-side compositing.
 .TP
 .BI \-s
 Server-side compositing with hard-edged shadows.
 .TP
 .BI \-n
 Simple client-side compositing.
 .TP
 .BI \-s
 Server-side compositing with hard-edged shadows.
+.TP
+.BI \-C
+When \-c is specified, attempts to avoid painting shadows on panels and docks.
+.TP
+.BI \-F
+When \-f is specified, also enables the fade effect when windows change their
+opacity, as with transset(1).
+.TP
+.BI \-S
+Enables synchronous operation.  Useful for debugging.
 .SH BUGS
 .SH BUGS
-Several.
+Probably.  Please report any you find to http://bugs.freedesktop.org/.
 .SH AUTHORS
 .SH AUTHORS
-Keith Packard, with contributions from Matthew Allum, Eric Anholt,
+Keith Packard, with contributions from Matthew Allum, Eric Anholt, Dan Doel,
 Matthew Hawn, Ely Levy, Phil Blundell, and Carl Worth.
 Matthew Hawn, Ely Levy, Phil Blundell, and Carl Worth.
index 3d78783..122d8b4 100644 (file)
@@ -79,7 +79,7 @@ typedef struct _win {
     int                        shadow_width;
     int                        shadow_height;
     unsigned int       opacity;
     int                        shadow_width;
     int                        shadow_height;
     unsigned int       opacity;
-
+    Atom                windowType;
     unsigned long      damage_sequence;    /* sequence when damage was created */
 
     /* for drawing translucent windows */
     unsigned long      damage_sequence;    /* sequence when damage was created */
 
     /* for drawing translucent windows */
@@ -96,6 +96,7 @@ typedef struct _fade {
     struct _fade       *next;
     win                        *w;
     double             cur;
     struct _fade       *next;
     win                        *w;
     double             cur;
+    double             finish;
     double             step;
     void               (*callback) (Display *dpy, win *w, Bool gone);
     Display            *dpy;
     double             step;
     void               (*callback) (Display *dpy, win *w, Bool gone);
     Display            *dpy;
@@ -128,6 +129,15 @@ int                composite_opcode;
 
 /* find these once and be done with it */
 Atom           opacityAtom;
 
 /* find these once and be done with it */
 Atom           opacityAtom;
+Atom            winTypeAtom;
+Atom            winDesktopAtom;
+Atom            winDockAtom;
+Atom            winToolbarAtom;
+Atom            winMenuAtom;
+Atom            winUtilAtom;
+Atom            winSplashAtom;
+Atom            winDialogAtom;
+Atom            winNormalAtom;
 
 /* opacity property name; sometime soon I'll write up an EWMH spec for it */
 #define OPACITY_PROP   "_NET_WM_WINDOW_OPACITY"
 
 /* opacity property name; sometime soon I'll write up an EWMH spec for it */
 #define OPACITY_PROP   "_NET_WM_WINDOW_OPACITY"
@@ -159,14 +169,23 @@ typedef enum _compMode {
 static void
 determine_mode(Display *dpy, win *w);
     
 static void
 determine_mode(Display *dpy, win *w);
     
+static double
+get_opacity_percent(Display *dpy, win *w, double def);
+
+static XserverRegion
+win_extents (Display *dpy, win *w);
+
 CompMode    compMode = CompSimple;
 
 int        shadowRadius = 12;
 
 CompMode    compMode = CompSimple;
 
 int        shadowRadius = 12;
 
-double fade_step =     0.05;
+double  fade_in_step =  0.028;
+double  fade_out_step = 0.03;
 int    fade_delta =    10;
 int    fade_time =     0;
 int    fade_delta =    10;
 int    fade_time =     0;
-Bool   fadeWindows;
+Bool   fadeWindows = False;
+Bool    excludeDockShadows = False;
+Bool   fadeTrans = False;
 
 Bool   autoRedirect = False;
 
 
 Bool   autoRedirect = False;
 
@@ -226,9 +245,9 @@ enqueue_fade (Display *dpy, fade *f)
 }
 
 static void
 }
 
 static void
-set_fade (Display *dpy, win *w, Bool in, 
+set_fade (Display *dpy, win *w, double start, double finish, double step,
          void (*callback) (Display *dpy, win *w, Bool gone),
          void (*callback) (Display *dpy, win *w, Bool gone),
-         Bool gone)
+         Bool gone, Bool exec_callback, Bool override)
 {
     fade    *f;
 
 {
     fade    *f;
 
@@ -238,16 +257,27 @@ set_fade (Display *dpy, win *w, Bool in,
        f = malloc (sizeof (fade));
        f->next = 0;
        f->w = w;
        f = malloc (sizeof (fade));
        f->next = 0;
        f->w = w;
-       if (in)
-           f->cur = 0;
-       else
-           f->cur = 1;
+       f->cur = start;
        enqueue_fade (dpy, f);
     }
        enqueue_fade (dpy, f);
     }
-    if (in)
-        f->step = fade_step;
+    else if(!override)
+       return;
     else
     else
-       f->step = -fade_step;
+    {
+       if (exec_callback)
+           if (f->callback)
+               (*f->callback)(dpy, f->w, f->gone);
+    }
+
+    if (finish < 0)
+       finish = 0;
+    if (finish > 1)
+       finish = 1;
+    f->finish = finish;
+    if (f->cur < finish)
+        f->step = step;
+    else if (f->cur > finish)
+       f->step = -step;
     f->callback = callback;
     f->gone = gone;
     w->opacity = f->cur * OPAQUE;
     f->callback = callback;
     f->gone = gone;
     w->opacity = f->cur * OPAQUE;
@@ -255,6 +285,12 @@ set_fade (Display *dpy, win *w, Bool in,
     printf ("set_fade start %g step %g\n", f->cur, f->step);
 #endif
     determine_mode (dpy, w);
     printf ("set_fade start %g step %g\n", f->cur, f->step);
 #endif
     determine_mode (dpy, w);
+    if (w->shadow)
+    {
+       XRenderFreePicture (dpy, w->shadow);
+       w->shadow = None;
+       w->extents = win_extents (dpy, w);
+    }
 }
 
 int
 }
 
 int
@@ -300,15 +336,27 @@ run_fades (Display *dpy)
        w->opacity = f->cur * OPAQUE;
        if (f->step > 0)
        {
        w->opacity = f->cur * OPAQUE;
        if (f->step > 0)
        {
-           if (f->cur >= 1)
+           if (f->cur >= f->finish)
+           {
+               w->opacity = f->finish*OPAQUE;
                dequeue_fade (dpy, f);
        }
                dequeue_fade (dpy, f);
        }
+       }
        else
        {
        else
        {
-           if (f->cur <= 0)
+           if (f->cur <= f->finish)
+           {
+               w->opacity = f->finish*OPAQUE;
                dequeue_fade (dpy, f);
        }
                dequeue_fade (dpy, f);
        }
+       }
        determine_mode (dpy, w);
        determine_mode (dpy, w);
+       if (w->shadow)
+       {
+           XRenderFreePicture (dpy, w->shadow);
+           w->shadow = None;
+           w->extents = win_extents(dpy, w);
+       }
     }
     fade_time = now + fade_delta;
 }
     }
     fade_time = now + fade_delta;
 }
@@ -517,11 +565,13 @@ make_shadow (Display *dpy, double opacity, int width, int height)
 }
 
 static Picture
 }
 
 static Picture
-shadow_picture (Display *dpy, double opacity, int width, int height, int *wp, int *hp)
+shadow_picture (Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp)
 {
     XImage  *shadowImage;
     Pixmap  shadowPixmap;
 {
     XImage  *shadowImage;
     Pixmap  shadowPixmap;
+    Pixmap  finalPixmap;
     Picture shadowPicture;
     Picture shadowPicture;
+    Picture finalPicture;
     GC     gc;
     
     shadowImage = make_shadow (dpy, opacity, width, height);
     GC     gc;
     
     shadowImage = make_shadow (dpy, opacity, width, height);
@@ -694,7 +744,7 @@ win_extents (Display *dpy, win *w)
     r.y = w->a.y;
     r.width = w->a.width + w->a.border_width * 2;
     r.height = w->a.height + w->a.border_width * 2;
     r.y = w->a.y;
     r.width = w->a.width + w->a.border_width * 2;
     r.height = w->a.height + w->a.border_width * 2;
-    if (compMode != CompSimple)
+    if (compMode != CompSimple && !(w->windowType == winDockAtom && excludeDockShadows))
     {
        if (compMode == CompServerShadows || w->mode != WINDOW_ARGB)
        {
     {
        if (compMode == CompServerShadows || w->mode != WINDOW_ARGB)
        {
@@ -715,8 +765,8 @@ win_extents (Display *dpy, win *w)
                {
                    double      opacity = SHADOW_OPACITY;
                    if (w->mode == WINDOW_TRANS)
                {
                    double      opacity = SHADOW_OPACITY;
                    if (w->mode == WINDOW_TRANS)
-                       opacity = opacity * TRANS_OPACITY;
-                   w->shadow = shadow_picture (dpy, opacity,
+                       opacity = opacity * ((double)w->opacity)/((double)OPAQUE);
+                   w->shadow = shadow_picture (dpy, opacity, w->alphaPict,
                                                w->a.width + w->a.border_width * 2,
                                                w->a.height + w->a.border_width * 2,
                                                &w->shadow_width, &w->shadow_height);
                                                w->a.width + w->a.border_width * 2,
                                                w->a.height + w->a.border_width * 2,
                                                &w->shadow_width, &w->shadow_height);
@@ -1030,13 +1080,20 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
 
     if (!w)
        return;
 
     if (!w)
        return;
+
     w->a.map_state = IsViewable;
     
     w->a.map_state = IsViewable;
     
+    /* This needs to be here or else we lose transparency messages */
+    XSelectInput (dpy, id, PropertyChangeMask);
+
 #if CAN_DO_USABLE
     w->damage_bounds.x = w->damage_bounds.y = 0;
     w->damage_bounds.width = w->damage_bounds.height = 0;
 #endif
     w->damaged = 0;
 #if CAN_DO_USABLE
     w->damage_bounds.x = w->damage_bounds.y = 0;
     w->damage_bounds.width = w->damage_bounds.height = 0;
 #endif
     w->damaged = 0;
+
+    if (fade && fadeWindows)
+       set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, False, True, True);
 }
 
 static void
 }
 
 static void
@@ -1105,9 +1162,10 @@ unmap_win (Display *dpy, Window id, Bool fade)
     win *w = find_win (dpy, id);
     if (!w)
        return;
     win *w = find_win (dpy, id);
     if (!w)
        return;
+    w->a.map_state = IsUnmapped;
 #if HAS_NAME_WINDOW_PIXMAP
     if (w->pixmap && fade && fadeWindows)
 #if HAS_NAME_WINDOW_PIXMAP
     if (w->pixmap && fade && fadeWindows)
-       set_fade (dpy, w, False, unmap_callback, False);
+       set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, False, True);
     else
 #endif
        finish_unmap_win (dpy, w);
     else
 #endif
        finish_unmap_win (dpy, w);
@@ -1124,11 +1182,11 @@ get_opacity_prop(Display *dpy, win *w, unsigned int def)
     int format;
     unsigned long n, left;
 
     int format;
     unsigned long n, left;
 
-    char *data;
-    XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False, 
+    unsigned char *data;
+    int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False, 
                       XA_CARDINAL, &actual, &format, 
                       XA_CARDINAL, &actual, &format, 
-                      &n, &left, (unsigned char **) &data);
-    if (data != None)
+                                   &n, &left, &data);
+    if (result == Success && data != None)
     {
        unsigned int i;
        memcpy (&i, data, sizeof (unsigned int));
     {
        unsigned int i;
        memcpy (&i, data, sizeof (unsigned int));
@@ -1138,10 +1196,44 @@ get_opacity_prop(Display *dpy, win *w, unsigned int def)
     return def;
 }
 
     return def;
 }
 
+/* Get the opacity property from the window in a percent format
+   not found: default
+   otherwise: the value
+*/
+static double
+get_opacity_percent(Display *dpy, win *w, double def)
+{
+    unsigned int opacity = get_opacity_prop (dpy, w, (unsigned int)(OPAQUE*def));
+
+    return opacity*1.0/OPAQUE;
+}
+
 /* determine mode for window all in one place.
    Future might check for menu flag and other cool things
 */
 
 /* determine mode for window all in one place.
    Future might check for menu flag and other cool things
 */
 
+static Atom
+get_wintype_prop(Display * dpy, Window w)
+{
+    Atom actual;
+    int format;
+    unsigned long n, left;
+
+    unsigned char *data;
+    int result = XGetWindowProperty (dpy, w, winTypeAtom, 0L, 1L, False,
+                                    XA_ATOM, &actual, &format,
+                                    &n, &left, &data);
+
+    if (result == Success && data != None)
+    {
+       Atom a;
+       memcpy (&a, data, sizeof (Atom));
+       XFree ( (void *) data);
+       return a;
+    }
+    return winNormalAtom;
+}
+
 static void
 determine_mode(Display *dpy, win *w)
 {
 static void
 determine_mode(Display *dpy, win *w)
 {
@@ -1193,6 +1285,29 @@ determine_mode(Display *dpy, win *w)
     }
 }
 
     }
 }
 
+static Atom
+determine_wintype (Display *dpy, Window w)
+{
+    Window       root_return, parent_return;
+    Window      *children;
+    unsigned int nchildren, i;
+    Atom         type;
+
+    type = get_wintype_prop (dpy, w);
+    if (type != winNormalAtom)
+       return type;
+
+    XQueryTree (dpy, w, &root_return, &parent_return, &children, &nchildren);
+    for (i = 0;i < nchildren;i++)
+    {
+       type = determine_wintype (dpy, children[i]);
+       if (type != winNormalAtom)
+           return type;
+    }
+
+    return winNormalAtom;
+}
+
 static void
 add_win (Display *dpy, Window id, Window prev)
 {
 static void
 add_win (Display *dpy, Window id, Window prev)
 {
@@ -1249,14 +1364,14 @@ add_win (Display *dpy, Window id, Window prev)
     new->prev_trans = 0;
 
     /* moved mode setting to one place */
     new->prev_trans = 0;
 
     /* moved mode setting to one place */
-    XSelectInput(dpy, id, PropertyChangeMask);
-    new->opacity = get_opacity_prop(dpy, new, OPAQUE);
+    new->opacity = get_opacity_prop (dpy, new, OPAQUE);
+    new->windowType = determine_wintype (dpy, new->id);
     determine_mode (dpy, new);
     
     new->next = *p;
     *p = new;
     if (new->a.map_state == IsViewable)
     determine_mode (dpy, new);
     
     new->next = *p;
     *p = new;
     if (new->a.map_state == IsViewable)
-       map_win (dpy, id, new->damage_sequence - 1, False);
+       map_win (dpy, id, new->damage_sequence - 1, True);
 }
 
 void
 }
 
 void
@@ -1384,6 +1499,7 @@ finish_destroy_win (Display *dpy, Window id, Bool gone)
            {
                set_ignore (dpy, NextRequest (dpy));
                XRenderFreePicture (dpy, w->picture);
            {
                set_ignore (dpy, NextRequest (dpy));
                XRenderFreePicture (dpy, w->picture);
+               w->picture = None;
            }
            if (w->alphaPict)
            {
            }
            if (w->alphaPict)
            {
@@ -1399,6 +1515,7 @@ finish_destroy_win (Display *dpy, Window id, Bool gone)
            {
                set_ignore (dpy, NextRequest (dpy));
                XDamageDestroy (dpy, w->damage);
            {
                set_ignore (dpy, NextRequest (dpy));
                XDamageDestroy (dpy, w->damage);
+               w->damage = None;
            }
            cleanup_fade (dpy, w);
            free (w);
            }
            cleanup_fade (dpy, w);
            free (w);
@@ -1420,7 +1537,7 @@ destroy_win (Display *dpy, Window id, Bool gone, Bool fade)
     win *w = find_win (dpy, id);
 #if HAS_NAME_WINDOW_PIXMAP
     if (w && w->pixmap && fade && fadeWindows)
     win *w = find_win (dpy, id);
 #if HAS_NAME_WINDOW_PIXMAP
     if (w && w->pixmap && fade && fadeWindows)
-       set_fade (dpy, w, False, destroy_callback, gone);
+       set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, destroy_callback, gone, False, True);
     else
 #endif
     {
     else
 #endif
     {
@@ -1497,7 +1614,7 @@ damage_win (Display *dpy, XDamageNotifyEvent *de)
        {
            clipChanged = True;
            if (fadeWindows)
        {
            clipChanged = True;
            if (fadeWindows)
-               set_fade (dpy, w, True, 0, False);
+               set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, False, True, True);
            w->usable = True;
        }
     }
            w->usable = True;
        }
     }
@@ -1614,7 +1731,7 @@ ev_window (XEvent *ev)
 void
 usage (char *program)
 {
 void
 usage (char *program)
 {
-    fprintf (stderr, "usage: %s [-d display] [-n] [-s] [-c] [-a]\n", program);
+    fprintf (stderr, "usage: %s [-d display] [-n] [-s] [-c] [-a] [-f] [-F] [-C]\n", program);
     exit (1);
 }
 
     exit (1);
 }
 
@@ -1642,7 +1759,7 @@ main (int argc, char **argv)
     char           *display = 0;
     int                    o;
 
     char           *display = 0;
     int                    o;
 
-    while ((o = getopt (argc, argv, "d:scnfaS")) != -1)
+    while ((o = getopt (argc, argv, "d:scnfFCaS")) != -1)
     {
        switch (o) {
        case 'd':
     {
        switch (o) {
        case 'd':
@@ -1654,12 +1771,18 @@ main (int argc, char **argv)
        case 'c':
            compMode = CompClientShadows;
            break;
        case 'c':
            compMode = CompClientShadows;
            break;
+       case 'C':
+           excludeDockShadows = True;
+           break;
        case 'n':
            compMode = CompSimple;
            break;
        case 'f':
            fadeWindows = True;
            break;
        case 'n':
            compMode = CompSimple;
            break;
        case 'f':
            fadeWindows = True;
            break;
+       case 'F':
+           fadeTrans = True;
+           break;
        case 'a':
            autoRedirect = True;
            break;
        case 'a':
            autoRedirect = True;
            break;
@@ -1713,6 +1836,15 @@ main (int argc, char **argv)
     }
     /* get atoms */
     opacityAtom = XInternAtom (dpy, OPACITY_PROP, False);
     }
     /* get atoms */
     opacityAtom = XInternAtom (dpy, OPACITY_PROP, False);
+    winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False);
+    winDesktopAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
+    winDockAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
+    winToolbarAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
+    winMenuAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
+    winUtilAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
+    winSplashAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
+    winDialogAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+    winNormalAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
 
     pa.subwindow_mode = IncludeInferiors;
 
 
     pa.subwindow_mode = IncludeInferiors;
 
@@ -1852,8 +1984,20 @@ main (int argc, char **argv)
                    win * w = find_win(dpy, ev.xproperty.window);
                    if (w)
                    {
                    win * w = find_win(dpy, ev.xproperty.window);
                    if (w)
                    {
+                       if (fadeTrans)
+                           set_fade (dpy, w, w->opacity*1.0/OPAQUE, get_opacity_percent (dpy, w, 1.0),
+                                     fade_out_step, 0, False, 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;
+                               w->extents = win_extents (dpy, w);
+                           }
+                       }
                    }
                }
                break;
                    }
                }
                break;