X-Git-Url: http://git.openbox.org/?p=dana%2Fxcompmgr.git;a=blobdiff_plain;f=xcompmgr.c;h=e06d08c105f542dee8a29d4b9b7c6904680ca2d1;hp=30ede4835f29fc0751c41858e2227c72fa36102d;hb=54fb13fa320dbebd5441ae4fdac22286391a3261;hpb=e142128ddea840d8140fdd0b28fff121cb2b4598 diff --git a/xcompmgr.c b/xcompmgr.c index 30ede48..e06d08c 100644 --- a/xcompmgr.c +++ b/xcompmgr.c @@ -1,6 +1,31 @@ +/* + * $Id$ + * + * 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. + */ + #include #include #include +#include #include #include #include @@ -34,13 +59,18 @@ Display *dpy; int scr; Window root; Picture rootPicture; +Picture rootBuffer; Picture transPicture; Picture rootTile; XserverRegion allDamage; +int root_height, root_width; + +#define BACKGROUND_PROP "_XROOTPMAP_ID" + +#define WINDOW_SOLID 0 +#define WINDOW_TRANS 1 +#define WINDOW_ARGB 2 -#define WINDOW_PLAIN 0 -#define WINDOW_DROP 1 -#define WINDOW_TRANS 2 #define TRANS_OPACITY 0.75 #define SHADOW_RADIUS 15 #define SHADOW_OPACITY 0.75 @@ -299,9 +329,10 @@ root_tile (Display *dpy) Bool fill; XRenderPictureAttributes pa; - if (XGetWindowProperty (dpy, root, XInternAtom (dpy, "_XROOTPMAP_ID", False), + if (XGetWindowProperty (dpy, root, XInternAtom (dpy, BACKGROUND_PROP, False), 0, 4, False, AnyPropertyType, - &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success) + &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); @@ -336,8 +367,8 @@ paint_root (Display *dpy) rootTile = root_tile (dpy); XRenderComposite (dpy, PictOpSrc, - rootTile, None, rootPicture, - 0, 0, 0, 0, 0, 0, 32767, 32767); + rootTile, None, rootBuffer, + 0, 0, 0, 0, 0, 0, root_width, root_height); } XserverRegion @@ -345,21 +376,31 @@ win_extents (Display *dpy, win *w) { XRectangle r; - if (!w->shadow) + if (w->mode == WINDOW_ARGB) { - double opacity = SHADOW_OPACITY; - if (w->mode == WINDOW_TRANS) - opacity = opacity * TRANS_OPACITY; - w->shadow = shadow_picture (dpy, opacity, SHADOW_RADIUS, - w->a.width, w->a.height, - &w->shadow_width, &w->shadow_height); - w->shadow_dx = SHADOW_OFFSET_X; - w->shadow_dy = SHADOW_OFFSET_Y; + 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; + } + else + { + if (!w->shadow) + { + double opacity = SHADOW_OPACITY; + if (w->mode == WINDOW_TRANS) + opacity = opacity * TRANS_OPACITY; + w->shadow = shadow_picture (dpy, opacity, SHADOW_RADIUS, + w->a.width, w->a.height, + &w->shadow_width, &w->shadow_height); + w->shadow_dx = SHADOW_OFFSET_X; + w->shadow_dy = SHADOW_OFFSET_Y; + } + r.x = w->a.x + w->a.border_width + w->shadow_dx; + r.y = w->a.y + w->a.border_width + w->shadow_dy; + r.width = w->shadow_width; + r.height = w->shadow_height; } - r.x = w->a.x + w->a.border_width + w->shadow_dx; - r.y = w->a.y + w->a.border_width + w->shadow_dy; - r.width = w->shadow_width; - r.height = w->shadow_height; return XFixesCreateRegion (dpy, &r, 1); } @@ -379,23 +420,46 @@ paint_all (Display *dpy, XserverRegion region) win *w; win *t = 0; + if (!region) + { + XRectangle r; + r.x = 0; + r.y = 0; + r.width = root_width; + r.height = root_height; + region = XFixesCreateRegion (dpy, &r, 1); + } + if (!rootBuffer) + { + Pixmap rootPixmap = XCreatePixmap (dpy, root, root_width, root_height, + DefaultDepth (dpy, scr)); + rootBuffer = XRenderCreatePicture (dpy, rootPixmap, + XRenderFindVisualFormat (dpy, + DefaultVisual (dpy, scr)), + 0, 0); + XFreePixmap (dpy, rootPixmap); + } + XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); for (w = list; w; w = w->next) { Picture mask; if (w->a.map_state != IsViewable) continue; + if (!w->picture) + continue; + if (w->borderSize) XFixesDestroyRegion (dpy, w->borderSize); w->borderSize = border_size (dpy, w); if (w->extents) XFixesDestroyRegion (dpy, w->extents); w->extents = win_extents (dpy, w); - if (w->mode != WINDOW_TRANS) + if (w->mode == WINDOW_SOLID) { - XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); + XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); - XRenderComposite (dpy, PictOpSrc, w->picture, None, rootPicture, + XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer, 0, 0, 0, 0, w->a.x + w->a.border_width, w->a.y + w->a.border_width, @@ -407,21 +471,28 @@ paint_all (Display *dpy, XserverRegion region) w->prev_trans = t; t = w; } - XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); + XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); paint_root (dpy); for (w = t; w; w = w->prev_trans) { - XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, w->borderClip); + XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); if (w->shadow) { - XRenderComposite (dpy, PictOpOver, w->shadow, None, rootPicture, + XRenderComposite (dpy, PictOpOver, w->shadow, None, rootBuffer, 0, 0, 0, 0, w->a.x + w->a.border_width + w->shadow_dx, w->a.y + w->a.border_width + w->shadow_dy, w->shadow_width, w->shadow_height); } if (w->mode == WINDOW_TRANS) - XRenderComposite (dpy, PictOpOver, w->picture, transPicture, rootPicture, + XRenderComposite (dpy, PictOpOver, w->picture, transPicture, rootBuffer, + 0, 0, 0, 0, + w->a.x + w->a.border_width, + w->a.y + w->a.border_width, + w->a.width, + w->a.height); + else if (w->mode == WINDOW_ARGB) + XRenderComposite (dpy, PictOpOver, w->picture, None, rootBuffer, 0, 0, 0, 0, w->a.x + w->a.border_width, w->a.y + w->a.border_width, @@ -431,6 +502,9 @@ paint_all (Display *dpy, XserverRegion region) w->borderClip = None; } XFixesDestroyRegion (dpy, region); + XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, None); + XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture, + 0, 0, 0, 0, 0, 0, root_width, root_height); } void @@ -470,9 +544,12 @@ map_win (Display *dpy, Window id) if (!w) return; w->a.map_state = IsViewable; - w->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); - region = win_extents (dpy, w); - add_damage (dpy, region); + if (w->picture) + { + w->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); + region = win_extents (dpy, w); + add_damage (dpy, region); + } } void @@ -498,10 +575,11 @@ unmap_win (Display *dpy, Window id) void add_win (Display *dpy, Window id, Window prev) { - win *new = malloc (sizeof (win)); - win **p; - XWindowAttributes a; - XRenderPictureAttributes pa; + win *new = malloc (sizeof (win)); + win **p; + XWindowAttributes a; + XRenderPictureAttributes pa; + XRenderPictFormat *format; if (!new) return; @@ -522,19 +600,29 @@ add_win (Display *dpy, Window id, Window prev) new->damaged = 0; new->damage = None; pa.subwindow_mode = IncludeInferiors; - new->picture = XRenderCreatePicture (dpy, id, - XRenderFindVisualFormat (dpy, - new->a.visual), - CPSubwindowMode, - &pa); + if (new->a.class == InputOnly) + { + new->picture = 0; + format = 0; + } + else + { + format = XRenderFindVisualFormat (dpy, new->a.visual); + new->picture = XRenderCreatePicture (dpy, id, + format, + CPSubwindowMode, + &pa); + } new->shadow = None; new->borderSize = None; new->extents = None; - if (new->a.override_redirect) + if (format && format->type == PictTypeDirect && format->direct.alphaMask) + new->mode = WINDOW_ARGB; + else if (new->a.override_redirect) new->mode = WINDOW_TRANS; else - new->mode = WINDOW_DROP; + new->mode = WINDOW_SOLID; new->next = *p; *p = new; if (new->a.map_state == IsViewable) @@ -549,7 +637,19 @@ configure_win (Display *dpy, XConfigureEvent *ce) 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 (w->a.map_state == IsViewable) { damage = XFixesCreateRegion (dpy, 0, 0); @@ -593,8 +693,9 @@ configure_win (Display *dpy, XConfigureEvent *ce) } if (damage) { - XserverRegion border = border_size (dpy, w); - XFixesUnionRegion (dpy, damage, damage, 0, 0, border, 0, 0); + XserverRegion extents = win_extents (dpy, w); + XFixesUnionRegion (dpy, damage, damage, 0, 0, extents, 0, 0); + XFixesDestroyRegion (dpy, extents); add_damage (dpy, damage); } } @@ -610,7 +711,8 @@ destroy_win (Display *dpy, Window id, Bool gone) if (!gone) { unmap_win (dpy, id); - XRenderFreePicture (dpy, w->picture); + if (w->picture) + XRenderFreePicture (dpy, w->picture); } *prev = w->next; free (w); @@ -656,6 +758,17 @@ expose_root (Display *dpy, Window root, XRectangle *rects, int nrects) add_damage (dpy, region); } +int +time_in_millis () +{ + struct timeval tp; + + gettimeofday (&tp, 0); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} + +#define INTERVAL 30 + main () { XEvent ev; @@ -673,6 +786,11 @@ main () GC gc; int size_expose = 0; int n_expose = 0; + struct pollfd ufd; + int n; + int last_update; + int now; + int timeout; dpy = XOpenDisplay (0); if (!dpy) @@ -694,6 +812,9 @@ main () c.alpha = 0xc0c0; XRenderFillRectangle (dpy, PictOpSrc, transPicture, &c, 0, 0, 1, 1); + root_width = DisplayWidth (dpy, scr); + root_height = DisplayHeight (dpy, scr); + rootPicture = XRenderCreatePicture (dpy, root, XRenderFindVisualFormat (dpy, DefaultVisual (dpy, scr)), @@ -704,26 +825,34 @@ main () fprintf (stderr, "No composite extension\n"); exit (1); } + printf ("Composite error %d\n", error_base); if (!XDamageQueryExtension (dpy, &damage_event, &damage_error)) { fprintf (stderr, "No damage extension\n"); exit (1); } + printf ("Damage error %d\n", damage_error); if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error)) { fprintf (stderr, "No XFixes extension\n"); exit (1); } + printf ("XFixes error %d\n", xfixes_error); allDamage = None; XGrabServer (dpy); XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual); - paint_root (dpy); - XSelectInput (dpy, root, SubstructureNotifyMask|ExposureMask); + XSelectInput (dpy, root, + SubstructureNotifyMask| + ExposureMask| + StructureNotifyMask| + PropertyChangeMask); 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); + paint_all (dpy, None); + last_update = time_in_millis (); for (;;) { /* dump_wins (); */ @@ -783,12 +912,34 @@ main () } } break; + case PropertyNotify: + if (ev.xproperty.atom == XInternAtom (dpy, BACKGROUND_PROP, False)) + { + if (rootTile) + { + XClearArea (dpy, root, 0, 0, 0, 0, True); + XRenderFreePicture (dpy, rootTile); + rootTile = None; + } + } + break; default: if (ev.type == damage_event + XDamageNotify) damage_win (dpy, (XDamageNotifyEvent *) &ev); break; } } while (XEventsQueued (dpy, QueuedAfterReading)); + now = time_in_millis (); + timeout = INTERVAL - (now - last_update); + if (timeout > 0) + { + ufd.fd = ConnectionNumber (dpy); + ufd.events = POLLIN; + n = poll (&ufd, 1, timeout); + if (n > 0 && (ufd.revents & POLLIN) && XEventsQueued (dpy, QueuedAfterReading)) + continue; + } + last_update = time_in_millis(); if (allDamage) { paint_all (dpy, allDamage);