More effects, bug fixes, doc updates.

This commit is contained in:
Adam Jackson 2004-09-10 05:55:19 +00:00
parent ff13f4a4b9
commit 36005e53a5
4 changed files with 199 additions and 35 deletions

View File

@ -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> 2004-09-08 Adam Jackson <ajax@freedesktop.org>
* xcompmgr.man, Makefile.am: * xcompmgr.man, Makefile.am:

View 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

View File

@ -4,7 +4,7 @@
xcompmgr \- sample X compositing manager xcompmgr \- sample X compositing manager
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.B xcompmgr [\-acfns] .B xcompmgr [\-d display] [\-acfnsCFS]
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
.B xcompmgr .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. and COMPOSITE extensions. It enables basic eye-candy effects.
.SH OPTIONS .SH OPTIONS
.TP .TP
.BI \-d\ display
Specifies the display to manage.
.TP
.BI \-a .BI \-a
Automatic server-side compositing. This instructs the server to use the Automatic server-side compositing. This instructs the server to use the
standard composition rules. Useful for debugging. standard composition rules. Useful for debugging.
@ -21,15 +24,25 @@ Client-side compositing with soft shadows and translucency support.
.TP .TP
.BI \-f .BI \-f
When \-c is specified, enables a smooth fade effect for transient windows like 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 .TP
.BI \-n .BI \-n
Simple client-side compositing. Simple client-side compositing.
.TP .TP
.BI \-s .BI \-s
Server-side compositing with hard-edged shadows. 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.

View File

