diff options
| author | Keith Packard <keithp@keithp.com> | 2003-11-09 07:08:23 +0000 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2003-11-09 07:08:23 +0000 | 
| commit | 1685456c7eeb02668dcd7ce165b6482a32763df2 (patch) | |
| tree | 97ab902609f836009c183adb5869fb998fb9e5d9 | |
| download | xcman-1685456c7eeb02668dcd7ce165b6482a32763df2.tar.gz xcman-1685456c7eeb02668dcd7ce165b6482a32763df2.tar.bz2 xcman-1685456c7eeb02668dcd7ce165b6482a32763df2.tar.xz | |
Initial revision
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | xcompmgr.c | 472 | 
2 files changed, 479 insertions, 0 deletions
| diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ad7079a --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +LIBS=`pkg-config --cflags --libs xcomposite xfixes xdamage xrender` + +xcompmgr: xcompmgr.c +	$(CC) -o $@ $(CFLAGS) xcompmgr.c $(LIBS) + +clean: +	rm xcompmgr diff --git a/xcompmgr.c b/xcompmgr.c new file mode 100644 index 0000000..8aa2c94 --- /dev/null +++ b/xcompmgr.c @@ -0,0 +1,472 @@ +#include <stdlib.h> +#include <stdio.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xdamage.h> +#include <X11/extensions/Xrender.h> + +typedef struct _win { +    struct _win		*next; +    Window		id; +    XWindowAttributes	a; +    int			damaged; +    int			mode; +    Damage		damage; +    Picture		picture; +    XserverRegion	borderSize; + +    /* for drawing translucent windows */ +    XserverRegion	borderClip; +    struct _win		*prev_trans; +} win; + +win *list; + +Display		*dpy; +int		scr; +Window		root; +Picture		rootPicture; +Picture		transPicture; +XserverRegion	allDamage; + +#define WINDOW_PLAIN	0 +#define WINDOW_DROP	1 +#define WINDOW_TRANS	2 + +win * +find_win (Display *dpy, Window id) +{ +    win	*w; + +    for (w = list; w; w = w->next) +	if (w->id == id) +	    return w; +    return 0; +} + +void +paint_root (Display *dpy) +{ +    XRenderColor    c; +     +    c.red = c.green = c.blue = 0x8080; +    c.alpha = 0xffff; +    XRenderFillRectangle (dpy, PictOpSrc, rootPicture, &c,  +			  0, 0, 32767, 32767); +} + +XserverRegion +border_size (Display *dpy, win *w) +{ +    XserverRegion   border; +    border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding); +    /* translate this */ +    XFixesUnionRegion (dpy, border, border, w->a.x, w->a.y, None, 0, 0); +    return border; +} + +void +paint_all (Display *dpy, XserverRegion region) +{ +    win	*w; +    win	*t = 0; +     +    for (w = list; w; w = w->next) +    { +	Picture	mask; +	 +	if (w->a.map_state != IsViewable) +	    continue; +	if (w->mode == WINDOW_TRANS) +	{ +	    w->borderClip = XFixesCreateRegion (dpy, 0, 0); +	    XFixesUnionRegion (dpy, w->borderClip, region, 0, 0, None, 0, 0); +	    w->prev_trans = t; +	    t = w; +	} +	else +	{ +	    XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); +	    if (w->borderSize) +		XFixesDestroyRegion (dpy, w->borderSize); +	    w->borderSize = border_size (dpy, w); +	    XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); +	    XRenderComposite (dpy, PictOpSrc, w->picture, None, rootPicture, +			      0, 0, 0, 0,  +			      w->a.x + w->a.border_width, +			      w->a.y + w->a.border_width, +			      w->a.width, +			      w->a.height); +	} +    } +    XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); +    paint_root (dpy); +    for (w = t; w; w = w->prev_trans) +    { +	XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, w->borderClip); +	XRenderComposite (dpy, PictOpOver, w->picture, transPicture, rootPicture, +			      0, 0, 0, 0,  +			      w->a.x + w->a.border_width, +			      w->a.y + w->a.border_width, +			      w->a.width, +			      w->a.height); +	XFixesDestroyRegion (dpy, w->borderClip); +	w->borderClip = None; +    } +    XFixesDestroyRegion (dpy, region); +} + +void +add_damage (Display *dpy, XserverRegion damage) +{ +    if (allDamage) +    { +	XFixesUnionRegion (dpy, allDamage, allDamage, 0, 0, damage, 0, 0); +	XFixesDestroyRegion (dpy, damage); +    } +    else +	allDamage = damage; +} + +void +repair_win (Display *dpy, Window id) +{ +    win		    *w = find_win (dpy, id); +    XserverRegion   parts; + +    if (!w) +	return; +/*    printf ("repair 0x%x\n", w->id); */ +    parts = XFixesCreateRegion (dpy, 0, 0); +    /* translate region */ +    XDamageSubtract (dpy, w->damage, None, parts); +    XFixesUnionRegion (dpy, parts, parts, w->a.x, w->a.y, None, 0, 0); +    add_damage (dpy, parts); +} + +void +map_win (Display *dpy, Window id) +{ +    win		    *w = find_win (dpy, id); +    XserverRegion   region; + +    if (!w) +	return; +    w->a.map_state = IsViewable; +    w->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); +    region = border_size (dpy, w); +    add_damage (dpy, region); +} + +void +unmap_win (Display *dpy, Window id) +{ +    win *w = find_win (dpy, id); + +    if (!w) +	return; +    w->a.map_state = IsUnmapped; +    if (w->damage != None) +    { +	XDamageDestroy (dpy, w->damage); +	w->damage = None; +    } +    if (w->borderSize != None) +    { +	add_damage (dpy, w->borderSize);    /* destroys region */ +	w->borderSize = None; +    } +} + +void +add_win (Display *dpy, Window id, Window prev) +{ +    win	*new = malloc (sizeof (win)); +    win	**p; +    XWindowAttributes a; +    XRenderPictureAttributes pa; +     +    if (!new) +	return; +    if (prev) +    { +	for (p = &list; *p; p = &(*p)->next) +	    if ((*p)->id == prev) +		break; +    } +    else +	p = &list; +    new->id = id; +    if (!XGetWindowAttributes (dpy, id, &new->a)) +    { +	free (new); +	return; +    } +    new->damaged = 0; +    new->damage = None; +    pa.subwindow_mode = IncludeInferiors; +    new->picture = XRenderCreatePicture (dpy, id, +					 XRenderFindVisualFormat (dpy,  +								  new->a.visual), +					 CPSubwindowMode, +					 &pa); +					  +    new->borderSize = None; +    if (new->a.override_redirect) +	new->mode = WINDOW_TRANS; +    else +	new->mode = WINDOW_DROP; +    new->next = *p; +    *p = new; +    if (new->a.map_state == IsViewable) +	map_win (dpy, id); +} + +void +configure_win (Display *dpy, XConfigureEvent *ce) +{ +    win		    *w = find_win (dpy, ce->window); +    Window	    above; +    XserverRegion   damage = None; +     +    if (!w) +	return; +    if (w->a.map_state == IsViewable) +    { +	damage = XFixesCreateRegion (dpy, 0, 0); +	if (w->borderSize != None)	 +	    XFixesUnionRegion (dpy, damage, w->borderSize, 0, 0, None, 0, 0); +    } +    w->a.x = ce->x; +    w->a.y = ce->y; +    w->a.width = ce->width; +    w->a.height = ce->height; +    w->a.border_width = ce->border_width; +    w->a.override_redirect = ce->override_redirect; +    if (w->next) +	above = w->next->id; +    else +	above = None; +    if (above != ce->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 == ce->above) +		break; +	} +	w->next = *prev; +	*prev = w; +    } +    if (damage) +    { +	XserverRegion	border = border_size (dpy, w); +	XFixesUnionRegion (dpy, damage, damage, 0, 0, border, 0, 0); +	add_damage (dpy, damage); +    } +} + +void +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) +	    { +		unmap_win (dpy, id); +		XRenderFreePicture (dpy, w->picture); +	    } +	    *prev = w->next; +	    free (w); +	    break; +	} +} + +void +dump_win (win *w) +{ +    printf ("\t%08x: %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); +} + +void +dump_wins (void) +{ +    win	*w; + +    printf ("windows:\n"); +    for (w = list; w; w = w->next) +	dump_win (w); +} + +void +damage_win (Display *dpy, XDamageNotifyEvent *de) +{ +    repair_win (dpy, de->drawable); +} + +int +error (Display *dpy, XErrorEvent *ev) +{ +    printf ("error %d request %d minor %d\n", +	    ev->error_code, ev->request_code, ev->minor_code); +} + +void +expose_root (Display *dpy, Window root, XRectangle *rects, int nrects) +{ +    XserverRegion  region = XFixesCreateRegion (dpy, rects, nrects); +     +    add_damage (dpy, region); +} + +main () +{ +    XEvent	    ev; +    int		    event_base, error_base; +    Window	    root_return, parent_return; +    Window	    *children; +    Pixmap	    transPixmap; +    unsigned int    nchildren; +    int		    i; +    int		    damage_event, damage_error; +    int		    xfixes_event, xfixes_error; +    XRenderPictureAttributes	pa; +    XRenderColor		c; +    XRectangle	    *expose_rects = 0; +    int		    size_expose = 0; +    int		    n_expose = 0; + +    dpy = XOpenDisplay (0); +    if (!dpy) +    { +	fprintf (stderr, "Can't open display\n"); +	exit (1); +    } +    XSetErrorHandler (error); +    scr = DefaultScreen (dpy); +    root = RootWindow (dpy, scr); +    pa.subwindow_mode = IncludeInferiors; +    transPixmap = XCreatePixmap (dpy, root, 1, 1, 8); +    pa.repeat = True; +    transPicture = XRenderCreatePicture (dpy, transPixmap, +					 XRenderFindStandardFormat (dpy, PictStandardA8), +					 CPRepeat, +					 &pa); +    c.red = c.green = c.blue = 0; +    c.alpha = 0xc0c0; +    XRenderFillRectangle (dpy, PictOpSrc, transPicture, &c, 0, 0, 1, 1); +     +    rootPicture = XRenderCreatePicture (dpy, root,  +					XRenderFindVisualFormat (dpy, +								 DefaultVisual (dpy, scr)), +					CPSubwindowMode, +					&pa); +    if (!XCompositeQueryExtension (dpy, &event_base, &error_base)) +    { +	fprintf (stderr, "No composite extension\n"); +	exit (1); +    } +    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); +    } +    allDamage = None; +    XGrabServer (dpy); +    XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual); +    paint_root (dpy); +    XSelectInput (dpy, root, SubstructureNotifyMask|ExposureMask); +    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); +    for (;;) +    { +/*	dump_wins (); */ +	do { +	    XNextEvent (dpy, &ev); +/*	    printf ("event %d\n", ev.type); */ +	    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); +		break; +	    case MapNotify: +		map_win (dpy, ev.xmap.window); +		break; +	    case UnmapNotify: +		unmap_win (dpy, ev.xunmap.window); +		break; +	    case ReparentNotify: +		if (ev.xreparent.parent == root) +		    add_win (dpy, ev.xreparent.window, 0); +		else +		    destroy_win (dpy, ev.xreparent.window, False); +		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; +	    default: +		if (ev.type == damage_event + XDamageNotify) +		    damage_win (dpy, (XDamageNotifyEvent *) &ev); +		break; +	    } +	} while (XEventsQueued (dpy, QueuedAfterReading)); +	if (allDamage) +	{ +	    paint_all (dpy, allDamage); +	    allDamage = None; +	} +    } +} | 
