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>
* xcompmgr.man, Makefile.am:

View File

@ -1,5 +1,5 @@
bin_PROGRAMS = xcompmgr
man_MANS = xcompmgr.man
man_MANS = xcompmgr.1
xcompmgr_LDADD = @XCOMPMGR_LIBS@ -lm

View File

@ -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.

View File

@ -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;