@ -79,7 +79,7 @@ typedef struct _win {
int shadow_width; int shadow_width;
int shadow_height; int shadow_height;
unsigned int opacity; unsigned int opacity;
Atom windowType;
unsigned long damage_sequence; /* sequence when damage was created */ unsigned long damage_sequence; /* sequence when damage was created */
/* for drawing translucent windows */ /* for drawing translucent windows */
@ -96,6 +96,7 @@ typedef struct _fade {
struct _fade *next; struct _fade *next;
win *w; win *w;
double cur; double cur;
double finish;
double step; double step;
void (*callback) (Display *dpy, win *w, Bool gone); void (*callback) (Display *dpy, win *w, Bool gone);
Display *dpy; Display *dpy;
@ -128,6 +129,15 @@ int composite_opcode;
/* find these once and be done with it */ /* find these once and be done with it */
Atom opacityAtom; 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 */ /* opacity property name; sometime soon I'll write up an EWMH spec for it */
#define OPACITY_PROP "_NET_WM_WINDOW_OPACITY" #define OPACITY_PROP "_NET_WM_WINDOW_OPACITY"
@ -159,14 +169,23 @@ typedef enum _compMode {
static void static void
determine_mode(Display *dpy, win *w); 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; CompMode compMode = CompSimple;
int shadowRadius = 12; 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_delta = 10;
int fade_time = 0; 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 = malloc (sizeof (fade));
f->next = 0; f->next = 0;
f->w = w; f->w = w;
if (in) f->cur = start;
f->cur = 0;
else
f->cur = 1;
enqueue_fade (dpy, f); enqueue_fade (dpy, f);
} }
if (in) else if(!override)
f->step = fade_step; 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->callback = callback;
f->gone = gone; f->gone = gone;
w->opacity = f->cur * OPAQUE; 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); printf ("set_fade start %g step %g\n", f->cur, f->step);
#endif #endif
determine_mode (dpy, w); 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; w->opacity = f->cur * OPAQUE;
if (f->step > 0) 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; XImage *shadowImage;
Pixmap shadowPixmap; Pixmap shadowPixmap;
Pixmap finalPixmap;
Picture shadowPicture; Picture shadowPicture;
Picture finalPicture;
GC gc; GC gc;
shadowImage = make_shadow (dpy, opacity, width, height); shadowImage = make_shadow (dpy, opacity, width, height);
@ -694,7 +744,7 @@ win_extents (Display *dpy, win *w)
r.y = w->a.y; r.y = w->a.y;
r.width = w->a.width + w->a.border_width * 2; r.width = w->a.width + w->a.border_width * 2;
r.height = w->a.height + 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; double opacity = SHADOW_OPACITY;
if (w->mode == WINDOW_TRANS) if (w->mode == WINDOW_TRANS)
opacity = opacity * TRANS_OPACITY; opacity = opacity * ((double)w->opacity)/((double)OPAQUE);
w->shadow = shadow_picture (dpy, opacity, w->shadow = shadow_picture (dpy, opacity, w->alphaPict,
w->a.width + w->a.border_width * 2, w->a.width + w->a.border_width * 2,
w->a.height + w->a.border_width * 2, w->a.height + w->a.border_width * 2,
&w->shadow_width, &w->shadow_height); &w->shadow_width, &w->shadow_height);
@ -1030,13 +1080,20 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
if (!w) if (!w)
return; 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 #if CAN_DO_USABLE
w->damage_bounds.x = w->damage_bounds.y = 0; w->damage_bounds.x = w->damage_bounds.y = 0;
w->damage_bounds.width = w->damage_bounds.height = 0; w->damage_bounds.width = w->damage_bounds.height = 0;
#endif #endif
w->damaged = 0; 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); win *w = find_win (dpy, id);
if (!w) if (!w)
return; return;
w->a.map_state = IsUnmapped;
#if HAS_NAME_WINDOW_PIXMAP #if HAS_NAME_WINDOW_PIXMAP
if (w->pixmap && fade && fadeWindows) 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 else
#endif #endif
finish_unmap_win (dpy, w); finish_unmap_win (dpy, w);
@ -1124,11 +1182,11 @@ get_opacity_prop(Display *dpy, win *w, unsigned int def)
int format; int format;
unsigned long n, left; unsigned long n, left;
char *data; unsigned char *data;
XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False, int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False,
XA_CARDINAL, &actual, &format, XA_CARDINAL, &actual, &format,
&n, &left, (unsigned char **) &data); &n, &left, &data);
if (data != None) if (result == Success && data != None)
{ {
unsigned int i; unsigned int i;
memcpy (&i, data, sizeof (unsigned int)); 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. /* determine mode for window all in one place.
Future might check for menu flag and other cool things 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 static void
determine_mode(Display *dpy, win *w) 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 static void
add_win (Display *dpy, Window id, Window prev) add_win (Display *dpy, Window id, Window prev)
{ {
@ -1249,14 +1364,14 @@ add_win (Display *dpy, Window id, Window prev)
new->prev_trans = 0; new->prev_trans = 0;
/* moved mode setting to one place */ /* 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); determine_mode (dpy, new);
new->next = *p; new->next = *p;
*p = new; *p = new;
if (new->a.map_state == IsViewable) 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)); set_ignore (dpy, NextRequest (dpy));
XRenderFreePicture (dpy, w->picture); 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)); set_ignore (dpy, NextRequest (dpy));
XDamageDestroy (dpy, w->damage); XDamageDestroy (dpy, w->damage);
w->damage = None;
} }
cleanup_fade (dpy, w); cleanup_fade (dpy, w);
free (w); free (w);
@ -1420,7 +1537,7 @@ destroy_win (Display *dpy, Window id, Bool gone, Bool fade)
win *w = find_win (dpy, id); win *w = find_win (dpy, id);
#if HAS_NAME_WINDOW_PIXMAP #if HAS_NAME_WINDOW_PIXMAP
if (w && w->pixmap && fade && fadeWindows) 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 else
#endif #endif
{ {
@ -1497,7 +1614,7 @@ damage_win (Display *dpy, XDamageNotifyEvent *de)
{ {
clipChanged = True; clipChanged = True;
if (fadeWindows) 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 void
usage (char *program) 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; char *display = 0;
int o; int o;
while ((o = getopt (argc, argv, "d:scnfaS")) != -1) while ((o = getopt (argc, argv, "d:scnfFCaS")) != -1)
{ {
switch (o) { switch (o) {
case 'd': case 'd':
@ -1654,12 +1771,18 @@ main (int argc, char **argv)
case 'c': case 'c':
compMode = CompClientShadows; compMode = CompClientShadows;
break; break;
case 'C':
excludeDockShadows = True;
break;
case 'n': case 'n':
compMode = CompSimple; compMode = CompSimple;
break; break;
case 'f': case 'f':
fadeWindows = True; fadeWindows = True;
break; break;
case 'F':
fadeTrans = True;
break;
case 'a': case 'a':
autoRedirect = True; autoRedirect = True;
break; break;
@ -1713,6 +1836,15 @@ main (int argc, char **argv)
} }
/* get atoms */ /* get atoms */
opacityAtom = XInternAtom (dpy, OPACITY_PROP, False); 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); win * w = find_win(dpy, ev.xproperty.window);
if (w) 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); w->opacity = get_opacity_prop(dpy, w, OPAQUE);
determine_mode(dpy, w); determine_mode(dpy, w);
if (w->shadow)
{
XRenderFreePicture (dpy, w->shadow);
w->shadow = None;
w->extents = win_extents (dpy, w);
}
}
} }
} }
break; break;