Mercurial > hg > index.fcgi > dwm > dwm-3.6.1-10pba
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 +}