From 949be62a369f0a9eb0ad9d54d4b40c104e61a4cc Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 6 Jan 2018 09:24:37 +0100 Subject: Simplify and remove all features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 21 +- COPYING | 19 - LICENSE | 20 + Makefile | 27 + Makefile.am | 19 - README | 32 +- autogen.sh | 14 - config.mk | 6 + configure.ac | 25 - man/Makefile.am | 12 - man/xcompmgr.man | 69 -- xcman.1 | 9 + xcman.c | 798 ++++++++++++++++++ xcompmgr.c | 2378 ------------------------------------------------------ 14 files changed, 869 insertions(+), 2580 deletions(-) delete mode 100644 COPYING create mode 100644 LICENSE create mode 100644 Makefile delete mode 100644 Makefile.am delete mode 100755 autogen.sh create mode 100644 config.mk delete mode 100644 configure.ac delete mode 100644 man/Makefile.am delete mode 100644 man/xcompmgr.man create mode 100644 xcman.1 create mode 100644 xcman.c delete mode 100644 xcompmgr.c diff --git a/.gitignore b/.gitignore index 9564fb0..83f13dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,3 @@ -.deps -Makefile -Makefile.in -aclocal.m4 -autom4te.cache -config.h -config.h.in -config.log -config.status -configure -depcomp -install-sh -missing -stamp-h1 -xcompmgr -*.o *~ -xcompmgr-*.tar.* -ChangeLog -tags +*\#* +/xcman diff --git a/COPYING b/COPYING deleted file mode 100644 index 2d6ef83..0000000 --- a/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright © 2003 Keith Packard - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation, and that the name of Keith Packard not be used in -advertising or publicity pertaining to distribution of the software without -specific, written prior permission. Keith Packard makes no -representations about the suitability of this software for any purpose. It -is provided "as is" without express or implied warranty. - -KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c90c31e --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright © 2018 Mattias Andrée +Copyright © 2003 Keith Packard (xcompmgr) + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Keith Packard not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Keith Packard makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..afde4e8 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +all: xcman + +install: xcman + mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1" + mkdir -p -- "$(DESTDIR)$(PREFIX)/share/licenses/xcman" + cp -- xcman "$(DESTDIR)$(PREFIX)/bin" + cp -- xcman.1 "$(DESTDIR)$(MANPREFIX)/man1" + cp -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/xcman" + +uninstall: + -rm -f -- "$(DESTDIR)$(PREFIX)/bin/xcman" + -rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/xcman.1" + -rm -rf -- "$(DESTDIR)$(PREFIX)/share/licenses/xcman" + +clean: + -rm -f -- xcman + +.SUFFIXES: +.SUFFIXES: .c + +.PHONY: all install uninstall clean diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 25d5adb..0000000 --- a/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -SUBDIRS = man - -bin_PROGRAMS = xcompmgr - -AM_CFLAGS = $(CWARNFLAGS) $(XCOMPMGR_CFLAGS) -xcompmgr_LDADD = $(XCOMPMGR_LIBS) -lm - -MAINTAINERCLEANFILES = ChangeLog INSTALL - -.PHONY: ChangeLog INSTALL - -INSTALL: - $(INSTALL_CMD) - -ChangeLog: - $(CHANGELOG_CMD) - -dist-hook: ChangeLog INSTALL - diff --git a/README b/README index 2458e22..2efb5a9 100644 --- a/README +++ b/README @@ -1,27 +1,9 @@ -xcompmgr is a sample compositing manager for X servers supporting the -XFIXES, DAMAGE, RENDER, and COMPOSITE extensions. It enables basic -eye-candy effects. +NAME + xcman - Minimal compositing manager for X -All questions regarding this software should be directed at the -Xorg mailing list: - - http://lists.freedesktop.org/mailman/listinfo/xorg - -Please submit bug reports to the Xorg bugzilla: - - https://bugs.freedesktop.org/enter_bug.cgi?product=xorg - -The master development code repository can be found at: - - git://anongit.freedesktop.org/git/xorg/app/xcompmgr - - http://cgit.freedesktop.org/xorg/app/xcompmgr - -For patch submission instructions, see: - - http://www.x.org/wiki/Development/Documentation/SubmittingPatches - -For more information on the git code manager, see: - - http://wiki.x.org/wiki/GitPage +SYNOPSIS + xcman +DESCRIPTION + xcman is a minimal compositing manager, for X, forked + from xcompmgr. It only provides transparancy support. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index fc34bd5..0000000 --- a/autogen.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/sh - -srcdir=`dirname $0` -test -z "$srcdir" && srcdir=. - -ORIGDIR=`pwd` -cd $srcdir - -autoreconf -v --install || exit 1 -cd $ORIGDIR || exit $? - -if test -z "$NOCONFIGURE"; then - $srcdir/configure "$@" -fi diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..64ac473 --- /dev/null +++ b/config.mk @@ -0,0 +1,6 @@ +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +CPPFLAGS = +CFLAGS = -std=c99 -Wall -Wextra $(CPPFLAGS) +LDFLAGS = -lXext -lXdamage -lXfixes -lXcomposite -lXrender -lX11 diff --git a/configure.ac b/configure.ac deleted file mode 100644 index e63f1e6..0000000 --- a/configure.ac +++ /dev/null @@ -1,25 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -# Initialize Autoconf -AC_PREREQ(2.60) -AC_INIT([xcompmgr], [1.1.7], - [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg]) -AC_CONFIG_SRCDIR([xcompmgr.c]) -AC_CONFIG_HEADERS([config.h]) - -# Initialize Automake -AM_INIT_AUTOMAKE([foreign dist-bzip2]) - -# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS -m4_ifndef([XORG_MACROS_VERSION], - [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.8) -XORG_DEFAULT_OPTIONS - -PKG_CHECK_MODULES(XCOMPMGR, xcomposite xfixes xdamage xrender xext) - -AC_CONFIG_FILES([ - Makefile - man/Makefile]) -AC_OUTPUT diff --git a/man/Makefile.am b/man/Makefile.am deleted file mode 100644 index 988f6ff..0000000 --- a/man/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ - -appmandir = $(APP_MAN_DIR) -appman_PRE = xcompmgr.man -appman_DATA = $(appman_PRE:man=$(APP_MAN_SUFFIX)) - -EXTRA_DIST = $(appman_PRE) -CLEANFILES = $(appman_DATA) -SUFFIXES = .$(APP_MAN_SUFFIX) .man - -# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure -.man.$(APP_MAN_SUFFIX): - $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ diff --git a/man/xcompmgr.man b/man/xcompmgr.man deleted file mode 100644 index 5f51ac5..0000000 --- a/man/xcompmgr.man +++ /dev/null @@ -1,69 +0,0 @@ -.ds q \N'34' -.TH xcompmgr 1 __xorgversion__ -.SH NAME -xcompmgr \- sample X compositing manager -.SH SYNOPSIS -.BI "xcompmgr [\-d " display "] [\-r " radius "]" -.BI "[\-o " opacity "] [\-l " left-offset "]" -.BI "[\-t " top-offset "] [\-acCfFnsS]" -.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 \-r\ radius -Specifies the blur radius for client-side shadows. -.TP -.BI \-o\ opacity -Specifies the opacity for client-side shadows. -.TP -.BI \-l\ left-offset -Specifies the left offset for client-side shadows. -.TP -.BI \-t\ top-offset -Specifies the top offset for client-side shadows. -.TP -.BI \-I\ fade-in-step -Specifies the opacity change between steps while fading in. -.TP -.BI \-O\ fade-out-step -Specifies the opacity change between steps while fading out. -.TP -.BI \-D\ fade-delta -Specifies the time (in milliseconds) between steps in a fade. -.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. This is the default mode. -.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, -Thomas Luebking, Matthew Hawn, Ely Levy, Phil Blundell, and Carl Worth. diff --git a/xcman.1 b/xcman.1 new file mode 100644 index 0000000..f7a3618 --- /dev/null +++ b/xcman.1 @@ -0,0 +1,9 @@ +.TH XCMAN 1 xcman +.SH NAME +xcman - Minimal compositing manager for X +.SH SYNOPSIS +.B xcman +.SH DESCRIPTION +.B xcman +is a minimal compositing manager, for X, forked +from xcompmgr. It only provides transparancy support. diff --git a/xcman.c b/xcman.c new file mode 100644 index 0000000..05823ce --- /dev/null +++ b/xcman.c @@ -0,0 +1,798 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define eprintf(...) (fprintf(stderr, __VA_ARGS__), exit(1)) +#define erealloc(P, N) ((tmp_ = realloc((P), (N))) ? tmp_ : (eprintf("realloc: out of memory\n"), NULL)) +#define ecalloc(N, M) ((tmp_ = calloc((N), (M))) ? tmp_ : (eprintf("calloc: out of memory\n"), NULL)) +static void *tmp_; + +#define OPAQUE (~(uint32_t)0) + +#define COPY_AREA(DEST, SRC)\ + ((DEST)->x = (SRC)->x,\ + (DEST)->y = (SRC)->y,\ + (DEST)->width = (SRC)->width,\ + (DEST)->height = (SRC)->height) + +struct window { + struct window *next; + Window id; + Pixmap pixmap; + XWindowAttributes a; + int solid; + int damaged; + Damage damage; + Picture picture; + Picture alpha_picture; + XserverRegion border_size; + XserverRegion extents; + uint32_t opacity; + int shaped; + XRectangle shape_bounds; + + /* for drawing translucent windows */ + XserverRegion border_clip; + struct window *prev_trans; +}; + +static unsigned long int *ignores = NULL; +static size_t n_ignores = 0, size_ignores = 0; +static Display *dpy; +static int screen; +static Window root; +static int root_height, root_width; +static int damage_error, xfixes_error, render_error; +static int damage_event, xshape_event; +static int composite_opcode; +static Atom opacity_atom; +static XRenderColor alpha_colour = {.red = 0, .green = 0, .blue = 0}; + +static struct window *window_list; +static Picture root_picture; +static Picture root_buffer; +static Picture root_tile; +static XserverRegion all_damage; +static int clip_changed; + +static const char *background_properties[] = {"_XROOTPMAP_ID", "_XSETROOT_ID", NULL}; + +static void +usage(const char *program) +{ + fprintf(stderr, "usage: %s\n", program); + exit(1); +} + +static Picture +solid_picture(double a) +{ + Pixmap pixmap; + Picture picture; + XRenderPictureAttributes pa; + + pixmap = XCreatePixmap(dpy, root, 1, 1, 8); + if (!pixmap) + return None; + + pa.repeat = 1; + picture = XRenderCreatePicture(dpy, pixmap, XRenderFindStandardFormat(dpy, PictStandardA8), CPRepeat, &pa); + if (!picture) { + XFreePixmap(dpy, pixmap); + return None; + } + + alpha_colour.alpha = a * 0xFFFF; + XRenderFillRectangle(dpy, PictOpSrc, picture, &alpha_colour, 0, 0, 1, 1); + XFreePixmap(dpy, pixmap); + return picture; +} + +static void +discard_ignore(unsigned long int sequence) +{ + size_t i; + for (i = 0; i < n_ignores && sequence > ignores[i]; i++); + memmove(ignores, &ignores[i], (n_ignores -= i) * sizeof(*ignores)); +} + +static void +set_ignore(unsigned long int sequence) +{ + if (n_ignores == size_ignores) + ignores = erealloc(ignores, (size_ignores += 64) * sizeof(*ignores)); + ignores[n_ignores++] = sequence; +} + +static int +should_ignore(unsigned long int sequence) +{ + discard_ignore(sequence); + return n_ignores && ignores[0] == sequence; +} + +static struct window * +find_window(Window id) +{ + struct window *w; + for (w = window_list; w; w = w->next) + if (w->id == id) + return w; + return NULL; +} + +static Picture +make_root_tile(void) +{ + Picture picture; + Atom actual_type; + Pixmap pixmap; + int actual_format; + unsigned long int nitems; + unsigned long int bytes_after; + unsigned char *prop; + int fill; + XRenderPictureAttributes pa; + int p; + + pixmap = None; + for (p = 0; background_properties[p]; p++) { + if (!XGetWindowProperty(dpy, root, XInternAtom(dpy, background_properties[p], 0), 0, 4, 0, AnyPropertyType, + &actual_type, &actual_format, &nitems, &bytes_after, &prop) && + actual_type == XInternAtom(dpy, "PIXMAP", 0) && actual_format == 32 && nitems == 1) { + memcpy(&pixmap, prop, 4); + XFree(prop); + fill = 0; + break; + } + } + if (!pixmap) { + pixmap = XCreatePixmap(dpy, root, 1, 1, DefaultDepth(dpy, screen)); + fill = 1; + } + pa.repeat = 1; + picture = XRenderCreatePicture(dpy, pixmap, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), CPRepeat, &pa); + if (fill) { + alpha_colour.alpha = 0xFFFF; + XRenderFillRectangle(dpy, PictOpSrc, picture, &alpha_colour, 0, 0, 1, 1); + } + return picture; +} + +static void +paint_root(void) +{ + if (!root_tile) + root_tile = make_root_tile(); + XRenderComposite(dpy, PictOpSrc, root_tile, None, root_buffer, 0, 0, 0, 0, 0, 0, root_width, root_height); +} + +static XserverRegion +win_extents(struct window *w) +{ + XRectangle r; + COPY_AREA(&r, &w->a); + r.width += w->a.border_width * 2; + r.height += w->a.border_width * 2; + return XFixesCreateRegion(dpy, &r, 1); +} + +static XserverRegion +border_size(struct window *w) +{ + XserverRegion border; + set_ignore(NextRequest(dpy)); + border = XFixesCreateRegionFromWindow(dpy, w->id, WindowRegionBounding); + set_ignore(NextRequest(dpy)); + XFixesTranslateRegion(dpy, border, w->a.x + w->a.border_width, w->a.y + w->a.border_width); + return border; +} + +static void +paint_all(XserverRegion region) +{ + struct window *w, *t = NULL; + XRectangle r; + int x, y, wid, hei; + Pixmap rootPixmap; + XRenderPictureAttributes pa; + XRenderPictFormat *format; + Drawable draw; + + if (!region) { + r.x = r.y = 0; + r.width = root_width; + r.height = root_height; + region = XFixesCreateRegion(dpy, &r, 1); + } + if (!root_buffer) { + rootPixmap = XCreatePixmap(dpy, root, root_width, root_height, DefaultDepth(dpy, screen)); + root_buffer = XRenderCreatePicture(dpy, rootPixmap, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + XFreePixmap(dpy, rootPixmap); + } + XFixesSetPictureClipRegion(dpy, root_picture, 0, 0, region); + for (w = window_list; w; w = w->next) { + if (!w->damaged) + continue; + if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 || w->a.x >= root_width || w->a.y >= root_height) + continue; + if (!w->picture) { + draw = w->id; + if (w->pixmap) + draw = w->pixmap; + else + w->pixmap = XCompositeNameWindowPixmap(dpy, w->id); + format = XRenderFindVisualFormat(dpy, w->a.visual); + pa.subwindow_mode = IncludeInferiors; + w->picture = XRenderCreatePicture(dpy, draw, format, CPSubwindowMode, &pa); + } + if (clip_changed) { + if (w->border_size) { + set_ignore(NextRequest(dpy)); + XFixesDestroyRegion(dpy, w->border_size); + w->border_size = None; + } + if (w->extents) { + XFixesDestroyRegion(dpy, w->extents); + w->extents = None; + } + if (w->border_clip) { + XFixesDestroyRegion(dpy, w->border_clip); + w->border_clip = None; + } + } + if (!w->border_size) + w->border_size = border_size(w); + if (!w->extents) + w->extents = win_extents(w); + if (w->solid) { + x = w->a.x; + y = w->a.y; + wid = w->a.width + w->a.border_width * 2; + hei = w->a.height + w->a.border_width * 2; + XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region); + set_ignore(NextRequest(dpy)); + XFixesSubtractRegion(dpy, region, region, w->border_size); + set_ignore(NextRequest(dpy)); + XRenderComposite(dpy, PictOpSrc, w->picture, None, root_buffer, 0, 0, 0, 0, x, y, wid, hei); + } + if (!w->border_clip) { + w->border_clip = XFixesCreateRegion(dpy, NULL, 0); + XFixesCopyRegion(dpy, w->border_clip, region); + XFixesIntersectRegion(dpy, w->border_clip, w->border_clip, w->border_size); + } + w->prev_trans = t; + t = w; + } + XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region); + paint_root(); + for (w = t; w; w = w->prev_trans) { + XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, w->border_clip); + if (w->opacity != OPAQUE && !w->alpha_picture) + w->alpha_picture = solid_picture((double)w->opacity / OPAQUE); + if (!w->solid) { + x = w->a.x; + y = w->a.y; + wid = w->a.width + w->a.border_width * 2; + hei = w->a.height + w->a.border_width * 2; + set_ignore(NextRequest(dpy)); + XRenderComposite(dpy, PictOpOver, w->picture, w->alpha_picture, root_buffer, 0, 0, 0, 0, x, y, wid, hei); + } + XFixesDestroyRegion(dpy, w->border_clip); + w->border_clip = None; + } + XFixesDestroyRegion(dpy, region); + if (root_buffer != root_picture) { + XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, None); + XRenderComposite(dpy, PictOpSrc, root_buffer, None, root_picture, 0, 0, 0, 0, 0, 0, root_width, root_height); + } +} + +static void +add_damage(XserverRegion damage) +{ + if (all_damage) { + XFixesUnionRegion(dpy, all_damage, all_damage, damage); + XFixesDestroyRegion(dpy, damage); + } else { + all_damage = damage; + } +} + +static unsigned int +get_opacity_prop(struct window *w, unsigned int def) +{ + uint32_t i; + Atom actual; + int format; + unsigned long int n, left; + unsigned char *data; + int err = XGetWindowProperty(dpy, w->id, opacity_atom, 0L, 1L, 0, XA_CARDINAL, &actual, &format, &n, &left, &data); + if (!err && data) { + i = *(uint32_t *)data; + XFree((void *)data); + return i; + } + return def; +} + +static void +determine_mode(struct window *w) +{ + XRenderPictFormat *format; + XserverRegion damage; + + if (w->alpha_picture) { + XRenderFreePicture(dpy, w->alpha_picture); + w->alpha_picture = None; + } + + w->opacity = get_opacity_prop(w, OPAQUE); + + w->solid = (w->opacity == OPAQUE && + ((format = w->a.class == InputOnly ? NULL : XRenderFindVisualFormat(dpy, w->a.visual)), + (!format || format->type != PictTypeDirect || !format->direct.alphaMask))); + + if (w->extents) { + damage = XFixesCreateRegion(dpy, NULL, 0); + XFixesCopyRegion(dpy, damage, w->extents); + add_damage(damage); + } +} + +static void +map_window(Window id) +{ + struct window *w = find_window(id); + if (!w) + return; + + w->a.map_state = IsViewable; + + /* This needs to be here or else we lose transparency messages */ + XSelectInput(dpy, id, PropertyChangeMask); + + /* This needs to be here since we don't get PropertyNotify when unmapped */ + determine_mode(w); + + w->damaged = 0; +} + +static void +finish_unmap_window(struct window *w) +{ + w->damaged = 0; + if (w->extents != None) { + add_damage(w->extents); /* destroys region */ + w->extents = None; + } + + if (w->pixmap) { + XFreePixmap(dpy, w->pixmap); + w->pixmap = None; + } + + if (w->picture) { + set_ignore(NextRequest(dpy)); + XRenderFreePicture(dpy, w->picture); + w->picture = None; + } + + /* don't care about properties anymore */ + set_ignore(NextRequest(dpy)); + XSelectInput(dpy, w->id, 0); + + if (w->border_size) { + set_ignore(NextRequest(dpy)); + XFixesDestroyRegion(dpy, w->border_size); + w->border_size = None; + } + if (w->border_clip) { + XFixesDestroyRegion(dpy, w->border_clip); + w->border_clip = None; + } + + clip_changed = 1; +} + +static void +unmap_window(Window id) +{ + struct window *w = find_window(id); + if (w) { + w->a.map_state = IsUnmapped; + finish_unmap_window(w); + } +} + +static void +add_window(Window id) +{ + struct window *w = ecalloc(1, sizeof(struct window)); + w->id = id; + set_ignore(NextRequest(dpy)); + if (!XGetWindowAttributes(dpy, id, &w->a)) { + free(w); + return; + } + COPY_AREA(&w->shape_bounds, &w->a); + if (w->a.class != InputOnly) { + w->damage = XDamageCreate(dpy, id, XDamageReportNonEmpty); + XShapeSelectInput(dpy, id, ShapeNotifyMask); + } + w->opacity = OPAQUE; + w->next = window_list; + window_list = w; + if (w->a.map_state == IsViewable) + map_window(id); +} + +static void +restack_window(struct window *w, Window new_above) +{ + Window old_above; + struct window **prev; + + old_above = w->next ? w->next->id : None; + + if (old_above != new_above) { + /* unhook */ + for (prev = &window_list; *prev; prev = &(*prev)->next) + if ((*prev) == w) + break; + *prev = w->next; + + /* rehook */ + for (prev = &window_list; *prev; prev = &(*prev)->next) + if ((*prev)->id == new_above) + break; + w->next = *prev; + *prev = w; + } +} + +static void +configure_window(XConfigureEvent *ce) +{ + struct window *w = find_window(ce->window); + XserverRegion extents, damage = None; + + if (!w) { + if (ce->window == root) { + if (root_buffer) { + XRenderFreePicture(dpy, root_buffer); + root_buffer = None; + } + root_width = ce->width; + root_height = ce->height; + } + return; + } + + damage = XFixesCreateRegion(dpy, NULL, 0); + if (w->extents != None) + XFixesCopyRegion(dpy, damage, w->extents); + if (w->a.width != ce->width || w->a.height != ce->height) { + if (w->pixmap) { + XFreePixmap(dpy, w->pixmap); + w->pixmap = None; + if (w->picture) { + XRenderFreePicture(dpy, w->picture); + w->picture = None; + } + } + } + w->shape_bounds.x -= w->a.x; + w->shape_bounds.y -= w->a.y; + COPY_AREA(&w->a, ce); + w->a.border_width = ce->border_width; + w->a.override_redirect = ce->override_redirect; + restack_window(w, ce->above); + if (damage) { + extents = win_extents(w); + XFixesUnionRegion(dpy, damage, damage, extents); + XFixesDestroyRegion(dpy, extents); + add_damage(damage); + } + w->shape_bounds.x += w->a.x; + w->shape_bounds.y += w->a.y; + if (!w->shaped) { + w->shape_bounds.width = w->a.width; + w->shape_bounds.height = w->a.height; + } + + clip_changed = 1; +} + +static void +circulate_window(XCirculateEvent *ce) +{ + Window new_above; + struct window *w = find_window(ce->window); + if (!w) + return; + new_above = ce->place == PlaceOnTop ? window_list->id : None; + restack_window(w, new_above); + clip_changed = 1; +} + +static void +destroy_window(Window id, int gone) +{ + struct window **prev, *w; + for (prev = &window_list; (w = *prev); prev = &w->next) { + if (w->id == id) { + if (gone) + finish_unmap_window(w); + *prev = w->next; + if (w->picture) { + set_ignore(NextRequest(dpy)); + XRenderFreePicture(dpy, w->picture); + w->picture = None; + } + if (w->alpha_picture) { + XRenderFreePicture(dpy, w->alpha_picture); + w->alpha_picture = None; + } + if (w->damage != None) { + set_ignore(NextRequest(dpy)); + XDamageDestroy(dpy, w->damage); + w->damage = None; + } + free(w); + break; + } + } +} + +static void +damage_window(XDamageNotifyEvent *de) +{ + XserverRegion parts; + struct window *w = find_window(de->drawable); + if (!w) + return; + if (!w->damaged) { + parts = win_extents(w); + set_ignore(NextRequest(dpy)); + XDamageSubtract(dpy, w->damage, None, None); + } else { + parts = XFixesCreateRegion(dpy, NULL, 0); + set_ignore(NextRequest(dpy)); + XDamageSubtract(dpy, w->damage, None, parts); + XFixesTranslateRegion(dpy, parts, w->a.x + w->a.border_width, w->a.y + w->a.border_width); + } + add_damage(parts); + w->damaged = 1; +} + +static void +shape_window(XShapeEvent *se) +{ + XserverRegion region0, region1; + struct window *w = find_window(se->window); + + if (!w) + return; + + if (se->kind == ShapeClip || se->kind == ShapeBounding) { + clip_changed = 1; + + region0 = XFixesCreateRegion(dpy, &w->shape_bounds, 1); + + if (se->shaped) { + w->shaped = 1; + COPY_AREA(&w->shape_bounds, se); + w->shape_bounds.x += w->a.x; + w->shape_bounds.y += w->a.y; + } else { + w->shaped = 0; + COPY_AREA(&w->shape_bounds, &w->a); + } + + region1 = XFixesCreateRegion(dpy, &w->shape_bounds, 1); + XFixesUnionRegion(dpy, region0, region0, region1); + XFixesDestroyRegion(dpy, region1); + + /* ask for repaint of the old and new region */ + paint_all(region0); + } +} + +static int +error(Display *display, XErrorEvent *ev) +{ + const char *name = NULL; + static char buffer[256]; + + if (should_ignore(ev->serial)) + return 0; + + if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows) + eprintf("another composite manager is already running\n"); + + if (ev->error_code - xfixes_error == BadRegion) { + name = "BadRegion"; + } else if (ev->error_code - damage_error == BadDamage) { + name = "BadDamage"; + } else { + switch (ev->error_code - render_error) { + case BadPictFormat: name = "BadPictFormat"; break; + case BadPicture: name = "BadPicture"; break; + case BadPictOp: name = "BadPictOp"; break; + case BadGlyphSet: name = "BadGlyphSet"; break; + case BadGlyph: name = "BadGlyph"; break; + default: + break; + } + } + + if (!name) { + buffer[0] = '\0'; + XGetErrorText(display, ev->error_code, buffer, sizeof(buffer)); + name = buffer; + } + + fprintf(stderr, "error %i: %s request %i minor %i serial %lu\n", + ev->error_code, (strlen(name) > 0) ? name : "unknown", + ev->request_code, ev->minor_code, ev->serial); + + return 0; +} + +static void +register_composite_manager(void) +{ + static char net_wm_cm[sizeof("_NET_WM_CM_S") + 3 * sizeof(screen)]; + Window w; + Atom a, winNameAtom; + XTextProperty tp; + char **strs; + int count; + + sprintf(net_wm_cm, "_NET_WM_CM_S%i", screen); + a = XInternAtom(dpy, net_wm_cm, 0); + + w = XGetSelectionOwner(dpy, a); + if (w != None) { + winNameAtom = XInternAtom(dpy, "_NET_WM_NAME", 0); + if (!XGetTextProperty(dpy, w, &tp, winNameAtom) && + !XGetTextProperty(dpy, w, &tp, XA_WM_NAME)) { + eprintf("another composite manager is already running (0x%lx)\n", (unsigned long int)w); + } + if (!XmbTextPropertyToTextList(dpy, &tp, &strs, &count)) { + fprintf(stderr, "another composite manager is already running (%s)\n", strs[0]); + XFreeStringList(strs); + } + XFree(tp.value); + exit(1); + } + + w = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 0, 0, 1, 1, 0, None, None); + Xutf8SetWMProperties(dpy, w, "xcompmgr", "xcompmgr", NULL, 0, NULL, NULL, NULL); + XSetSelectionOwner(dpy, a, w, 0); +} + +int +main(int argc, char **argv) +{ + XEvent ev; + Window root_return, parent_return, *children; + XRenderPictureAttributes pa; + XRectangle *expose_rects = NULL; + size_t n_expose = 0, size_expose = 0; + unsigned int i, n; + int more, composite_major, composite_minor; + struct window *w; + + if (argc > 1) + usage(argv[0]); + + dpy = XOpenDisplay(NULL); + if (!dpy) + eprintf("cannot open display\n"); + XSetErrorHandler(error); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + + if (!XRenderQueryExtension(dpy, &(int){0}, &render_error)) + eprintf("no render extension\n"); + if (!XQueryExtension(dpy, COMPOSITE_NAME, &composite_opcode, &(int){0}, &(int){0})) + eprintf("no composite extension\n"); + XCompositeQueryVersion(dpy, &composite_major, &composite_minor); + if (!composite_major && composite_minor < 2) + eprintf("no composite extension version is too old\n"); + if (!XDamageQueryExtension(dpy, &damage_event, &damage_error)) + eprintf("no damage extension\n"); + if (!XFixesQueryExtension(dpy, &(int){0}, &xfixes_error)) + eprintf("no XFixes extension\n"); + if (!XShapeQueryExtension(dpy, &xshape_event, &(int){0})) + eprintf("no XShape extension\n"); + + register_composite_manager(); + opacity_atom = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", 0); + pa.subwindow_mode = IncludeInferiors; + root_width = DisplayWidth(dpy, screen); + root_height = DisplayHeight(dpy, screen); + root_picture = XRenderCreatePicture(dpy, root, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), CPSubwindowMode, &pa); + all_damage = None; + clip_changed = 1; + XGrabServer(dpy); + XCompositeRedirectSubwindows(dpy, root, CompositeRedirectManual); + XSelectInput(dpy, root, SubstructureNotifyMask | ExposureMask | StructureNotifyMask | PropertyChangeMask); + XShapeSelectInput(dpy, root, ShapeNotifyMask); + XQueryTree(dpy, root, &root_return, &parent_return, &children, &n); + for (i = 0; i < n; i++) + add_window(children[i]); + XFree(children); + XUngrabServer(dpy); + paint_all(None); + + for (;;) { + XNextEvent(dpy, &ev); + if ((ev.type & 0x7F) != KeymapNotify) + discard_ignore(ev.xany.serial); + switch (ev.type) { + case CreateNotify: add_window(ev.xcreatewindow.window); break; + case ConfigureNotify: configure_window(&ev.xconfigure); break; + case DestroyNotify: destroy_window(ev.xdestroywindow.window, 1); break; + case CirculateNotify: circulate_window(&ev.xcirculate); break; + case MapNotify: map_window(ev.xmap.window); break; + case UnmapNotify: unmap_window(ev.xunmap.window); break; + case ReparentNotify: + if (ev.xreparent.parent == root) + add_window(ev.xreparent.window); + else + destroy_window(ev.xreparent.window, 0); + break; + case Expose: + if (ev.xexpose.window == root) { + more = ev.xexpose.count + 1; + if (n_expose == size_expose) + expose_rects = erealloc(expose_rects, (size_expose += more) * sizeof(XRectangle)); + COPY_AREA(&expose_rects[n_expose], &ev.xexpose); + n_expose++; + if (!ev.xexpose.count) { + add_damage(XFixesCreateRegion(dpy, expose_rects, n_expose)); + n_expose = 0; + } + } + break; + case PropertyNotify: + if (ev.xproperty.atom == opacity_atom) { + if ((w = find_window(ev.xproperty.window))) + determine_mode(w); + } else if (root_tile) { + for (i = 0; background_properties[i]; i++) { + if (ev.xproperty.atom == XInternAtom(dpy, background_properties[i], 0)) { + XClearArea(dpy, root, 0, 0, 0, 0, 1); + XRenderFreePicture(dpy, root_tile); + root_tile = None; + break; + } + } + } + break; + default: + if (ev.type == damage_event + XDamageNotify) + damage_window((XDamageNotifyEvent *)&ev); + else if (ev.type == xshape_event + ShapeNotify) + shape_window((XShapeEvent *)&ev); + break; + } + if (!QLength(dpy) && all_damage) { + paint_all(all_damage); + XSync(dpy, 0); + all_damage = None; + clip_changed = 0; + } + } +} diff --git a/xcompmgr.c b/xcompmgr.c deleted file mode 100644 index 3968def..0000000 --- a/xcompmgr.c +++ /dev/null @@ -1,2378 +0,0 @@ -/* - * Copyright © 2003 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - - -/* Modified by Matthew Hawn. I don't know what to say here so follow what it - says above. Not that I can really do anything about it -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAS_NAME_WINDOW_PIXMAP 1 -#endif - -#define CAN_DO_USABLE 0 - -typedef struct _ignore { - struct _ignore *next; - unsigned long sequence; -} ignore; - -typedef struct _win { - struct _win *next; - Window id; -#if HAS_NAME_WINDOW_PIXMAP - Pixmap pixmap; -#endif - XWindowAttributes a; -#if CAN_DO_USABLE - Bool usable; /* mapped and all damaged at one point */ - XRectangle damage_bounds; /* bounds of damage */ -#endif - int mode; - int damaged; - Damage damage; - Picture picture; - Picture alphaPict; - Picture shadowPict; - XserverRegion borderSize; - XserverRegion extents; - Picture shadow; - int shadow_dx; - int shadow_dy; - int shadow_width; - int shadow_height; - unsigned int opacity; - Atom windowType; - unsigned long damage_sequence; /* sequence when damage was created */ - Bool shaped; - XRectangle shape_bounds; - - /* for drawing translucent windows */ - XserverRegion borderClip; - struct _win *prev_trans; -} win; - -typedef struct _conv { - int size; - double *data; -} conv; - -typedef struct _fade { - struct _fade *next; - win *w; - double cur; - double finish; - double step; - void (*callback) (Display *dpy, win *w, Bool gone); - Display *dpy; - Bool gone; -} fade; - -static win *list; -static fade *fades; -static int scr; -static Window root; -static Picture rootPicture; -static Picture rootBuffer; -static Picture blackPicture; -static Picture transBlackPicture; -static Picture rootTile; -static XserverRegion allDamage; -static Bool clipChanged; -#if HAS_NAME_WINDOW_PIXMAP -static Bool hasNamePixmap; -#endif -static int root_height, root_width; -static ignore *ignore_head, **ignore_tail = &ignore_head; -static int xfixes_event, xfixes_error; -static int damage_event, damage_error; -static int composite_event, composite_error; -static int render_event, render_error; -static int xshape_event, xshape_error; -static Bool synchronize; -static int composite_opcode; - -/* find these once and be done with it */ -static Atom opacityAtom; -static Atom winTypeAtom; -static Atom winDesktopAtom; -static Atom winDockAtom; -static Atom winToolbarAtom; -static Atom winMenuAtom; -static Atom winUtilAtom; -static Atom winSplashAtom; -static Atom winDialogAtom; -static Atom winNormalAtom; - -/* opacity property name; sometime soon I'll write up an EWMH spec for it */ -#define OPACITY_PROP "_NET_WM_WINDOW_OPACITY" - -#define TRANSLUCENT 0xe0000000 -#define OPAQUE 0xffffffff - -static conv *gaussianMap; - -#define WINDOW_SOLID 0 -#define WINDOW_TRANS 1 -#define WINDOW_ARGB 2 - -#define TRANS_OPACITY 0.75 - -#define DEBUG_REPAINT 0 -#define DEBUG_EVENTS 0 -#define DEBUG_SHAPE 0 -#define MONITOR_REPAINT 0 - -#define SHADOWS 1 -#define SHARP_SHADOW 0 - -typedef enum _compMode { - CompSimple, /* looks like a regular X server */ - CompServerShadows, /* use window alpha for shadow; sharp, but precise */ - CompClientShadows, /* use window extents for shadow, blurred */ -} 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); - -static CompMode compMode = CompSimple; - -static int shadowRadius = 12; -static int shadowOffsetX = -15; -static int shadowOffsetY = -15; -static double shadowOpacity = .75; - -static double fade_in_step = 0.028; -static double fade_out_step = 0.03; -static int fade_delta = 10; -static int fade_time = 0; -static Bool fadeWindows = False; -static Bool excludeDockShadows = False; -static Bool fadeTrans = False; - -static Bool autoRedirect = False; - -/* For shadow precomputation */ -static int Gsize = -1; -static unsigned char *shadowCorner = NULL; -static unsigned char *shadowTop = NULL; - -static int -get_time_in_milliseconds (void) -{ - struct timeval tv; - - gettimeofday (&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static fade * -find_fade (win *w) -{ - fade *f; - - for (f = fades; f; f = f->next) - { - if (f->w == w) - return f; - } - return NULL; -} - -static void -dequeue_fade (Display *dpy, fade *f) -{ - fade **prev; - - for (prev = &fades; *prev; prev = &(*prev)->next) - if (*prev == f) - { - *prev = f->next; - if (f->callback) - (*f->callback) (dpy, f->w, f->gone); - free (f); - break; - } -} - -static void -cleanup_fade (Display *dpy, win *w) -{ - fade *f = find_fade (w); - if (f) - dequeue_fade (dpy, f); -} - -static void -enqueue_fade (Display *dpy, fade *f) -{ - if (!fades) - fade_time = get_time_in_milliseconds () + fade_delta; - f->next = fades; - fades = f; -} - -static void -set_fade (Display *dpy, win *w, double start, double finish, double step, - void (*callback) (Display *dpy, win *w, Bool gone), - Bool gone, Bool exec_callback, Bool override) -{ - fade *f; - - f = find_fade (w); - if (!f) - { - f = malloc (sizeof (fade)); - f->next = NULL; - f->w = w; - f->cur = start; - enqueue_fade (dpy, f); - } - else if(!override) - return; - else - { - 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; -#if 0 - 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); - } -} - -static int -fade_timeout (void) -{ - int now; - int delta; - if (!fades) - return -1; - now = get_time_in_milliseconds(); - delta = fade_time - now; - if (delta < 0) - delta = 0; -/* printf ("timeout %d\n", delta); */ - return delta; -} - -static void -run_fades (Display *dpy) -{ - int now = get_time_in_milliseconds(); - fade *next = fades; - int steps; - Bool need_dequeue; - -#if 0 - printf ("run fades\n"); -#endif - if (fade_time - now > 0) - return; - steps = 1 + (now - fade_time) / fade_delta; - - while (next) - { - fade *f = next; - win *w = f->w; - next = f->next; - f->cur += f->step * steps; - if (f->cur >= 1) - f->cur = 1; - else if (f->cur < 0) - f->cur = 0; -#if 0 - printf ("opacity now %g\n", f->cur); -#endif - w->opacity = f->cur * OPAQUE; - need_dequeue = False; - if (f->step > 0) - { - if (f->cur >= f->finish) - { - w->opacity = f->finish*OPAQUE; - need_dequeue = True; - } - } - else - { - if (f->cur <= f->finish) - { - w->opacity = f->finish*OPAQUE; - need_dequeue = True; - } - } - determine_mode (dpy, w); - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - w->extents = win_extents(dpy, w); - } - /* Must do this last as it might destroy f->w in callbacks */ - if (need_dequeue) - dequeue_fade (dpy, f); - } - fade_time = now + fade_delta; -} - -static double -gaussian (double r, double x, double y) -{ - return ((1 / (sqrt (2 * M_PI * r))) * - exp ((- (x * x + y * y)) / (2 * r * r))); -} - - -static conv * -make_gaussian_map (Display *dpy, double r) -{ - conv *c; - int size = ((int) ceil ((r * 3)) + 1) & ~1; - int center = size / 2; - int x, y; - double t; - double g; - - c = malloc (sizeof (conv) + size * size * sizeof (double)); - c->size = size; - c->data = (double *) (c + 1); - t = 0.0; - for (y = 0; y < size; y++) - for (x = 0; x < size; x++) - { - g = gaussian (r, (double) (x - center), (double) (y - center)); - t += g; - c->data[y * size + x] = g; - } -/* printf ("gaussian total %f\n", t); */ - for (y = 0; y < size; y++) - for (x = 0; x < size; x++) - { - c->data[y*size + x] /= t; - } - return c; -} - -/* - * A picture will help - * - * -center 0 width width+center - * -center +-----+-------------------+-----+ - * | | | | - * | | | | - * 0 +-----+-------------------+-----+ - * | | | | - * | | | | - * | | | | - * height +-----+-------------------+-----+ - * | | | | - * height+ | | | | - * center +-----+-------------------+-----+ - */ - -static unsigned char -sum_gaussian (conv *map, double opacity, int x, int y, int width, int height) -{ - int fx, fy; - double *g_data; - double *g_line = map->data; - int g_size = map->size; - int center = g_size / 2; - int fx_start, fx_end; - int fy_start, fy_end; - double v; - - /* - * Compute set of filter values which are "in range", - * that's the set with: - * 0 <= x + (fx-center) && x + (fx-center) < width && - * 0 <= y + (fy-center) && y + (fy-center) < height - * - * 0 <= x + (fx - center) x + fx - center < width - * center - x <= fx fx < width + center - x - */ - - fx_start = center - x; - if (fx_start < 0) - fx_start = 0; - fx_end = width + center - x; - if (fx_end > g_size) - fx_end = g_size; - - fy_start = center - y; - if (fy_start < 0) - fy_start = 0; - fy_end = height + center - y; - if (fy_end > g_size) - fy_end = g_size; - - g_line = g_line + fy_start * g_size + fx_start; - - v = 0; - for (fy = fy_start; fy < fy_end; fy++) - { - g_data = g_line; - g_line += g_size; - - for (fx = fx_start; fx < fx_end; fx++) - v += *g_data++; - } - if (v > 1) - v = 1; - - return ((unsigned char) (v * opacity * 255.0)); -} - -/* precompute shadow corners and sides to save time for large windows */ -static void -presum_gaussian (conv *map) -{ - int center = map->size/2; - int opacity, x, y; - - Gsize = map->size; - - if (shadowCorner) - free ((void *)shadowCorner); - if (shadowTop) - free ((void *)shadowTop); - - shadowCorner = (unsigned char *)(malloc ((Gsize + 1) * (Gsize + 1) * 26)); - shadowTop = (unsigned char *)(malloc ((Gsize + 1) * 26)); - - for (x = 0; x <= Gsize; x++) - { - shadowTop[25 * (Gsize + 1) + x] = sum_gaussian (map, 1, x - center, center, Gsize * 2, Gsize * 2); - for(opacity = 0; opacity < 25; opacity++) - shadowTop[opacity * (Gsize + 1) + x] = shadowTop[25 * (Gsize + 1) + x] * opacity / 25; - for(y = 0; y <= x; y++) - { - shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] - = sum_gaussian (map, 1, x - center, y - center, Gsize * 2, Gsize * 2); - shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y] - = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]; - for(opacity = 0; opacity < 25; opacity++) - shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] - = shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y] - = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] * opacity / 25; - } - } -} - -static XImage * -make_shadow (Display *dpy, double opacity, int width, int height) -{ - XImage *ximage; - unsigned char *data; - int gsize = gaussianMap->size; - int ylimit, xlimit; - int swidth = width + gsize; - int sheight = height + gsize; - int center = gsize / 2; - int x, y; - unsigned char d; - int x_diff; - int opacity_int = (int)(opacity * 25); - data = malloc (swidth * sheight * sizeof (unsigned char)); - if (!data) - return NULL; - ximage = XCreateImage (dpy, - DefaultVisual(dpy, DefaultScreen(dpy)), - 8, - ZPixmap, - 0, - (char *) data, - swidth, sheight, 8, swidth * sizeof (unsigned char)); - if (!ximage) - { - free (data); - return NULL; - } - /* - * Build the gaussian in sections - */ - - /* - * center (fill the complete data array) - */ - if (Gsize > 0) - d = shadowTop[opacity_int * (Gsize + 1) + Gsize]; - else - d = sum_gaussian (gaussianMap, opacity, center, center, width, height); - memset(data, d, sheight * swidth); - - /* - * corners - */ - ylimit = gsize; - if (ylimit > sheight / 2) - ylimit = (sheight + 1) / 2; - xlimit = gsize; - if (xlimit > swidth / 2) - xlimit = (swidth + 1) / 2; - - for (y = 0; y < ylimit; y++) - for (x = 0; x < xlimit; x++) - { - if (xlimit == Gsize && ylimit == Gsize) - d = shadowCorner[opacity_int * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]; - else - d = sum_gaussian (gaussianMap, opacity, x - center, y - center, width, height); - data[y * swidth + x] = d; - data[(sheight - y - 1) * swidth + x] = d; - data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - - /* - * top/bottom - */ - x_diff = swidth - (gsize * 2); - if (x_diff > 0 && ylimit > 0) - { - for (y = 0; y < ylimit; y++) - { - if (ylimit == Gsize) - d = shadowTop[opacity_int * (Gsize + 1) + y]; - else - d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height); - memset (&data[y * swidth + gsize], d, x_diff); - memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff); - } - } - - /* - * sides - */ - - for (x = 0; x < xlimit; x++) - { - if (xlimit == Gsize) - d = shadowTop[opacity_int * (Gsize + 1) + x]; - else - d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height); - for (y = gsize; y < sheight - gsize; y++) - { - data[y * swidth + x] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - } - - return ximage; -} - -static Picture -shadow_picture (Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp) -{ - XImage *shadowImage; - Pixmap shadowPixmap; - Picture shadowPicture; - GC gc; - - shadowImage = make_shadow (dpy, opacity, width, height); - if (!shadowImage) - return None; - shadowPixmap = XCreatePixmap (dpy, root, - shadowImage->width, - shadowImage->height, - 8); - if (!shadowPixmap) - { - XDestroyImage (shadowImage); - return None; - } - - shadowPicture = XRenderCreatePicture (dpy, shadowPixmap, - XRenderFindStandardFormat (dpy, PictStandardA8), - 0, NULL); - if (!shadowPicture) - { - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - return (Picture)None; - } - - gc = XCreateGC (dpy, shadowPixmap, 0, NULL); - if (!gc) - { - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - XRenderFreePicture (dpy, shadowPicture); - return (Picture)None; - } - - XPutImage (dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0, - shadowImage->width, - shadowImage->height); - *wp = shadowImage->width; - *hp = shadowImage->height; - XFreeGC (dpy, gc); - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - return shadowPicture; -} - -static Picture -solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b) -{ - Pixmap pixmap; - Picture picture; - XRenderPictureAttributes pa; - XRenderColor c; - - pixmap = XCreatePixmap (dpy, root, 1, 1, argb ? 32 : 8); - if (!pixmap) - return None; - - pa.repeat = True; - picture = XRenderCreatePicture (dpy, pixmap, - XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8), - CPRepeat, - &pa); - if (!picture) - { - XFreePixmap (dpy, pixmap); - return None; - } - - c.alpha = a * 0xffff; - c.red = r * 0xffff; - c.green = g * 0xffff; - c.blue = b * 0xffff; - XRenderFillRectangle (dpy, PictOpSrc, picture, &c, 0, 0, 1, 1); - XFreePixmap (dpy, pixmap); - return picture; -} - -static void -discard_ignore (Display *dpy, unsigned long sequence) -{ - while (ignore_head) - { - if ((long) (sequence - ignore_head->sequence) > 0) - { - ignore *next = ignore_head->next; - free (ignore_head); - ignore_head = next; - if (!ignore_head) - ignore_tail = &ignore_head; - } - else - break; - } -} - -static void -set_ignore (Display *dpy, unsigned long sequence) -{ - ignore *i = malloc (sizeof (ignore)); - if (!i) - return; - i->sequence = sequence; - i->next = NULL; - *ignore_tail = i; - ignore_tail = &i->next; -} - -static int -should_ignore (Display *dpy, unsigned long sequence) -{ - discard_ignore (dpy, sequence); - return ignore_head && ignore_head->sequence == sequence; -} - -static win * -find_win (Display *dpy, Window id) -{ - win *w; - - for (w = list; w; w = w->next) - if (w->id == id) - return w; - return NULL; -} - -static const char *backgroundProps[] = { - "_XROOTPMAP_ID", - "_XSETROOT_ID", - NULL, -}; - -static Picture -root_tile (Display *dpy) -{ - Picture picture; - Atom actual_type; - Pixmap pixmap; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop; - Bool fill; - XRenderPictureAttributes pa; - int p; - - pixmap = None; - for (p = 0; backgroundProps[p]; p++) - { - if (XGetWindowProperty (dpy, root, XInternAtom (dpy, backgroundProps[p], False), - 0, 4, False, AnyPropertyType, - &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success && - actual_type == XInternAtom (dpy, "PIXMAP", False) && actual_format == 32 && nitems == 1) - { - memcpy (&pixmap, prop, 4); - XFree (prop); - fill = False; - break; - } - } - if (!pixmap) - { - pixmap = XCreatePixmap (dpy, root, 1, 1, DefaultDepth (dpy, scr)); - fill = True; - } - pa.repeat = True; - picture = XRenderCreatePicture (dpy, pixmap, - XRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - CPRepeat, &pa); - if (fill) - { - XRenderColor c; - - c.red = c.green = c.blue = 0x8080; - c.alpha = 0xffff; - XRenderFillRectangle (dpy, PictOpSrc, picture, &c, - 0, 0, 1, 1); - } - return picture; -} - -static void -paint_root (Display *dpy) -{ - if (!rootTile) - rootTile = root_tile (dpy); - - XRenderComposite (dpy, PictOpSrc, - rootTile, None, rootBuffer, - 0, 0, 0, 0, 0, 0, root_width, root_height); -} - -static XserverRegion -win_extents (Display *dpy, win *w) -{ - XRectangle r; - - r.x = w->a.x; - 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 && !(w->windowType == winDockAtom && excludeDockShadows)) - { - if (compMode == CompServerShadows || w->mode != WINDOW_ARGB) - { - XRectangle sr; - - if (compMode == CompServerShadows) - { - w->shadow_dx = 2; - w->shadow_dy = 7; - w->shadow_width = w->a.width; - w->shadow_height = w->a.height; - } - else - { - w->shadow_dx = shadowOffsetX; - w->shadow_dy = shadowOffsetY; - if (!w->shadow) - { - double opacity = shadowOpacity; - if (w->mode == WINDOW_TRANS) - 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); - } - } - sr.x = w->a.x + w->shadow_dx; - sr.y = w->a.y + w->shadow_dy; - sr.width = w->shadow_width; - sr.height = w->shadow_height; - if (sr.x < r.x) - { - r.width = (r.x + r.width) - sr.x; - r.x = sr.x; - } - if (sr.y < r.y) - { - r.height = (r.y + r.height) - sr.y; - r.y = sr.y; - } - if (sr.x + sr.width > r.x + r.width) - r.width = sr.x + sr.width - r.x; - if (sr.y + sr.height > r.y + r.height) - r.height = sr.y + sr.height - r.y; - } - } - return XFixesCreateRegion (dpy, &r, 1); -} - -static XserverRegion -border_size (Display *dpy, win *w) -{ - XserverRegion border; - /* - * if window doesn't exist anymore, this will generate an error - * as well as not generate a region. Perhaps a better XFixes - * architecture would be to have a request that copies instead - * of creates, that way you'd just end up with an empty region - * instead of an invalid XID. - */ - set_ignore (dpy, NextRequest (dpy)); - border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding); - /* translate this */ - set_ignore (dpy, NextRequest (dpy)); - XFixesTranslateRegion (dpy, border, - w->a.x + w->a.border_width, - w->a.y + w->a.border_width); - return border; -} - -static void -paint_all (Display *dpy, XserverRegion region) -{ - win *w; - win *t = NULL; - - if (!region) - { - XRectangle r; - r.x = 0; - r.y = 0; - r.width = root_width; - r.height = root_height; - region = XFixesCreateRegion (dpy, &r, 1); - } -#if MONITOR_REPAINT - rootBuffer = rootPicture; -#else - if (!rootBuffer) - { - Pixmap rootPixmap = XCreatePixmap (dpy, root, root_width, root_height, - DefaultDepth (dpy, scr)); - rootBuffer = XRenderCreatePicture (dpy, rootPixmap, - XRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - 0, NULL); - XFreePixmap (dpy, rootPixmap); - } -#endif - XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); -#if MONITOR_REPAINT - XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootPicture, - 0, 0, 0, 0, 0, 0, root_width, root_height); -#endif -#if DEBUG_REPAINT - printf ("paint:"); -#endif - for (w = list; w; w = w->next) - { -#if CAN_DO_USABLE - if (!w->usable) - continue; -#endif - /* never painted, ignore it */ - if (!w->damaged) - continue; - /* if invisible, ignore it */ - if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 - || w->a.x >= root_width || w->a.y >= root_height) - continue; - if (!w->picture) - { - XRenderPictureAttributes pa; - XRenderPictFormat *format; - Drawable draw = w->id; - -#if HAS_NAME_WINDOW_PIXMAP - if (hasNamePixmap && !w->pixmap) - w->pixmap = XCompositeNameWindowPixmap (dpy, w->id); - if (w->pixmap) - draw = w->pixmap; -#endif - format = XRenderFindVisualFormat (dpy, w->a.visual); - pa.subwindow_mode = IncludeInferiors; - w->picture = XRenderCreatePicture (dpy, draw, - format, - CPSubwindowMode, - &pa); - } -#if DEBUG_REPAINT - printf (" 0x%x", w->id); -#endif - if (clipChanged) - { - if (w->borderSize) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->borderSize); - w->borderSize = None; - } - if (w->extents) - { - XFixesDestroyRegion (dpy, w->extents); - w->extents = None; - } - if (w->borderClip) - { - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - } - if (!w->borderSize) - w->borderSize = border_size (dpy, w); - if (!w->extents) - w->extents = win_extents (dpy, w); - if (w->mode == WINDOW_SOLID) - { - int x, y, wid, hei; -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#else - x = w->a.x + w->a.border_width; - y = w->a.y + w->a.border_width; - wid = w->a.width; - hei = w->a.height; -#endif - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); - set_ignore (dpy, NextRequest (dpy)); - XFixesSubtractRegion (dpy, region, region, w->borderSize); - set_ignore (dpy, NextRequest (dpy)); - XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer, - 0, 0, 0, 0, - x, y, wid, hei); - } - if (!w->borderClip) - { - w->borderClip = XFixesCreateRegion (dpy, NULL, 0); - XFixesCopyRegion (dpy, w->borderClip, region); - XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize); - } - w->prev_trans = t; - t = w; - } -#if DEBUG_REPAINT - printf ("\n"); - fflush (stdout); -#endif - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); - paint_root (dpy); - for (w = t; w; w = w->prev_trans) - { - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); - switch (compMode) { - case CompSimple: - break; - case CompServerShadows: - /* dont' bother drawing shadows on desktop windows */ - if (w->windowType == winDesktopAtom) - break; - set_ignore (dpy, NextRequest (dpy)); - if (w->opacity != OPAQUE && !w->shadowPict) - w->shadowPict = solid_picture (dpy, True, - (double) w->opacity / OPAQUE * 0.3, - 0, 0, 0); - XRenderComposite (dpy, PictOpOver, - w->shadowPict ? w->shadowPict : transBlackPicture, - w->picture, rootBuffer, - 0, 0, 0, 0, - w->a.x + w->shadow_dx, - w->a.y + w->shadow_dy, - w->shadow_width, w->shadow_height); - break; - case CompClientShadows: - /* don't bother drawing shadows on desktop windows */ - if (w->shadow && w->windowType != winDesktopAtom) - { - XRenderComposite (dpy, PictOpOver, blackPicture, w->shadow, rootBuffer, - 0, 0, 0, 0, - w->a.x + w->shadow_dx, - w->a.y + w->shadow_dy, - w->shadow_width, w->shadow_height); - } - break; - } - if (w->opacity != OPAQUE && !w->alphaPict) - w->alphaPict = solid_picture (dpy, False, - (double) w->opacity / OPAQUE, 0, 0, 0); - if (w->mode == WINDOW_TRANS) - { - int x, y, wid, hei; -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#else - x = w->a.x + w->a.border_width; - y = w->a.y + w->a.border_width; - wid = w->a.width; - hei = w->a.height; -#endif - set_ignore (dpy, NextRequest (dpy)); - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, 0, 0, 0, - x, y, wid, hei); - } - else if (w->mode == WINDOW_ARGB) - { - int x, y, wid, hei; -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#else - x = w->a.x + w->a.border_width; - y = w->a.y + w->a.border_width; - wid = w->a.width; - hei = w->a.height; -#endif - set_ignore (dpy, NextRequest (dpy)); - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, 0, 0, 0, - x, y, wid, hei); - } - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - XFixesDestroyRegion (dpy, region); - if (rootBuffer != rootPicture) - { - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, None); - XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture, - 0, 0, 0, 0, 0, 0, root_width, root_height); - } -} - -static void -add_damage (Display *dpy, XserverRegion damage) -{ - if (allDamage) - { - XFixesUnionRegion (dpy, allDamage, allDamage, damage); - XFixesDestroyRegion (dpy, damage); - } - else - allDamage = damage; -} - -static void -repair_win (Display *dpy, win *w) -{ - XserverRegion parts; - - if (!w->damaged) - { - parts = win_extents (dpy, w); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, None); - } - else - { - XserverRegion o; - parts = XFixesCreateRegion (dpy, NULL, 0); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, parts); - XFixesTranslateRegion (dpy, parts, - w->a.x + w->a.border_width, - w->a.y + w->a.border_width); - if (compMode == CompServerShadows) - { - o = XFixesCreateRegion (dpy, NULL, 0); - XFixesCopyRegion (dpy, o, parts); - XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy); - XFixesUnionRegion (dpy, parts, parts, o); - XFixesDestroyRegion (dpy, o); - } - } - add_damage (dpy, parts); - w->damaged = 1; -} - -static unsigned int -get_opacity_prop (Display *dpy, win *w, unsigned int def); - -static void -map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) -{ - win *w = find_win (dpy, id); - - if (!w) - return; - - w->a.map_state = IsViewable; - - /* This needs to be here or else we lose transparency messages */ - XSelectInput (dpy, id, PropertyChangeMask); - - /* This needs to be here since we don't get PropertyNotify when unmapped */ - w->opacity = get_opacity_prop (dpy, w, OPAQUE); - determine_mode (dpy, w); - -#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, NULL, False, True, True); -} - -static void -finish_unmap_win (Display *dpy, win *w) -{ - w->damaged = 0; -#if CAN_DO_USABLE - w->usable = False; -#endif - if (w->extents != None) - { - add_damage (dpy, w->extents); /* destroys region */ - w->extents = None; - } - -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - } -#endif - - if (w->picture) - { - set_ignore (dpy, NextRequest (dpy)); - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - - /* don't care about properties anymore */ - set_ignore (dpy, NextRequest (dpy)); - XSelectInput(dpy, w->id, 0); - - if (w->borderSize) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->borderSize); - w->borderSize = None; - } - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - if (w->borderClip) - { - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - - clipChanged = True; -} - -#if HAS_NAME_WINDOW_PIXMAP -static void -unmap_callback (Display *dpy, win *w, Bool gone) -{ - finish_unmap_win (dpy, w); -} -#endif - -static void -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, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, False, True); - else -#endif - finish_unmap_win (dpy, w); -} - -/* Get the opacity prop from window - not found: default - otherwise the value - */ -static unsigned int -get_opacity_prop(Display *dpy, win *w, unsigned int def) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data; - int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL) - { - unsigned int i; - memcpy (&i, data, sizeof (unsigned int)); - XFree( (void *) data); - return i; - } - 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 != (unsigned char *)None) - { - Atom a; - memcpy (&a, data, sizeof (Atom)); - XFree ( (void *) data); - return a; - } - return winNormalAtom; -} - -static void -determine_mode(Display *dpy, win *w) -{ - int mode; - XRenderPictFormat *format; - - /* if trans prop == -1 fall back on previous tests*/ - - if (w->alphaPict) - { - XRenderFreePicture (dpy, w->alphaPict); - w->alphaPict = None; - } - if (w->shadowPict) - { - XRenderFreePicture (dpy, w->shadowPict); - w->shadowPict = None; - } - - if (w->a.class == InputOnly) - { - format = NULL; - } - else - { - format = XRenderFindVisualFormat (dpy, w->a.visual); - } - - if (format && format->type == PictTypeDirect && format->direct.alphaMask) - { - mode = WINDOW_ARGB; - } - else if (w->opacity != OPAQUE) - { - mode = WINDOW_TRANS; - } - else - { - mode = WINDOW_SOLID; - } - w->mode = mode; - if (w->extents) - { - XserverRegion damage; - damage = XFixesCreateRegion (dpy, NULL, 0); - XFixesCopyRegion (dpy, damage, w->extents); - add_damage (dpy, damage); - } -} - -static Atom -determine_wintype (Display *dpy, Window w) -{ - Window root_return, parent_return; - Window *children = NULL; - unsigned int nchildren, i; - Atom type; - - type = get_wintype_prop (dpy, w); - if (type != winNormalAtom) - return type; - - if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, - &nchildren)) - { - /* XQueryTree failed. */ - if (children) - XFree ((void *)children); - return winNormalAtom; - } - - for (i = 0;i < nchildren;i++) - { - type = determine_wintype (dpy, children[i]); - if (type != winNormalAtom) - return type; - } - - if (children) - XFree ((void *)children); - - return winNormalAtom; -} - -static void -add_win (Display *dpy, Window id, Window prev) -{ - win *new = malloc (sizeof (win)); - win **p; - - if (!new) - return; - if (prev) - { - for (p = &list; *p; p = &(*p)->next) - if ((*p)->id == prev) - break; - } - else - p = &list; - new->id = id; - set_ignore (dpy, NextRequest (dpy)); - if (!XGetWindowAttributes (dpy, id, &new->a)) - { - free (new); - return; - } - new->shaped = False; - new->shape_bounds.x = new->a.x; - new->shape_bounds.y = new->a.y; - new->shape_bounds.width = new->a.width; - new->shape_bounds.height = new->a.height; - new->damaged = 0; -#if CAN_DO_USABLE - new->usable = False; -#endif -#if HAS_NAME_WINDOW_PIXMAP - new->pixmap = None; -#endif - new->picture = None; - if (new->a.class == InputOnly) - { - new->damage_sequence = 0; - new->damage = None; - } - else - { - new->damage_sequence = NextRequest (dpy); - new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); - XShapeSelectInput (dpy, id, ShapeNotifyMask); - } - new->alphaPict = None; - new->shadowPict = None; - new->borderSize = None; - new->extents = None; - new->shadow = None; - new->shadow_dx = 0; - new->shadow_dy = 0; - new->shadow_width = 0; - new->shadow_height = 0; - new->opacity = OPAQUE; - - new->borderClip = None; - new->prev_trans = NULL; - - new->windowType = determine_wintype (dpy, new->id); - - new->next = *p; - *p = new; - if (new->a.map_state == IsViewable) - map_win (dpy, id, new->damage_sequence - 1, True); -} - -static void -restack_win (Display *dpy, win *w, Window new_above) -{ - Window old_above; - - if (w->next) - old_above = w->next->id; - else - old_above = None; - if (old_above != new_above) - { - win **prev; - - /* unhook */ - for (prev = &list; *prev; prev = &(*prev)->next) - if ((*prev) == w) - break; - *prev = w->next; - - /* rehook */ - for (prev = &list; *prev; prev = &(*prev)->next) - { - if ((*prev)->id == new_above) - break; - } - w->next = *prev; - *prev = w; - } -} - -static void -configure_win (Display *dpy, XConfigureEvent *ce) -{ - win *w = find_win (dpy, ce->window); - XserverRegion damage = None; - - if (!w) - { - if (ce->window == root) - { - if (rootBuffer) - { - XRenderFreePicture (dpy, rootBuffer); - rootBuffer = None; - } - root_width = ce->width; - root_height = ce->height; - } - return; - } -#if CAN_DO_USABLE - if (w->usable) -#endif - { - damage = XFixesCreateRegion (dpy, NULL, 0); - if (w->extents != None) - XFixesCopyRegion (dpy, damage, w->extents); - } - w->shape_bounds.x -= w->a.x; - w->shape_bounds.y -= w->a.y; - w->a.x = ce->x; - w->a.y = ce->y; - if (w->a.width != ce->width || w->a.height != ce->height) - { -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - if (w->picture) - { - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - } -#endif - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - } - w->a.width = ce->width; - w->a.height = ce->height; - w->a.border_width = ce->border_width; - w->a.override_redirect = ce->override_redirect; - restack_win (dpy, w, ce->above); - if (damage) - { - XserverRegion extents = win_extents (dpy, w); - XFixesUnionRegion (dpy, damage, damage, extents); - XFixesDestroyRegion (dpy, extents); - add_damage (dpy, damage); - } - w->shape_bounds.x += w->a.x; - w->shape_bounds.y += w->a.y; - if (!w->shaped) - { - w->shape_bounds.width = w->a.width; - w->shape_bounds.height = w->a.height; - } - - clipChanged = True; -} - -static void -circulate_win (Display *dpy, XCirculateEvent *ce) -{ - win *w = find_win (dpy, ce->window); - Window new_above; - - if (!w) - return; - - if (ce->place == PlaceOnTop) - new_above = list->id; - else - new_above = None; - restack_win (dpy, w, new_above); - clipChanged = True; -} - -static void -finish_destroy_win (Display *dpy, Window id, Bool gone) -{ - win **prev, *w; - - for (prev = &list; (w = *prev); prev = &w->next) - if (w->id == id) - { - if (gone) - finish_unmap_win (dpy, w); - *prev = w->next; - if (w->picture) - { - set_ignore (dpy, NextRequest (dpy)); - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - if (w->alphaPict) - { - XRenderFreePicture (dpy, w->alphaPict); - w->alphaPict = None; - } - if (w->shadowPict) - { - XRenderFreePicture (dpy, w->shadowPict); - w->shadowPict = None; - } - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - if (w->damage != None) - { - set_ignore (dpy, NextRequest (dpy)); - XDamageDestroy (dpy, w->damage); - w->damage = None; - } - cleanup_fade (dpy, w); - free (w); - break; - } -} - -#if HAS_NAME_WINDOW_PIXMAP -static void -destroy_callback (Display *dpy, win *w, Bool gone) -{ - finish_destroy_win (dpy, w->id, gone); -} -#endif - -static void -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, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, destroy_callback, gone, False, True); - else -#endif - { - finish_destroy_win (dpy, id, gone); - } -} - -/* -static void -dump_win (win *w) -{ - printf ("\t%08lx: %d x %d + %d + %d (%d)\n", w->id, - w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width); -} - - -static void -dump_wins (void) -{ - win *w; - - printf ("windows:\n"); - for (w = list; w; w = w->next) - dump_win (w); -} -*/ - -static void -damage_win (Display *dpy, XDamageNotifyEvent *de) -{ - win *w = find_win (dpy, de->drawable); - - if (!w) - return; -#if CAN_DO_USABLE - if (!w->usable) - { - if (w->damage_bounds.width == 0 || w->damage_bounds.height == 0) - { - w->damage_bounds = de->area; - } - else - { - if (de->area.x < w->damage_bounds.x) - { - w->damage_bounds.width += (w->damage_bounds.x - de->area.x); - w->damage_bounds.x = de->area.x; - } - if (de->area.y < w->damage_bounds.y) - { - w->damage_bounds.height += (w->damage_bounds.y - de->area.y); - w->damage_bounds.y = de->area.y; - } - if (de->area.x + de->area.width > w->damage_bounds.x + w->damage_bounds.width) - w->damage_bounds.width = de->area.x + de->area.width - w->damage_bounds.x; - if (de->area.y + de->area.height > w->damage_bounds.y + w->damage_bounds.height) - w->damage_bounds.height = de->area.y + de->area.height - w->damage_bounds.y; - } -#if 0 - printf ("unusable damage %d, %d: %d x %d bounds %d, %d: %d x %d\n", - de->area.x, - de->area.y, - de->area.width, - de->area.height, - w->damage_bounds.x, - w->damage_bounds.y, - w->damage_bounds.width, - w->damage_bounds.height); -#endif - if (w->damage_bounds.x <= 0 && - w->damage_bounds.y <= 0 && - w->a.width <= w->damage_bounds.x + w->damage_bounds.width && - w->a.height <= w->damage_bounds.y + w->damage_bounds.height) - { - clipChanged = True; - if (fadeWindows) - set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, False, True, True); - w->usable = True; - } - } - if (w->usable) -#endif - repair_win (dpy, w); -} - -#if DEBUG_SHAPE -static const char * -shape_kind(int kind) -{ - static char buf[128]; - - switch(kind){ - case ShapeBounding: - return "ShapeBounding"; - case ShapeClip: - return "ShapeClip"; - case ShapeInput: - return "ShapeInput"; - default: - sprintf (buf, "Shape %d", kind); - return buf; - } -} -#endif - -static void -shape_win (Display *dpy, XShapeEvent *se) -{ - win *w = find_win (dpy, se->window); - - if (!w) - return; - - if (se->kind == ShapeClip || se->kind == ShapeBounding) - { - XserverRegion region0; - XserverRegion region1; - -#if DEBUG_SHAPE - printf("win 0x%lx %s:%s %ux%u+%d+%d\n", - (unsigned long) se->window, - shape_kind(se->kind), - (se->shaped == True) ? "true" : "false", - se->width, se->height, - se->x, se->y); -#endif - - clipChanged = True; - - region0 = XFixesCreateRegion (dpy, &w->shape_bounds, 1); - - if (se->shaped == True) - { - w->shaped = True; - w->shape_bounds.x = w->a.x + se->x; - w->shape_bounds.y = w->a.y + se->y; - w->shape_bounds.width = se->width; - w->shape_bounds.height = se->height; - } - else - { - w->shaped = False; - w->shape_bounds.x = w->a.x; - w->shape_bounds.y = w->a.y; - w->shape_bounds.width = w->a.width; - w->shape_bounds.height = w->a.height; - } - - region1 = XFixesCreateRegion (dpy, &w->shape_bounds, 1); - XFixesUnionRegion (dpy, region0, region0, region1); - XFixesDestroyRegion (dpy, region1); - - /* ask for repaint of the old and new region */ - paint_all (dpy, region0); - } -} - -static int -error (Display *dpy, XErrorEvent *ev) -{ - int o; - const char *name = NULL; - static char buffer[256]; - - if (should_ignore (dpy, ev->serial)) - return 0; - - if (ev->request_code == composite_opcode && - ev->minor_code == X_CompositeRedirectSubwindows) - { - fprintf (stderr, "Another composite manager is already running\n"); - exit (1); - } - - o = ev->error_code - xfixes_error; - switch (o) { - case BadRegion: name = "BadRegion"; break; - default: break; - } - o = ev->error_code - damage_error; - switch (o) { - case BadDamage: name = "BadDamage"; break; - default: break; - } - o = ev->error_code - render_error; - switch (o) { - case BadPictFormat: name ="BadPictFormat"; break; - case BadPicture: name ="BadPicture"; break; - case BadPictOp: name ="BadPictOp"; break; - case BadGlyphSet: name ="BadGlyphSet"; break; - case BadGlyph: name ="BadGlyph"; break; - default: break; - } - - if (name == NULL) - { - buffer[0] = '\0'; - XGetErrorText (dpy, ev->error_code, buffer, sizeof (buffer)); - name = buffer; - } - - fprintf (stderr, "error %d: %s request %d minor %d serial %lu\n", - ev->error_code, (strlen (name) > 0) ? name : "unknown", - ev->request_code, ev->minor_code, ev->serial); - -/* abort (); this is just annoying to most people */ - return 0; -} - -static void -expose_root (Display *dpy, Window root, XRectangle *rects, int nrects) -{ - XserverRegion region = XFixesCreateRegion (dpy, rects, nrects); - - add_damage (dpy, region); -} - -#if DEBUG_EVENTS -static int -ev_serial (XEvent *ev) -{ - if (ev->type & 0x7f != KeymapNotify) - return ev->xany.serial; - return NextRequest (ev->xany.display); -} - -static char * -ev_name (XEvent *ev) -{ - static char buf[128]; - switch (ev->type & 0x7f) { - case Expose: - return "Expose"; - case MapNotify: - return "Map"; - case UnmapNotify: - return "Unmap"; - case ReparentNotify: - return "Reparent"; - case CirculateNotify: - return "Circulate"; - default: - if (ev->type == damage_event + XDamageNotify) - { - return "Damage"; - } - else if (ev->type == xshape_event + ShapeNotify) - { - return "Shape"; - } - sprintf (buf, "Event %d", ev->type); - return buf; - } -} - -static Window -ev_window (XEvent *ev) -{ - switch (ev->type) { - case Expose: - return ev->xexpose.window; - case MapNotify: - return ev->xmap.window; - case UnmapNotify: - return ev->xunmap.window; - case ReparentNotify: - return ev->xreparent.window; - case CirculateNotify: - return ev->xcirculate.window; - default: - if (ev->type == damage_event + XDamageNotify) - { - return ((XDamageNotifyEvent *) ev)->drawable; - } - else if (ev->type == xshape_event + ShapeNotify) - { - return ((XShapeEvent *) ev)->window; - } - return 0; - } -} -#endif - -static void -usage (const char *program) -{ - fprintf (stderr, "%s v%s\n", program, PACKAGE_VERSION); - fprintf (stderr, "usage: %s [options]\n%s\n", program, - "Options:\n" - " -d display\n" - " Specifies which display should be managed.\n" - " -r radius\n" - " Specifies the blur radius for client-side shadows. (default 12)\n" - " -o opacity\n" - " Specifies the translucency for client-side shadows. (default .75)\n" - " -l left-offset\n" - " Specifies the left offset for client-side shadows. (default -15)\n" - " -t top-offset\n" - " Specifies the top offset for clinet-side shadows. (default -15)\n" - " -I fade-in-step\n" - " Specifies the opacity change between steps while fading in. (default 0.028)\n" - " -O fade-out-step\n" - " Specifies the opacity change between steps while fading out. (default 0.03)\n" - " -D fade-delta-time\n" - " Specifies the time between steps in a fade in milliseconds. (default 10)\n" - " -a\n" - " Use automatic server-side compositing. Faster, but no special effects.\n" - " -c\n" - " Draw client-side shadows with fuzzy edges.\n" - " -C\n" - " Avoid drawing shadows on dock/panel windows.\n" - " -f\n" - " Fade windows in/out when opening/closing.\n" - " -F\n" - " Fade windows during opacity changes.\n" - " -n\n" - " Normal client-side compositing with transparency support\n" - " -s\n" - " Draw server-side shadows with sharp edges.\n" - " -S\n" - " Enable synchronous operation (for debugging).\n" - ); - exit (1); -} - -static Bool -register_cm (Display *dpy) -{ - Window w; - Atom a; - static char net_wm_cm[] = "_NET_WM_CM_Sxx"; - - snprintf (net_wm_cm, sizeof (net_wm_cm), "_NET_WM_CM_S%d", scr); - a = XInternAtom (dpy, net_wm_cm, False); - - w = XGetSelectionOwner (dpy, a); - if (w != None) - { - XTextProperty tp; - char **strs; - int count; - Atom winNameAtom = XInternAtom (dpy, "_NET_WM_NAME", False); - - if (!XGetTextProperty (dpy, w, &tp, winNameAtom) && - !XGetTextProperty (dpy, w, &tp, XA_WM_NAME)) - { - fprintf (stderr, - "Another composite manager is already running (0x%lx)\n", - (unsigned long) w); - return False; - } - if (XmbTextPropertyToTextList (dpy, &tp, &strs, &count) == Success) - { - fprintf (stderr, - "Another composite manager is already running (%s)\n", - strs[0]); - - XFreeStringList (strs); - } - - XFree (tp.value); - - return False; - } - - w = XCreateSimpleWindow (dpy, RootWindow (dpy, scr), 0, 0, 1, 1, 0, None, - None); - - Xutf8SetWMProperties (dpy, w, "xcompmgr", "xcompmgr", NULL, 0, NULL, NULL, - NULL); - - XSetSelectionOwner (dpy, a, w, 0); - - return True; -} - -int -main (int argc, char **argv) -{ - Display *dpy; - XEvent ev; - Window root_return, parent_return; - Window *children; - unsigned int nchildren; - int i; - XRenderPictureAttributes pa; - XRectangle *expose_rects = NULL; - int size_expose = 0; - int n_expose = 0; - struct pollfd ufd; - int p; - int composite_major, composite_minor; - char *display = NULL; - int o; - - while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:scnfFCaS")) != -1) - { - switch (o) { - case 'd': - display = optarg; - break; - case 'D': - fade_delta = atoi (optarg); - if (fade_delta < 1) - fade_delta = 10; - break; - case 'I': - fade_in_step = atof (optarg); - if (fade_in_step <= 0) - fade_in_step = 0.01; - break; - case 'O': - fade_out_step = atof (optarg); - if (fade_out_step <= 0) - fade_out_step = 0.01; - break; - case 's': - compMode = CompServerShadows; - break; - 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; - case 'S': - synchronize = True; - break; - case 'r': - shadowRadius = atoi (optarg); - break; - case 'o': - shadowOpacity = atof (optarg); - break; - case 'l': - shadowOffsetX = atoi (optarg); - break; - case 't': - shadowOffsetY = atoi (optarg); - break; - default: - usage (argv[0]); - break; - } - } - - dpy = XOpenDisplay (display); - if (!dpy) - { - fprintf (stderr, "Can't open display\n"); - exit (1); - } - XSetErrorHandler (error); - if (synchronize) - XSynchronize (dpy, 1); - scr = DefaultScreen (dpy); - root = RootWindow (dpy, scr); - - if (!XRenderQueryExtension (dpy, &render_event, &render_error)) - { - fprintf (stderr, "No render extension\n"); - exit (1); - } - if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, - &composite_event, &composite_error)) - { - fprintf (stderr, "No composite extension\n"); - exit (1); - } - XCompositeQueryVersion (dpy, &composite_major, &composite_minor); -#if HAS_NAME_WINDOW_PIXMAP - if (composite_major > 0 || composite_minor >= 2) - hasNamePixmap = True; -#endif - - if (!XDamageQueryExtension (dpy, &damage_event, &damage_error)) - { - fprintf (stderr, "No damage extension\n"); - exit (1); - } - if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error)) - { - fprintf (stderr, "No XFixes extension\n"); - exit (1); - } - if (!XShapeQueryExtension (dpy, &xshape_event, &xshape_error)) - { - fprintf (stderr, "No XShape extension\n"); - exit (1); - } - - if (!register_cm(dpy)) - { - exit (1); - } - - /* 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; - - if (compMode == CompClientShadows) - { - gaussianMap = make_gaussian_map(dpy, shadowRadius); - presum_gaussian (gaussianMap); - } - - root_width = DisplayWidth (dpy, scr); - root_height = DisplayHeight (dpy, scr); - - rootPicture = XRenderCreatePicture (dpy, root, - XRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - CPSubwindowMode, - &pa); - blackPicture = solid_picture (dpy, True, 1, 0, 0, 0); - if (compMode == CompServerShadows) - transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0); - allDamage = None; - clipChanged = True; - XGrabServer (dpy); - if (autoRedirect) - XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic); - else - { - XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual); - XSelectInput (dpy, root, - SubstructureNotifyMask| - ExposureMask| - StructureNotifyMask| - PropertyChangeMask); - XShapeSelectInput (dpy, root, ShapeNotifyMask); - XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren); - for (i = 0; i < nchildren; i++) - add_win (dpy, children[i], i ? children[i-1] : None); - XFree (children); - } - XUngrabServer (dpy); - ufd.fd = ConnectionNumber (dpy); - ufd.events = POLLIN; - if (!autoRedirect) - paint_all (dpy, None); - for (;;) - { - /* dump_wins (); */ - do { - if (autoRedirect) - XFlush (dpy); - if (!QLength (dpy)) - { - if (poll (&ufd, 1, fade_timeout()) == 0) - { - run_fades (dpy); - break; - } - } - - XNextEvent (dpy, &ev); - if ((ev.type & 0x7f) != KeymapNotify) - discard_ignore (dpy, ev.xany.serial); -#if DEBUG_EVENTS - printf ("event %10.10s serial 0x%08x window 0x%08x\n", - ev_name(&ev), ev_serial (&ev), ev_window (&ev)); -#endif - if (!autoRedirect) switch (ev.type) { - case CreateNotify: - add_win (dpy, ev.xcreatewindow.window, 0); - break; - case ConfigureNotify: - configure_win (dpy, &ev.xconfigure); - break; - case DestroyNotify: - destroy_win (dpy, ev.xdestroywindow.window, True, True); - break; - case MapNotify: - map_win (dpy, ev.xmap.window, ev.xmap.serial, True); - break; - case UnmapNotify: - unmap_win (dpy, ev.xunmap.window, True); - break; - case ReparentNotify: - if (ev.xreparent.parent == root) - add_win (dpy, ev.xreparent.window, 0); - else - destroy_win (dpy, ev.xreparent.window, False, True); - break; - case CirculateNotify: - circulate_win (dpy, &ev.xcirculate); - break; - case Expose: - if (ev.xexpose.window == root) - { - int more = ev.xexpose.count + 1; - if (n_expose == size_expose) - { - if (expose_rects) - { - expose_rects = realloc (expose_rects, - (size_expose + more) * - sizeof (XRectangle)); - size_expose += more; - } - else - { - expose_rects = malloc (more * sizeof (XRectangle)); - size_expose = more; - } - } - expose_rects[n_expose].x = ev.xexpose.x; - expose_rects[n_expose].y = ev.xexpose.y; - expose_rects[n_expose].width = ev.xexpose.width; - expose_rects[n_expose].height = ev.xexpose.height; - n_expose++; - if (ev.xexpose.count == 0) - { - expose_root (dpy, root, expose_rects, n_expose); - n_expose = 0; - } - } - break; - case PropertyNotify: - for (p = 0; backgroundProps[p]; p++) - { - if (ev.xproperty.atom == XInternAtom (dpy, backgroundProps[p], False)) - { - if (rootTile) - { - XClearArea (dpy, root, 0, 0, 0, 0, True); - XRenderFreePicture (dpy, rootTile); - rootTile = None; - break; - } - } - } - /* check if Trans property was changed */ - if (ev.xproperty.atom == opacityAtom) - { - /* 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, NULL, 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; - default: - if (ev.type == damage_event + XDamageNotify) - { - damage_win (dpy, (XDamageNotifyEvent *) &ev); - } - else if (ev.type == xshape_event + ShapeNotify) - { - shape_win (dpy, (XShapeEvent *) &ev); - } - break; - } - } while (QLength (dpy)); - if (allDamage && !autoRedirect) - { - static int paint; - paint_all (dpy, allDamage); - paint++; - XSync (dpy, False); - allDamage = None; - clipChanged = False; - } - } -} -- cgit v1.2.3-70-g09d2