commit 6b88abeaacce4423d2d24dd6dbd9a8ed9a08fd99
parent 978775693673e8c49e507ceeeaa67354d8439e27
Author: Kris Maglione <jg@suckless.org>
Date: Sat, 16 Feb 2008 20:12:59 -0500
Support alpha-transparant windows. May not last.
Diffstat:
11 files changed, 127 insertions(+), 37 deletions(-)
diff --git a/cmd/Makefile b/cmd/Makefile
@@ -2,6 +2,9 @@ ROOT=..
include $(ROOT)/mk/hdr.mk
include $(ROOT)/mk/wmii.mk
+all:
+ false
+
wmiir.c: $(ROOT)/mk/wmii.mk
DIRS = wmii
diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c
@@ -92,6 +92,8 @@ client_create(XWindow w, XWindowAttributes *wa) {
Client **t, *c;
WinAttr fwa;
Point p;
+ Visual *vis;
+ int depth;
c = emallocz(sizeof *c);
c->border = wa->border_width;
@@ -104,6 +106,15 @@ client_create(XWindow w, XWindowAttributes *wa) {
c->w.w = w;
c->w.r = c->r;
+ depth = scr.depth;
+ vis = scr.visual;
+ c->ibuf = &screen->ibuf;
+ if(render_argb_p(wa->visual)) {
+ depth = 32;
+ vis = render_visual;
+ c->ibuf = &screen->ibuf32;
+ }
+
client_prop(c, xatom("WM_PROTOCOLS"));
client_prop(c, xatom("WM_TRANSIENT_FOR"));
client_prop(c, xatom("WM_NORMAL_HINTS"));
@@ -115,8 +126,9 @@ client_create(XWindow w, XWindowAttributes *wa) {
XSetWindowBorderWidth(display, w, 0);
XAddToSaveSet(display, w);
- fwa.override_redirect = true;
fwa.background_pixmap = None;
+ fwa.border_pixel = 0;
+ fwa.colormap = XCreateColormap(display, scr.root.w, vis, AllocNone);
fwa.event_mask = SubstructureRedirectMask
| SubstructureNotifyMask
| ExposureMask
@@ -124,10 +136,17 @@ client_create(XWindow w, XWindowAttributes *wa) {
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask;
- c->framewin = createwindow(&scr.root, c->r, scr.depth, InputOutput,
- &fwa, CWOverrideRedirect
+ fwa.override_redirect = true;
+ c->framewin = createwindow_visual(&scr.root, c->r,
+ depth, vis, InputOutput,
+ &fwa, CWBackPixmap
+ /* These next two matter for argb windows. Donno why. */
+ | CWBorderPixel
+ | CWColormap
| CWEventMask
- | CWBackPixmap);
+ | CWOverrideRedirect);
+ XFreeColormap(display, fwa.colormap);
+
c->framewin->aux = c;
c->w.aux = c;
sethandler(c->framewin, &framehandler);
@@ -180,8 +199,7 @@ client_manage(Client *c) {
utflcpy(c->tags, trans->tags, sizeof c->tags);
free(tags);
- /* Maybe not the best idea... */
- if(!c->trans || !c->tags[0])
+ if(!c->tags[0])
apply_rules(c);
if(c->tags[0])
apply_tags(c, c->tags);
diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h
@@ -146,6 +146,7 @@ struct Client {
Frame* sel;
Window w;
Window* framewin;
+ Image** ibuf;
XWindow trans;
Regex tagre;
Regex tagvre;
@@ -309,6 +310,7 @@ EXTERN struct WMScreen {
Client* hasgrab;
Window* barwin;
Image* ibuf;
+ Image* ibuf32;
Rectangle r;
Rectangle brect;
@@ -354,6 +356,7 @@ EXTERN char* execstr;
EXTERN int debugflag;
EXTERN int debugfile;
EXTERN long xtime;
+EXTERN Visual* render_visual;
EXTERN Client* kludge;
diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h
@@ -251,7 +251,7 @@ void xdnd_initwindow(Window*);
/* xext.c */
void randr_event(XEvent*);
-void randr_init(void);
+bool render_argb_p(Visual*);
void xext_event(XEvent*);
void xext_init(void);
diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c
@@ -358,6 +358,7 @@ frame_draw(Frame *f) {
Client *c;
CTuple *col;
Frame *tf;
+ Image *img;
uint w;
if(f->view != screen->sel)
@@ -366,6 +367,7 @@ frame_draw(Frame *f) {
return;
c = f->client;
+ img = *c->ibuf;
fr = rectsetorigin(c->framewin->r, ZP);
/* Pick colors. */
@@ -383,12 +385,12 @@ frame_draw(Frame *f) {
/* Background/border */
r = fr;
- fill(screen->ibuf, r, col->bg);
- border(screen->ibuf, r, 1, col->border);
+ fill(img, r, col->bg);
+ border(img, r, 1, col->border);
/* Title border */
r.max.y = r.min.y + labelh(def.font);
- border(screen->ibuf, r, 1, col->border);
+ border(img, r, 1, col->border);
f->titlebar = insetrect(r, 3);
f->titlebar.max.y += 3;
@@ -397,7 +399,7 @@ frame_draw(Frame *f) {
/* Draw a border just inside the titlebar. */
/* FIXME: Perhaps this should be normcolored? */
if(c != selclient() && col == &def.focuscolor)
- border(screen->ibuf, insetrect(r, 1), 1, def.normcolor.bg);
+ border(img, insetrect(r, 1), 1, def.normcolor.bg);
/* grabbox */
r.min = Pt(2, 2);
@@ -406,13 +408,13 @@ frame_draw(Frame *f) {
f->grabbox = r;
if(c->urgent)
- fill(screen->ibuf, r, col->fg);
- border(screen->ibuf, r, 1, col->border);
+ fill(img, r, col->fg);
+ border(img, r, 1, col->border);
/* Odd focus. Selected, without keyboard focus. */
/* Draw a border around the grabbox. */
if(c != screen->focus && col == &def.focuscolor)
- border(screen->ibuf, insetrect(r, -1), 1, def.normcolor.bg);
+ border(img, insetrect(r, -1), 1, def.normcolor.bg);
/* Draw a border on borderless/titleless selected apps. */
if(c->borderless && c->titleless && c == selclient())
@@ -427,7 +429,7 @@ frame_draw(Frame *f) {
r.max.y = labelh(def.font);
if(c->floating)
r.max.x -= Dx(f->grabbox);
- w = drawstring(screen->ibuf, def.font, r, West,
+ w = drawstring(img, def.font, r, West,
c->name, col->fg);
if(f->area->floating) {
@@ -435,7 +437,7 @@ frame_draw(Frame *f) {
r.max.x = f->titlebar.max.x + 1;
r.min.y = f->grabbox.min.y;
r.max.y = f->grabbox.max.y;
- border(screen->ibuf, r, 1, col->border);
+ border(img, r, 1, col->border);
}
/* Border increment gaps... */
@@ -443,7 +445,7 @@ frame_draw(Frame *f) {
r.min.x = max(1, f->crect.min.x - 1);
r.max.x = min(fr.max.x - 1, f->crect.max.x + 1);
r.max.y = min(fr.max.y - 1, f->crect.max.y + 1);
- border(screen->ibuf, r, 1, col->border);
+ border(img, r, 1, col->border);
/* Why? Because some non-ICCCM-compliant apps feel the need to
* change the background properties of all of their ancestor windows
@@ -453,7 +455,7 @@ frame_draw(Frame *f) {
*/
XSetWindowBackgroundPixmap(display, c->framewin->w, None);
- copyimage(c->framewin, fr, screen->ibuf, ZP);
+ copyimage(c->framewin, fr, img, ZP);
sync();
}
diff --git a/cmd/wmii/fs.c b/cmd/wmii/fs.c
@@ -1052,7 +1052,6 @@ fs_clunk(Ixp9Req *r) {
PLink *pl;
Queue *qu;
char *p, *q;
- Client *c;
IxpMsg m;
f = r->fid->aux;
@@ -1088,9 +1087,11 @@ fs_clunk(Ixp9Req *r) {
break;
case FsFTagRules:
update_rules(&f->p.rule->rule, f->p.rule->string);
+ /*
for(c=client; c; c=c->next)
apply_rules(c);
view_update_all();
+ */
break;
case FsFKeys:
update_keys();
diff --git a/cmd/wmii/main.c b/cmd/wmii/main.c
@@ -140,7 +140,11 @@ init_screen(WMScreen *screen) {
screen->r = scr.rect;
def.snap = Dy(scr.rect) / 63;
freeimage(screen->ibuf);
+ freeimage(screen->ibuf32);
screen->ibuf = allocimage(Dx(screen->r), Dy(screen->r), scr.depth);
+ /* Probably shouldn't do this until it's needed. */
+ if(render_visual)
+ screen->ibuf32 = allocimage(Dx(screen->r), Dy(screen->r), 32);
}
static void
@@ -189,8 +193,11 @@ errorhandler(Display *dpy, XErrorEvent *error) {
argv0, error->request_code, error->error_code);
/* Try to cleanup, but only try once, in case we're called recursively. */
+ USED(dead);
+#ifdef notdef
if(!dead++)
cleanup();
+#endif
return xlib_errorhandler(display, error); /* calls exit() */
}
diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c
@@ -215,7 +215,7 @@ freeimage(Image *img) {
/* Windows */
Window*
-createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) {
+createwindow_visual(Window *parent, Rectangle r, int depth, Visual *vis, uint class, WinAttr *wa, int valmask) {
Window *w;
assert(parent->type == WWindow);
@@ -224,8 +224,12 @@ createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, in
w->type = WWindow;
w->parent = parent;
- w->w = XCreateWindow(display, parent->w, r.min.x, r.min.y, Dx(r), Dy(r),
- 0 /* border */, depth, class, scr.visual, valmask, wa);
+ w->w = XCreateWindow(display, parent->w, r.min.x, r.min.y, Dx(r), Dy(r),
+ 0 /* border */, depth, class, vis, valmask, wa);
+#if 0
+ print("createwindow_visual(%W, %R, %d, %p, %ud, %p, %x) = %W\n",
+ parent, r, depth, vis, class, wa, valmask, w);
+#endif
if(class != InputOnly)
w->gc = XCreateGC(display, w->w, 0, nil);
@@ -235,6 +239,11 @@ createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, in
}
Window*
+createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) {
+ return createwindow_visual(parent, r, depth, scr.visual, class, wa, valmask);
+}
+
+Window*
window(XWindow xw) {
Window *w;
@@ -528,7 +537,8 @@ namedcolor(char *name, ulong *ret) {
XColor c, c2;
if(XAllocNamedColor(display, scr.colormap, name, &c, &c2)) {
- *ret = c.pixel;
+ /* FIXME: Kludge. */
+ *ret = c.pixel | 0xff000000;
return true;
}
return false;
diff --git a/cmd/wmii/xext.c b/cmd/wmii/xext.c
@@ -3,6 +3,7 @@
*/
#define _X11_VISIBLE
#include "dat.h"
+#include <X11/extensions/Xrender.h>
#include "fns.h"
#if RANDR_MAJOR < 1
@@ -11,23 +12,27 @@
static void randr_screenchange(XRRScreenChangeNotifyEvent*);
static bool randr_event_p(XEvent *e);
+static void randr_init(void);
+static void render_init(void);
typedef void (*EvHandler)(XEvent*);
static EvHandler randr_handlers[RRNumberEvents];
bool have_RandR;
+bool have_render;
int randr_eventbase;
static void
-handle(XEvent *e, EvHandler ha[], int base) {
+handle(XEvent *e, EvHandler h[], int base) {
- if(ha[e->type-base])
- ha[e->type-base](e);
+ if(h[e->type-base])
+ h[e->type-base](e);
}
void
xext_init(void) {
randr_init();
+ render_init();
}
void
@@ -37,7 +42,7 @@ xext_event(XEvent *e) {
handle(e, randr_handlers, randr_eventbase);
}
-void
+static void
randr_init(void) {
int errorbase, major, minor;
@@ -80,3 +85,41 @@ static EvHandler randr_handlers[] = {
[RRScreenChangeNotify] = (EvHandler)randr_screenchange,
};
+/* Ripped most graciously from ecore_x. XRender documentation
+ * is sparse.
+ */
+static void
+render_init(void) {
+ XVisualInfo *vip;
+ XVisualInfo vi;
+ int base, i, n;
+
+ have_render = XRenderQueryExtension(display, &base, &base);
+ if(!have_render)
+ return;
+
+ vi.class = TrueColor;
+ vi.depth = 32;
+ vi.screen = scr.screen;
+ vip = XGetVisualInfo(display, VisualClassMask
+ | VisualDepthMask
+ | VisualScreenMask,
+ &vi, &n);
+ for(i=0; i < n; i++)
+ if(render_argb_p(vip[i].visual)) {
+ render_visual = vip[i].visual;
+ break;
+ }
+ XFree(vip);
+}
+
+bool
+render_argb_p(Visual *v) {
+ XRenderPictFormat *f;
+
+ f = XRenderFindVisualFormat(display, v);
+ return f
+ && f->type == PictTypeDirect
+ && f->direct.alphaMask;
+}
+
diff --git a/include/x11.h b/include/x11.h
@@ -184,7 +184,8 @@ void changeprop_textlist(Window*, char*, char*, char*[]);
void changeprop_ulong(Window*, char*, char*, ulong[], int);
void changeproperty(Window*, char*, char*, int width, uchar*, int);
void copyimage(Image*, Rectangle, Image*, Point);
-Window* createwindow(Window *parent, Rectangle, int depth, uint class, WinAttr*, int valuemask);
+Window* createwindow(Window*, Rectangle, int depth, uint class, WinAttr*, int valuemask);
+Window* createwindow_visual(Window*, Rectangle, int depth, Visual*, uint class, WinAttr*, int);
void delproperty(Window*, char*);
void destroywindow(Window*);
Point divpt(Point, Point);
diff --git a/mk/dir.mk b/mk/dir.mk
@@ -1,12 +1,14 @@
-MKSUBDIR = targ=$@; targ=$${targ\#d}; \
- for i in $$dirs; do \
- export BASE=$(BASE)$$i/; \
- if [ ! -d $$i ]; then \
- echo Skipping nonexistent directory: $$i 1>&2; \
- else \
- echo MAKE $$targ $$BASE; \
- (cd $$i && $(MAKE) $$targ) || exit $?; \
- fi; \
+MKSUBDIR = \
+ set -e \
+ targ=$@; targ=$${targ\#d}; \
+ for i in $$dirs; do \
+ export BASE=$(BASE)$$i/; \
+ if [ ! -d $$i ]; then \
+ echo Skipping nonexistent directory: $$i 1>&2; \
+ else \
+ echo MAKE $$targ $$BASE; \
+ (cd $$i && $(MAKE) $$targ) || exit $?; \
+ fi; \
done
dall: