diff --git a/xcompmgr.c b/xcompmgr.c index 5a38cf1..55fa93f 100644 --- a/xcompmgr.c +++ b/xcompmgr.c @@ -43,6 +43,7 @@ #include #include #include +#include #if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 #define HAS_NAME_WINDOW_PIXMAP 1 @@ -82,6 +83,8 @@ typedef struct _win { 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; @@ -125,6 +128,7 @@ 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; @@ -997,7 +1001,7 @@ paint_all (Display *dpy, XserverRegion region) w->borderSize = border_size (dpy, w); if (!w->extents) w->extents = win_extents (dpy, w); - if (w->mode == WINDOW_SOLID) + if (w->mode == WINDOW_SOLID || w->shaped) { int x, y, wid, hei; #if HAS_NAME_WINDOW_PIXMAP @@ -1071,7 +1075,7 @@ paint_all (Display *dpy, XserverRegion region) if (w->opacity != OPAQUE && !w->alphaPict) w->alphaPict = solid_picture (dpy, False, (double) w->opacity / OPAQUE, 0, 0, 0); - if (w->mode == WINDOW_TRANS) + if (w->mode == WINDOW_TRANS && !w->shaped) { int x, y, wid, hei; #if HAS_NAME_WINDOW_PIXMAP @@ -1090,7 +1094,7 @@ paint_all (Display *dpy, XserverRegion region) 0, 0, 0, 0, x, y, wid, hei); } - else if (w->mode == WINDOW_ARGB) + else if (w->mode == WINDOW_ARGB && !w->shaped) { int x, y, wid, hei; #if HAS_NAME_WINDOW_PIXMAP @@ -1441,6 +1445,11 @@ add_win (Display *dpy, Window id, Window prev) 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; @@ -1458,6 +1467,7 @@ add_win (Display *dpy, Window id, Window prev) { new->damage_sequence = NextRequest (dpy); new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); + XShapeSelectInput (dpy, id, ShapeNotifyMask); } new->alphaPict = None; new->shadowPict = None; @@ -1539,6 +1549,8 @@ configure_win (Display *dpy, XConfigureEvent *ce) 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) @@ -1573,6 +1585,14 @@ configure_win (Display *dpy, XConfigureEvent *ce) 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; } @@ -1737,6 +1757,76 @@ damage_win (Display *dpy, XDamageNotifyEvent *de) repair_win (dpy, w); } +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; + } +} + +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 0 + 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) { @@ -1814,7 +1913,13 @@ ev_name (XEvent *ev) 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; } @@ -1836,7 +1941,13 @@ ev_window (XEvent *ev) 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; } } @@ -2005,6 +2116,11 @@ main (int argc, char **argv) fprintf (stderr, "No XFixes extension\n"); exit (1); } + if (!XShapeQueryExtension (dpy, &xshape_event, &xshape_error)) + { + fprintf (stderr, "No XShape extension\n"); + exit (1); + } register_cm(); @@ -2052,6 +2168,7 @@ main (int argc, char **argv) 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); @@ -2180,7 +2298,13 @@ main (int argc, char **argv) break; default: if (ev.type == damage_event + XDamageNotify) - damage_win (dpy, (XDamageNotifyEvent *) &ev); + { + damage_win (dpy, (XDamageNotifyEvent *) &ev); + } + else if (ev.type == xshape_event + ShapeNotify) + { + shape_win (dpy, (XShapeEvent *) &ev); + } break; } } while (QLength (dpy));