aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Makefile.am2
-rw-r--r--xcompmgr.1 (renamed from xcompmgr.man)21
-rw-r--r--xcompmgr.c204
4 files changed, 199 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index dfa1cc7..f9abcd0 100644
--- 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:
diff --git a/Makefile.am b/Makefile.am
index 96c4dfd..aee1748 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
bin_PROGRAMS = xcompmgr
-man_MANS = xcompmgr.man
+man_MANS = xcompmgr.1
xcompmgr_LDADD = @XCOMPMGR_LIBS@ -lm
diff --git a/xcompmgr.man b/xcompmgr.1
index 9646b5f..d5d43d8 100644
--- a/xcompmgr.man
+++ b/xcompmgr.1
@@ -4,7 +4,7 @@
xcompmgr \- sample X compositing manager
.SH SYNOPSIS
.nf
-.B xcompmgr [\-acfns]
+.B xcompmgr [\-d display] [\-acfnsCFS]
.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
+.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.
@@ -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
-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 \-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
-Several.
+Probably. Please report any you find to http://bugs.freedesktop.org/.
.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.
diff --git a/xcompmgr.c b/xcompmgr.c
index 3d78783..122d8b4 100644
--- a/xcompmgr.c
+++ b/xcompmgr.c
@@ -79,7 +79,7 @@ typedef struct _win {
int shadow_width;
int shadow_height;
unsigned int opacity;
-
+ Atom windowType;
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;
+ double finish;
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;
+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"
@@ -159,14 +169,23 @@ typedef enum _compMode {
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;
-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;
-Bool fadeWindows;
+Bool fadeWindows = False;
+Bool excludeDockShadows = False;
+Bool fadeTrans = False;
Bool autoRedirect = False;
@@ -226,9 +245,9 @@ enqueue_fade (Display *dpy, fade *f)
}
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),
- Bool gone)
+ Bool gone, Bool exec_callback, Bool override)
{
fade *f;
@@ -238,16 +257,27 @@ set_fade (Display *dpy, win *w, Bool in,
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);
}
- if (in)
- f->step = fade_step;
+ else if(!override)
+ return;
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;
@@ -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);
+ if (w->shadow)
+ {
+ XRenderFreePicture (dpy, w->shadow);
+ w->shadow = None;
+ w->extents = win_extents (dpy, w);
+ }
}
int
@@ -300,15 +336,27 @@ run_fades (Display *dpy)
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);
}
+ }
else
{
- if (f->cur <= 0)
+ if (f->cur <= f->finish)
+ {
+ w->opacity = f->finish*OPAQUE;
dequeue_fade (dpy, f);
}
+ }
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;
}
@@ -517,11 +565,13 @@ make_shadow (Display *dpy, double opacity, int width, int height)
}
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;
+ Pixmap finalPixmap;
Picture shadowPicture;
+ Picture finalPicture;
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;
- if (compMode != CompSimple)
+ if (compMode != CompSimple && !(w->windowType == winDockAtom && excludeDockShadows))
{
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)
- 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);
@@ -1030,13 +1080,20 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
if (!w)
return;
+
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 (fade && fadeWindows)
+ set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, False, True, True);
}
static void
@@ -1105,9 +1162,10 @@ unmap_win (Display *dpy, Window id, Bool fade)
win *w = find_win (dpy, id);
if (!w)
return;
+ w->a.map_state = IsUnmapped;
#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);
@@ -1124,11 +1182,11 @@ get_opacity_prop(Display *dpy, win *w, unsigned int def)
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,
- &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));
@@ -1138,10 +1196,44 @@ get_opacity_prop(Display *dpy, win *w, unsigned int 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
*/
+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)
{
@@ -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)
{
@@ -1249,14 +1364,14 @@ add_win (Display *dpy, Window id, Window prev)
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)
- map_win (dpy, id, new->damage_sequence - 1, False);
+ map_win (dpy, id, new->damage_sequence - 1, True);
}
void
@@ -1384,6 +1499,7 @@ finish_destroy_win (Display *dpy, Window id, Bool gone)
{
set_ignore (dpy, NextRequest (dpy));
XRenderFreePicture (dpy, w->picture);
+ w->picture = None;
}
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);
+ w->damage = None;
}
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)
- 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
{
@@ -1497,7 +1614,7 @@ damage_win (Display *dpy, XDamageNotifyEvent *de)
{
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;
}
}
@@ -1614,7 +1731,7 @@ ev_window (XEvent *ev)
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);
}
@@ -1642,7 +1759,7 @@ main (int argc, char **argv)
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':
@@ -1654,12 +1771,18 @@ main (int argc, char **argv)
case 'c':
compMode = CompClientShadows;
break;
+ case 'C':
+ excludeDockShadows = True;
+ break;
case 'n':
compMode = CompSimple;
break;
case 'f':
fadeWindows = True;
break;
+ case 'F':
+ fadeTrans = True;
+ break;
case 'a':
autoRedirect = True;
break;
@@ -1713,6 +1836,15 @@ main (int argc, char **argv)
}
/* 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;
@@ -1852,8 +1984,20 @@ main (int argc, char **argv)
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);
+ if (w->shadow)
+ {
+ XRenderFreePicture (dpy, w->shadow);
+ w->shadow = None;
+ w->extents = win_extents (dpy, w);
+ }
+ }
}
}
break;