More effects, bug fixes, doc updates.
This commit is contained in:
parent
ff13f4a4b9
commit
36005e53a5
|
@ -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:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
bin_PROGRAMS = xcompmgr
|
||||
man_MANS = xcompmgr.man
|
||||
man_MANS = xcompmgr.1
|
||||
|
||||
xcompmgr_LDADD = @XCOMPMGR_LIBS@ -lm
|
||||
|
||||
|
|
|
@ -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.
|
204
xcompmgr.c
204
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;
|
||||
|
||||
|
@ -1851,9 +1983,21 @@ main (int argc, char **argv)
|
|||
/* reset mode and redraw window */
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue