wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

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:
cmd/Makefile | 3+++
cmd/wmii/client.c | 30++++++++++++++++++++++++------
cmd/wmii/dat.h | 3+++
cmd/wmii/fns.h | 2+-
cmd/wmii/frame.c | 24+++++++++++++-----------
cmd/wmii/fs.c | 3++-
cmd/wmii/main.c | 7+++++++
cmd/wmii/x11.c | 18++++++++++++++----
cmd/wmii/xext.c | 51+++++++++++++++++++++++++++++++++++++++++++++++----
include/x11.h | 3++-
mk/dir.mk | 20+++++++++++---------
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: