changeset 0:7024076fa948

initial add
author paulo@localhost
date Sun, 22 Mar 2009 23:26:35 -0700
parents
children ba504f41828f
files LICENSE Makefile README client.c config.arg.h config.default.h config.h config.mk draw.c dwm.1 dwm.h event.c layout.c main.c tag.c util.c
diffstat 16 files changed, 2874 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/LICENSE	Sun Mar 22 23:26:35 2009 -0700
     1.3 @@ -0,0 +1,22 @@
     1.4 +MIT/X Consortium License
     1.5 +
     1.6 +(C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     1.7 +(C)opyright MMVI-MMVII Sander van Dijk <a dot h dot vandijk at gmail dot com>
     1.8 +
     1.9 +Permission is hereby granted, free of charge, to any person obtaining a
    1.10 +copy of this software and associated documentation files (the "Software"),
    1.11 +to deal in the Software without restriction, including without limitation
    1.12 +the rights to use, copy, modify, merge, publish, distribute, sublicense,
    1.13 +and/or sell copies of the Software, and to permit persons to whom the 
    1.14 +Software is furnished to do so, subject to the following conditions:
    1.15 +
    1.16 +The above copyright notice and this permission notice shall be included in 
    1.17 +all copies or substantial portions of the Software. 
    1.18 +
    1.19 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    1.20 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    1.21 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
    1.22 +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    1.23 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    1.24 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    1.25 +DEALINGS IN THE SOFTWARE.
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Sun Mar 22 23:26:35 2009 -0700
     2.3 @@ -0,0 +1,61 @@
     2.4 +# dwm - dynamic window manager
     2.5 +#   (C)opyright MMVI-MMVII Anselm R. Garbe
     2.6 +
     2.7 +include config.mk
     2.8 +
     2.9 +SRC = client.c draw.c event.c layout.c main.c tag.c util.c
    2.10 +OBJ = ${SRC:.c=.o}
    2.11 +
    2.12 +all: options dwm
    2.13 +
    2.14 +options:
    2.15 +	@echo dwm build options:
    2.16 +	@echo "CFLAGS   = ${CFLAGS}"
    2.17 +	@echo "LDFLAGS  = ${LDFLAGS}"
    2.18 +	@echo "CC       = ${CC}"
    2.19 +
    2.20 +.c.o:
    2.21 +	@echo CC $<
    2.22 +	@${CC} -c ${CFLAGS} $<
    2.23 +
    2.24 +${OBJ}: dwm.h config.h config.mk
    2.25 +
    2.26 +config.h:
    2.27 +	@echo creating $@ from config.default.h
    2.28 +	@cp config.default.h $@
    2.29 +
    2.30 +dwm: ${OBJ}
    2.31 +	@echo CC -o $@
    2.32 +	@${CC} -o $@ ${OBJ} ${LDFLAGS}
    2.33 +	@strip $@
    2.34 +
    2.35 +clean:
    2.36 +	@echo cleaning
    2.37 +	@rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
    2.38 +
    2.39 +dist: clean
    2.40 +	@echo creating dist tarball
    2.41 +	@mkdir -p dwm-${VERSION}
    2.42 +	@cp -R LICENSE Makefile README config.*.h config.mk \
    2.43 +		dwm.1 dwm.h ${SRC} dwm-${VERSION}
    2.44 +	@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
    2.45 +	@gzip dwm-${VERSION}.tar
    2.46 +	@rm -rf dwm-${VERSION}
    2.47 +
    2.48 +install: all
    2.49 +	@echo installing executable file to ${DESTDIR}${PREFIX}/bin
    2.50 +	@mkdir -p ${DESTDIR}${PREFIX}/bin
    2.51 +	@cp -f dwm ${DESTDIR}${PREFIX}/bin
    2.52 +	@chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
    2.53 +	@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
    2.54 +	@mkdir -p ${DESTDIR}${MANPREFIX}/man1
    2.55 +	@sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
    2.56 +	@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
    2.57 +
    2.58 +uninstall:
    2.59 +	@echo removing executable file from ${DESTDIR}${PREFIX}/bin
    2.60 +	@rm -f ${DESTDIR}${PREFIX}/bin/dwm
    2.61 +	@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
    2.62 +	@rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1
    2.63 +
    2.64 +.PHONY: all options clean dist install uninstall
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/README	Sun Mar 22 23:26:35 2009 -0700
     3.3 @@ -0,0 +1,48 @@
     3.4 +dwm - dynamic window manager
     3.5 +============================
     3.6 +dwm is an extremely fast, small, and dynamic window manager for X.
     3.7 +
     3.8 +
     3.9 +Requirements
    3.10 +------------
    3.11 +In order to build dwm you need the Xlib header files.
    3.12 +
    3.13 +
    3.14 +Installation
    3.15 +------------
    3.16 +Edit config.mk to match your local setup (dwm is installed into
    3.17 +the /usr/local namespace by default).
    3.18 +
    3.19 +Afterwards enter the following command to build and install dwm (if
    3.20 +necessary as root):
    3.21 +
    3.22 +    make clean install
    3.23 +
    3.24 +
    3.25 +Running dwm
    3.26 +-----------
    3.27 +Add the following line to your .xinitrc to start dwm using startx:
    3.28 +
    3.29 +    exec dwm
    3.30 +
    3.31 +In order to connect dwm to a specific display, make sure that
    3.32 +the DISPLAY environment variable is set correctly, e.g.:
    3.33 +
    3.34 +    DISPLAY=foo.bar:1 exec dwm
    3.35 +
    3.36 +(This will start dwm on display :1 of the host foo.bar.)
    3.37 +
    3.38 +In order to display status info in the bar, you can do something
    3.39 +like this in your .xinitrc:
    3.40 +
    3.41 +    while true
    3.42 +    do
    3.43 +        echo `date` `uptime | sed 's/.*,//'`
    3.44 +        sleep 1
    3.45 +    done | dwm
    3.46 +
    3.47 +
    3.48 +Configuration
    3.49 +-------------
    3.50 +The configuration of dwm is done by creating a custom config.h
    3.51 +and (re)compiling the source code.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/client.c	Sun Mar 22 23:26:35 2009 -0700
     4.3 @@ -0,0 +1,517 @@
     4.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     4.5 + * See LICENSE file for license details.
     4.6 + */
     4.7 +#include "dwm.h"
     4.8 +#include <stdio.h>
     4.9 +#include <stdlib.h>
    4.10 +#include <string.h>
    4.11 +#include <X11/Xatom.h>
    4.12 +#include <X11/Xutil.h>
    4.13 +
    4.14 +/* static */
    4.15 +
    4.16 +static void
    4.17 +attachstack(Client *c) {
    4.18 +	c->snext = stack;
    4.19 +	stack = c;
    4.20 +}
    4.21 +
    4.22 +static void
    4.23 +detachstack(Client *c) {
    4.24 +	Client **tc;
    4.25 +
    4.26 +	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
    4.27 +	*tc = c->snext;
    4.28 +}
    4.29 +
    4.30 +static void
    4.31 +grabbuttons(Client *c, Bool focused) {
    4.32 +	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
    4.33 +
    4.34 +	if(focused) {
    4.35 +		XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
    4.36 +				GrabModeAsync, GrabModeSync, None, None);
    4.37 +		XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
    4.38 +				GrabModeAsync, GrabModeSync, None, None);
    4.39 +		XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
    4.40 +				GrabModeAsync, GrabModeSync, None, None);
    4.41 +		XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
    4.42 +				GrabModeAsync, GrabModeSync, None, None);
    4.43 +
    4.44 +		XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
    4.45 +				GrabModeAsync, GrabModeSync, None, None);
    4.46 +		XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
    4.47 +				GrabModeAsync, GrabModeSync, None, None);
    4.48 +		XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
    4.49 +				GrabModeAsync, GrabModeSync, None, None);
    4.50 +		XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
    4.51 +				GrabModeAsync, GrabModeSync, None, None);
    4.52 +
    4.53 +		XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
    4.54 +				GrabModeAsync, GrabModeSync, None, None);
    4.55 +		XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
    4.56 +				GrabModeAsync, GrabModeSync, None, None);
    4.57 +		XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
    4.58 +				GrabModeAsync, GrabModeSync, None, None);
    4.59 +		XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
    4.60 +				GrabModeAsync, GrabModeSync, None, None);
    4.61 +	}
    4.62 +	else
    4.63 +		XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
    4.64 +				GrabModeAsync, GrabModeSync, None, None);
    4.65 +}
    4.66 +
    4.67 +static Bool
    4.68 +isprotodel(Client *c) {
    4.69 +	int i, n;
    4.70 +	Atom *protocols;
    4.71 +	Bool ret = False;
    4.72 +
    4.73 +	if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
    4.74 +		for(i = 0; !ret && i < n; i++)
    4.75 +			if(protocols[i] == wmatom[WMDelete])
    4.76 +				ret = True;
    4.77 +		XFree(protocols);
    4.78 +	}
    4.79 +	return ret;
    4.80 +}
    4.81 +
    4.82 +static void
    4.83 +setclientstate(Client *c, long state) {
    4.84 +	long data[] = {state, None};
    4.85 +
    4.86 +	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
    4.87 +			PropModeReplace, (unsigned char *)data, 2);
    4.88 +}
    4.89 +
    4.90 +static void
    4.91 +togglemax(Client *c) {
    4.92 +	XEvent ev;
    4.93 +
    4.94 +	if(c->isfixed)
    4.95 +		return;
    4.96 +	if((c->ismax = !c->ismax)) {
    4.97 +		c->rx = c->x;
    4.98 +		c->ry = c->y;
    4.99 +		c->rw = c->w;
   4.100 +		c->rh = c->h;
   4.101 +		resize(c, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True);
   4.102 +	}
   4.103 +	else
   4.104 +		resize(c, c->rx, c->ry, c->rw, c->rh, True);
   4.105 +	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   4.106 +}
   4.107 +
   4.108 +static int
   4.109 +xerrordummy(Display *dsply, XErrorEvent *ee) {
   4.110 +	return 0;
   4.111 +}
   4.112 +
   4.113 +/* extern */
   4.114 +
   4.115 +void
   4.116 +attach(Client *c) {
   4.117 +	if(clients)
   4.118 +		clients->prev = c;
   4.119 +	c->next = clients;
   4.120 +	clients = c;
   4.121 +}
   4.122 +
   4.123 +void
   4.124 +configure(Client *c) {
   4.125 +	XConfigureEvent ce;
   4.126 +
   4.127 +	ce.type = ConfigureNotify;
   4.128 +	ce.display = dpy;
   4.129 +	ce.event = c->win;
   4.130 +	ce.window = c->win;
   4.131 +	ce.x = c->x;
   4.132 +	ce.y = c->y;
   4.133 +	ce.width = c->w;
   4.134 +	ce.height = c->h;
   4.135 +	ce.border_width = c->border;
   4.136 +	ce.above = None;
   4.137 +	ce.override_redirect = False;
   4.138 +	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   4.139 +}
   4.140 +
   4.141 +void
   4.142 +detach(Client *c) {
   4.143 +	if(c->prev)
   4.144 +		c->prev->next = c->next;
   4.145 +	if(c->next)
   4.146 +		c->next->prev = c->prev;
   4.147 +	if(c == clients)
   4.148 +		clients = c->next;
   4.149 +	c->next = c->prev = NULL;
   4.150 +}
   4.151 +
   4.152 +void
   4.153 +focus(Client *c) {
   4.154 +	if(c && !isvisible(c))
   4.155 +		return;
   4.156 +	if(sel && sel != c) {
   4.157 +		grabbuttons(sel, False);
   4.158 +		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   4.159 +	}
   4.160 +	if(c) {
   4.161 +		detachstack(c);
   4.162 +		attachstack(c);
   4.163 +		grabbuttons(c, True);
   4.164 +	}
   4.165 +	sel = c;
   4.166 +	drawstatus();
   4.167 +	if(!selscreen)
   4.168 +		return;
   4.169 +	if(c) {
   4.170 +		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   4.171 +		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   4.172 +	}
   4.173 +	else
   4.174 +		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   4.175 +}
   4.176 +
   4.177 +void
   4.178 +killclient(Arg *arg) {
   4.179 +	if(!sel)
   4.180 +		return;
   4.181 +	if(isprotodel(sel))
   4.182 +		sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
   4.183 +	else
   4.184 +		XKillClient(dpy, sel->win);
   4.185 +}
   4.186 +
   4.187 +void
   4.188 +manage(Window w, XWindowAttributes *wa) {
   4.189 +	Client *c, *t;
   4.190 +	Window trans;
   4.191 +	XWindowChanges wc;
   4.192 +
   4.193 +	c = emallocz(sizeof(Client));
   4.194 +	c->tags = emallocz(ntags * sizeof(Bool));
   4.195 +	c->win = w;
   4.196 +	c->x = wa->x;
   4.197 +	c->y = wa->y;
   4.198 +	c->w = wa->width;
   4.199 +	c->h = wa->height;
   4.200 +	if(c->w == sw && c->h == sh) {
   4.201 +		c->border = 0;
   4.202 +		c->x = sx;
   4.203 +		c->y = sy;
   4.204 +	}
   4.205 +	else { 
   4.206 +		c->border = BORDERPX;
   4.207 +		if(c->x > wax + waw && c-> w < waw)
   4.208 +			c->x = wax + waw - c->w - 2 * c->border;
   4.209 +		if(c->y > way + wah && c-> h < wah)
   4.210 +			c->y = way + wah - c->h - 2 * c->border;
   4.211 +		if(c->x < wax && c->w < waw)
   4.212 +			c->x = wax;
   4.213 +		if(c->y < way && c->h < wah)
   4.214 +			c->y = way;
   4.215 +	}
   4.216 +	XSelectInput(dpy, w,
   4.217 +		StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
   4.218 +	XGetTransientForHint(dpy, w, &trans);
   4.219 +	grabbuttons(c, False);
   4.220 +	wc.border_width = c->border;
   4.221 +	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
   4.222 +	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
   4.223 +	configure(c); /* propagates border_width, if size doesn't change */
   4.224 +	updatetitle(c);
   4.225 +	for(t = clients; t && t->win != trans; t = t->next);
   4.226 +	settags(c, t);
   4.227 +	if(!c->isversatile)
   4.228 +		c->isversatile = (t != NULL) || c->isfixed;
   4.229 +	attach(c);
   4.230 +	attachstack(c);
   4.231 +	c->isbanned = True;
   4.232 +	XMoveWindow(dpy, w, c->x + 2 * sw, c->y);
   4.233 +	XMapWindow(dpy, w);
   4.234 +	setclientstate(c, NormalState);
   4.235 +	if(isvisible(c))
   4.236 +		focus(c);
   4.237 +	updatesizehints(c);
   4.238 +	lt->arrange();
   4.239 +}
   4.240 +
   4.241 +void
   4.242 +resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
   4.243 +	float actual, dx, dy, max, min;
   4.244 +	XWindowChanges wc;
   4.245 +
   4.246 +	if(w <= 0 || h <= 0)
   4.247 +		return;
   4.248 +	if(sizehints) {
   4.249 +		if(c->minw && w < c->minw)
   4.250 +			w = c->minw;
   4.251 +		if(c->minh && h < c->minh)
   4.252 +			h = c->minh;
   4.253 +		if(c->maxw && w > c->maxw)
   4.254 +			w = c->maxw;
   4.255 +		if(c->maxh && h > c->maxh)
   4.256 +			h = c->maxh;
   4.257 +		/* inspired by algorithm from fluxbox */
   4.258 +		if(c->minay > 0 && c->maxay && (h - c->baseh) > 0) {
   4.259 +			dx = (float)(w - c->basew);
   4.260 +			dy = (float)(h - c->baseh);
   4.261 +			min = (float)(c->minax) / (float)(c->minay);
   4.262 +			max = (float)(c->maxax) / (float)(c->maxay);
   4.263 +			actual = dx / dy;
   4.264 +			if(max > 0 && min > 0 && actual > 0) {
   4.265 +				if(actual < min) {
   4.266 +					dy = (dx * min + dy) / (min * min + 1);
   4.267 +					dx = dy * min;
   4.268 +					w = (int)dx + c->basew;
   4.269 +					h = (int)dy + c->baseh;
   4.270 +				}
   4.271 +				else if(actual > max) {
   4.272 +					dy = (dx * min + dy) / (max * max + 1);
   4.273 +					dx = dy * min;
   4.274 +					w = (int)dx + c->basew;
   4.275 +					h = (int)dy + c->baseh;
   4.276 +				}
   4.277 +			}
   4.278 +		}
   4.279 +		if(c->incw)
   4.280 +			w -= (w - c->basew) % c->incw;
   4.281 +		if(c->inch)
   4.282 +			h -= (h - c->baseh) % c->inch;
   4.283 +	}
   4.284 +	if(w == sw && h == sh)
   4.285 +		c->border = 0; 
   4.286 +	else
   4.287 +		c->border = BORDERPX;
   4.288 +	/* offscreen appearance fixes */
   4.289 +	if(x > sw)
   4.290 +		x = sw - w - 2 * c->border;
   4.291 +	if(y > sh)
   4.292 +		y = sh - h - 2 * c->border;
   4.293 +	if(x + w + 2 * c->border < sx)
   4.294 +		x = sx;
   4.295 +	if(y + h + 2 * c->border < sy)
   4.296 +		y = sy;
   4.297 +	/* if(c->x != x || c->y != y || c->w != w || c->h != h) { */
   4.298 +		c->x = wc.x = x;
   4.299 +		c->y = wc.y = y;
   4.300 +		c->w = wc.width = w;
   4.301 +		c->h = wc.height = h;
   4.302 +		wc.border_width = c->border;
   4.303 +		XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
   4.304 +		configure(c);
   4.305 +		XSync(dpy, False);
   4.306 +	/* } */
   4.307 +}
   4.308 +
   4.309 +void
   4.310 +toggleversatile(Arg *arg) {
   4.311 +	if(!sel || lt->arrange == versatile)
   4.312 +		return;
   4.313 +	sel->isversatile = !sel->isversatile;
   4.314 +	lt->arrange();
   4.315 +}
   4.316 +
   4.317 +void
   4.318 +updatesizehints(Client *c) {
   4.319 +	long msize;
   4.320 +	XSizeHints size;
   4.321 +
   4.322 +	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
   4.323 +		size.flags = PSize;
   4.324 +	c->flags = size.flags;
   4.325 +	if(c->flags & PBaseSize) {
   4.326 +		c->basew = size.base_width;
   4.327 +		c->baseh = size.base_height;
   4.328 +	}
   4.329 +	else
   4.330 +		c->basew = c->baseh = 0;
   4.331 +	if(c->flags & PResizeInc) {
   4.332 +		c->incw = size.width_inc;
   4.333 +		c->inch = size.height_inc;
   4.334 +	}
   4.335 +	else
   4.336 +		c->incw = c->inch = 0;
   4.337 +	if(c->flags & PMaxSize) {
   4.338 +		c->maxw = size.max_width;
   4.339 +		c->maxh = size.max_height;
   4.340 +	}
   4.341 +	else
   4.342 +		c->maxw = c->maxh = 0;
   4.343 +	if(c->flags & PMinSize) {
   4.344 +		c->minw = size.min_width;
   4.345 +		c->minh = size.min_height;
   4.346 +	}
   4.347 +	else
   4.348 +		c->minw = c->minh = 0;
   4.349 +	if(c->flags & PAspect) {
   4.350 +		c->minax = size.min_aspect.x;
   4.351 +		c->minay = size.min_aspect.y;
   4.352 +		c->maxax = size.max_aspect.x;
   4.353 +		c->maxay = size.max_aspect.y;
   4.354 +	}
   4.355 +	else
   4.356 +		c->minax = c->minay = c->maxax = c->maxay = 0;
   4.357 +	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
   4.358 +			&& c->maxw == c->minw && c->maxh == c->minh);
   4.359 +}
   4.360 +
   4.361 +void
   4.362 +updatetitle(Client *c) {
   4.363 +	char **list = NULL;
   4.364 +	int n;
   4.365 +	XTextProperty name;
   4.366 +
   4.367 +	name.nitems = 0;
   4.368 +	c->name[0] = 0;
   4.369 +	XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
   4.370 +	if(!name.nitems)
   4.371 +		XGetWMName(dpy, c->win, &name);
   4.372 +	if(!name.nitems)
   4.373 +		return;
   4.374 +	if(name.encoding == XA_STRING)
   4.375 +		strncpy(c->name, (char *)name.value, sizeof c->name);
   4.376 +	else {
   4.377 +		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
   4.378 +		&& n > 0 && *list)
   4.379 +		{
   4.380 +			strncpy(c->name, *list, sizeof c->name);
   4.381 +			XFreeStringList(list);
   4.382 +		}
   4.383 +	}
   4.384 +	XFree(name.value);
   4.385 +}
   4.386 +
   4.387 +void
   4.388 +unmanage(Client *c) {
   4.389 +	Client *nc;
   4.390 +
   4.391 +	/* The server grab construct avoids race conditions. */
   4.392 +	XGrabServer(dpy);
   4.393 +	XSetErrorHandler(xerrordummy);
   4.394 +	detach(c);
   4.395 +	detachstack(c);
   4.396 +	if(sel == c) {
   4.397 +		for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
   4.398 +		focus(nc);
   4.399 +	}
   4.400 +	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   4.401 +	setclientstate(c, WithdrawnState);
   4.402 +	free(c->tags);
   4.403 +	free(c);
   4.404 +	XSync(dpy, False);
   4.405 +	XSetErrorHandler(xerror);
   4.406 +	XUngrabServer(dpy);
   4.407 +	lt->arrange();
   4.408 +}
   4.409 +
   4.410 +void
   4.411 +zoom(Arg *arg) {
   4.412 +	unsigned int n;
   4.413 +	Client *c;
   4.414 +
   4.415 +	if(!sel)
   4.416 +		return;
   4.417 +	if(sel->isversatile || (lt->arrange == versatile)) {
   4.418 +		togglemax(sel);
   4.419 +		return;
   4.420 +	}
   4.421 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
   4.422 +		n++;
   4.423 +	if((c = sel) == nexttiled(clients))
   4.424 +		if(!(c = nexttiled(c->next)))
   4.425 +			return;
   4.426 +	detach(c);
   4.427 +	attach(c);
   4.428 +	focus(c);
   4.429 +	lt->arrange();
   4.430 +}
   4.431 +
   4.432 +Client *
   4.433 +prevtiled(Client *c) {
   4.434 +	for(; c && (c->isversatile || !isvisible(c)); c = c->prev);
   4.435 +	return c;
   4.436 +}
   4.437 +
   4.438 +void
   4.439 +pushup(Arg *arg) {
   4.440 +	Client *c;
   4.441 +
   4.442 +	if(!sel || sel->isversatile)
   4.443 +		return;
   4.444 +	if((c = prevtiled(sel->prev))) {
   4.445 +		/* attach before c */
   4.446 +		detach(sel);
   4.447 +		sel->next = c;
   4.448 +		sel->prev = c->prev;
   4.449 +		c->prev = sel;
   4.450 +		if(sel->prev)
   4.451 +			sel->prev->next = sel;
   4.452 +		else
   4.453 +			clients = sel;
   4.454 +	} else {
   4.455 +		/* move to the end */
   4.456 +		for(c = sel; c->next; c = c->next);
   4.457 +		detach(sel);
   4.458 +		sel->prev = c;
   4.459 +		c->next = sel;
   4.460 +	}
   4.461 +	focus(sel);
   4.462 +	lt->arrange();
   4.463 +}
   4.464 +
   4.465 +void
   4.466 +pushdown(Arg *arg) {
   4.467 +	Client *c;
   4.468 +
   4.469 +	if(!sel || sel->isversatile)
   4.470 +		return;
   4.471 +	if((c = nexttiled(sel->next))) {
   4.472 +		/* attach after c */
   4.473 +		detach(sel);
   4.474 +		sel->prev = c;
   4.475 +		sel->next = c->next;
   4.476 +		c->next = sel;
   4.477 +		if(sel->next)
   4.478 +			sel->next->prev = sel;
   4.479 +	} else {
   4.480 +		/* move to the front */
   4.481 +		detach(sel);
   4.482 +		attach(sel);
   4.483 +	}
   4.484 +	focus(sel);
   4.485 +	lt->arrange();
   4.486 +}
   4.487 +
   4.488 +void
   4.489 +moveresize(Arg *arg) {
   4.490 +	int x, y, w, h, nx, ny, nw, nh, ox, oy, ow, oh;
   4.491 +	char xAbs, yAbs, wAbs, hAbs;
   4.492 +	int mx, my, dx, dy, nmx, nmy;
   4.493 +	unsigned int dui;
   4.494 +	Window dummy;
   4.495 +
   4.496 +	if (lt->arrange != versatile)
   4.497 +		if (!sel || !sel->isversatile || !arg)
   4.498 +			return;
   4.499 +	if(sscanf(arg->cmd, "%d%c %d%c %d%c %d%c", &x, &xAbs, &y, &yAbs, &w, &wAbs, &h, &hAbs) != 8)
   4.500 +		return;
   4.501 +	nx = xAbs == 'X' ? x : sel->x + x;
   4.502 +	ny = yAbs == 'Y' ? y : sel->y + y;
   4.503 +	nw = wAbs == 'W' ? w : sel->w + w;
   4.504 +	nh = hAbs == 'H' ? h : sel->h + h;
   4.505 +
   4.506 +	ox = sel->x;
   4.507 +	oy = sel->y;
   4.508 +	ow = sel->w;
   4.509 +	oh = sel->h;
   4.510 +
   4.511 +	Bool xqp = XQueryPointer(dpy, root, &dummy, &dummy, &mx, &my, &dx, &dy, &dui);
   4.512 +	resize(sel, nx, ny, nw, nh, True);
   4.513 +	if (xqp && ox <= mx && (ox + ow) >= mx && oy <= my && (oy + oh) >= my)
   4.514 +	{
   4.515 +		nmx = mx-ox+sel->w-ow-1 < 0 ? 0 : mx-ox+sel->w-ow-1;
   4.516 +		nmy = my-oy+sel->h-oh-1 < 0 ? 0 : my-oy+sel->h-oh-1;
   4.517 +		XWarpPointer(dpy, None, sel->win, 0, 0, 0, 0, nmx, nmy);
   4.518 +	}
   4.519 +}
   4.520 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/config.arg.h	Sun Mar 22 23:26:35 2009 -0700
     5.3 @@ -0,0 +1,99 @@
     5.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     5.5 + * See LICENSE file for license details.
     5.6 + */
     5.7 +
     5.8 +/* appearance */
     5.9 +#define BORDERPX		1
    5.10 +#define FONT			"-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*"
    5.11 +#define NORMBORDERCOLOR		"#333"
    5.12 +#define NORMBGCOLOR		"#222"
    5.13 +#define NORMFGCOLOR		"#ccc"
    5.14 +#define SELBORDERCOLOR		"#69c"
    5.15 +#define SELBGCOLOR		"#555"
    5.16 +#define SELFGCOLOR		"#fff"
    5.17 +#define TOPBAR			True		/* False */
    5.18 +
    5.19 +/* behavior */
    5.20 +#define SNAP			40		/* pixel */
    5.21 +#define TAGS \
    5.22 +const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
    5.23 +#define RULES \
    5.24 +static Rule rule[] = { \
    5.25 +	/* class:instance:title regex	tags regex	isversatile */ \
    5.26 +	{ "Firefox",			"3",		False }, \
    5.27 +	{ "Gimp",			NULL,		True }, \
    5.28 +	{ "MPlayer",			NULL,		True }, \
    5.29 +	{ "Acroread",			NULL,		True }, \
    5.30 +};
    5.31 +
    5.32 +/* layout(s) */
    5.33 +#define LAYOUTS \
    5.34 +static Layout layout[] = { \
    5.35 +	/* symbol		function */ \
    5.36 +	{ "[]=",		tile }, /* first entry is default */ \
    5.37 +	{ "><>",		versatile }, \
    5.38 +};
    5.39 +#define MASTER			600		/* per thousand */
    5.40 +#define NMASTER			1		/* clients in master area */
    5.41 +
    5.42 +/* key definitions */
    5.43 +#define MODKEY			Mod1Mask
    5.44 +#define KEYS \
    5.45 +static Key key[] = { \
    5.46 +	/* modifier			key		function	argument */ \
    5.47 +	{ MODKEY|ShiftMask,		XK_Return,	spawn, \
    5.48 +		{ .cmd = "exec uxterm -bg '#222' -fg '#eee' -cr '#eee' +sb -fn '"FONT"'" } }, \
    5.49 +	{ MODKEY,			XK_p,		spawn, \
    5.50 +		{ .cmd = "exe=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \
    5.51 +			" | dmenu -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' " \
    5.52 +			"-sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"')\" && exec $exe" } }, \
    5.53 +	{ MODKEY,			XK_j,		focusnext,	{ 0 } }, \
    5.54 +	{ MODKEY,			XK_k,		focusprev,	{ 0 } }, \
    5.55 +	{ MODKEY,			XK_Return,	zoom,		{ 0 } }, \
    5.56 +	{ MODKEY,			XK_g,		resizemaster,	{ .i = 15 } }, \
    5.57 +	{ MODKEY,			XK_s,		resizemaster,	{ .i = -15 } }, \
    5.58 +	{ MODKEY,			XK_i,		incnmaster,	{ .i = 1 } }, \
    5.59 +	{ MODKEY,			XK_d,		incnmaster,	{ .i = -1 } }, \
    5.60 +	{ MODKEY|ShiftMask,		XK_0,		tag,		{ .i = -1 } }, \
    5.61 +	{ MODKEY|ShiftMask,		XK_1,		tag,		{ .i = 0 } }, \
    5.62 +	{ MODKEY|ShiftMask,		XK_2,		tag,		{ .i = 1 } }, \
    5.63 +	{ MODKEY|ShiftMask,		XK_3,		tag,		{ .i = 2 } }, \
    5.64 +	{ MODKEY|ShiftMask,		XK_4,		tag,		{ .i = 3 } }, \
    5.65 +	{ MODKEY|ShiftMask,		XK_5,		tag,		{ .i = 4 } }, \
    5.66 +	{ MODKEY|ShiftMask,		XK_6,		tag,		{ .i = 5 } }, \
    5.67 +	{ MODKEY|ShiftMask,		XK_7,		tag,		{ .i = 6 } }, \
    5.68 +	{ MODKEY|ShiftMask,		XK_8,		tag,		{ .i = 7 } }, \
    5.69 +	{ MODKEY|ShiftMask,		XK_9,		tag,		{ .i = 8 } }, \
    5.70 +	{ MODKEY|ControlMask|ShiftMask,	XK_1,		toggletag,	{ .i = 0 } }, \
    5.71 +	{ MODKEY|ControlMask|ShiftMask,	XK_2,		toggletag,	{ .i = 1 } }, \
    5.72 +	{ MODKEY|ControlMask|ShiftMask,	XK_3,		toggletag,	{ .i = 2 } }, \
    5.73 +	{ MODKEY|ControlMask|ShiftMask,	XK_4,		toggletag,	{ .i = 3 } }, \
    5.74 +	{ MODKEY|ControlMask|ShiftMask,	XK_5,		toggletag,	{ .i = 4 } }, \
    5.75 +	{ MODKEY|ControlMask|ShiftMask,	XK_6,		toggletag,	{ .i = 5 } }, \
    5.76 +	{ MODKEY|ControlMask|ShiftMask,	XK_7,		toggletag,	{ .i = 6 } }, \
    5.77 +	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	{ .i = 7 } }, \
    5.78 +	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	{ .i = 8 } }, \
    5.79 +	{ MODKEY|ShiftMask,		XK_c,		killclient,	{ 0 } }, \
    5.80 +	{ MODKEY,			XK_space,	setlayout,	{ .i = -1 } }, \
    5.81 +	{ MODKEY|ShiftMask,		XK_space,	toggleversatile,{ 0 } }, \
    5.82 +	{ MODKEY,			XK_0,		view,		{ .i = -1 } }, \
    5.83 +	{ MODKEY,			XK_1,		view,		{ .i = 0 } }, \
    5.84 +	{ MODKEY,			XK_2,		view,		{ .i = 1 } }, \
    5.85 +	{ MODKEY,			XK_3,		view,		{ .i = 2 } }, \
    5.86 +	{ MODKEY,			XK_4,		view,		{ .i = 3 } }, \
    5.87 +	{ MODKEY,			XK_5,		view,		{ .i = 4 } }, \
    5.88 +	{ MODKEY,			XK_6,		view,		{ .i = 5 } }, \
    5.89 +	{ MODKEY,			XK_7,		view,		{ .i = 6 } }, \
    5.90 +	{ MODKEY,			XK_8,		view,		{ .i = 7 } }, \
    5.91 +	{ MODKEY,			XK_9,		view,		{ .i = 8 } }, \
    5.92 +	{ MODKEY|ControlMask,		XK_1,		toggleview,	{ .i = 0 } }, \
    5.93 +	{ MODKEY|ControlMask,		XK_2,		toggleview,	{ .i = 1 } }, \
    5.94 +	{ MODKEY|ControlMask,		XK_3,		toggleview,	{ .i = 2 } }, \
    5.95 +	{ MODKEY|ControlMask,		XK_4,		toggleview,	{ .i = 3 } }, \
    5.96 +	{ MODKEY|ControlMask,		XK_5,		toggleview,	{ .i = 4 } }, \
    5.97 +	{ MODKEY|ControlMask,		XK_6,		toggleview,	{ .i = 5 } }, \
    5.98 +	{ MODKEY|ControlMask,		XK_7,		toggleview,	{ .i = 6 } }, \
    5.99 +	{ MODKEY|ControlMask,		XK_8,		toggleview,	{ .i = 7 } }, \
   5.100 +	{ MODKEY|ControlMask,		XK_9,		toggleview,	{ .i = 8 } }, \
   5.101 +	{ MODKEY|ShiftMask,		XK_q,		quit,		{ 0 } }, \
   5.102 +};
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/config.default.h	Sun Mar 22 23:26:35 2009 -0700
     6.3 @@ -0,0 +1,95 @@
     6.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     6.5 + * See LICENSE file for license details.
     6.6 + */
     6.7 +
     6.8 +/* appearance */
     6.9 +#define BORDERPX		1
    6.10 +#define FONT			"-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
    6.11 +#define NORMBORDERCOLOR		"#dddddd"
    6.12 +#define NORMBGCOLOR		"#eeeeee"
    6.13 +#define NORMFGCOLOR		"#222222"
    6.14 +#define SELBORDERCOLOR		"#ff0000"
    6.15 +#define SELBGCOLOR		"#006699"
    6.16 +#define SELFGCOLOR		"#ffffff"
    6.17 +#define TOPBAR			True		/* False */
    6.18 +
    6.19 +/* behavior */
    6.20 +#define SNAP			20		/* pixel */
    6.21 +#define TAGS \
    6.22 +const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
    6.23 +/* Query class:instance:title for regex matching info with following command:
    6.24 + * xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/ { printf("%s\n",$2) }' */
    6.25 +#define RULES \
    6.26 +static Rule rule[] = { \
    6.27 +	/* class:instance:title regex	tags regex	isversatile */ \
    6.28 +	{ "Gimp",			NULL,		True }, \
    6.29 +	{ "MPlayer",			NULL,		True }, \
    6.30 +	{ "Acroread",			NULL,		True }, \
    6.31 +};
    6.32 +
    6.33 +/* layout(s) */
    6.34 +#define LAYOUTS \
    6.35 +static Layout layout[] = { \
    6.36 +	/* symbol		function */ \
    6.37 +	{ "[]=",		tile }, /* first entry is default */ \
    6.38 +	{ "><>",		versatile }, \
    6.39 +};
    6.40 +#define MASTER			600		/* per thousand */
    6.41 +#define NMASTER			1		/* clients in master area */
    6.42 +
    6.43 +/* key definitions */
    6.44 +#define MODKEY			Mod1Mask
    6.45 +#define KEYS \
    6.46 +static Key key[] = { \
    6.47 +	/* modifier			key		function	argument */ \
    6.48 +	{ MODKEY|ShiftMask,		XK_Return,	spawn,		{ .cmd = "exec xterm" } }, \
    6.49 +	{ MODKEY,			XK_Tab,		focusnext,	{ 0 } }, \
    6.50 +	{ MODKEY|ShiftMask,		XK_Tab,		focusprev,	{ 0 } }, \
    6.51 +	{ MODKEY,			XK_Return,	zoom,		{ 0 } }, \
    6.52 +	{ MODKEY,			XK_g,		resizemaster,	{ .i = 15 } }, \
    6.53 +	{ MODKEY,			XK_s,		resizemaster,	{ .i = -15 } }, \
    6.54 +	{ MODKEY,			XK_i,		incnmaster,	{ .i = 1 } }, \
    6.55 +	{ MODKEY,			XK_d,		incnmaster,	{ .i = -1 } }, \
    6.56 +	{ MODKEY|ShiftMask,		XK_0,		tag,		{ .i = -1 } }, \
    6.57 +	{ MODKEY|ShiftMask,		XK_1,		tag,		{ .i = 0 } }, \
    6.58 +	{ MODKEY|ShiftMask,		XK_2,		tag,		{ .i = 1 } }, \
    6.59 +	{ MODKEY|ShiftMask,		XK_3,		tag,		{ .i = 2 } }, \
    6.60 +	{ MODKEY|ShiftMask,		XK_4,		tag,		{ .i = 3 } }, \
    6.61 +	{ MODKEY|ShiftMask,		XK_5,		tag,		{ .i = 4 } }, \
    6.62 +	{ MODKEY|ShiftMask,		XK_6,		tag,		{ .i = 5 } }, \
    6.63 +	{ MODKEY|ShiftMask,		XK_7,		tag,		{ .i = 6 } }, \
    6.64 +	{ MODKEY|ShiftMask,		XK_8,		tag,		{ .i = 7 } }, \
    6.65 +	{ MODKEY|ShiftMask,		XK_9,		tag,		{ .i = 8 } }, \
    6.66 +	{ MODKEY|ControlMask|ShiftMask,	XK_1,		toggletag,	{ .i = 0 } }, \
    6.67 +	{ MODKEY|ControlMask|ShiftMask,	XK_2,		toggletag,	{ .i = 1 } }, \
    6.68 +	{ MODKEY|ControlMask|ShiftMask,	XK_3,		toggletag,	{ .i = 2 } }, \
    6.69 +	{ MODKEY|ControlMask|ShiftMask,	XK_4,		toggletag,	{ .i = 3 } }, \
    6.70 +	{ MODKEY|ControlMask|ShiftMask,	XK_5,		toggletag,	{ .i = 4 } }, \
    6.71 +	{ MODKEY|ControlMask|ShiftMask,	XK_6,		toggletag,	{ .i = 5 } }, \
    6.72 +	{ MODKEY|ControlMask|ShiftMask,	XK_7,		toggletag,	{ .i = 6 } }, \
    6.73 +	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	{ .i = 7 } }, \
    6.74 +	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	{ .i = 8 } }, \
    6.75 +	{ MODKEY|ShiftMask,		XK_c,		killclient,	{ 0 } }, \
    6.76 +	{ MODKEY,			XK_space,	setlayout,	{ .i = -1 } }, \
    6.77 +	{ MODKEY|ShiftMask,		XK_space,	toggleversatile,{ 0 } }, \
    6.78 +	{ MODKEY,			XK_0,		view,		{ .i = -1 } }, \
    6.79 +	{ MODKEY,			XK_1,		view,		{ .i = 0 } }, \
    6.80 +	{ MODKEY,			XK_2,		view,		{ .i = 1 } }, \
    6.81 +	{ MODKEY,			XK_3,		view,		{ .i = 2 } }, \
    6.82 +	{ MODKEY,			XK_4,		view,		{ .i = 3 } }, \
    6.83 +	{ MODKEY,			XK_5,		view,		{ .i = 4 } }, \
    6.84 +	{ MODKEY,			XK_6,		view,		{ .i = 5 } }, \
    6.85 +	{ MODKEY,			XK_7,		view,		{ .i = 6 } }, \
    6.86 +	{ MODKEY,			XK_8,		view,		{ .i = 7 } }, \
    6.87 +	{ MODKEY,			XK_9,		view,		{ .i = 8 } }, \
    6.88 +	{ MODKEY|ControlMask,		XK_1,		toggleview,	{ .i = 0 } }, \
    6.89 +	{ MODKEY|ControlMask,		XK_2,		toggleview,	{ .i = 1 } }, \
    6.90 +	{ MODKEY|ControlMask,		XK_3,		toggleview,	{ .i = 2 } }, \
    6.91 +	{ MODKEY|ControlMask,		XK_4,		toggleview,	{ .i = 3 } }, \
    6.92 +	{ MODKEY|ControlMask,		XK_5,		toggleview,	{ .i = 4 } }, \
    6.93 +	{ MODKEY|ControlMask,		XK_6,		toggleview,	{ .i = 5 } }, \
    6.94 +	{ MODKEY|ControlMask,		XK_7,		toggleview,	{ .i = 6 } }, \
    6.95 +	{ MODKEY|ControlMask,		XK_8,		toggleview,	{ .i = 7 } }, \
    6.96 +	{ MODKEY|ControlMask,		XK_9,		toggleview,	{ .i = 8 } }, \
    6.97 +	{ MODKEY|ShiftMask,		XK_q,		quit,		{ 0 } }, \
    6.98 +};
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/config.h	Sun Mar 22 23:26:35 2009 -0700
     7.3 @@ -0,0 +1,131 @@
     7.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     7.5 + * See LICENSE file for license details.
     7.6 + */
     7.7 +
     7.8 +/* appearance */
     7.9 +#define BORDERPX		1
    7.10 +#define FONT			"6x9"
    7.11 +#define NORMBORDERCOLOR		"#aaaaaa"
    7.12 +#define NORMBGCOLOR		"#222222"
    7.13 +#define NORMFGCOLOR		"#eeeeee"
    7.14 +#define SELBORDERCOLOR		"#ff0000"
    7.15 +#define SELBGCOLOR		"#222222"
    7.16 +#define SELFGCOLOR		"#00ff00"
    7.17 +#define TOPBAR			True		/* False */
    7.18 +
    7.19 +/* behavior */
    7.20 +#define SNAP			10		/* pixel */
    7.21 +#define TAGS \
    7.22 +const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", NULL };
    7.23 +/* Query class:instance:title for regex matching info with following command:
    7.24 + * xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/ { printf("%s\n",$2) }' */
    7.25 +#define RULES \
    7.26 +static Rule rule[] = { \
    7.27 +	/* class:instance:title regex	tags regex	isversatile */ \
    7.28 +	{ "Gimp",			NULL,		False }, \
    7.29 +	{ "MPlayer",			NULL,		False }, \
    7.30 +	{ "Acroread",			NULL,		False }, \
    7.31 +};
    7.32 +
    7.33 +/* layout(s) */
    7.34 +#define LAYOUTS \
    7.35 +static Layout layout[] = { \
    7.36 +	/* symbol		function */ \
    7.37 +	{ " ",		versatile }, \
    7.38 +	{ "@",		spiral }, \
    7.39 +	{ "&",		spiral_h }, \
    7.40 +	{ "X",		monocle }, \
    7.41 +	{ "#",		grid }, \
    7.42 +	{ "U",		bstack }, \
    7.43 +	{ "!",		tile }, \
    7.44 +	/*{ "\\",		cascade },*/ \
    7.45 +	/* first entry is default */ \
    7.46 +};
    7.47 +#define MASTER			650		/* per thousand */
    7.48 +#define NMASTER			1		/* clients in master area */
    7.49 +
    7.50 +/* key definitions */
    7.51 +#define MODKEY			Mod4Mask
    7.52 +#define KEYS \
    7.53 +static Key key[] = { \
    7.54 +	/* modifier			key		function	argument */ \
    7.55 +	{ MODKEY|ShiftMask,		XK_Return,	spawn,		{ .cmd = "/home/paulo/bin/myterm.sh" } }, \
    7.56 +	{ MODKEY,			XK_backslash,	spawn,		{ .cmd = "/home/paulo/bin/myterm.sh -e /home/paulo/bin/viclip.sh" } }, \
    7.57 +	{ MODKEY,			XK_n,		pushdown,	{ 0 } }, \
    7.58 +	{ MODKEY,			XK_p,		pushup,	{ 0 } }, \
    7.59 +	{ MODKEY,			XK_Tab,		focusnext,	{ 0 } }, \
    7.60 +	{ MODKEY|ShiftMask,		XK_Tab,		focusprev,	{ 0 } }, \
    7.61 +	{ MODKEY,			XK_Return,	zoom,		{ 0 } }, \
    7.62 +	{ MODKEY,			XK_g,		resizemaster,	{ .i = 15 } }, \
    7.63 +	{ MODKEY,			XK_s,		resizemaster,	{ .i = -15 } }, \
    7.64 +	{ MODKEY,			XK_i,		incnmaster,	{ .i = 1 } }, \
    7.65 +	{ MODKEY,			XK_d,		incnmaster,	{ .i = -1 } }, \
    7.66 +	{ MODKEY|ShiftMask,		XK_grave,		tag,		{ .i = -1 } }, \
    7.67 +	{ MODKEY|ShiftMask,		XK_1,		tag,		{ .i = 0 } }, \
    7.68 +	{ MODKEY|ShiftMask,		XK_2,		tag,		{ .i = 1 } }, \
    7.69 +	{ MODKEY|ShiftMask,		XK_3,		tag,		{ .i = 2 } }, \
    7.70 +	{ MODKEY|ShiftMask,		XK_4,		tag,		{ .i = 3 } }, \
    7.71 +	{ MODKEY|ShiftMask,		XK_5,		tag,		{ .i = 4 } }, \
    7.72 +	{ MODKEY|ShiftMask,		XK_6,		tag,		{ .i = 5 } }, \
    7.73 +	{ MODKEY|ShiftMask,		XK_7,		tag,		{ .i = 6 } }, \
    7.74 +	{ MODKEY|ShiftMask,		XK_8,		tag,		{ .i = 7 } }, \
    7.75 +	{ MODKEY|ShiftMask,		XK_9,		tag,		{ .i = 8 } }, \
    7.76 +	{ MODKEY|ShiftMask,		XK_0,		tag,		{ .i = 9 } }, \
    7.77 +	{ MODKEY|ControlMask|ShiftMask,	XK_1,		toggletag,	{ .i = 0 } }, \
    7.78 +	{ MODKEY|ControlMask|ShiftMask,	XK_2,		toggletag,	{ .i = 1 } }, \
    7.79 +	{ MODKEY|ControlMask|ShiftMask,	XK_3,		toggletag,	{ .i = 2 } }, \
    7.80 +	{ MODKEY|ControlMask|ShiftMask,	XK_4,		toggletag,	{ .i = 3 } }, \
    7.81 +	{ MODKEY|ControlMask|ShiftMask,	XK_5,		toggletag,	{ .i = 4 } }, \
    7.82 +	{ MODKEY|ControlMask|ShiftMask,	XK_6,		toggletag,	{ .i = 5 } }, \
    7.83 +	{ MODKEY|ControlMask|ShiftMask,	XK_7,		toggletag,	{ .i = 6 } }, \
    7.84 +	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	{ .i = 7 } }, \
    7.85 +	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	{ .i = 8 } }, \
    7.86 +	{ MODKEY|ControlMask|ShiftMask,	XK_0,		toggletag,	{ .i = 9 } }, \
    7.87 +	{ MODKEY|ShiftMask,		XK_c,		killclient,	{ 0 } }, \
    7.88 +	{ MODKEY,			XK_space,	setlayout,	{ .i = -1 } }, \
    7.89 +	{ MODKEY,			XK_F1,	setlayout,	{ .i = 0 } }, \
    7.90 +	{ MODKEY,			XK_F2,	setlayout,	{ .i = 1 } }, \
    7.91 +	{ MODKEY,			XK_F3,	setlayout,	{ .i = 2 } }, \
    7.92 +	{ MODKEY,			XK_F4,	setlayout,	{ .i = 3 } }, \
    7.93 +	{ MODKEY,			XK_F5,	setlayout,	{ .i = 4 } }, \
    7.94 +	{ MODKEY,			XK_F6,	setlayout,	{ .i = 5 } }, \
    7.95 +	{ MODKEY,			XK_F7,	setlayout,	{ .i = 6 } }, \
    7.96 +	{ MODKEY|ShiftMask,		XK_space,	toggleversatile,{ 0 } }, \
    7.97 +	{ MODKEY,			XK_grave,		view,		{ .i = -1 } }, \
    7.98 +	{ MODKEY,			XK_1,		view,		{ .i = 0 } }, \
    7.99 +	{ MODKEY,			XK_2,		view,		{ .i = 1 } }, \
   7.100 +	{ MODKEY,			XK_3,		view,		{ .i = 2 } }, \
   7.101 +	{ MODKEY,			XK_4,		view,		{ .i = 3 } }, \
   7.102 +	{ MODKEY,			XK_5,		view,		{ .i = 4 } }, \
   7.103 +	{ MODKEY,			XK_6,		view,		{ .i = 5 } }, \
   7.104 +	{ MODKEY,			XK_7,		view,		{ .i = 6 } }, \
   7.105 +	{ MODKEY,			XK_8,		view,		{ .i = 7 } }, \
   7.106 +	{ MODKEY,			XK_9,		view,		{ .i = 8 } }, \
   7.107 +	{ MODKEY,			XK_0,		view,		{ .i = 9 } }, \
   7.108 +	{ MODKEY,			XK_BackSpace,		last_view,		{ 0 } }, \
   7.109 +	{ MODKEY|ControlMask,		XK_1,		toggleview,	{ .i = 0 } }, \
   7.110 +	{ MODKEY|ControlMask,		XK_2,		toggleview,	{ .i = 1 } }, \
   7.111 +	{ MODKEY|ControlMask,		XK_3,		toggleview,	{ .i = 2 } }, \
   7.112 +	{ MODKEY|ControlMask,		XK_4,		toggleview,	{ .i = 3 } }, \
   7.113 +	{ MODKEY|ControlMask,		XK_5,		toggleview,	{ .i = 4 } }, \
   7.114 +	{ MODKEY|ControlMask,		XK_6,		toggleview,	{ .i = 5 } }, \
   7.115 +	{ MODKEY|ControlMask,		XK_7,		toggleview,	{ .i = 6 } }, \
   7.116 +	{ MODKEY|ControlMask,		XK_8,		toggleview,	{ .i = 7 } }, \
   7.117 +	{ MODKEY|ControlMask,		XK_9,		toggleview,	{ .i = 8 } }, \
   7.118 +	{ MODKEY|ControlMask,		XK_0,		toggleview,	{ .i = 9 } }, \
   7.119 +	{ MODKEY|ShiftMask,		XK_q,		quit,		{ 0 } }, \
   7.120 +	{ MODKEY,		XK_h,		moveresize,		"-25x 0y 0w 0h" }, \
   7.121 +	{ MODKEY,		XK_l,		moveresize,		"25x 0y 0w 0h" }, \
   7.122 +	{ MODKEY,		XK_j,		moveresize,		"0x 25y 0w 0h" }, \
   7.123 +	{ MODKEY,		XK_k,		moveresize,		"0x -25y 0w 0h" }, \
   7.124 +	{ MODKEY|ControlMask,		XK_h,		moveresize,		"0X 0y 0w 0h" }, \
   7.125 +	{ MODKEY|ControlMask,		XK_l,		moveresize,		"9000X 0y 0w 0h" }, \
   7.126 +	{ MODKEY|ControlMask,		XK_j,		moveresize,		"0x 9000Y 0w 0h" }, \
   7.127 +	{ MODKEY|ControlMask,		XK_k,		moveresize,		"0x 15Y 0w 0h" }, \
   7.128 +	{ MODKEY|ShiftMask,		XK_h,		moveresize,		"0x 0y -25w 0h" }, \
   7.129 +	{ MODKEY|ShiftMask,		XK_l,		moveresize,		"0x 0y 25w 0h" }, \
   7.130 +	{ MODKEY|ShiftMask,		XK_j,		moveresize,		"0x 0y 0w 25h" }, \
   7.131 +	{ MODKEY|ShiftMask,		XK_k,		moveresize,		"0x 0y 0w -25h" }, \
   7.132 +};
   7.133 +
   7.134 +#define MAX_TASKS		10		/* max number of apps in taskbar */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/config.mk	Sun Mar 22 23:26:35 2009 -0700
     8.3 @@ -0,0 +1,29 @@
     8.4 +# dwm version
     8.5 +VERSION = 3.6.1
     8.6 +
     8.7 +# Customize below to fit your system
     8.8 +
     8.9 +# paths
    8.10 +PREFIX = /usr/local
    8.11 +MANPREFIX = ${PREFIX}/share/man
    8.12 +
    8.13 +X11INC = /usr/X11R6/include
    8.14 +X11LIB = /usr/X11R6/lib
    8.15 +
    8.16 +# includes and libs
    8.17 +INCS = -I. -I/usr/include -I${X11INC}
    8.18 +LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
    8.19 +
    8.20 +# flags
    8.21 +CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
    8.22 +LDFLAGS = ${LIBS}
    8.23 +#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
    8.24 +#LDFLAGS = -g ${LIBS}
    8.25 +
    8.26 +# Solaris
    8.27 +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
    8.28 +#LDFLAGS = ${LIBS}
    8.29 +#CFLAGS += -xtarget=ultra
    8.30 +
    8.31 +# compiler and linker
    8.32 +CC = cc
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/draw.c	Sun Mar 22 23:26:35 2009 -0700
     9.3 @@ -0,0 +1,154 @@
     9.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
     9.5 + * See LICENSE file for license details.
     9.6 + */
     9.7 +#include "dwm.h"
     9.8 +#include <string.h>
     9.9 +
    9.10 +/* static */
    9.11 +
    9.12 +static void
    9.13 +drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
    9.14 +	int x;
    9.15 +	XGCValues gcv;
    9.16 +	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
    9.17 +
    9.18 +	gcv.foreground = col[ColFG];
    9.19 +	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
    9.20 +	x = (dc.font.ascent + dc.font.descent + 2) / 4;
    9.21 +	r.x = dc.x + 1;
    9.22 +	r.y = dc.y + 1;
    9.23 +	if(filled) {
    9.24 +		r.width = r.height = x + 1;
    9.25 +		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
    9.26 +	}
    9.27 +	else if(empty) {
    9.28 +		r.width = r.height = x;
    9.29 +		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
    9.30 +	}
    9.31 +}
    9.32 +
    9.33 +static Bool
    9.34 +isoccupied(unsigned int t) {
    9.35 +	Client *c;
    9.36 +
    9.37 +	for(c = clients; c; c = c->next)
    9.38 +		if(c->tags[t])
    9.39 +			return True;
    9.40 +	return False;
    9.41 +}
    9.42 +
    9.43 +static unsigned int
    9.44 +textnw(const char *text, unsigned int len) {
    9.45 +	XRectangle r;
    9.46 +
    9.47 +	if(dc.font.set) {
    9.48 +		XmbTextExtents(dc.font.set, text, len, NULL, &r);
    9.49 +		return r.width;
    9.50 +	}
    9.51 +	return XTextWidth(dc.font.xfont, text, len);
    9.52 +}
    9.53 +
    9.54 +/* extern */
    9.55 +
    9.56 +void
    9.57 +drawstatus(void) {
    9.58 +	Client *c;
    9.59 +	int i, j, x;
    9.60 +
    9.61 +	dc.x = dc.y = 0;
    9.62 +	for(i = 0; i < ntags; i++) {
    9.63 +		dc.w = textw(tags[i]);
    9.64 +		if(seltag[i]) {
    9.65 +			drawtext(tags[i], dc.sel);
    9.66 +			drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
    9.67 +		}
    9.68 +		else {
    9.69 +			drawtext(tags[i], dc.norm);
    9.70 +			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
    9.71 +		}
    9.72 +		dc.x += dc.w;
    9.73 +	}
    9.74 +	dc.w = blw;
    9.75 +	drawtext(lt->symbol, dc.norm);
    9.76 +	x = dc.x + dc.w;
    9.77 +	dc.w = textw(stext);
    9.78 +	dc.x = sw - dc.w;
    9.79 +	if(dc.x < x) {
    9.80 +		dc.x = x;
    9.81 +		dc.w = sw - x;
    9.82 +	}
    9.83 +	drawtext(stext, dc.norm);
    9.84 +	if((dc.w = dc.x - x) > bh) {
    9.85 +		dc.x = x;
    9.86 +		for(j=0, c = clients; c; c = c->next) {
    9.87 +			if(isvisible(c))
    9.88 +				j++;
    9.89 +		}
    9.90 +		if(j && j < MAX_TASKS)
    9.91 +			dc.w /= j;
    9.92 +		else {
    9.93 +			drawtext(sel ? sel->name : NULL, sel ? dc.sel : dc.norm);
    9.94 +			j = 0;
    9.95 +		}
    9.96 +		for(c = clients; j && c; c = c->next) {
    9.97 +			if(isvisible(c)) {
    9.98 +				drawtext(c->name, (c == sel) ? dc.sel : dc.norm);
    9.99 +				dc.x += dc.w;
   9.100 +				j--;
   9.101 +			}
   9.102 +		}
   9.103 +	}
   9.104 +	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
   9.105 +	XSync(dpy, False);
   9.106 +}
   9.107 +
   9.108 +void
   9.109 +drawtext(const char *text, unsigned long col[ColLast]) {
   9.110 +	int x, y, w, h;
   9.111 +	static char buf[256];
   9.112 +	unsigned int len, olen;
   9.113 +	XGCValues gcv;
   9.114 +	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   9.115 +
   9.116 +	XSetForeground(dpy, dc.gc, col[ColBG]);
   9.117 +	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   9.118 +	if(!text)
   9.119 +		return;
   9.120 +	w = 0;
   9.121 +	olen = len = strlen(text);
   9.122 +	if(len >= sizeof buf)
   9.123 +		len = sizeof buf - 1;
   9.124 +	memcpy(buf, text, len);
   9.125 +	buf[len] = 0;
   9.126 +	h = dc.font.ascent + dc.font.descent;
   9.127 +	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
   9.128 +	x = dc.x + (h / 2);
   9.129 +	/* shorten text if necessary */
   9.130 +	while(len && (w = textnw(buf, len)) > dc.w - h)
   9.131 +		buf[--len] = 0;
   9.132 +	if(len < olen) {
   9.133 +		if(len > 1)
   9.134 +			buf[len - 1] = '.';
   9.135 +		if(len > 2)
   9.136 +			buf[len - 2] = '.';
   9.137 +		if(len > 3)
   9.138 +			buf[len - 3] = '.';
   9.139 +	}
   9.140 +	if(w > dc.w)
   9.141 +		return; /* too long */
   9.142 +	gcv.foreground = col[ColFG];
   9.143 +	if(dc.font.set) {
   9.144 +		XChangeGC(dpy, dc.gc, GCForeground, &gcv);
   9.145 +		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
   9.146 +	}
   9.147 +	else {
   9.148 +		gcv.font = dc.font.xfont->fid;
   9.149 +		XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
   9.150 +		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   9.151 +	}
   9.152 +}
   9.153 +
   9.154 +unsigned int
   9.155 +textw(const char *text) {
   9.156 +	return textnw(text, strlen(text)) + dc.font.height;
   9.157 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/dwm.1	Sun Mar 22 23:26:35 2009 -0700
    10.3 @@ -0,0 +1,149 @@
    10.4 +.TH DWM 1 dwm-VERSION
    10.5 +.SH NAME
    10.6 +dwm \- dynamic window manager
    10.7 +.SH SYNOPSIS
    10.8 +.B dwm
    10.9 +.RB [ \-v ]
   10.10 +.SH DESCRIPTION
   10.11 +dwm is a dynamic window manager for X. It manages windows in tiling and
   10.12 +versatile layouts. Either layout can be applied dynamically, optimizing the
   10.13 +environment for the application in use and the task performed.
   10.14 +.P
   10.15 +In tiling layout windows are managed in a master and stacking area. The master
   10.16 +area contains the windows which currently need most attention, whereas the
   10.17 +stacking area contains all other windows. In versatile layout windows can be
   10.18 +resized and moved freely. Dialog windows are always managed versatile,
   10.19 +regardless of the layout applied.
   10.20 +.P
   10.21 +Windows are grouped by tags. Each window can be tagged with one or multiple
   10.22 +tags. Selecting certain tags displays all windows with these tags.
   10.23 +.P
   10.24 +dwm contains a small status bar which displays all available tags, the layout,
   10.25 +the title of the focused window, and the text read from standard input. The
   10.26 +selected tags are indicated with a different color. The tags of the focused
   10.27 +window are indicated with a filled square in the top left corner.  The tags
   10.28 +which are applied to one or more windows are indicated with an empty square in
   10.29 +the top left corner.
   10.30 +.P
   10.31 +dwm draws a small border around windows to indicate the focus state.
   10.32 +.SH OPTIONS
   10.33 +.TP
   10.34 +.B \-v
   10.35 +prints version information to standard output, then exits.
   10.36 +.SH USAGE
   10.37 +.SS Status bar
   10.38 +.TP
   10.39 +.B Standard input
   10.40 +is read and displayed in the status text area.
   10.41 +.TP
   10.42 +.B Button1
   10.43 +click on a tag label to display all windows with that tag, click on the layout
   10.44 +label toggles between tiling and versatile layout.
   10.45 +.TP
   10.46 +.B Button3
   10.47 +click on a tag label adds/removes all windows with that tag to/from the view.
   10.48 +.TP
   10.49 +.B Button4
   10.50 +click on the layout label increases the number of windows in the master area (tiling layout only).
   10.51 +.TP
   10.52 +.B Button5
   10.53 +click on the layout label decreases the number of windows in the master area (tiling layout only).
   10.54 +.TP
   10.55 +.B Mod1-Button1
   10.56 +click on a tag label applies that tag to the focused window.
   10.57 +.TP
   10.58 +.B Mod1-Button3
   10.59 +click on a tag label adds/removes that tag to/from the focused window.
   10.60 +.SS Keyboard commands
   10.61 +.TP
   10.62 +.B Mod1-Shift-Return
   10.63 +Start
   10.64 +.BR xterm (1).
   10.65 +.TP
   10.66 +.B Mod1-Tab
   10.67 +Focus next window.
   10.68 +.TP
   10.69 +.B Mod1-Shift-Tab
   10.70 +Focus previous window.
   10.71 +.TP
   10.72 +.B Mod1-Return
   10.73 +Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (versatile layout).
   10.74 +.TP
   10.75 +.B Mod1-g
   10.76 +Grow master area (tiling layout only).
   10.77 +.TP
   10.78 +.B Mod1-s
   10.79 +Shrink master area (tiling layout only).
   10.80 +.TP
   10.81 +.B Mod1-i
   10.82 +Increase the number of windows in the master area (tiling layout only).
   10.83 +.TP
   10.84 +.B Mod1-d
   10.85 +Decrease the number of windows in the master area (tiling layout only).
   10.86 +.TP
   10.87 +.B Mod1-Shift-[1..n]
   10.88 +Apply
   10.89 +.RB nth
   10.90 +tag to current window.
   10.91 +.TP
   10.92 +.B Mod1-Shift-0
   10.93 +Apply all tags to current window.
   10.94 +.TP
   10.95 +.B Mod1-Control-Shift-[1..n]
   10.96 +Add/remove
   10.97 +.B nth
   10.98 +tag to/from current window.
   10.99 +.TP
  10.100 +.B Mod1-Shift-c
  10.101 +Close focused window.
  10.102 +.TP
  10.103 +.B Mod1-space
  10.104 +Toggle between tiling and versatile layout (affects all windows).
  10.105 +.TP
  10.106 +.B Mod1-Shift-space
  10.107 +Toggle focused window between versatile and non-versatile state (tiling layout only).
  10.108 +.TP
  10.109 +.B Mod1-[1..n]
  10.110 +View all windows with
  10.111 +.BR nth
  10.112 +tag.
  10.113 +.TP
  10.114 +.B Mod1-0
  10.115 +View all windows with any tag.
  10.116 +.TP
  10.117 +.B Mod1-Control-[1..n]
  10.118 +Add/remove all windows with
  10.119 +.BR nth
  10.120 +tag to/from the view.
  10.121 +.TP
  10.122 +.B Mod1-Shift-q
  10.123 +Quit dwm.
  10.124 +.SS Mouse commands
  10.125 +.TP
  10.126 +.B Mod1-Button1
  10.127 +Move current window while dragging (versatile layout only).
  10.128 +.TP
  10.129 +.B Mod1-Button2
  10.130 +Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (versatile layout).
  10.131 +.TP
  10.132 +.B Mod1-Button3
  10.133 +Resize current window while dragging (versatile layout only).
  10.134 +.SH CUSTOMIZATION
  10.135 +dwm is customized by creating a custom config.h and (re)compiling the source
  10.136 +code. This keeps it fast, secure and simple.
  10.137 +.SH SEE ALSO
  10.138 +.BR dmenu (1)
  10.139 +.SH BUGS
  10.140 +The status bar may display
  10.141 +.BR "EOF"
  10.142 +when dwm has been started by an X session manager like
  10.143 +.BR xdm (1),
  10.144 +because those close standard output before executing dwm.
  10.145 +.P
  10.146 +Java applications which use the XToolkit/XAWT backend may draw grey windows
  10.147 +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
  10.148 +JDK 1.6 versions, because it assumes a reparenting window manager. As a workaround
  10.149 +you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
  10.150 +can set the following environment variable (to use the older Motif
  10.151 +backend instead):
  10.152 +.BR AWT_TOOLKIT=MToolkit .
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/dwm.h	Sun Mar 22 23:26:35 2009 -0700
    11.3 @@ -0,0 +1,160 @@
    11.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    11.5 + * See LICENSE file for license details.
    11.6 + *
    11.7 + * dynamic window manager is designed like any other X client as well. It is
    11.8 + * driven through handling X events. In contrast to other X clients, a window
    11.9 + * manager selects for SubstructureRedirectMask on the root window, to receive
   11.10 + * events about window (dis-)appearance.  Only one X connection at a time is
   11.11 + * allowed to select for this event mask.
   11.12 + *
   11.13 + * Calls to fetch an X event from the event queue are blocking.  Due reading
   11.14 + * status text from standard input, a select()-driven main loop has been
   11.15 + * implemented which selects for reads on the X connection and STDIN_FILENO to
   11.16 + * handle all data smoothly. The event handlers of dwm are organized in an
   11.17 + * array which is accessed whenever a new event has been fetched. This allows
   11.18 + * event dispatching in O(1) time.
   11.19 + *
   11.20 + * Each child of the root window is called a client, except windows which have
   11.21 + * set the override_redirect flag.  Clients are organized in a global
   11.22 + * doubly-linked client list, the focus history is remembered through a global
   11.23 + * stack list. Each client contains an array of Bools of the same size as the
   11.24 + * global tags array to indicate the tags of a client.  For each client dwm
   11.25 + * creates a small title window, which is resized whenever the (_NET_)WM_NAME
   11.26 + * properties are updated or the client is moved/resized.
   11.27 + *
   11.28 + * Keys and tagging rules are organized as arrays and defined in the config.h
   11.29 + * file. These arrays are kept static in event.o and tag.o respectively,
   11.30 + * because no other part of dwm needs access to them.  The current layout is
   11.31 + * represented by the lt pointer.
   11.32 + *
   11.33 + * To understand everything else, start reading main.c:main().
   11.34 + */
   11.35 +
   11.36 +#include "config.h"
   11.37 +#include <X11/Xlib.h>
   11.38 +
   11.39 +/* mask shorthands, used in event.c and client.c */
   11.40 +#define BUTTONMASK		(ButtonPressMask | ButtonReleaseMask)
   11.41 +
   11.42 +enum { NetSupported, NetWMName, NetLast };		/* EWMH atoms */
   11.43 +enum { WMProtocols, WMDelete, WMState, WMLast };	/* default atoms */
   11.44 +enum { CurNormal, CurResize, CurMove, CurLast };	/* cursor */
   11.45 +enum { ColBorder, ColFG, ColBG, ColLast };		/* color */
   11.46 +
   11.47 +typedef union {
   11.48 +	const char *cmd;
   11.49 +	int i;
   11.50 +} Arg; /* argument type */
   11.51 +
   11.52 +typedef struct {
   11.53 +	int ascent;
   11.54 +	int descent;
   11.55 +	int height;
   11.56 +	XFontSet set;
   11.57 +	XFontStruct *xfont;
   11.58 +} Fnt;
   11.59 +
   11.60 +typedef struct {
   11.61 +	int x, y, w, h;
   11.62 +	unsigned long norm[ColLast];
   11.63 +	unsigned long sel[ColLast];
   11.64 +	Drawable drawable;
   11.65 +	Fnt font;
   11.66 +	GC gc;
   11.67 +} DC; /* draw context */
   11.68 +
   11.69 +typedef struct Client Client;
   11.70 +struct Client {
   11.71 +	char name[256];
   11.72 +	int x, y, w, h;
   11.73 +	int rx, ry, rw, rh; /* revert geometry */
   11.74 +	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
   11.75 +	int minax, minay, maxax, maxay;
   11.76 +	long flags; 
   11.77 +	unsigned int border;
   11.78 +	Bool isbanned, isfixed, ismax, isversatile;
   11.79 +	Bool *tags;
   11.80 +	Client *next;
   11.81 +	Client *prev;
   11.82 +	Client *snext;
   11.83 +	Window win;
   11.84 +};
   11.85 +
   11.86 +typedef struct {
   11.87 +	const char *symbol;
   11.88 +	void (*arrange)(void);
   11.89 +} Layout;
   11.90 +
   11.91 +extern const char *tags[];			/* all tags */
   11.92 +extern char stext[256];				/* status text */
   11.93 +extern int screen, sx, sy, sw, sh;		/* screen geometry */
   11.94 +extern int wax, way, wah, waw;			/* windowarea geometry */
   11.95 +extern unsigned int bh, blw;			/* bar height, bar layout label width */
   11.96 +extern unsigned int master, nmaster;		/* master percent, number of master clients */
   11.97 +extern unsigned int ntags, numlockmask;		/* number of tags, dynamic lock mask */
   11.98 +extern void (*handler[LASTEvent])(XEvent *);	/* event handler */
   11.99 +extern Atom wmatom[WMLast], netatom[NetLast];
  11.100 +extern Bool selscreen, *seltag;			/* seltag is array of Bool */
  11.101 +extern Client *clients, *sel, *stack;		/* global client list and stack */
  11.102 +extern Cursor cursor[CurLast];
  11.103 +extern DC dc;					/* global draw context */
  11.104 +extern Display *dpy;
  11.105 +extern Layout *lt;
  11.106 +extern Window root, barwin;
  11.107 +
  11.108 +/* client.c */
  11.109 +extern void configure(Client *c);		/* send synthetic configure event */
  11.110 +extern void focus(Client *c);			/* focus c, c may be NULL */
  11.111 +extern void killclient(Arg *arg);		/* kill c nicely */
  11.112 +extern void manage(Window w, XWindowAttributes *wa);	/* manage new client */
  11.113 +extern void resize(Client *c, int x, int y,
  11.114 +		int w, int h, Bool sizehints);	/* resize with given coordinates c*/
  11.115 +extern void toggleversatile(Arg *arg);		/* toggles focused client between versatile/and non-versatile state */
  11.116 +extern void updatesizehints(Client *c);		/* update the size hint variables of c */
  11.117 +extern void updatetitle(Client *c);		/* update the name of c */
  11.118 +extern void unmanage(Client *c);		/* destroy c */
  11.119 +extern void zoom(Arg *arg);			/* zooms the focused client to master area, arg is ignored */
  11.120 +extern void pushup(Arg *arg);
  11.121 +extern void pushdown(Arg *arg);
  11.122 +extern void moveresize(Arg *arg);
  11.123 +
  11.124 +/* draw.c */
  11.125 +extern void drawstatus(void);			/* draw the bar */
  11.126 +extern void drawtext(const char *text,
  11.127 +		unsigned long col[ColLast]);	/* draw text */
  11.128 +extern unsigned int textw(const char *text);	/* return the width of text in px*/
  11.129 +
  11.130 +/* event.c */
  11.131 +extern void grabkeys(void);			/* grab all keys defined in config.h */
  11.132 +
  11.133 +/* layout.c */
  11.134 +extern void focusnext(Arg *arg);		/* focuses next visible client, arg is ignored  */
  11.135 +extern void focusprev(Arg *arg);		/* focuses previous visible client, arg is ignored */
  11.136 +extern void incnmaster(Arg *arg);		/* increments nmaster with arg's index value */
  11.137 +extern void initlayouts(void);			/* initialize layout array */
  11.138 +extern Client *nexttiled(Client *c);		/* returns tiled successor of c */
  11.139 +extern void resizemaster(Arg *arg);		/* resizes the master percent with arg's index value */
  11.140 +extern void restack(void);			/* restores z layers of all clients */
  11.141 +extern void setlayout(Arg *arg);		/* sets layout, -1 toggles */
  11.142 +extern void versatile(void);			/* arranges all windows versatile */
  11.143 +
  11.144 +/* main.c */
  11.145 +extern void quit(Arg *arg);			/* quit dwm nicely */
  11.146 +extern void sendevent(Window w, Atom a, long value);	/* send synthetic event to w */
  11.147 +extern int xerror(Display *dsply, XErrorEvent *ee);	/* dwm's X error handler */
  11.148 +
  11.149 +/* tag.c */
  11.150 +extern void compileregs(void);			/* initialize regexps of rules defined in config.h */
  11.151 +extern Bool isvisible(Client *c);		/* returns True if client is visible */
  11.152 +extern void settags(Client *c, Client *trans);	/* sets tags of c */
  11.153 +extern void tag(Arg *arg);			/* tags c with arg's index */
  11.154 +extern void toggletag(Arg *arg);		/* toggles c tags with arg's index */
  11.155 +extern void toggleview(Arg *arg);		/* toggles the tag with arg's index (in)visible */
  11.156 +extern void view(Arg *arg);			/* views the tag with arg's index */
  11.157 +extern void last_view(Arg *arg);			/* go to last viewed tag */
  11.158 +
  11.159 +/* util.c */
  11.160 +extern void *emallocz(unsigned int size);	/* allocates zero-initialized memory, exits on error */
  11.161 +extern void eprint(const char *errstr, ...);	/* prints errstr and exits with 1 */
  11.162 +extern void spawn(Arg *arg);			/* forks a new subprocess with arg's cmd */
  11.163 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/event.c	Sun Mar 22 23:26:35 2009 -0700
    12.3 @@ -0,0 +1,380 @@
    12.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    12.5 + * See LICENSE file for license details.
    12.6 + */
    12.7 +#include "dwm.h"
    12.8 +#include <stdlib.h>
    12.9 +#include <X11/keysym.h>
   12.10 +#include <X11/Xatom.h>
   12.11 +
   12.12 +/* static */
   12.13 +
   12.14 +typedef struct {
   12.15 +	unsigned long mod;
   12.16 +	KeySym keysym;
   12.17 +	void (*func)(Arg *arg);
   12.18 +	Arg arg;
   12.19 +} Key;
   12.20 +
   12.21 +KEYS
   12.22 +
   12.23 +#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
   12.24 +#define MOUSEMASK		(BUTTONMASK | PointerMotionMask)
   12.25 +
   12.26 +static Client *
   12.27 +getclient(Window w) {
   12.28 +	Client *c;
   12.29 +
   12.30 +	for(c = clients; c && c->win != w; c = c->next);
   12.31 +	return c;
   12.32 +}
   12.33 +
   12.34 +static void
   12.35 +movemouse(Client *c) {
   12.36 +	int x1, y1, ocx, ocy, di, nx, ny;
   12.37 +	unsigned int dui;
   12.38 +	Window dummy;
   12.39 +	XEvent ev;
   12.40 +
   12.41 +	ocx = nx = c->x;
   12.42 +	ocy = ny = c->y;
   12.43 +	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   12.44 +			None, cursor[CurMove], CurrentTime) != GrabSuccess)
   12.45 +		return;
   12.46 +	c->ismax = False;
   12.47 +	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
   12.48 +	for(;;) {
   12.49 +		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
   12.50 +		switch (ev.type) {
   12.51 +		case ButtonRelease:
   12.52 +			XUngrabPointer(dpy, CurrentTime);
   12.53 +			return;
   12.54 +		case ConfigureRequest:
   12.55 +		case Expose:
   12.56 +		case MapRequest:
   12.57 +			handler[ev.type](&ev);
   12.58 +			break;
   12.59 +		case MotionNotify:
   12.60 +			XSync(dpy, False);
   12.61 +			nx = ocx + (ev.xmotion.x - x1);
   12.62 +			ny = ocy + (ev.xmotion.y - y1);
   12.63 +			if(abs(wax + nx) < SNAP)
   12.64 +				nx = wax;
   12.65 +			else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP)
   12.66 +				nx = wax + waw - c->w - 2 * c->border;
   12.67 +			if(abs(way - ny) < SNAP)
   12.68 +				ny = way;
   12.69 +			else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP)
   12.70 +				ny = way + wah - c->h - 2 * c->border;
   12.71 +			resize(c, nx, ny, c->w, c->h, False);
   12.72 +			break;
   12.73 +		}
   12.74 +	}
   12.75 +}
   12.76 +
   12.77 +static void
   12.78 +resizemouse(Client *c) {
   12.79 +	int ocx, ocy;
   12.80 +	int nw, nh;
   12.81 +	XEvent ev;
   12.82 +
   12.83 +	ocx = c->x;
   12.84 +	ocy = c->y;
   12.85 +	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   12.86 +			None, cursor[CurResize], CurrentTime) != GrabSuccess)
   12.87 +		return;
   12.88 +	c->ismax = False;
   12.89 +	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
   12.90 +	for(;;) {
   12.91 +		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
   12.92 +		switch(ev.type) {
   12.93 +		case ButtonRelease:
   12.94 +			XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
   12.95 +					c->w + c->border - 1, c->h + c->border - 1);
   12.96 +			XUngrabPointer(dpy, CurrentTime);
   12.97 +			while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   12.98 +			return;
   12.99 +		case ConfigureRequest:
  12.100 +		case Expose:
  12.101 +		case MapRequest:
  12.102 +			handler[ev.type](&ev);
  12.103 +			break;
  12.104 +		case MotionNotify:
  12.105 +			XSync(dpy, False);
  12.106 +			if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0)
  12.107 +				nw = 1;
  12.108 +			if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0)
  12.109 +				nh = 1;
  12.110 +			resize(c, c->x, c->y, nw, nh, True);
  12.111 +			break;
  12.112 +		}
  12.113 +	}
  12.114 +}
  12.115 +
  12.116 +static void
  12.117 +buttonpress(XEvent *e) {
  12.118 +	int x;
  12.119 +	Arg a;
  12.120 +	Client *c;
  12.121 +	XButtonPressedEvent *ev = &e->xbutton;
  12.122 +
  12.123 +	if(barwin == ev->window) {
  12.124 +		x = 0;
  12.125 +		for(a.i = 0; a.i < ntags; a.i++) {
  12.126 +			x += textw(tags[a.i]);
  12.127 +			if(ev->x < x) {
  12.128 +				if(ev->button == Button1) {
  12.129 +					if(ev->state & MODKEY)
  12.130 +						tag(&a);
  12.131 +					else
  12.132 +						view(&a);
  12.133 +				}
  12.134 +				else if(ev->button == Button3) {
  12.135 +					if(ev->state & MODKEY)
  12.136 +						toggletag(&a);
  12.137 +					else
  12.138 +						toggleview(&a);
  12.139 +				}
  12.140 +				return;
  12.141 +			}
  12.142 +		}
  12.143 +		if(ev->x < x + blw)
  12.144 +			switch(ev->button) {
  12.145 +			case Button1:
  12.146 +				a.i = -1;
  12.147 +				setlayout(&a);
  12.148 +				break;
  12.149 +			case Button4:
  12.150 +				a.i = 1;
  12.151 +				incnmaster(&a);
  12.152 +				break;
  12.153 +			case Button5:
  12.154 +				a.i = -1;
  12.155 +				incnmaster(&a);
  12.156 +				break;
  12.157 +			}
  12.158 +		if(ev->x > x + blw)
  12.159 +			switch(ev->button) {
  12.160 +			case Button1: zoom(NULL); break;
  12.161 +			case Button2: toggleversatile(NULL); break;
  12.162 +			case Button3: killclient(NULL); break;
  12.163 +			case Button4: focusprev(NULL); break;
  12.164 +			case Button5: focusnext(NULL); break;
  12.165 +		}
  12.166 +	}
  12.167 +	else if((c = getclient(ev->window))) {
  12.168 +		focus(c);
  12.169 +		if(CLEANMASK(ev->state) != MODKEY)
  12.170 +			return;
  12.171 +		if(ev->button == Button1 && (lt->arrange == versatile || c->isversatile)) {
  12.172 +			restack();
  12.173 +			movemouse(c);
  12.174 +		}
  12.175 +		else if(ev->button == Button2)
  12.176 +			zoom(NULL);
  12.177 +		else if(ev->button == Button3
  12.178 +		&& (lt->arrange == versatile || c->isversatile) && !c->isfixed)
  12.179 +		{
  12.180 +			restack();
  12.181 +			resizemouse(c);
  12.182 +		}
  12.183 +	}
  12.184 +}
  12.185 +
  12.186 +static void
  12.187 +configurerequest(XEvent *e) {
  12.188 +	Client *c;
  12.189 +	XConfigureRequestEvent *ev = &e->xconfigurerequest;
  12.190 +	XWindowChanges wc;
  12.191 +
  12.192 +	if((c = getclient(ev->window))) {
  12.193 +		c->ismax = False;
  12.194 +		if(ev->value_mask & CWBorderWidth)
  12.195 +			c->border = ev->border_width;
  12.196 +		if(c->isfixed || c->isversatile || (lt->arrange == versatile)) {
  12.197 +			if(ev->value_mask & CWX)
  12.198 +				c->x = ev->x;
  12.199 +			if(ev->value_mask & CWY)
  12.200 +				c->y = ev->y;
  12.201 +			if(ev->value_mask & CWWidth)
  12.202 +				c->w = ev->width;
  12.203 +			if(ev->value_mask & CWHeight)
  12.204 +				c->h = ev->height;
  12.205 +			if((ev->value_mask & (CWX | CWY))
  12.206 +			&& !(ev->value_mask & (CWWidth | CWHeight)))
  12.207 +				configure(c);
  12.208 +			if(isvisible(c))
  12.209 +				/* XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); */
  12.210 +				resize(c, c->x, c->y, c->w, c->h, False);
  12.211 +		}
  12.212 +		else
  12.213 +			configure(c);
  12.214 +	}
  12.215 +	else {
  12.216 +		wc.x = ev->x;
  12.217 +		wc.y = ev->y;
  12.218 +		wc.width = ev->width;
  12.219 +		wc.height = ev->height;
  12.220 +		wc.border_width = ev->border_width;
  12.221 +		wc.sibling = ev->above;
  12.222 +		wc.stack_mode = ev->detail;
  12.223 +		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
  12.224 +	}
  12.225 +	XSync(dpy, False);
  12.226 +}
  12.227 +
  12.228 +static void
  12.229 +destroynotify(XEvent *e) {
  12.230 +	Client *c;
  12.231 +	XDestroyWindowEvent *ev = &e->xdestroywindow;
  12.232 +
  12.233 +	if((c = getclient(ev->window)))
  12.234 +		unmanage(c);
  12.235 +}
  12.236 +
  12.237 +static void
  12.238 +enternotify(XEvent *e) {
  12.239 +	Client *c;
  12.240 +	XCrossingEvent *ev = &e->xcrossing;
  12.241 +
  12.242 +	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
  12.243 +		return;
  12.244 +	if((c = getclient(ev->window)) && isvisible(c))
  12.245 +		focus(c);
  12.246 +	else if(ev->window == root) {
  12.247 +		selscreen = True;
  12.248 +		for(c = stack; c && !isvisible(c); c = c->snext);
  12.249 +		focus(c);
  12.250 +	}
  12.251 +}
  12.252 +
  12.253 +static void
  12.254 +expose(XEvent *e) {
  12.255 +	XExposeEvent *ev = &e->xexpose;
  12.256 +
  12.257 +	if(ev->count == 0) {
  12.258 +		if(barwin == ev->window)
  12.259 +			drawstatus();
  12.260 +	}
  12.261 +}
  12.262 +
  12.263 +static void
  12.264 +keypress(XEvent *e) {
  12.265 +	static unsigned int len = sizeof key / sizeof key[0];
  12.266 +	unsigned int i;
  12.267 +	KeySym keysym;
  12.268 +	XKeyEvent *ev = &e->xkey;
  12.269 +
  12.270 +	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
  12.271 +	for(i = 0; i < len; i++)
  12.272 +		if(keysym == key[i].keysym
  12.273 +		&& CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
  12.274 +		{
  12.275 +			if(key[i].func)
  12.276 +				key[i].func(&key[i].arg);
  12.277 +		}
  12.278 +}
  12.279 +
  12.280 +static void
  12.281 +leavenotify(XEvent *e) {
  12.282 +	XCrossingEvent *ev = &e->xcrossing;
  12.283 +
  12.284 +	if((ev->window == root) && !ev->same_screen) {
  12.285 +		selscreen = False;
  12.286 +		focus(NULL);
  12.287 +	}
  12.288 +}
  12.289 +
  12.290 +static void
  12.291 +mappingnotify(XEvent *e) {
  12.292 +	XMappingEvent *ev = &e->xmapping;
  12.293 +
  12.294 +	XRefreshKeyboardMapping(ev);
  12.295 +	if(ev->request == MappingKeyboard)
  12.296 +		grabkeys();
  12.297 +}
  12.298 +
  12.299 +static void
  12.300 +maprequest(XEvent *e) {
  12.301 +	static XWindowAttributes wa;
  12.302 +	XMapRequestEvent *ev = &e->xmaprequest;
  12.303 +
  12.304 +	if(!XGetWindowAttributes(dpy, ev->window, &wa))
  12.305 +		return;
  12.306 +	if(wa.override_redirect)
  12.307 +		return;
  12.308 +	if(!getclient(ev->window))
  12.309 +		manage(ev->window, &wa);
  12.310 +}
  12.311 +
  12.312 +static void
  12.313 +propertynotify(XEvent *e) {
  12.314 +	Client *c;
  12.315 +	Window trans;
  12.316 +	XPropertyEvent *ev = &e->xproperty;
  12.317 +
  12.318 +	if(ev->state == PropertyDelete)
  12.319 +		return; /* ignore */
  12.320 +	if((c = getclient(ev->window))) {
  12.321 +		switch (ev->atom) {
  12.322 +			default: break;
  12.323 +			case XA_WM_TRANSIENT_FOR:
  12.324 +				XGetTransientForHint(dpy, c->win, &trans);
  12.325 +				if(!c->isversatile && (c->isversatile = (getclient(trans) != NULL)))
  12.326 +					lt->arrange();
  12.327 +				break;
  12.328 +			case XA_WM_NORMAL_HINTS:
  12.329 +				updatesizehints(c);
  12.330 +				break;
  12.331 +		}
  12.332 +		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
  12.333 +			updatetitle(c);
  12.334 +			if(c == sel)
  12.335 +				drawstatus();
  12.336 +		}
  12.337 +	}
  12.338 +}
  12.339 +
  12.340 +static void
  12.341 +unmapnotify(XEvent *e) {
  12.342 +	Client *c;
  12.343 +	XUnmapEvent *ev = &e->xunmap;
  12.344 +
  12.345 +	if((c = getclient(ev->window)))
  12.346 +		unmanage(c);
  12.347 +}
  12.348 +
  12.349 +/* extern */
  12.350 +
  12.351 +void (*handler[LASTEvent]) (XEvent *) = {
  12.352 +	[ButtonPress] = buttonpress,
  12.353 +	[ConfigureRequest] = configurerequest,
  12.354 +	[DestroyNotify] = destroynotify,
  12.355 +	[EnterNotify] = enternotify,
  12.356 +	[LeaveNotify] = leavenotify,
  12.357 +	[Expose] = expose,
  12.358 +	[KeyPress] = keypress,
  12.359 +	[MappingNotify] = mappingnotify,
  12.360 +	[MapRequest] = maprequest,
  12.361 +	[PropertyNotify] = propertynotify,
  12.362 +	[UnmapNotify] = unmapnotify
  12.363 +};
  12.364 +
  12.365 +void
  12.366 +grabkeys(void) {
  12.367 +	static unsigned int len = sizeof key / sizeof key[0];
  12.368 +	unsigned int i;
  12.369 +	KeyCode code;
  12.370 +
  12.371 +	XUngrabKey(dpy, AnyKey, AnyModifier, root);
  12.372 +	for(i = 0; i < len; i++) {
  12.373 +		code = XKeysymToKeycode(dpy, key[i].keysym);
  12.374 +		XGrabKey(dpy, code, key[i].mod, root, True,
  12.375 +				GrabModeAsync, GrabModeAsync);
  12.376 +		XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
  12.377 +				GrabModeAsync, GrabModeAsync);
  12.378 +		XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
  12.379 +				GrabModeAsync, GrabModeAsync);
  12.380 +		XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
  12.381 +				GrabModeAsync, GrabModeAsync);
  12.382 +	}
  12.383 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/layout.c	Sun Mar 22 23:26:35 2009 -0700
    13.3 @@ -0,0 +1,471 @@
    13.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    13.5 + * See LICENSE file for license details.
    13.6 + */
    13.7 +#include "dwm.h"
    13.8 +
    13.9 +unsigned int master = MASTER;
   13.10 +unsigned int nmaster = NMASTER;
   13.11 +unsigned int blw = 0;
   13.12 +Layout *lt = NULL;
   13.13 +
   13.14 +/* static */
   13.15 +
   13.16 +static unsigned int nlayouts = 0;
   13.17 +
   13.18 +static void
   13.19 +spiral(void) {
   13.20 +	unsigned int i, n, nx, ny, nw, nh;
   13.21 +	Client *c;
   13.22 +
   13.23 +	nx = wax;
   13.24 +	ny = way + wah;
   13.25 +	nw = waw;
   13.26 +	nh = wah;
   13.27 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
   13.28 +		n++;
   13.29 +	for(i = 0, c = clients; c; c = c->next)
   13.30 +		if(isvisible(c)) {
   13.31 +			if(c->isbanned)
   13.32 +				XMoveWindow(dpy, c->win, c->x, c->y);
   13.33 +			c->isbanned = False;
   13.34 +			if(c->isversatile)
   13.35 +				continue;
   13.36 +			c->ismax = False;
   13.37 +			if((i % 2 && nh / 2 > 2 * c->border)
   13.38 +				|| (!(i % 2) && nw / 2 > 2 * c->border))
   13.39 +			{
   13.40 +				if(i < n - 1) {
   13.41 +					if(i % 2)
   13.42 +						nh /= 2;
   13.43 +				   else
   13.44 +						nw /= 2;
   13.45 +				   if((i % 4) == 2)
   13.46 +						nx += nw;
   13.47 +				   else if((i % 4) == 3)
   13.48 +						ny += nh;
   13.49 +				}
   13.50 +				if((i % 4) == 0)
   13.51 +					ny -= nh;
   13.52 +				else if((i % 4) == 1)
   13.53 +					nx += nw;
   13.54 +				else if((i % 4) == 2)
   13.55 +					ny += nh;
   13.56 +				else
   13.57 +					nx -= nw;
   13.58 +				i++;
   13.59 +			}
   13.60 +			resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
   13.61 +		}
   13.62 +		else {
   13.63 +			c->isbanned = True;
   13.64 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
   13.65 +		}
   13.66 +	if(!sel || !isvisible(sel)) {
   13.67 +		for(c = stack; c && !isvisible(c); c = c->snext);
   13.68 +		focus(c);
   13.69 +	}
   13.70 +	restack();
   13.71 +}
   13.72 +
   13.73 +static void
   13.74 +spiral_h(void) {
   13.75 +	unsigned int i, n, nx, ny, nw, nh;
   13.76 +	Client *c;
   13.77 +
   13.78 +	nx = wax + waw;
   13.79 +	ny = way;
   13.80 +	nw = waw;
   13.81 +	nh = wah;
   13.82 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
   13.83 +		n++;
   13.84 +	for(i = 0, c = clients; c; c = c->next)
   13.85 +		if(isvisible(c)) {
   13.86 +			if(c->isbanned)
   13.87 +				XMoveWindow(dpy, c->win, c->x, c->y);
   13.88 +			c->isbanned = False;
   13.89 +			if(c->isversatile)
   13.90 +				continue;
   13.91 +			c->ismax = False;
   13.92 +			if((i % 2 && nw / 2 > 2 * c->border)
   13.93 +				|| (!(i % 2) && nh / 2 > 2 * c->border))
   13.94 +			{
   13.95 +				if(i < n - 1) {
   13.96 +					if(i % 2)
   13.97 +						nw /= 2;
   13.98 +					else
   13.99 +						nh /= 2;
  13.100 +				   if((i % 4) == 2)
  13.101 +						ny += nh;
  13.102 +				   else if((i % 4) == 3)
  13.103 +						nx += nw;
  13.104 +				}
  13.105 +				if((i % 4) == 0)
  13.106 +					nx -= nw;
  13.107 +				else if((i % 4) == 1)
  13.108 +					ny += nh;
  13.109 +				else if((i % 4) == 2)
  13.110 +					nx += nw;
  13.111 +				else 
  13.112 +					ny -= nh;
  13.113 +				i++;
  13.114 +			}
  13.115 +			resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
  13.116 +		}
  13.117 +		else {
  13.118 +			c->isbanned = True;
  13.119 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.120 +		}
  13.121 +	if(!sel || !isvisible(sel)) {
  13.122 +		for(c = stack; c && !isvisible(c); c = c->snext);
  13.123 +		focus(c);
  13.124 +	}
  13.125 +	restack();
  13.126 +}
  13.127 +
  13.128 +static void
  13.129 +monocle(void) {
  13.130 +	Client *c;
  13.131 +
  13.132 +	for(c = clients; c; c = c->next)
  13.133 +		if(isvisible(c) && c->isbanned) {
  13.134 +			XMoveWindow(dpy, c->win, c->x, c->y);
  13.135 +			c->isbanned = False;
  13.136 +		}
  13.137 +		else if(!isvisible(c)) {
  13.138 +			c->isbanned = True;
  13.139 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.140 +		}
  13.141 +
  13.142 +	for(c = nexttiled(clients); c; c = nexttiled(c->next))
  13.143 +		resize(c, wax, way, waw - 2*c->border, wah - 2*c->border, False); 
  13.144 +
  13.145 +	restack();
  13.146 +}
  13.147 +
  13.148 +static void
  13.149 +cascade(void) {
  13.150 +	unsigned int i, n, px = 20;	
  13.151 +	Client *c;
  13.152 +
  13.153 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
  13.154 +
  13.155 +	for(i = 0, c = clients; c; c = c->next)
  13.156 +		if(isvisible(c)) {
  13.157 +			if(c->isbanned) {
  13.158 +				XMoveWindow(dpy, c->win, c->x, c->y);
  13.159 +				c->isbanned = False;
  13.160 +			}
  13.161 +			if(!c->isversatile) {
  13.162 +				resize(c, wax+(px*i), way+(px*i), waw-(px*(n-1))-2*c->border, wah-(px*(n-1))-2*c->border, True); 
  13.163 +				i++;
  13.164 +			}
  13.165 +		}
  13.166 +		else if(!isvisible(c)) {
  13.167 +			c->isbanned = True;
  13.168 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.169 +		}
  13.170 +
  13.171 +	restack();
  13.172 +}
  13.173 +
  13.174 +static void
  13.175 +bstack(void) {
  13.176 +	unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
  13.177 +	Client *c;
  13.178 +
  13.179 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  13.180 +		n++;
  13.181 +	/* window geoms */
  13.182 +	mh = (n > nmaster) ? (wah * master) / 1000 : wah;
  13.183 +	mw = (n > nmaster) ? waw / nmaster : waw / (n > 0 ? n : 1);
  13.184 +	th = wah - mh;
  13.185 +	tw = (n > nmaster) ? waw / (n - nmaster) : 0;
  13.186 +
  13.187 +	for(i = 0, c = clients; c; c = c->next)
  13.188 +		if(isvisible(c)) {
  13.189 +			if(c->isbanned)
  13.190 +				XMoveWindow(dpy, c->win, c->x, c->y);
  13.191 +			c->isbanned = False;
  13.192 +			if(c->isversatile)
  13.193 +				continue;
  13.194 +			c->ismax = False;
  13.195 +			nx = wax;
  13.196 +			ny = way;
  13.197 +			if(i < nmaster) {
  13.198 +				nx += i * mw;
  13.199 +				nw = mw - 2 * BORDERPX;
  13.200 +				nh = mh - 2 * BORDERPX;
  13.201 +			}
  13.202 +			else {  /* tile window */
  13.203 +				ny += mh;
  13.204 +				nh = th - 2 * BORDERPX;
  13.205 +				if(tw > 2 * BORDERPX) {
  13.206 +					nx += (i - nmaster) * tw;
  13.207 +					nw = tw - 2 * BORDERPX;
  13.208 +				}
  13.209 +				else /* fallback if th <= 2 * BORDERPX */
  13.210 +					nw = waw - 2 * BORDERPX;
  13.211 +			}
  13.212 +			resize(c, nx, ny, nw, nh, False);
  13.213 +			i++;
  13.214 +		}
  13.215 +		else {
  13.216 +			c->isbanned = True;
  13.217 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.218 +		}
  13.219 +	if(!sel || !isvisible(sel)) {
  13.220 +		for(c = stack; c && !isvisible(c); c = c->snext);
  13.221 +		focus(c);
  13.222 +	}
  13.223 +	restack();
  13.224 +}
  13.225 +
  13.226 +static void
  13.227 +grid(void) {
  13.228 +	unsigned int i, n, nx, ny, nw, nh, aw, ah, tw, th, cols, rows;
  13.229 +	Client *c;
  13.230 +	
  13.231 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  13.232 +		n++;
  13.233 +	
  13.234 +	for(rows = 0; rows <= n/2; rows++)
  13.235 +		if(rows*rows >= n)
  13.236 +			break;
  13.237 +	cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
  13.238 +	
  13.239 +	th = (sh - dc.h) / (rows ? rows : 1);
  13.240 +	tw = sw / (cols ? cols : 1);
  13.241 +	nw = tw - 2 * BORDERPX;
  13.242 +	nh = th - 2 * BORDERPX;
  13.243 +	
  13.244 +	for(i = 0, c = clients; c; c = c->next)
  13.245 +		if(isvisible(c)) {
  13.246 +			if(c->isbanned)
  13.247 +				XMoveWindow(dpy, c->win, c->x, c->y);
  13.248 +			c->isbanned = False;
  13.249 +			if(c->isversatile)
  13.250 +				continue;
  13.251 +			c->ismax = False;
  13.252 +			nx = (i / rows) * tw;
  13.253 +			ny = (i % rows) * th + (TOPBAR ? dc.h : 0);
  13.254 +			/* adjust height and width of last row's and last column's windows */ 
  13.255 +			ah = ((i + 1) % rows == 0) ? sh - th * rows - dc.h : 0;
  13.256 +			aw = (i >= rows * (cols - 1)) ? sw - tw * cols : 0;
  13.257 +			resize(c, nx, ny, nw + aw, nh + ah, False);
  13.258 +			i++;
  13.259 +		}
  13.260 +		else {
  13.261 +			c->isbanned = True;
  13.262 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.263 +		}
  13.264 +	
  13.265 +	if(!sel || !isvisible(sel)) {
  13.266 +		for(c = stack; c && !isvisible(c); c = c->snext);
  13.267 +		focus(c);
  13.268 +	}
  13.269 +	restack();
  13.270 +}
  13.271 +
  13.272 +static void
  13.273 +tile(void) {
  13.274 +	unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
  13.275 +	Client *c;
  13.276 +
  13.277 +	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  13.278 +		n++;
  13.279 +	/* window geoms */
  13.280 +	mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
  13.281 +	mw = (n > nmaster) ? (waw * master) / 1000 : waw;
  13.282 +	th = (n > nmaster) ? wah / (n - nmaster) : 0;
  13.283 +	tw = waw - mw;
  13.284 +
  13.285 +	for(i = 0, c = clients; c; c = c->next)
  13.286 +		if(isvisible(c)) {
  13.287 +			if(c->isbanned)
  13.288 +				XMoveWindow(dpy, c->win, c->x, c->y);
  13.289 +			c->isbanned = False;
  13.290 +			if(c->isversatile)
  13.291 +				continue;
  13.292 +			c->ismax = False;
  13.293 +			nx = wax;
  13.294 +			ny = way;
  13.295 +			if(i < nmaster) {
  13.296 +				ny += i * mh;
  13.297 +				nw = mw - 2 * BORDERPX;
  13.298 +				nh = mh - 2 * BORDERPX;
  13.299 +			}
  13.300 +			else {  /* tile window */
  13.301 +				nx += mw;
  13.302 +				nw = tw - 2 * BORDERPX;
  13.303 +				if(th > 2 * BORDERPX) {
  13.304 +					ny += (i - nmaster) * th;
  13.305 +					nh = th - 2 * BORDERPX;
  13.306 +				}
  13.307 +				else /* fallback if th <= 2 * BORDERPX */
  13.308 +					nh = wah - 2 * BORDERPX;
  13.309 +			}
  13.310 +			resize(c, nx, ny, nw, nh, False);
  13.311 +			i++;
  13.312 +		}
  13.313 +		else {
  13.314 +			c->isbanned = True;
  13.315 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.316 +		}
  13.317 +	if(!sel || !isvisible(sel)) {
  13.318 +		for(c = stack; c && !isvisible(c); c = c->snext);
  13.319 +		focus(c);
  13.320 +	}
  13.321 +	restack();
  13.322 +}
  13.323 +
  13.324 +LAYOUTS
  13.325 +
  13.326 +/* extern */
  13.327 +
  13.328 +void
  13.329 +focusnext(Arg *arg) {
  13.330 +	Client *c;
  13.331 +   
  13.332 +	if(!sel)
  13.333 +		return;
  13.334 +	for(c = sel->next; c && !isvisible(c); c = c->next);
  13.335 +	if(!c)
  13.336 +		for(c = clients; c && !isvisible(c); c = c->next);
  13.337 +	if(c) {
  13.338 +		focus(c);
  13.339 +		restack();
  13.340 +	}
  13.341 +}
  13.342 +
  13.343 +void
  13.344 +focusprev(Arg *arg) {
  13.345 +	Client *c;
  13.346 +
  13.347 +	if(!sel)
  13.348 +		return;
  13.349 +	for(c = sel->prev; c && !isvisible(c); c = c->prev);
  13.350 +	if(!c) {
  13.351 +		for(c = clients; c && c->next; c = c->next);
  13.352 +		for(; c && !isvisible(c); c = c->prev);
  13.353 +	}
  13.354 +	if(c) {
  13.355 +		focus(c);
  13.356 +		restack();
  13.357 +	}
  13.358 +}
  13.359 +
  13.360 +void
  13.361 +incnmaster(Arg *arg) {
  13.362 +	//if((lt->arrange != tile) || (nmaster + arg->i < 1)
  13.363 +	//|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
  13.364 +	//	return;
  13.365 +	if(nmaster + arg->i < 1 && nmaster + arg->i <= MAX_TASKS)
  13.366 +		return;
  13.367 +	nmaster += arg->i;
  13.368 +	if(sel)
  13.369 +		lt->arrange();
  13.370 +	else
  13.371 +		drawstatus();
  13.372 +}
  13.373 +
  13.374 +void
  13.375 +initlayouts(void) {
  13.376 +	unsigned int i, w;
  13.377 +
  13.378 +	lt = &layout[0];
  13.379 +	nlayouts = sizeof layout / sizeof layout[0];
  13.380 +	for(blw = i = 0; i < nlayouts; i++) {
  13.381 +		w = textw(layout[i].symbol);
  13.382 +		if(w > blw)
  13.383 +			blw = w;
  13.384 +	}
  13.385 +}
  13.386 +
  13.387 +Client *
  13.388 +nexttiled(Client *c) {
  13.389 +	for(; c && (c->isversatile || !isvisible(c)); c = c->next);
  13.390 +	return c;
  13.391 +}
  13.392 +
  13.393 +void
  13.394 +resizemaster(Arg *arg) {
  13.395 +	//if(lt->arrange != tile)
  13.396 +	//	return;
  13.397 +	if(arg->i == 0)
  13.398 +		master = MASTER;
  13.399 +	else {
  13.400 +		//if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
  13.401 +		//|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
  13.402 +		//	return;
  13.403 +		master += arg->i;
  13.404 +	}
  13.405 +	lt->arrange();
  13.406 +}
  13.407 +
  13.408 +void
  13.409 +restack(void) {
  13.410 +	Client *c;
  13.411 +	XEvent ev;
  13.412 +
  13.413 +	drawstatus();
  13.414 +	if(!sel)
  13.415 +		return;
  13.416 +	if(sel->isversatile || lt->arrange == versatile)
  13.417 +		XRaiseWindow(dpy, sel->win);
  13.418 +	if(lt->arrange != versatile) {
  13.419 +		if(!sel->isversatile)
  13.420 +			XLowerWindow(dpy, sel->win);
  13.421 +		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
  13.422 +			if(c == sel)
  13.423 +				continue;
  13.424 +			XLowerWindow(dpy, c->win);
  13.425 +		}
  13.426 +	}
  13.427 +	XSync(dpy, False);
  13.428 +	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  13.429 +}
  13.430 +
  13.431 +void
  13.432 +setlayout(Arg *arg) {
  13.433 +	unsigned int i;
  13.434 +
  13.435 +	if(arg->i == -1) {
  13.436 +		for(i = 0; i < nlayouts && lt != &layout[i]; i++);
  13.437 +		if(i == nlayouts - 1)
  13.438 +			lt = &layout[0];
  13.439 +		else
  13.440 +			lt = &layout[++i];
  13.441 +	}
  13.442 +	else {
  13.443 +		if(arg->i < 0 || arg->i >= nlayouts)
  13.444 +			return;
  13.445 +		lt = &layout[arg->i];
  13.446 +	}
  13.447 +	if(sel)
  13.448 +		lt->arrange();
  13.449 +	else
  13.450 +		drawstatus();
  13.451 +}
  13.452 +
  13.453 +void
  13.454 +versatile(void) {
  13.455 +	Client *c;
  13.456 +
  13.457 +	for(c = clients; c; c = c->next) {
  13.458 +		if(isvisible(c)) {
  13.459 +			if(c->isbanned)
  13.460 +				XMoveWindow(dpy, c->win, c->x, c->y);
  13.461 +			c->isbanned = False;
  13.462 +			resize(c, c->x, c->y, c->w, c->h, True);
  13.463 +		}
  13.464 +		else {
  13.465 +			c->isbanned = True;
  13.466 +			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  13.467 +		}
  13.468 +	}
  13.469 +	if(!sel || !isvisible(sel)) {
  13.470 +		for(c = stack; c && !isvisible(c); c = c->snext);
  13.471 +		focus(c);
  13.472 +	}
  13.473 +	restack();
  13.474 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/main.c	Sun Mar 22 23:26:35 2009 -0700
    14.3 @@ -0,0 +1,338 @@
    14.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    14.5 + * See LICENSE file for license details.
    14.6 + */
    14.7 +
    14.8 +#include "dwm.h"
    14.9 +#include <errno.h>
   14.10 +#include <locale.h>
   14.11 +#include <stdio.h>
   14.12 +#include <stdlib.h>
   14.13 +#include <string.h>
   14.14 +#include <unistd.h>
   14.15 +#include <sys/select.h>
   14.16 +#include <X11/cursorfont.h>
   14.17 +#include <X11/keysym.h>
   14.18 +#include <X11/Xatom.h>
   14.19 +#include <X11/Xproto.h>
   14.20 +
   14.21 +/* extern */
   14.22 +
   14.23 +char stext[256];
   14.24 +int screen, sx, sy, sw, sh, wax, way, waw, wah;
   14.25 +unsigned int bh, ntags, numlockmask;
   14.26 +Atom wmatom[WMLast], netatom[NetLast];
   14.27 +Bool *seltag;
   14.28 +Bool selscreen = True;
   14.29 +Client *clients = NULL;
   14.30 +Client *sel = NULL;
   14.31 +Client *stack = NULL;
   14.32 +Cursor cursor[CurLast];
   14.33 +Display *dpy;
   14.34 +DC dc = {0};
   14.35 +Window root, barwin;
   14.36 +
   14.37 +/* static */
   14.38 +
   14.39 +static int (*xerrorxlib)(Display *, XErrorEvent *);
   14.40 +static Bool otherwm, readin;
   14.41 +static Bool running = True;
   14.42 +
   14.43 +static void
   14.44 +cleanup(void) {
   14.45 +	close(STDIN_FILENO);
   14.46 +	while(stack) {
   14.47 +		if(stack->isbanned)
   14.48 +			XMoveWindow(dpy, stack->win, stack->x, stack->y);
   14.49 +		unmanage(stack);
   14.50 +	}
   14.51 +	if(dc.font.set)
   14.52 +		XFreeFontSet(dpy, dc.font.set);
   14.53 +	else
   14.54 +		XFreeFont(dpy, dc.font.xfont);
   14.55 +	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   14.56 +	XFreePixmap(dpy, dc.drawable);
   14.57 +	XFreeGC(dpy, dc.gc);
   14.58 +	XDestroyWindow(dpy, barwin);
   14.59 +	XFreeCursor(dpy, cursor[CurNormal]);
   14.60 +	XFreeCursor(dpy, cursor[CurResize]);
   14.61 +	XFreeCursor(dpy, cursor[CurMove]);
   14.62 +	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   14.63 +	XSync(dpy, False);
   14.64 +	free(seltag);
   14.65 +}
   14.66 +
   14.67 +static unsigned long
   14.68 +initcolor(const char *colstr) {
   14.69 +	Colormap cmap = DefaultColormap(dpy, screen);
   14.70 +	XColor color;
   14.71 +
   14.72 +	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   14.73 +		eprint("error, cannot allocate color '%s'\n", colstr);
   14.74 +	return color.pixel;
   14.75 +}
   14.76 +
   14.77 +static void
   14.78 +initfont(const char *fontstr) {
   14.79 +	char *def, **missing;
   14.80 +	int i, n;
   14.81 +
   14.82 +	missing = NULL;
   14.83 +	if(dc.font.set)
   14.84 +		XFreeFontSet(dpy, dc.font.set);
   14.85 +	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
   14.86 +	if(missing) {
   14.87 +		while(n--)
   14.88 +			fprintf(stderr, "missing fontset: %s\n", missing[n]);
   14.89 +		XFreeStringList(missing);
   14.90 +	}
   14.91 +	if(dc.font.set) {
   14.92 +		XFontSetExtents *font_extents;
   14.93 +		XFontStruct **xfonts;
   14.94 +		char **font_names;
   14.95 +		dc.font.ascent = dc.font.descent = 0;
   14.96 +		font_extents = XExtentsOfFontSet(dc.font.set);
   14.97 +		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
   14.98 +		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
   14.99 +			if(dc.font.ascent < (*xfonts)->ascent)
  14.100 +				dc.font.ascent = (*xfonts)->ascent;
  14.101 +			if(dc.font.descent < (*xfonts)->descent)
  14.102 +				dc.font.descent = (*xfonts)->descent;
  14.103 +			xfonts++;
  14.104 +		}
  14.105 +	}
  14.106 +	else {
  14.107 +		if(dc.font.xfont)
  14.108 +			XFreeFont(dpy, dc.font.xfont);
  14.109 +		dc.font.xfont = NULL;
  14.110 +		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
  14.111 +			eprint("error, cannot load font: '%s'\n", fontstr);
  14.112 +		dc.font.ascent = dc.font.xfont->ascent;
  14.113 +		dc.font.descent = dc.font.xfont->descent;
  14.114 +	}
  14.115 +	dc.font.height = dc.font.ascent + dc.font.descent;
  14.116 +}
  14.117 +
  14.118 +static void
  14.119 +scan(void) {
  14.120 +	unsigned int i, num;
  14.121 +	Window *wins, d1, d2;
  14.122 +	XWindowAttributes wa;
  14.123 +
  14.124 +	wins = NULL;
  14.125 +	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  14.126 +		for(i = 0; i < num; i++) {
  14.127 +			if(!XGetWindowAttributes(dpy, wins[i], &wa)
  14.128 +			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
  14.129 +				continue;
  14.130 +			if(wa.map_state == IsViewable)
  14.131 +				manage(wins[i], &wa);
  14.132 +		}
  14.133 +	}
  14.134 +	if(wins)
  14.135 +		XFree(wins);
  14.136 +}
  14.137 +
  14.138 +static void
  14.139 +setup(void) {
  14.140 +	int i, j;
  14.141 +	unsigned int mask;
  14.142 +	Window w;
  14.143 +	XModifierKeymap *modmap;
  14.144 +	XSetWindowAttributes wa;
  14.145 +
  14.146 +	/* init atoms */
  14.147 +	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
  14.148 +	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  14.149 +	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
  14.150 +	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  14.151 +	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  14.152 +	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  14.153 +			PropModeReplace, (unsigned char *) netatom, NetLast);
  14.154 +	/* init cursors */
  14.155 +	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  14.156 +	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  14.157 +	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  14.158 +	/* init modifier map */
  14.159 +	numlockmask = 0;
  14.160 +	modmap = XGetModifierMapping(dpy);
  14.161 +	for (i = 0; i < 8; i++)
  14.162 +		for (j = 0; j < modmap->max_keypermod; j++) {
  14.163 +			if(modmap->modifiermap[i * modmap->max_keypermod + j]
  14.164 +					== XKeysymToKeycode(dpy, XK_Num_Lock))
  14.165 +				numlockmask = (1 << i);
  14.166 +		}
  14.167 +	XFreeModifiermap(modmap);
  14.168 +	/* select for events */
  14.169 +	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  14.170 +		| EnterWindowMask | LeaveWindowMask;
  14.171 +	wa.cursor = cursor[CurNormal];
  14.172 +	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
  14.173 +	grabkeys();
  14.174 +	compileregs();
  14.175 +	for(ntags = 0; tags[ntags]; ntags++);
  14.176 +	seltag = emallocz(sizeof(Bool) * ntags);
  14.177 +	seltag[0] = True;
  14.178 +	/* style */
  14.179 +	dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR);
  14.180 +	dc.norm[ColBG] = initcolor(NORMBGCOLOR);
  14.181 +	dc.norm[ColFG] = initcolor(NORMFGCOLOR);
  14.182 +	dc.sel[ColBorder] = initcolor(SELBORDERCOLOR);
  14.183 +	dc.sel[ColBG] = initcolor(SELBGCOLOR);
  14.184 +	dc.sel[ColFG] = initcolor(SELFGCOLOR);
  14.185 +	initfont(FONT);
  14.186 +	/* geometry */
  14.187 +	sx = sy = 0;
  14.188 +	sw = DisplayWidth(dpy, screen);
  14.189 +	sh = DisplayHeight(dpy, screen);
  14.190 +	initlayouts();
  14.191 +	/* bar */
  14.192 +	dc.h = bh = dc.font.height + 2;
  14.193 +	wa.override_redirect = 1;
  14.194 +	wa.background_pixmap = ParentRelative;
  14.195 +	wa.event_mask = ButtonPressMask | ExposureMask;
  14.196 +	barwin = XCreateWindow(dpy, root, sx, sy + (TOPBAR ? 0 : sh - bh), sw, bh, 0,
  14.197 +			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
  14.198 +			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
  14.199 +	XDefineCursor(dpy, barwin, cursor[CurNormal]);
  14.200 +	XMapRaised(dpy, barwin);
  14.201 +	strcpy(stext, "dwm-"VERSION);
  14.202 +	/* windowarea */
  14.203 +	wax = sx;
  14.204 +	way = sy + (TOPBAR ? bh : 0);
  14.205 +	wah = sh - bh;
  14.206 +	waw = sw;
  14.207 +	/* pixmap for everything */
  14.208 +	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
  14.209 +	dc.gc = XCreateGC(dpy, root, 0, 0);
  14.210 +	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  14.211 +	/* multihead support */
  14.212 +	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
  14.213 +}
  14.214 +
  14.215 +/*
  14.216 + * Startup Error handler to check if another window manager
  14.217 + * is already running.
  14.218 + */
  14.219 +static int
  14.220 +xerrorstart(Display *dsply, XErrorEvent *ee) {
  14.221 +	otherwm = True;
  14.222 +	return -1;
  14.223 +}
  14.224 +
  14.225 +/* extern */
  14.226 +
  14.227 +void
  14.228 +sendevent(Window w, Atom a, long value) {
  14.229 +	XEvent e;
  14.230 +
  14.231 +	e.type = ClientMessage;
  14.232 +	e.xclient.window = w;
  14.233 +	e.xclient.message_type = a;
  14.234 +	e.xclient.format = 32;
  14.235 +	e.xclient.data.l[0] = value;
  14.236 +	e.xclient.data.l[1] = CurrentTime;
  14.237 +	XSendEvent(dpy, w, False, NoEventMask, &e);
  14.238 +	XSync(dpy, False);
  14.239 +}
  14.240 +
  14.241 +void
  14.242 +quit(Arg *arg) {
  14.243 +	readin = running = False;
  14.244 +}
  14.245 +
  14.246 +/* There's no way to check accesses to destroyed windows, thus those cases are
  14.247 + * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  14.248 + * default error handler, which may call exit.
  14.249 + */
  14.250 +int
  14.251 +xerror(Display *dpy, XErrorEvent *ee) {
  14.252 +	if(ee->error_code == BadWindow
  14.253 +	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
  14.254 +	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
  14.255 +	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
  14.256 +	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
  14.257 +	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
  14.258 +	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
  14.259 +	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
  14.260 +		return 0;
  14.261 +	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
  14.262 +		ee->request_code, ee->error_code);
  14.263 +	return xerrorxlib(dpy, ee); /* may call exit */
  14.264 +}
  14.265 +
  14.266 +int
  14.267 +main(int argc, char *argv[]) {
  14.268 +	char *p;
  14.269 +	int r, xfd;
  14.270 +	fd_set rd;
  14.271 +	XEvent ev;
  14.272 +
  14.273 +	if(argc == 2 && !strncmp("-v", argv[1], 3))
  14.274 +		eprint("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n");
  14.275 +	else if(argc != 1)
  14.276 +		eprint("usage: dwm [-v]\n");
  14.277 +	setlocale(LC_CTYPE, "");
  14.278 +	if(!(dpy = XOpenDisplay(0)))
  14.279 +		eprint("dwm: cannot open display\n");
  14.280 +	xfd = ConnectionNumber(dpy);
  14.281 +	screen = DefaultScreen(dpy);
  14.282 +	root = RootWindow(dpy, screen);
  14.283 +	otherwm = False;
  14.284 +	XSetErrorHandler(xerrorstart);
  14.285 +	/* this causes an error if some other window manager is running */
  14.286 +	XSelectInput(dpy, root, SubstructureRedirectMask);
  14.287 +	XSync(dpy, False);
  14.288 +	if(otherwm)
  14.289 +		eprint("dwm: another window manager is already running\n");
  14.290 +
  14.291 +	XSync(dpy, False);
  14.292 +	XSetErrorHandler(NULL);
  14.293 +	xerrorxlib = XSetErrorHandler(xerror);
  14.294 +	XSync(dpy, False);
  14.295 +	setup();
  14.296 +	drawstatus();
  14.297 +	scan();
  14.298 +
  14.299 +	/* main event loop, also reads status text from stdin */
  14.300 +	XSync(dpy, False);
  14.301 +	readin = True;
  14.302 +	while(running) {
  14.303 +		FD_ZERO(&rd);
  14.304 +		if(readin)
  14.305 +			FD_SET(STDIN_FILENO, &rd);
  14.306 +		FD_SET(xfd, &rd);
  14.307 +		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
  14.308 +			if(errno == EINTR)
  14.309 +				continue;
  14.310 +			eprint("select failed\n");
  14.311 +		}
  14.312 +		if(FD_ISSET(STDIN_FILENO, &rd)) {
  14.313 +			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
  14.314 +			case -1:
  14.315 +				strncpy(stext, strerror(errno), sizeof stext - 1);
  14.316 +				stext[sizeof stext - 1] = '\0';
  14.317 +				readin = False;
  14.318 +				break;
  14.319 +			case 0:
  14.320 +				strncpy(stext, "EOF", 4);
  14.321 +				readin = False;
  14.322 +				break;
  14.323 +			default:
  14.324 +				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
  14.325 +				for(; p >= stext && *p != '\n'; --p);
  14.326 +				if(p > stext)
  14.327 +					strncpy(stext, p + 1, sizeof stext);
  14.328 +			}
  14.329 +			drawstatus();
  14.330 +		}
  14.331 +		if(FD_ISSET(xfd, &rd))
  14.332 +			while(XPending(dpy)) {
  14.333 +				XNextEvent(dpy, &ev);
  14.334 +				if(handler[ev.type])
  14.335 +					(handler[ev.type])(&ev); /* call handler */
  14.336 +			}
  14.337 +	}
  14.338 +	cleanup();
  14.339 +	XCloseDisplay(dpy);
  14.340 +	return 0;
  14.341 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tag.c	Sun Mar 22 23:26:35 2009 -0700
    15.3 @@ -0,0 +1,166 @@
    15.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    15.5 + * See LICENSE file for license details.
    15.6 + */
    15.7 +#include "dwm.h"
    15.8 +#include <regex.h>
    15.9 +#include <stdio.h>
   15.10 +#include <stdlib.h>
   15.11 +#include <X11/Xutil.h>
   15.12 +
   15.13 +/* static */
   15.14 +
   15.15 +typedef struct {
   15.16 +	const char *prop;
   15.17 +	const char *tags;
   15.18 +	Bool isversatile;
   15.19 +} Rule;
   15.20 +
   15.21 +typedef struct {
   15.22 +	regex_t *propregex;
   15.23 +	regex_t *tagregex;
   15.24 +} Regs;
   15.25 +
   15.26 +TAGS
   15.27 +RULES
   15.28 +
   15.29 +static Regs *regs = NULL;
   15.30 +static unsigned int nrules = 0;
   15.31 +static unsigned int lastview = 0;
   15.32 +
   15.33 +/* extern */
   15.34 +
   15.35 +void
   15.36 +compileregs(void) {
   15.37 +	unsigned int i;
   15.38 +	regex_t *reg;
   15.39 +
   15.40 +	if(regs)
   15.41 +		return;
   15.42 +	nrules = sizeof rule / sizeof rule[0];
   15.43 +	regs = emallocz(nrules * sizeof(Regs));
   15.44 +	for(i = 0; i < nrules; i++) {
   15.45 +		if(rule[i].prop) {
   15.46 +			reg = emallocz(sizeof(regex_t));
   15.47 +			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
   15.48 +				free(reg);
   15.49 +			else
   15.50 +				regs[i].propregex = reg;
   15.51 +		}
   15.52 +		if(rule[i].tags) {
   15.53 +			reg = emallocz(sizeof(regex_t));
   15.54 +			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
   15.55 +				free(reg);
   15.56 +			else
   15.57 +				regs[i].tagregex = reg;
   15.58 +		}
   15.59 +	}
   15.60 +}
   15.61 +
   15.62 +Bool
   15.63 +isvisible(Client *c) {
   15.64 +	unsigned int i;
   15.65 +
   15.66 +	for(i = 0; i < ntags; i++)
   15.67 +		if(c->tags[i] && seltag[i])
   15.68 +			return True;
   15.69 +	return False;
   15.70 +}
   15.71 +
   15.72 +void
   15.73 +settags(Client *c, Client *trans) {
   15.74 +	char prop[512];
   15.75 +	unsigned int i, j;
   15.76 +	regmatch_t tmp;
   15.77 +	Bool matched = trans != NULL;
   15.78 +	XClassHint ch = { 0 };
   15.79 +
   15.80 +	if(matched)
   15.81 +		for(i = 0; i < ntags; i++)
   15.82 +			c->tags[i] = trans->tags[i];
   15.83 +	else {
   15.84 +		XGetClassHint(dpy, c->win, &ch);
   15.85 +		snprintf(prop, sizeof prop, "%s:%s:%s",
   15.86 +				ch.res_class ? ch.res_class : "",
   15.87 +				ch.res_name ? ch.res_name : "", c->name);
   15.88 +		for(i = 0; i < nrules; i++)
   15.89 +			if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
   15.90 +				c->isversatile = rule[i].isversatile;
   15.91 +				for(j = 0; regs[i].tagregex && j < ntags; j++) {
   15.92 +					if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
   15.93 +						matched = True;
   15.94 +						c->tags[j] = True;
   15.95 +					}
   15.96 +				}
   15.97 +			}
   15.98 +		if(ch.res_class)
   15.99 +			XFree(ch.res_class);
  15.100 +		if(ch.res_name)
  15.101 +			XFree(ch.res_name);
  15.102 +	}
  15.103 +	if(!matched)
  15.104 +		for(i = 0; i < ntags; i++)
  15.105 +			c->tags[i] = seltag[i];
  15.106 +}
  15.107 +
  15.108 +void
  15.109 +tag(Arg *arg) {
  15.110 +	unsigned int i;
  15.111 +
  15.112 +	if(!sel)
  15.113 +		return;
  15.114 +	for(i = 0; i < ntags; i++)
  15.115 +		sel->tags[i] = (arg->i == -1) ? True : False;
  15.116 +	if(arg->i >= 0 && arg->i < ntags)
  15.117 +		sel->tags[arg->i] = True;
  15.118 +	lt->arrange();
  15.119 +}
  15.120 +
  15.121 +void
  15.122 +toggletag(Arg *arg) {
  15.123 +	unsigned int i;
  15.124 +
  15.125 +	if(!sel)
  15.126 +		return;
  15.127 +	sel->tags[arg->i] = !sel->tags[arg->i];
  15.128 +	for(i = 0; i < ntags && !sel->tags[i]; i++);
  15.129 +	if(i == ntags)
  15.130 +		sel->tags[arg->i] = True;
  15.131 +	lt->arrange();
  15.132 +}
  15.133 +
  15.134 +void
  15.135 +toggleview(Arg *arg) {
  15.136 +	unsigned int i;
  15.137 +
  15.138 +	seltag[arg->i] = !seltag[arg->i];
  15.139 +	for(i = 0; i < ntags && !seltag[i]; i++);
  15.140 +	if(i == ntags)
  15.141 +		seltag[arg->i] = True; /* cannot toggle last view */
  15.142 +	lt->arrange();
  15.143 +}
  15.144 +
  15.145 +void
  15.146 +view(Arg *arg) {
  15.147 +	unsigned int i;
  15.148 +	Arg a;
  15.149 +	
  15.150 +	a.i = 0;
  15.151 +	setlayout(&a); /* back to default layout */
  15.152 +
  15.153 +	for(i = 0; i < ntags; i++) {
  15.154 +		if (seltag[i] == True)
  15.155 +			lastview = i;
  15.156 +		seltag[i] = (arg->i == -1) ? True : False;
  15.157 +	}
  15.158 +	if(arg->i >= 0 && arg->i < ntags)
  15.159 +		seltag[arg->i] = True;
  15.160 +	lt->arrange();
  15.161 +}
  15.162 +
  15.163 +void
  15.164 +last_view(Arg *arg) {
  15.165 +	Arg a;
  15.166 +
  15.167 +	a.i = lastview;
  15.168 +	view(&a);
  15.169 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/util.c	Sun Mar 22 23:26:35 2009 -0700
    16.3 @@ -0,0 +1,54 @@
    16.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
    16.5 + * See LICENSE file for license details.
    16.6 + */
    16.7 +#include "dwm.h"
    16.8 +#include <stdarg.h>
    16.9 +#include <stdio.h>
   16.10 +#include <stdlib.h>
   16.11 +#include <sys/wait.h>
   16.12 +#include <unistd.h>
   16.13 +
   16.14 +/* extern */
   16.15 +
   16.16 +void *
   16.17 +emallocz(unsigned int size) {
   16.18 +	void *res = calloc(1, size);
   16.19 +
   16.20 +	if(!res)
   16.21 +		eprint("fatal: could not malloc() %u bytes\n", size);
   16.22 +	return res;
   16.23 +}
   16.24 +
   16.25 +void
   16.26 +eprint(const char *errstr, ...) {
   16.27 +	va_list ap;
   16.28 +
   16.29 +	va_start(ap, errstr);
   16.30 +	vfprintf(stderr, errstr, ap);
   16.31 +	va_end(ap);
   16.32 +	exit(EXIT_FAILURE);
   16.33 +}
   16.34 +
   16.35 +void
   16.36 +spawn(Arg *arg) {
   16.37 +	static char *shell = NULL;
   16.38 +
   16.39 +	if(!shell && !(shell = getenv("SHELL")))
   16.40 +		shell = "/bin/sh";
   16.41 +	if(!arg->cmd)
   16.42 +		return;
   16.43 +	/* The double-fork construct avoids zombie processes and keeps the code
   16.44 +	 * clean from stupid signal handlers. */
   16.45 +	if(fork() == 0) {
   16.46 +		if(fork() == 0) {
   16.47 +			if(dpy)
   16.48 +				close(ConnectionNumber(dpy));
   16.49 +			setsid();
   16.50 +			execl(shell, shell, "-c", arg->cmd, (char *)NULL);
   16.51 +			fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
   16.52 +			perror(" failed");
   16.53 +		}
   16.54 +		exit(0);
   16.55 +	}
   16.56 +	wait(0);
   16.57 +}