From 36005e53a518c6e028d76ff82ac7ff54e1eac9b0 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 10 Sep 2004 05:55:19 +0000 Subject: More effects, bug fixes, doc updates. --- ChangeLog | 7 ++ Makefile.am | 2 +- xcompmgr.1 | 48 ++++++++++++++ xcompmgr.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- xcompmgr.man | 35 ---------- 5 files changed, 230 insertions(+), 66 deletions(-) create mode 100644 xcompmgr.1 delete mode 100644 xcompmgr.man diff --git a/ChangeLog b/ChangeLog index dfa1cc7..f9abcd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-09-10 Adam Jackson + + * 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 * 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.1 b/xcompmgr.1 new file mode 100644 index 0000000..d5d43d8 --- /dev/null +++ b/xcompmgr.1 @@ -0,0 +1,48 @@ +.ds q \N'34' +.TH xcompmgr 1 +.SH NAME +xcompmgr \- sample X compositing manager +.SH SYNOPSIS +.nf +.B xcompmgr [\-d display] [\-acfnsCFS] +.fi +.SH DESCRIPTION +.B xcompmgr +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. +.TP +.BI \-c +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, 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 +Probably. Please report any you find to http://bugs.freedesktop.org/. +.SH AUTHORS +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; diff --git a/xcompmgr.man b/xcompmgr.man deleted file mode 100644 index 9646b5f..0000000 --- a/xcompmgr.man +++ /dev/null @@ -1,35 +0,0 @@ -.ds q \N'34' -.TH xcompmgr 1 -.SH NAME -xcompmgr \- sample X compositing manager -.SH SYNOPSIS -.nf -.B xcompmgr [\-acfns] -.fi -.SH DESCRIPTION -.B xcompmgr -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 \-a -Automatic server-side compositing. This instructs the server to use the -standard composition rules. Useful for debugging. -.TP -.BI \-c -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. -.TP -.BI \-n -Simple client-side compositing. -.TP -.BI \-s -Server-side compositing with hard-edged shadows. -.SH BUGS -Several. -.SH AUTHORS -Keith Packard, with contributions from Matthew Allum, Eric Anholt, -Matthew Hawn, Ely Levy, Phil Blundell, and Carl Worth. -- cgit v1.2.3