aewl
changeset 754:4c12dccc288d
this is the (second) begin of aewl - my personal stipped down dwm
author | meillo@marmaro.de |
---|---|
date | Thu, 29 May 2008 23:12:30 +0200 |
parents | c459e05a61a8 |
children | cdd895c163bd |
files | Makefile client.c config.arg.h config.default.h config.meillo.h config.mk draw.c dwm.c dwm.h event.c main.c tag.c util.c view.c |
diffstat | 14 files changed, 1851 insertions(+), 2133 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sat Jun 16 21:49:51 2007 +0200 1.2 +++ b/Makefile Thu May 29 23:12:30 2008 +0200 1.3 @@ -3,8 +3,6 @@ 1.4 1.5 include config.mk 1.6 1.7 -SRC = client.c draw.c event.c main.c tag.c util.c view.c 1.8 -OBJ = ${SRC:.c=.o} 1.9 1.10 all: options dwm 1.11 1.12 @@ -14,19 +12,13 @@ 1.13 @echo "LDFLAGS = ${LDFLAGS}" 1.14 @echo "CC = ${CC}" 1.15 1.16 -.c.o: 1.17 +dwm.o: dwm.c config.h config.mk 1.18 @echo CC $< 1.19 @${CC} -c ${CFLAGS} $< 1.20 1.21 -${OBJ}: dwm.h config.h config.mk 1.22 - 1.23 -config.h: config.meillo.h 1.24 - @echo creating $@ from config.meillo.h 1.25 - @cp config.meillo.h $@ 1.26 - 1.27 -dwm: ${OBJ} 1.28 +dwm: dwm.o 1.29 @echo CC -o $@ 1.30 - @${CC} -o $@ ${OBJ} ${LDFLAGS} 1.31 + @${CC} -o $@ dwm.o ${LDFLAGS} 1.32 @strip $@ 1.33 1.34 clean:
2.1 --- a/client.c Sat Jun 16 21:49:51 2007 +0200 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,356 +0,0 @@ 2.4 -/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 2.5 - * See LICENSE file for license details. 2.6 - */ 2.7 -#include "dwm.h" 2.8 -#include <stdlib.h> 2.9 -#include <string.h> 2.10 -#include <X11/Xatom.h> 2.11 -#include <X11/Xutil.h> 2.12 - 2.13 -/* static */ 2.14 - 2.15 -static void 2.16 -detachstack(Client *c) { 2.17 - Client **tc; 2.18 - for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); 2.19 - *tc = c->snext; 2.20 -} 2.21 - 2.22 -static void 2.23 -grabbuttons(Client *c, Bool focused) { 2.24 - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); 2.25 - 2.26 - if(focused) { 2.27 - XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, 2.28 - GrabModeAsync, GrabModeSync, None, None); 2.29 - XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, 2.30 - GrabModeAsync, GrabModeSync, None, None); 2.31 - XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, 2.32 - GrabModeAsync, GrabModeSync, None, None); 2.33 - XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 2.34 - GrabModeAsync, GrabModeSync, None, None); 2.35 - 2.36 - XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, 2.37 - GrabModeAsync, GrabModeSync, None, None); 2.38 - XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, 2.39 - GrabModeAsync, GrabModeSync, None, None); 2.40 - XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, 2.41 - GrabModeAsync, GrabModeSync, None, None); 2.42 - XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 2.43 - GrabModeAsync, GrabModeSync, None, None); 2.44 - 2.45 - XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, 2.46 - GrabModeAsync, GrabModeSync, None, None); 2.47 - XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, 2.48 - GrabModeAsync, GrabModeSync, None, None); 2.49 - XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, 2.50 - GrabModeAsync, GrabModeSync, None, None); 2.51 - XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 2.52 - GrabModeAsync, GrabModeSync, None, None); 2.53 - } 2.54 - else 2.55 - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, 2.56 - GrabModeAsync, GrabModeSync, None, None); 2.57 -} 2.58 - 2.59 -static void 2.60 -setclientstate(Client *c, long state) { 2.61 - long data[] = {state, None}; 2.62 - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, 2.63 - PropModeReplace, (unsigned char *)data, 2); 2.64 -} 2.65 - 2.66 -static int 2.67 -xerrordummy(Display *dsply, XErrorEvent *ee) { 2.68 - return 0; 2.69 -} 2.70 - 2.71 -/* extern */ 2.72 - 2.73 -void 2.74 -configure(Client *c) { 2.75 - XEvent synev; 2.76 - 2.77 - synev.type = ConfigureNotify; 2.78 - synev.xconfigure.display = dpy; 2.79 - synev.xconfigure.event = c->win; 2.80 - synev.xconfigure.window = c->win; 2.81 - synev.xconfigure.x = c->x; 2.82 - synev.xconfigure.y = c->y; 2.83 - synev.xconfigure.width = c->w; 2.84 - synev.xconfigure.height = c->h; 2.85 - synev.xconfigure.border_width = c->border; 2.86 - synev.xconfigure.above = None; 2.87 - XSendEvent(dpy, c->win, True, NoEventMask, &synev); 2.88 -} 2.89 - 2.90 -void 2.91 -focus(Client *c) { 2.92 - if(c && !isvisible(c)) 2.93 - return; 2.94 - if(sel && sel != c) { 2.95 - grabbuttons(sel, False); 2.96 - XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); 2.97 - } 2.98 - if(c) { 2.99 - detachstack(c); 2.100 - c->snext = stack; 2.101 - stack = c; 2.102 - grabbuttons(c, True); 2.103 - } 2.104 - sel = c; 2.105 - drawstatus(); 2.106 - if(!selscreen) 2.107 - return; 2.108 - if(c) { 2.109 - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); 2.110 - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); 2.111 - } 2.112 - else 2.113 - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); 2.114 -} 2.115 - 2.116 -Client * 2.117 -getclient(Window w) { 2.118 - Client *c; 2.119 - 2.120 - for(c = clients; c; c = c->next) 2.121 - if(c->win == w) 2.122 - return c; 2.123 - return NULL; 2.124 -} 2.125 - 2.126 -Bool 2.127 -isprotodel(Client *c) { 2.128 - int i, n; 2.129 - Atom *protocols; 2.130 - Bool ret = False; 2.131 - 2.132 - if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { 2.133 - for(i = 0; !ret && i < n; i++) 2.134 - if(protocols[i] == wmatom[WMDelete]) 2.135 - ret = True; 2.136 - XFree(protocols); 2.137 - } 2.138 - return ret; 2.139 -} 2.140 - 2.141 -void 2.142 -killclient(Arg *arg) { 2.143 - if(!sel) 2.144 - return; 2.145 - if(isprotodel(sel)) 2.146 - sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); 2.147 - else 2.148 - XKillClient(dpy, sel->win); 2.149 -} 2.150 - 2.151 -void 2.152 -manage(Window w, XWindowAttributes *wa) { 2.153 - Client *c; 2.154 - Window trans; 2.155 - 2.156 - c = emallocz(sizeof(Client)); 2.157 - c->tags = emallocz(ntags * sizeof(Bool)); 2.158 - c->win = w; 2.159 - c->x = wa->x; 2.160 - c->y = wa->y; 2.161 - c->w = wa->width; 2.162 - c->h = wa->height; 2.163 - if(c->w == sw && c->h == sh) { 2.164 - c->border = 0; 2.165 - c->x = sx; 2.166 - c->y = sy; 2.167 - } 2.168 - else { 2.169 - c->border = BORDERPX; 2.170 - if(c->x + c->w + 2 * c->border > wax + waw) 2.171 - c->x = wax + waw - c->w - 2 * c->border; 2.172 - if(c->y + c->h + 2 * c->border > way + wah) 2.173 - c->y = way + wah - c->h - 2 * c->border; 2.174 - if(c->x < wax) 2.175 - c->x = wax; 2.176 - if(c->y < way) 2.177 - c->y = way; 2.178 - } 2.179 - updatesizehints(c); 2.180 - XSelectInput(dpy, c->win, 2.181 - StructureNotifyMask | PropertyChangeMask | EnterWindowMask); 2.182 - XGetTransientForHint(dpy, c->win, &trans); 2.183 - grabbuttons(c, False); 2.184 - XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); 2.185 - updatetitle(c); 2.186 - settags(c, getclient(trans)); 2.187 - if(!c->isfloat) 2.188 - c->isfloat = trans || c->isfixed; 2.189 - if(clients) 2.190 - clients->prev = c; 2.191 - c->next = clients; 2.192 - c->snext = stack; 2.193 - stack = clients = c; 2.194 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 2.195 - XMapWindow(dpy, c->win); 2.196 - setclientstate(c, NormalState); 2.197 - if(isvisible(c)) 2.198 - focus(c); 2.199 - arrange(); 2.200 -} 2.201 - 2.202 -void 2.203 -resize(Client *c, Bool sizehints) { 2.204 - float actual, dx, dy, max, min; 2.205 - XWindowChanges wc; 2.206 - 2.207 - if(c->w <= 0 || c->h <= 0) 2.208 - return; 2.209 - if(sizehints) { 2.210 - if(c->minw && c->w < c->minw) 2.211 - c->w = c->minw; 2.212 - if(c->minh && c->h < c->minh) 2.213 - c->h = c->minh; 2.214 - if(c->maxw && c->w > c->maxw) 2.215 - c->w = c->maxw; 2.216 - if(c->maxh && c->h > c->maxh) 2.217 - c->h = c->maxh; 2.218 - /* inspired by algorithm from fluxbox */ 2.219 - if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) { 2.220 - dx = (float)(c->w - c->basew); 2.221 - dy = (float)(c->h - c->baseh); 2.222 - min = (float)(c->minax) / (float)(c->minay); 2.223 - max = (float)(c->maxax) / (float)(c->maxay); 2.224 - actual = dx / dy; 2.225 - if(max > 0 && min > 0 && actual > 0) { 2.226 - if(actual < min) { 2.227 - dy = (dx * min + dy) / (min * min + 1); 2.228 - dx = dy * min; 2.229 - c->w = (int)dx + c->basew; 2.230 - c->h = (int)dy + c->baseh; 2.231 - } 2.232 - else if(actual > max) { 2.233 - dy = (dx * min + dy) / (max * max + 1); 2.234 - dx = dy * min; 2.235 - c->w = (int)dx + c->basew; 2.236 - c->h = (int)dy + c->baseh; 2.237 - } 2.238 - } 2.239 - } 2.240 - if(c->incw) 2.241 - c->w -= (c->w - c->basew) % c->incw; 2.242 - if(c->inch) 2.243 - c->h -= (c->h - c->baseh) % c->inch; 2.244 - } 2.245 - if(c->w == sw && c->h == sh) 2.246 - c->border = 0; 2.247 - else 2.248 - c->border = BORDERPX; 2.249 - /* offscreen appearance fixes */ 2.250 - if(c->x > sw) 2.251 - c->x = sw - c->w - 2 * c->border; 2.252 - if(c->y > sh) 2.253 - c->y = sh - c->h - 2 * c->border; 2.254 - if(c->x + c->w + 2 * c->border < sx) 2.255 - c->x = sx; 2.256 - if(c->y + c->h + 2 * c->border < sy) 2.257 - c->y = sy; 2.258 - wc.x = c->x; 2.259 - wc.y = c->y; 2.260 - wc.width = c->w; 2.261 - wc.height = c->h; 2.262 - wc.border_width = c->border; 2.263 - XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); 2.264 - configure(c); 2.265 - XSync(dpy, False); 2.266 -} 2.267 - 2.268 -void 2.269 -updatesizehints(Client *c) { 2.270 - long msize; 2.271 - XSizeHints size; 2.272 - 2.273 - if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) 2.274 - size.flags = PSize; 2.275 - c->flags = size.flags; 2.276 - if(c->flags & PBaseSize) { 2.277 - c->basew = size.base_width; 2.278 - c->baseh = size.base_height; 2.279 - } 2.280 - else 2.281 - c->basew = c->baseh = 0; 2.282 - if(c->flags & PResizeInc) { 2.283 - c->incw = size.width_inc; 2.284 - c->inch = size.height_inc; 2.285 - } 2.286 - else 2.287 - c->incw = c->inch = 0; 2.288 - if(c->flags & PMaxSize) { 2.289 - c->maxw = size.max_width; 2.290 - c->maxh = size.max_height; 2.291 - } 2.292 - else 2.293 - c->maxw = c->maxh = 0; 2.294 - if(c->flags & PMinSize) { 2.295 - c->minw = size.min_width; 2.296 - c->minh = size.min_height; 2.297 - } 2.298 - else 2.299 - c->minw = c->minh = 0; 2.300 - if(c->flags & PAspect) { 2.301 - c->minax = size.min_aspect.x; 2.302 - c->minay = size.min_aspect.y; 2.303 - c->maxax = size.max_aspect.x; 2.304 - c->maxay = size.max_aspect.y; 2.305 - } 2.306 - else 2.307 - c->minax = c->minay = c->maxax = c->maxay = 0; 2.308 - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh && 2.309 - c->maxw == c->minw && c->maxh == c->minh); 2.310 -} 2.311 - 2.312 -void 2.313 -updatetitle(Client *c) { 2.314 - char **list = NULL; 2.315 - int n; 2.316 - XTextProperty name; 2.317 - 2.318 - name.nitems = 0; 2.319 - c->name[0] = 0; 2.320 - XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); 2.321 - if(!name.nitems) 2.322 - XGetWMName(dpy, c->win, &name); 2.323 - if(!name.nitems) 2.324 - return; 2.325 - if(name.encoding == XA_STRING) 2.326 - strncpy(c->name, (char *)name.value, sizeof c->name); 2.327 - else { 2.328 - if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success 2.329 - && n > 0 && *list) 2.330 - { 2.331 - strncpy(c->name, *list, sizeof c->name); 2.332 - XFreeStringList(list); 2.333 - } 2.334 - } 2.335 - XFree(name.value); 2.336 -} 2.337 - 2.338 -void 2.339 -unmanage(Client *c) { 2.340 - Client *nc; 2.341 - 2.342 - /* The server grab construct avoids race conditions. */ 2.343 - XGrabServer(dpy); 2.344 - XSetErrorHandler(xerrordummy); 2.345 - detach(c); 2.346 - detachstack(c); 2.347 - if(sel == c) { 2.348 - for(nc = stack; nc && !isvisible(nc); nc = nc->snext); 2.349 - focus(nc); 2.350 - } 2.351 - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); 2.352 - setclientstate(c, WithdrawnState); 2.353 - free(c->tags); 2.354 - free(c); 2.355 - XSync(dpy, False); 2.356 - XSetErrorHandler(xerror); 2.357 - XUngrabServer(dpy); 2.358 - arrange(); 2.359 -}
3.1 --- a/config.arg.h Sat Jun 16 21:49:51 2007 +0200 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,94 +0,0 @@ 3.4 -/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 3.5 - * See LICENSE file for license details. 3.6 - */ 3.7 - 3.8 -#define TAGS \ 3.9 -const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; 3.10 - 3.11 -#define BORDERPX 1 3.12 -#define DEFMODE dotile /* dofloat */ 3.13 -#define FLOATSYMBOL "><>" 3.14 -#define TILESYMBOL "[]=" 3.15 - 3.16 -#define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*" 3.17 -#define NORMBORDERCOLOR "#333" 3.18 -#define NORMBGCOLOR "#222" 3.19 -#define NORMFGCOLOR "#ccc" 3.20 -#define SELBORDERCOLOR "#69c" 3.21 -#define SELBGCOLOR "#555" 3.22 -#define SELFGCOLOR "#fff" 3.23 - 3.24 -#define MASTER 600 /* per thousand */ 3.25 -#define MODKEY Mod1Mask 3.26 -#define NMASTER 1 /* clients in master area */ 3.27 -#define SNAP 40 /* pixel */ 3.28 -#define TOPBAR True /* False */ 3.29 - 3.30 -#define KEYS \ 3.31 -static Key key[] = { \ 3.32 - /* modifier key function argument */ \ 3.33 - { MODKEY|ShiftMask, XK_Return, spawn, \ 3.34 - { .cmd = "exec uxterm -bg '#222' -fg '#eee' -cr '#eee' +sb -fn '"FONT"'" } }, \ 3.35 - { MODKEY, XK_p, spawn, \ 3.36 - { .cmd = "exe=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \ 3.37 - " | dmenu -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' " \ 3.38 - "-sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"')\" && exec $exe" } }, \ 3.39 - { MODKEY, XK_j, focusnext, { 0 } }, \ 3.40 - { MODKEY, XK_k, focusprev, { 0 } }, \ 3.41 - { MODKEY, XK_Return, zoom, { 0 } }, \ 3.42 - { MODKEY, XK_g, resizemaster, { .i = 15 } }, \ 3.43 - { MODKEY, XK_s, resizemaster, { .i = -15 } }, \ 3.44 - { MODKEY, XK_i, incnmaster, { .i = 1 } }, \ 3.45 - { MODKEY, XK_d, incnmaster, { .i = -1 } }, \ 3.46 - { MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \ 3.47 - { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ 3.48 - { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ 3.49 - { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ 3.50 - { MODKEY|ShiftMask, XK_4, tag, { .i = 3 } }, \ 3.51 - { MODKEY|ShiftMask, XK_5, tag, { .i = 4 } }, \ 3.52 - { MODKEY|ShiftMask, XK_6, tag, { .i = 5 } }, \ 3.53 - { MODKEY|ShiftMask, XK_7, tag, { .i = 6 } }, \ 3.54 - { MODKEY|ShiftMask, XK_8, tag, { .i = 7 } }, \ 3.55 - { MODKEY|ShiftMask, XK_9, tag, { .i = 8 } }, \ 3.56 - { MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 0 } }, \ 3.57 - { MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 1 } }, \ 3.58 - { MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 2 } }, \ 3.59 - { MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \ 3.60 - { MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \ 3.61 - { MODKEY|ControlMask|ShiftMask, XK_6, toggletag, { .i = 5 } }, \ 3.62 - { MODKEY|ControlMask|ShiftMask, XK_7, toggletag, { .i = 6 } }, \ 3.63 - { MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \ 3.64 - { MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \ 3.65 - { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ 3.66 - { MODKEY, XK_space, togglemode, { 0 } }, \ 3.67 - { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ 3.68 - { MODKEY, XK_0, view, { .i = -1 } }, \ 3.69 - { MODKEY, XK_1, view, { .i = 0 } }, \ 3.70 - { MODKEY, XK_2, view, { .i = 1 } }, \ 3.71 - { MODKEY, XK_3, view, { .i = 2 } }, \ 3.72 - { MODKEY, XK_4, view, { .i = 3 } }, \ 3.73 - { MODKEY, XK_5, view, { .i = 4 } }, \ 3.74 - { MODKEY, XK_6, view, { .i = 5 } }, \ 3.75 - { MODKEY, XK_7, view, { .i = 6 } }, \ 3.76 - { MODKEY, XK_8, view, { .i = 7 } }, \ 3.77 - { MODKEY, XK_9, view, { .i = 8 } }, \ 3.78 - { MODKEY|ControlMask, XK_1, toggleview, { .i = 0 } }, \ 3.79 - { MODKEY|ControlMask, XK_2, toggleview, { .i = 1 } }, \ 3.80 - { MODKEY|ControlMask, XK_3, toggleview, { .i = 2 } }, \ 3.81 - { MODKEY|ControlMask, XK_4, toggleview, { .i = 3 } }, \ 3.82 - { MODKEY|ControlMask, XK_5, toggleview, { .i = 4 } }, \ 3.83 - { MODKEY|ControlMask, XK_6, toggleview, { .i = 5 } }, \ 3.84 - { MODKEY|ControlMask, XK_7, toggleview, { .i = 6 } }, \ 3.85 - { MODKEY|ControlMask, XK_8, toggleview, { .i = 7 } }, \ 3.86 - { MODKEY|ControlMask, XK_9, toggleview, { .i = 8 } }, \ 3.87 - { MODKEY|ShiftMask, XK_q, quit, { 0 } }, \ 3.88 -}; 3.89 - 3.90 -#define RULES \ 3.91 -static Rule rule[] = { \ 3.92 - /* class:instance:title regex tags regex isfloat */ \ 3.93 - { "Firefox.*", "3", False }, \ 3.94 - { "Gimp.*", NULL, True }, \ 3.95 - { "MPlayer.*", NULL, True }, \ 3.96 - { "Acroread.*", NULL, True }, \ 3.97 -};
4.1 --- a/config.default.h Sat Jun 16 21:49:51 2007 +0200 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,90 +0,0 @@ 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 - 4.8 -#define TAGS \ 4.9 -const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; 4.10 - 4.11 -#define BORDERPX 1 4.12 -#define DEFMODE dotile /* dofloat */ 4.13 -#define FLOATSYMBOL "><>" 4.14 -#define TILESYMBOL "[]=" 4.15 - 4.16 -#define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*" 4.17 -#define NORMBORDERCOLOR "#dddddd" 4.18 -#define NORMBGCOLOR "#eeeeee" 4.19 -#define NORMFGCOLOR "#222222" 4.20 -#define SELBORDERCOLOR "#ff0000" 4.21 -#define SELBGCOLOR "#006699" 4.22 -#define SELFGCOLOR "#ffffff" 4.23 - 4.24 -#define MASTER 600 /* per thousand */ 4.25 -#define MODKEY Mod1Mask 4.26 -#define NMASTER 1 /* clients in master area */ 4.27 -#define SNAP 20 /* pixel */ 4.28 -#define TOPBAR True /* False */ 4.29 - 4.30 -#define KEYS \ 4.31 -static Key key[] = { \ 4.32 - /* modifier key function argument */ \ 4.33 - { MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \ 4.34 - { MODKEY, XK_Tab, focusnext, { 0 } }, \ 4.35 - { MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \ 4.36 - { MODKEY, XK_Return, zoom, { 0 } }, \ 4.37 - { MODKEY, XK_g, resizemaster, { .i = 15 } }, \ 4.38 - { MODKEY, XK_s, resizemaster, { .i = -15 } }, \ 4.39 - { MODKEY, XK_i, incnmaster, { .i = 1 } }, \ 4.40 - { MODKEY, XK_d, incnmaster, { .i = -1 } }, \ 4.41 - { MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \ 4.42 - { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ 4.43 - { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ 4.44 - { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ 4.45 - { MODKEY|ShiftMask, XK_4, tag, { .i = 3 } }, \ 4.46 - { MODKEY|ShiftMask, XK_5, tag, { .i = 4 } }, \ 4.47 - { MODKEY|ShiftMask, XK_6, tag, { .i = 5 } }, \ 4.48 - { MODKEY|ShiftMask, XK_7, tag, { .i = 6 } }, \ 4.49 - { MODKEY|ShiftMask, XK_8, tag, { .i = 7 } }, \ 4.50 - { MODKEY|ShiftMask, XK_9, tag, { .i = 8 } }, \ 4.51 - { MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 0 } }, \ 4.52 - { MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 1 } }, \ 4.53 - { MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 2 } }, \ 4.54 - { MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \ 4.55 - { MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \ 4.56 - { MODKEY|ControlMask|ShiftMask, XK_6, toggletag, { .i = 5 } }, \ 4.57 - { MODKEY|ControlMask|ShiftMask, XK_7, toggletag, { .i = 6 } }, \ 4.58 - { MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \ 4.59 - { MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \ 4.60 - { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ 4.61 - { MODKEY, XK_space, togglemode, { 0 } }, \ 4.62 - { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ 4.63 - { MODKEY, XK_0, view, { .i = -1 } }, \ 4.64 - { MODKEY, XK_1, view, { .i = 0 } }, \ 4.65 - { MODKEY, XK_2, view, { .i = 1 } }, \ 4.66 - { MODKEY, XK_3, view, { .i = 2 } }, \ 4.67 - { MODKEY, XK_4, view, { .i = 3 } }, \ 4.68 - { MODKEY, XK_5, view, { .i = 4 } }, \ 4.69 - { MODKEY, XK_6, view, { .i = 5 } }, \ 4.70 - { MODKEY, XK_7, view, { .i = 6 } }, \ 4.71 - { MODKEY, XK_8, view, { .i = 7 } }, \ 4.72 - { MODKEY, XK_9, view, { .i = 8 } }, \ 4.73 - { MODKEY|ControlMask, XK_1, toggleview, { .i = 0 } }, \ 4.74 - { MODKEY|ControlMask, XK_2, toggleview, { .i = 1 } }, \ 4.75 - { MODKEY|ControlMask, XK_3, toggleview, { .i = 2 } }, \ 4.76 - { MODKEY|ControlMask, XK_4, toggleview, { .i = 3 } }, \ 4.77 - { MODKEY|ControlMask, XK_5, toggleview, { .i = 4 } }, \ 4.78 - { MODKEY|ControlMask, XK_6, toggleview, { .i = 5 } }, \ 4.79 - { MODKEY|ControlMask, XK_7, toggleview, { .i = 6 } }, \ 4.80 - { MODKEY|ControlMask, XK_8, toggleview, { .i = 7 } }, \ 4.81 - { MODKEY|ControlMask, XK_9, toggleview, { .i = 8 } }, \ 4.82 - { MODKEY|ShiftMask, XK_q, quit, { 0 } }, \ 4.83 -}; 4.84 - 4.85 -/* Query class:instance:title for regex matching info with following command: 4.86 - * xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/ { printf("%s\n",$2) }' */ 4.87 -#define RULES \ 4.88 -static Rule rule[] = { \ 4.89 - /* class:instance:title regex tags regex isfloat */ \ 4.90 - { "Gimp.*", NULL, True }, \ 4.91 - { "MPlayer.*", NULL, True }, \ 4.92 - { "Acroread.*", NULL, True }, \ 4.93 -};
5.1 --- a/config.meillo.h Sat Jun 16 21:49:51 2007 +0200 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,61 +0,0 @@ 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 -#define TAGS \ 5.9 -const char *tags[] = { "Das Alles", "Das Nichts", NULL }; 5.10 - 5.11 -#define BORDERPX 1 5.12 -#define DEFMODE domax /* dotile */ 5.13 -#define FLOATSYMBOL "" 5.14 -#define TILESYMBOL "" 5.15 - 5.16 -#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-*-*" 5.17 -#define NORMBGCOLOR "#333333" 5.18 -#define NORMFGCOLOR "#bbbbbb" 5.19 -#define SELBGCOLOR "#eec900" 5.20 -#define SELFGCOLOR "#000000" 5.21 -#define NORMBORDERCOLOR NORMBGCOLOR 5.22 -#define SELBORDERCOLOR SELBGCOLOR 5.23 - 5.24 -#define MASTER 500 /* per thousand */ 5.25 -#define MODKEY Mod1Mask 5.26 -#define NMASTER 1 /* clients in master area */ 5.27 -#define SNAP 5 /* pixel */ 5.28 -#define TOPBAR True /* False */ 5.29 - 5.30 -#define KEYS \ 5.31 -static Key key[] = { \ 5.32 - /* modifier key function argument */ \ 5.33 - { MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec urxvt" } }, \ 5.34 - { MODKEY, XK_F1, viewnext, { .i = 0 } }, \ 5.35 - { MODKEY, XK_Tab, focusnext, { 0 } }, \ 5.36 - { MODKEY, XK_asciicircum, spawn, \ 5.37 - { .cmd = "exe=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \ 5.38 - " | dmenu -font '"FONT"' -normbg '"NORMBGCOLOR"' -normfg '"NORMFGCOLOR"' " \ 5.39 - "-selbg '"SELBGCOLOR"' -selfg '"SELFGCOLOR"')\" && exec $exe" } }, \ 5.40 - { MODKEY, XK_1, zoom, { 0 } }, \ 5.41 - { MODKEY, XK_2, killclient, { 0 } }, \ 5.42 - { MODKEY|ShiftMask, XK_q, quit, { 0 } }, \ 5.43 - { MODKEY|ShiftMask, XK_F4, spawn, { .cmd = "sudo /sbin/shutdown -t 3 now" } }, \ 5.44 - { MODKEY, XK_space, togglemode, { 0 } }, \ 5.45 - { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ 5.46 - { MODKEY, XK_g, resizemaster, { .i = 15 } }, \ 5.47 - { MODKEY, XK_s, resizemaster, { .i = -15 } }, \ 5.48 - { MODKEY, XK_i, incnmaster, { .i = 1 } }, \ 5.49 - { MODKEY, XK_d, incnmaster, { .i = -1 } }, \ 5.50 - { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ 5.51 - { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ 5.52 -}; 5.53 - 5.54 -/* Query class:instance:title for regex matching info with following command: 5.55 - * xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/ { printf("%s\n",$2) }' */ 5.56 -#define RULES \ 5.57 -static Rule rule[] = { \ 5.58 - /* class:instance:title regex tags regex isfloat */ \ 5.59 - { "URxvt.*", "Das Nichts", False }, \ 5.60 - { "MPlayer.*", NULL, True }, \ 5.61 - { "qiv.*", NULL, False }, \ 5.62 - { "Gimp.*", "Das Alles", True }, \ 5.63 - { ".*", "Das Alles", False }, \ 5.64 -};
6.1 --- a/config.mk Sat Jun 16 21:49:51 2007 +0200 6.2 +++ b/config.mk Thu May 29 23:12:30 2008 +0200 6.3 @@ -1,5 +1,5 @@ 6.4 # dwm version 6.5 -VERSION = 3.5 6.6 +VERSION = 4.4.1 6.7 6.8 # Customize below to fit your system 6.9 6.10 @@ -15,7 +15,7 @@ 6.11 LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 6.12 6.13 # flags 6.14 -CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" 6.15 +CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" -W -Wall 6.16 LDFLAGS = ${LIBS} 6.17 #CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" 6.18 #LDFLAGS = -g ${LIBS}
7.1 --- a/draw.c Sat Jun 16 21:49:51 2007 +0200 7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 7.3 @@ -1,164 +0,0 @@ 7.4 -/* (C)opyright MMIV-MMVII Anselm R. Garbe <garbeam at gmail dot com> 7.5 - * See LICENSE file for license details. 7.6 - */ 7.7 -#include "dwm.h" 7.8 -#include <stdio.h> 7.9 -#include <string.h> 7.10 - 7.11 -/* static */ 7.12 - 7.13 -static Bool 7.14 -isoccupied(unsigned int t) 7.15 -{ 7.16 - Client *c; 7.17 - for(c = clients; c; c = c->next) 7.18 - if(c->tags[t]) 7.19 - return True; 7.20 - return False; 7.21 -} 7.22 - 7.23 -static unsigned int 7.24 -textnw(const char *text, unsigned int len) { 7.25 - XRectangle r; 7.26 - 7.27 - if(dc.font.set) { 7.28 - XmbTextExtents(dc.font.set, text, len, NULL, &r); 7.29 - return r.width; 7.30 - } 7.31 - return XTextWidth(dc.font.xfont, text, len); 7.32 -} 7.33 - 7.34 -static void 7.35 -drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool emptysquare) { 7.36 - int x, y, w, h; 7.37 - static char buf[256]; 7.38 - unsigned int len, olen; 7.39 - XGCValues gcv; 7.40 - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; 7.41 - 7.42 - XSetForeground(dpy, dc.gc, col[ColBG]); 7.43 - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); 7.44 - if(!text) 7.45 - return; 7.46 - w = 0; 7.47 - olen = len = strlen(text); 7.48 - if(len >= sizeof buf) 7.49 - len = sizeof buf - 1; 7.50 - memcpy(buf, text, len); 7.51 - buf[len] = 0; 7.52 - h = dc.font.ascent + dc.font.descent; 7.53 - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; 7.54 - x = dc.x + (h / 2); 7.55 - /* shorten text if necessary */ 7.56 - while(len && (w = textnw(buf, len)) > dc.w - h) 7.57 - buf[--len] = 0; 7.58 - if(len < olen) { 7.59 - if(len > 1) 7.60 - buf[len - 1] = '.'; 7.61 - if(len > 2) 7.62 - buf[len - 2] = '.'; 7.63 - if(len > 3) 7.64 - buf[len - 3] = '.'; 7.65 - } 7.66 - if(w > dc.w) 7.67 - return; /* too long */ 7.68 - gcv.foreground = col[ColFG]; 7.69 - if(dc.font.set) { 7.70 - XChangeGC(dpy, dc.gc, GCForeground, &gcv); 7.71 - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); 7.72 - } 7.73 - else { 7.74 - gcv.font = dc.font.xfont->fid; 7.75 - XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv); 7.76 - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); 7.77 - } 7.78 -} 7.79 - 7.80 -/* extern */ 7.81 - 7.82 -void 7.83 -drawstatus(void) { 7.84 - int i, x; 7.85 - 7.86 - dc.x = dc.y = 0; 7.87 - for(i = 0; i < ntags; i++) { 7.88 - dc.w = textw(tags[i]); 7.89 - if(seltag[i]) 7.90 - drawtext(tags[i], dc.sel, sel && sel->tags[i], isoccupied(i)); 7.91 - else 7.92 - drawtext(tags[i], dc.norm, sel && sel->tags[i], isoccupied(i)); 7.93 - dc.x += dc.w + 1; 7.94 - } 7.95 - dc.w = bmw; 7.96 - drawtext("", dc.norm, False, False); 7.97 - x = dc.x + dc.w; 7.98 - dc.w = textw(stext); 7.99 - dc.x = sw - dc.w; 7.100 - if(dc.x < x) { 7.101 - dc.x = x; 7.102 - dc.w = sw - x; 7.103 - } 7.104 - drawtext(stext, dc.norm, False, False); 7.105 - if((dc.w = dc.x - x) > bh) { 7.106 - dc.x = x; 7.107 - drawtext(sel ? sel->name : NULL, dc.norm, False, False); 7.108 - } 7.109 - XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); 7.110 - XSync(dpy, False); 7.111 -} 7.112 - 7.113 -unsigned long 7.114 -getcolor(const char *colstr) { 7.115 - Colormap cmap = DefaultColormap(dpy, screen); 7.116 - XColor color; 7.117 - 7.118 - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) 7.119 - eprint("error, cannot allocate color '%s'\n", colstr); 7.120 - return color.pixel; 7.121 -} 7.122 - 7.123 -void 7.124 -setfont(const char *fontstr) { 7.125 - char *def, **missing; 7.126 - int i, n; 7.127 - 7.128 - missing = NULL; 7.129 - if(dc.font.set) 7.130 - XFreeFontSet(dpy, dc.font.set); 7.131 - dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); 7.132 - if(missing) { 7.133 - while(n--) 7.134 - fprintf(stderr, "missing fontset: %s\n", missing[n]); 7.135 - XFreeStringList(missing); 7.136 - } 7.137 - if(dc.font.set) { 7.138 - XFontSetExtents *font_extents; 7.139 - XFontStruct **xfonts; 7.140 - char **font_names; 7.141 - dc.font.ascent = dc.font.descent = 0; 7.142 - font_extents = XExtentsOfFontSet(dc.font.set); 7.143 - n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); 7.144 - for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { 7.145 - if(dc.font.ascent < (*xfonts)->ascent) 7.146 - dc.font.ascent = (*xfonts)->ascent; 7.147 - if(dc.font.descent < (*xfonts)->descent) 7.148 - dc.font.descent = (*xfonts)->descent; 7.149 - xfonts++; 7.150 - } 7.151 - } 7.152 - else { 7.153 - if(dc.font.xfont) 7.154 - XFreeFont(dpy, dc.font.xfont); 7.155 - dc.font.xfont = NULL; 7.156 - if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))) 7.157 - eprint("error, cannot load font: '%s'\n", fontstr); 7.158 - dc.font.ascent = dc.font.xfont->ascent; 7.159 - dc.font.descent = dc.font.xfont->descent; 7.160 - } 7.161 - dc.font.height = dc.font.ascent + dc.font.descent; 7.162 -} 7.163 - 7.164 -unsigned int 7.165 -textw(const char *text) { 7.166 - return textnw(text, strlen(text)) + dc.font.height; 7.167 -}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/dwm.c Thu May 29 23:12:30 2008 +0200 8.3 @@ -0,0 +1,1846 @@ 8.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 8.5 + * See LICENSE file for license details. 8.6 + * 8.7 + * dynamic window manager is designed like any other X client as well. It is 8.8 + * driven through handling X events. In contrast to other X clients, a window 8.9 + * manager selects for SubstructureRedirectMask on the root window, to receive 8.10 + * events about window (dis-)appearance. Only one X connection at a time is 8.11 + * allowed to select for this event mask. 8.12 + * 8.13 + * Calls to fetch an X event from the event queue are blocking. Due reading 8.14 + * status text from standard input, a select()-driven main loop has been 8.15 + * implemented which selects for reads on the X connection and STDIN_FILENO to 8.16 + * handle all data smoothly. The event handlers of dwm are organized in an 8.17 + * array which is accessed whenever a new event has been fetched. This allows 8.18 + * event dispatching in O(1) time. 8.19 + * 8.20 + * Each child of the root window is called a client, except windows which have 8.21 + * set the override_redirect flag. Clients are organized in a global 8.22 + * doubly-linked client list, the focus history is remembered through a global 8.23 + * stack list. Each client contains an array of Bools of the same size as the 8.24 + * global tags array to indicate the tags of a client. For each client dwm 8.25 + * creates a small title window, which is resized whenever the (_NET_)WM_NAME 8.26 + * properties are updated or the client is moved/resized. 8.27 + * 8.28 + * Keys and tagging rules are organized as arrays and defined in the config.h 8.29 + * file. These arrays are kept static in event.o and tag.o respectively, 8.30 + * because no other part of dwm needs access to them. The current mode is 8.31 + * represented by the arrange() function pointer, which wether points to 8.32 + * dofloat() or dotile(). 8.33 + * 8.34 + * To understand everything else, start reading main.c:main(). 8.35 + */ 8.36 + 8.37 +#include "config.h" 8.38 +#include <errno.h> 8.39 +#include <locale.h> 8.40 +#include <regex.h> 8.41 +#include <stdio.h> 8.42 +#include <stdarg.h> 8.43 +#include <stdlib.h> 8.44 +#include <string.h> 8.45 +#include <unistd.h> 8.46 +#include <sys/select.h> 8.47 +#include <sys/types.h> 8.48 +#include <sys/wait.h> 8.49 +#include <X11/cursorfont.h> 8.50 +#include <X11/keysym.h> 8.51 +#include <X11/Xatom.h> 8.52 +#include <X11/Xlib.h> 8.53 +#include <X11/Xproto.h> 8.54 +#include <X11/Xutil.h> 8.55 + 8.56 +/* mask shorthands, used in event.c and client.c */ 8.57 +#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) 8.58 + 8.59 +enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ 8.60 +enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ 8.61 +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 8.62 +enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ 8.63 + 8.64 +typedef union { 8.65 + const char *cmd; 8.66 + int i; 8.67 +} Arg; /* argument type */ 8.68 + 8.69 +typedef struct { 8.70 + int ascent; 8.71 + int descent; 8.72 + int height; 8.73 + XFontSet set; 8.74 + XFontStruct *xfont; 8.75 +} Fnt; 8.76 + 8.77 +typedef struct { 8.78 + int x, y, w, h; 8.79 + unsigned long norm[ColLast]; 8.80 + unsigned long sel[ColLast]; 8.81 + Drawable drawable; 8.82 + Fnt font; 8.83 + GC gc; 8.84 +} DC; /* draw context */ 8.85 + 8.86 +typedef struct Client Client; 8.87 +struct Client { 8.88 + char name[256]; 8.89 + int x, y, w, h; 8.90 + int rx, ry, rw, rh; /* revert geometry */ 8.91 + int basew, baseh, incw, inch, maxw, maxh, minw, minh; 8.92 + int minax, minay, maxax, maxay; 8.93 + long flags; 8.94 + unsigned int border; 8.95 + Bool isfixed, isfloat, ismax; 8.96 + Bool *tags; 8.97 + Client *next; 8.98 + Client *prev; 8.99 + Client *snext; 8.100 + Window win; 8.101 +}; 8.102 + 8.103 +typedef struct { 8.104 + const char *clpattern; 8.105 + const char *tpattern; 8.106 + Bool isfloat; 8.107 +} Rule; 8.108 + 8.109 +typedef struct { 8.110 + regex_t *clregex; 8.111 + regex_t *tregex; 8.112 +} RReg; 8.113 + 8.114 + 8.115 +typedef struct { 8.116 + unsigned long mod; 8.117 + KeySym keysym; 8.118 + void (*func)(Arg *arg); 8.119 + Arg arg; 8.120 +} Key; 8.121 + 8.122 + 8.123 +#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) 8.124 +#define MOUSEMASK (BUTTONMASK | PointerMotionMask) 8.125 + 8.126 + 8.127 + 8.128 +const char *tags[]; /* all tags */ 8.129 +char stext[256]; /* status text */ 8.130 +int bh, bmw; /* bar height, bar mode label width */ 8.131 +int screen, sx, sy, sw, sh; /* screen geometry */ 8.132 +int wax, way, wah, waw; /* windowarea geometry */ 8.133 +unsigned int nmaster; /* number of master clients */ 8.134 +unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */ 8.135 +void (*handler[LASTEvent])(XEvent *); /* event handler */ 8.136 +void (*arrange)(void); /* arrange function, indicates mode */ 8.137 +Atom wmatom[WMLast], netatom[NetLast]; 8.138 +Bool running, selscreen, *seltag; /* seltag is array of Bool */ 8.139 +Client *clients, *sel, *stack; /* global client list and stack */ 8.140 +Cursor cursor[CurLast]; 8.141 +DC dc; /* global draw context */ 8.142 +Display *dpy; 8.143 +Window root, barwin; 8.144 + 8.145 +Bool running = True; 8.146 +Bool selscreen = True; 8.147 +Client *clients = NULL; 8.148 +Client *sel = NULL; 8.149 +Client *stack = NULL; 8.150 +DC dc = {0}; 8.151 + 8.152 +static int (*xerrorxlib)(Display *, XErrorEvent *); 8.153 +static Bool otherwm, readin; 8.154 +static RReg *rreg = NULL; 8.155 +static unsigned int len = 0; 8.156 + 8.157 + 8.158 +TAGS 8.159 +RULES 8.160 + 8.161 + 8.162 +/* client.c */ 8.163 +void configure(Client *c); /* send synthetic configure event */ 8.164 +void focus(Client *c); /* focus c, c may be NULL */ 8.165 +Client *getclient(Window w); /* return client of w */ 8.166 +Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */ 8.167 +void killclient(Arg *arg); /* kill c nicely */ 8.168 +void manage(Window w, XWindowAttributes *wa); /* manage new client */ 8.169 +void resize(Client *c, Bool sizehints); /* resize c*/ 8.170 +void updatesizehints(Client *c); /* update the size hint variables of c */ 8.171 +void updatetitle(Client *c); /* update the name of c */ 8.172 +void unmanage(Client *c); /* destroy c */ 8.173 + 8.174 +/* draw.c */ 8.175 +void drawstatus(void); /* draw the bar */ 8.176 +unsigned long getcolor(const char *colstr); /* return color of colstr */ 8.177 +void setfont(const char *fontstr); /* set the font for DC */ 8.178 +unsigned int textw(const char *text); /* return the width of text in px*/ 8.179 + 8.180 +/* event.c */ 8.181 +void grabkeys(void); /* grab all keys defined in config.h */ 8.182 +void procevent(void); /* process pending X events */ 8.183 + 8.184 +/* main.c */ 8.185 +void quit(Arg *arg); /* quit dwm nicely */ 8.186 +void sendevent(Window w, Atom a, long value); /* send synthetic event to w */ 8.187 +int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ 8.188 + 8.189 +/* tag.c */ 8.190 +void initrregs(void); /* initialize regexps of rules defined in config.h */ 8.191 +Client *getnext(Client *c); /* returns next visible client */ 8.192 +Client *getprev(Client *c); /* returns previous visible client */ 8.193 +void settags(Client *c, Client *trans); /* sets tags of c */ 8.194 +void tag(Arg *arg); /* tags c with arg's index */ 8.195 +void toggletag(Arg *arg); /* toggles c tags with arg's index */ 8.196 +void viewnext(Arg *arg); /* view next tag(s) */ 8.197 + 8.198 +/* util.c */ 8.199 +void *emallocz(unsigned int size); /* allocates zero-initialized memory, exits on error */ 8.200 +void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */ 8.201 +void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */ 8.202 + 8.203 +/* view.c */ 8.204 +void detach(Client *c); /* detaches c from global client list */ 8.205 +void dofloat(void); /* arranges all windows floating */ 8.206 +void dotile(void); /* arranges all windows tiled */ 8.207 +void domax(void); /* arranges all windows fullscreen */ 8.208 +void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */ 8.209 +void incnmaster(Arg *arg); /* increments nmaster with arg's index value */ 8.210 +Bool isvisible(Client *c); /* returns True if client is visible */ 8.211 +void restack(void); /* restores z layers of all clients */ 8.212 +void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */ 8.213 +void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */ 8.214 +void view(Arg *arg); /* views the tag with arg's index */ 8.215 +void zoom(Arg *arg); /* zooms the focused client to master area, arg is ignored */ 8.216 + 8.217 + 8.218 + 8.219 + 8.220 + 8.221 + 8.222 + 8.223 + 8.224 + 8.225 + 8.226 +/* from view.c */ 8.227 +/* static */ 8.228 + 8.229 +static Client * 8.230 +nexttiled(Client *c) { 8.231 + for(c = getnext(c); c && c->isfloat; c = getnext(c->next)); 8.232 + return c; 8.233 +} 8.234 + 8.235 +static void 8.236 +togglemax(Client *c) { 8.237 + XEvent ev; 8.238 + 8.239 + if(c->isfixed) 8.240 + return; 8.241 + 8.242 + if((c->ismax = !c->ismax)) { 8.243 + c->rx = c->x; c->x = wax; 8.244 + c->ry = c->y; c->y = way; 8.245 + c->rw = c->w; c->w = waw - 2 * BORDERPX; 8.246 + c->rh = c->h; c->h = wah - 2 * BORDERPX; 8.247 + } 8.248 + else { 8.249 + c->x = c->rx; 8.250 + c->y = c->ry; 8.251 + c->w = c->rw; 8.252 + c->h = c->rh; 8.253 + } 8.254 + resize(c, True); 8.255 + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 8.256 +} 8.257 + 8.258 + 8.259 + 8.260 +void (*arrange)(void) = DEFMODE; 8.261 + 8.262 +void 8.263 +detach(Client *c) { 8.264 + if(c->prev) 8.265 + c->prev->next = c->next; 8.266 + if(c->next) 8.267 + c->next->prev = c->prev; 8.268 + if(c == clients) 8.269 + clients = c->next; 8.270 + c->next = c->prev = NULL; 8.271 +} 8.272 + 8.273 +void 8.274 +dofloat(void) { 8.275 + Client *c; 8.276 + 8.277 + for(c = clients; c; c = c->next) { 8.278 + if(isvisible(c)) { 8.279 + resize(c, True); 8.280 + } 8.281 + else 8.282 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.283 + } 8.284 + if(!sel || !isvisible(sel)) { 8.285 + for(c = stack; c && !isvisible(c); c = c->snext); 8.286 + focus(c); 8.287 + } 8.288 + restack(); 8.289 +} 8.290 + 8.291 +void 8.292 +dotile(void) { 8.293 + unsigned int i, n, mw, mh, tw, th; 8.294 + Client *c; 8.295 + 8.296 + for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) 8.297 + n++; 8.298 + /* window geoms */ 8.299 + mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1); 8.300 + mw = (n > nmaster) ? waw / 2 : waw; 8.301 + th = (n > nmaster) ? wah / (n - nmaster) : 0; 8.302 + tw = waw - mw; 8.303 + 8.304 + for(i = 0, c = clients; c; c = c->next) 8.305 + if(isvisible(c)) { 8.306 + if(c->isfloat) { 8.307 + resize(c, True); 8.308 + continue; 8.309 + } 8.310 + c->ismax = False; 8.311 + c->x = wax; 8.312 + c->y = way; 8.313 + if(i < nmaster) { 8.314 + c->y += i * mh; 8.315 + c->w = mw - 2 * BORDERPX; 8.316 + c->h = mh - 2 * BORDERPX; 8.317 + } 8.318 + else { /* tile window */ 8.319 + c->x += mw; 8.320 + c->w = tw - 2 * BORDERPX; 8.321 + if(th > 2 * BORDERPX) { 8.322 + c->y += (i - nmaster) * th; 8.323 + c->h = th - 2 * BORDERPX; 8.324 + } 8.325 + else /* fallback if th <= 2 * BORDERPX */ 8.326 + c->h = wah - 2 * BORDERPX; 8.327 + } 8.328 + resize(c, False); 8.329 + i++; 8.330 + } 8.331 + else 8.332 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.333 + if(!sel || !isvisible(sel)) { 8.334 + for(c = stack; c && !isvisible(c); c = c->snext); 8.335 + focus(c); 8.336 + } 8.337 + restack(); 8.338 +} 8.339 + 8.340 +/* begin code by mitch */ 8.341 +void 8.342 +arrangemax(Client *c) { 8.343 + if(c == sel) { 8.344 + c->ismax = True; 8.345 + c->x = sx; 8.346 + c->y = bh; 8.347 + c->w = sw - 2 * BORDERPX; 8.348 + c->h = sh - bh - 2 * BORDERPX; 8.349 + XRaiseWindow(dpy, c->win); 8.350 + } else { 8.351 + c->ismax = False; 8.352 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.353 + XLowerWindow(dpy, c->win); 8.354 + } 8.355 +} 8.356 + 8.357 +void 8.358 +domax(void) { 8.359 + Client *c; 8.360 + 8.361 + for(c = clients; c; c = c->next) { 8.362 + if(isvisible(c)) { 8.363 + if(c->isfloat) { 8.364 + resize(c, True); 8.365 + continue; 8.366 + } 8.367 + arrangemax(c); 8.368 + resize(c, False); 8.369 + } else { 8.370 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.371 + } 8.372 + 8.373 + } 8.374 + if(!sel || !isvisible(sel)) { 8.375 + for(c = stack; c && !isvisible(c); c = c->snext); 8.376 + focus(c); 8.377 + } 8.378 + restack(); 8.379 +} 8.380 +/* end code by mitch */ 8.381 + 8.382 +void 8.383 +focusnext(Arg *arg) { 8.384 + Client *c; 8.385 + 8.386 + if(!sel) 8.387 + return; 8.388 + if(!(c = getnext(sel->next))) 8.389 + c = getnext(clients); 8.390 + if(c) { 8.391 + focus(c); 8.392 + restack(); 8.393 + } 8.394 +} 8.395 + 8.396 +void 8.397 +incnmaster(Arg *arg) { 8.398 + if((arrange == dofloat) || (nmaster + arg->i < 1) 8.399 + || (wah / (nmaster + arg->i) <= 2 * BORDERPX)) 8.400 + return; 8.401 + nmaster += arg->i; 8.402 + if(sel) 8.403 + arrange(); 8.404 + else 8.405 + drawstatus(); 8.406 +} 8.407 + 8.408 +Bool 8.409 +isvisible(Client *c) { 8.410 + unsigned int i; 8.411 + 8.412 + for(i = 0; i < ntags; i++) 8.413 + if(c->tags[i] && seltag[i]) 8.414 + return True; 8.415 + return False; 8.416 +} 8.417 + 8.418 +void 8.419 +restack(void) { 8.420 + Client *c; 8.421 + XEvent ev; 8.422 + 8.423 + drawstatus(); 8.424 + if(!sel) 8.425 + return; 8.426 + if(sel->isfloat || arrange == dofloat) 8.427 + XRaiseWindow(dpy, sel->win); 8.428 + 8.429 + /* begin code by mitch */ 8.430 + if(arrange == domax) { 8.431 + for(c = nexttiled(clients); c; c = nexttiled(c->next)) { 8.432 + arrangemax(c); 8.433 + resize(c, False); 8.434 + } 8.435 + 8.436 + } else if (arrange == dotile) { 8.437 + /* end code by mitch */ 8.438 + 8.439 + if(!sel->isfloat) 8.440 + XLowerWindow(dpy, sel->win); 8.441 + for(c = nexttiled(clients); c; c = nexttiled(c->next)) { 8.442 + if(c == sel) 8.443 + continue; 8.444 + XLowerWindow(dpy, c->win); 8.445 + } 8.446 + } 8.447 + XSync(dpy, False); 8.448 + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 8.449 +} 8.450 + 8.451 +void 8.452 +togglefloat(Arg *arg) { 8.453 + if (!sel || arrange == dofloat) 8.454 + return; 8.455 + sel->isfloat = !sel->isfloat; 8.456 + arrange(); 8.457 +} 8.458 + 8.459 +void 8.460 +togglemode(Arg *arg) { 8.461 + /* only toggle between tile and max - float is just available through togglefloat */ 8.462 + arrange = (arrange == dotile) ? domax : dotile; 8.463 + if(sel) 8.464 + arrange(); 8.465 + else 8.466 + drawstatus(); 8.467 +} 8.468 + 8.469 +void 8.470 +view(Arg *arg) { 8.471 + unsigned int i; 8.472 + 8.473 + for(i = 0; i < ntags; i++) 8.474 + seltag[i] = (arg->i == -1) ? True : False; 8.475 + if(arg->i >= 0 && arg->i < ntags) 8.476 + seltag[arg->i] = True; 8.477 + arrange(); 8.478 +} 8.479 + 8.480 +void 8.481 +zoom(Arg *arg) { 8.482 + unsigned int n; 8.483 + Client *c; 8.484 + 8.485 + if(!sel) 8.486 + return; 8.487 + if(sel->isfloat || (arrange == dofloat)) { 8.488 + togglemax(sel); 8.489 + return; 8.490 + } 8.491 + for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) 8.492 + n++; 8.493 + 8.494 + if((c = sel) == nexttiled(clients)) 8.495 + if(!(c = nexttiled(c->next))) 8.496 + return; 8.497 + detach(c); 8.498 + if(clients) 8.499 + clients->prev = c; 8.500 + c->next = clients; 8.501 + clients = c; 8.502 + focus(c); 8.503 + arrange(); 8.504 +} 8.505 + 8.506 + 8.507 + 8.508 + 8.509 + 8.510 + 8.511 + 8.512 + 8.513 + 8.514 + 8.515 + 8.516 + 8.517 + 8.518 + 8.519 + 8.520 + 8.521 +/* from util.c */ 8.522 + 8.523 + 8.524 +void * 8.525 +emallocz(unsigned int size) { 8.526 + void *res = calloc(1, size); 8.527 + 8.528 + if(!res) 8.529 + eprint("fatal: could not malloc() %u bytes\n", size); 8.530 + return res; 8.531 +} 8.532 + 8.533 +void 8.534 +eprint(const char *errstr, ...) { 8.535 + va_list ap; 8.536 + 8.537 + va_start(ap, errstr); 8.538 + vfprintf(stderr, errstr, ap); 8.539 + va_end(ap); 8.540 + exit(EXIT_FAILURE); 8.541 +} 8.542 + 8.543 +void 8.544 +spawn(Arg *arg) { 8.545 + static char *shell = NULL; 8.546 + 8.547 + if(!shell && !(shell = getenv("SHELL"))) 8.548 + shell = "/bin/sh"; 8.549 + if(!arg->cmd) 8.550 + return; 8.551 + /* The double-fork construct avoids zombie processes and keeps the code 8.552 + * clean from stupid signal handlers. */ 8.553 + if(fork() == 0) { 8.554 + if(fork() == 0) { 8.555 + if(dpy) 8.556 + close(ConnectionNumber(dpy)); 8.557 + setsid(); 8.558 + execl(shell, shell, "-c", arg->cmd, (char *)NULL); 8.559 + fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd); 8.560 + perror(" failed"); 8.561 + } 8.562 + exit(0); 8.563 + } 8.564 + wait(0); 8.565 +} 8.566 + 8.567 + 8.568 + 8.569 + 8.570 + 8.571 + 8.572 + 8.573 + 8.574 + 8.575 + 8.576 + 8.577 + 8.578 + 8.579 +/* from tag.c */ 8.580 + 8.581 +/* static */ 8.582 + 8.583 +Client * 8.584 +getnext(Client *c) { 8.585 + for(; c && !isvisible(c); c = c->next); 8.586 + return c; 8.587 +} 8.588 + 8.589 +Client * 8.590 +getprev(Client *c) { 8.591 + for(; c && !isvisible(c); c = c->prev); 8.592 + return c; 8.593 +} 8.594 + 8.595 +void 8.596 +initrregs(void) { 8.597 + unsigned int i; 8.598 + regex_t *reg; 8.599 + 8.600 + if(rreg) 8.601 + return; 8.602 + len = sizeof rule / sizeof rule[0]; 8.603 + rreg = emallocz(len * sizeof(RReg)); 8.604 + for(i = 0; i < len; i++) { 8.605 + if(rule[i].clpattern) { 8.606 + reg = emallocz(sizeof(regex_t)); 8.607 + if(regcomp(reg, rule[i].clpattern, REG_EXTENDED)) 8.608 + free(reg); 8.609 + else 8.610 + rreg[i].clregex = reg; 8.611 + } 8.612 + if(rule[i].tpattern) { 8.613 + reg = emallocz(sizeof(regex_t)); 8.614 + if(regcomp(reg, rule[i].tpattern, REG_EXTENDED)) 8.615 + free(reg); 8.616 + else 8.617 + rreg[i].tregex = reg; 8.618 + } 8.619 + } 8.620 +} 8.621 + 8.622 +void 8.623 +settags(Client *c, Client *trans) { 8.624 + char prop[512]; 8.625 + unsigned int i, j; 8.626 + regmatch_t tmp; 8.627 + Bool matched = trans != NULL; 8.628 + XClassHint ch = { 0 }; 8.629 + 8.630 + if(matched) { 8.631 + for(i = 0; i < ntags; i++) 8.632 + c->tags[i] = trans->tags[i]; 8.633 + } 8.634 + else { 8.635 + XGetClassHint(dpy, c->win, &ch); 8.636 + snprintf(prop, sizeof prop, "%s:%s:%s", 8.637 + ch.res_class ? ch.res_class : "", 8.638 + ch.res_name ? ch.res_name : "", c->name); 8.639 + for(i = 0; i < len; i++) 8.640 + if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) { 8.641 + c->isfloat = rule[i].isfloat; 8.642 + for(j = 0; rreg[i].tregex && j < ntags; j++) { 8.643 + if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) { 8.644 + matched = True; 8.645 + c->tags[j] = True; 8.646 + } 8.647 + } 8.648 + break; /* perform only the first rule matching */ 8.649 + } 8.650 + if(ch.res_class) 8.651 + XFree(ch.res_class); 8.652 + if(ch.res_name) 8.653 + XFree(ch.res_name); 8.654 + } 8.655 + if(!matched) 8.656 + for(i = 0; i < ntags; i++) 8.657 + c->tags[i] = seltag[i]; 8.658 +} 8.659 + 8.660 +void 8.661 +tag(Arg *arg) { 8.662 + unsigned int i; 8.663 + 8.664 + if(!sel) 8.665 + return; 8.666 + for(i = 0; i < ntags; i++) 8.667 + sel->tags[i] = (arg->i == -1) ? True : False; 8.668 + if(arg->i >= 0 && arg->i < ntags) 8.669 + sel->tags[arg->i] = True; 8.670 + arrange(); 8.671 +} 8.672 + 8.673 +void 8.674 +toggletag(Arg *arg) { 8.675 + unsigned int i; 8.676 + 8.677 + if(!sel) 8.678 + return; 8.679 + sel->tags[arg->i] = !sel->tags[arg->i]; 8.680 + for(i = 0; i < ntags && !sel->tags[i]; i++); 8.681 + if(i == ntags) 8.682 + sel->tags[arg->i] = True; 8.683 + arrange(); 8.684 +} 8.685 + 8.686 +/* begin code by jukka */ 8.687 +void 8.688 +viewnext(Arg *arg) { 8.689 + unsigned int i; 8.690 + Bool last = seltag[ntags-1]; 8.691 + 8.692 + for (i=ntags-1; i>0; --i) 8.693 + seltag[i] = seltag[i-1]; 8.694 + seltag[0] = last; 8.695 + arrange(); 8.696 +} 8.697 +/* end code by jukka */ 8.698 + 8.699 + 8.700 + 8.701 + 8.702 + 8.703 + 8.704 + 8.705 + 8.706 + 8.707 + 8.708 + 8.709 + 8.710 + 8.711 + 8.712 + 8.713 + 8.714 +/* from event.c */ 8.715 +/* static */ 8.716 + 8.717 +KEYS 8.718 + 8.719 + 8.720 + 8.721 +static void 8.722 +movemouse(Client *c) { 8.723 + int x1, y1, ocx, ocy, di; 8.724 + unsigned int dui; 8.725 + Window dummy; 8.726 + XEvent ev; 8.727 + 8.728 + ocx = c->x; 8.729 + ocy = c->y; 8.730 + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 8.731 + None, cursor[CurMove], CurrentTime) != GrabSuccess) 8.732 + return; 8.733 + c->ismax = False; 8.734 + XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); 8.735 + for(;;) { 8.736 + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); 8.737 + switch (ev.type) { 8.738 + case ButtonRelease: 8.739 + resize(c, True); 8.740 + XUngrabPointer(dpy, CurrentTime); 8.741 + return; 8.742 + case ConfigureRequest: 8.743 + case Expose: 8.744 + case MapRequest: 8.745 + handler[ev.type](&ev); 8.746 + break; 8.747 + case MotionNotify: 8.748 + XSync(dpy, False); 8.749 + c->x = ocx + (ev.xmotion.x - x1); 8.750 + c->y = ocy + (ev.xmotion.y - y1); 8.751 + if(abs(wax + c->x) < SNAP) 8.752 + c->x = wax; 8.753 + else if(abs((wax + waw) - (c->x + c->w + 2 * c->border)) < SNAP) 8.754 + c->x = wax + waw - c->w - 2 * c->border; 8.755 + if(abs(way - c->y) < SNAP) 8.756 + c->y = way; 8.757 + else if(abs((way + wah) - (c->y + c->h + 2 * c->border)) < SNAP) 8.758 + c->y = way + wah - c->h - 2 * c->border; 8.759 + resize(c, False); 8.760 + break; 8.761 + } 8.762 + } 8.763 +} 8.764 + 8.765 +static void 8.766 +resizemouse(Client *c) { 8.767 + int ocx, ocy; 8.768 + int nw, nh; 8.769 + XEvent ev; 8.770 + 8.771 + ocx = c->x; 8.772 + ocy = c->y; 8.773 + if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 8.774 + None, cursor[CurResize], CurrentTime) != GrabSuccess) 8.775 + return; 8.776 + c->ismax = False; 8.777 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); 8.778 + for(;;) { 8.779 + XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); 8.780 + switch(ev.type) { 8.781 + case ButtonRelease: 8.782 + resize(c, True); 8.783 + XUngrabPointer(dpy, CurrentTime); 8.784 + return; 8.785 + case ConfigureRequest: 8.786 + case Expose: 8.787 + case MapRequest: 8.788 + handler[ev.type](&ev); 8.789 + break; 8.790 + case MotionNotify: 8.791 + XSync(dpy, False); 8.792 + nw = ev.xmotion.x - ocx - 2 * c->border + 1; 8.793 + c->w = nw > 0 ? nw : 1; 8.794 + nh = ev.xmotion.y - ocy - 2 * c->border + 1; 8.795 + c->h = nh > 0 ? nh : 1; 8.796 + resize(c, True); 8.797 + break; 8.798 + } 8.799 + } 8.800 +} 8.801 + 8.802 +static void 8.803 +buttonpress(XEvent *e) { 8.804 + int x; 8.805 + Arg a; 8.806 + Client *c; 8.807 + XButtonPressedEvent *ev = &e->xbutton; 8.808 + 8.809 + if(barwin == ev->window) { 8.810 + x = 0; 8.811 + for(a.i = 0; a.i < ntags; a.i++) { 8.812 + x += textw(tags[a.i]); 8.813 + if(ev->x < x) { 8.814 + if(ev->button == Button1) { 8.815 + view(&a); 8.816 + } 8.817 + return; 8.818 + } 8.819 + } 8.820 + if(ev->x < x + bmw) 8.821 + if (ev->button == Button1) { 8.822 + togglemode(NULL); 8.823 + } 8.824 + } 8.825 + else if((c = getclient(ev->window))) { 8.826 + focus(c); 8.827 + if(CLEANMASK(ev->state) != MODKEY) 8.828 + return; 8.829 + if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) { 8.830 + restack(); 8.831 + movemouse(c); 8.832 + } 8.833 + else if(ev->button == Button2) 8.834 + zoom(NULL); 8.835 + else if(ev->button == Button3 && (arrange == dofloat || c->isfloat) && 8.836 + !c->isfixed) { 8.837 + restack(); 8.838 + resizemouse(c); 8.839 + } 8.840 + } 8.841 +} 8.842 + 8.843 +static void 8.844 +configurerequest(XEvent *e) { 8.845 + unsigned long newmask; 8.846 + Client *c; 8.847 + XConfigureRequestEvent *ev = &e->xconfigurerequest; 8.848 + XWindowChanges wc; 8.849 + 8.850 + if((c = getclient(ev->window))) { 8.851 + c->ismax = False; 8.852 + if(ev->value_mask & CWX) 8.853 + c->x = ev->x; 8.854 + if(ev->value_mask & CWY) 8.855 + c->y = ev->y; 8.856 + if(ev->value_mask & CWWidth) 8.857 + c->w = ev->width; 8.858 + if(ev->value_mask & CWHeight) 8.859 + c->h = ev->height; 8.860 + if(ev->value_mask & CWBorderWidth) 8.861 + c->border = ev->border_width; 8.862 + wc.x = c->x; 8.863 + wc.y = c->y; 8.864 + wc.width = c->w; 8.865 + wc.height = c->h; 8.866 + newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth)); 8.867 + if(newmask) 8.868 + XConfigureWindow(dpy, c->win, newmask, &wc); 8.869 + else 8.870 + configure(c); 8.871 + XSync(dpy, False); 8.872 + if(c->isfloat) { 8.873 + resize(c, False); 8.874 + if(!isvisible(c)) 8.875 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.876 + } 8.877 + else 8.878 + arrange(); 8.879 + } 8.880 + else { 8.881 + wc.x = ev->x; 8.882 + wc.y = ev->y; 8.883 + wc.width = ev->width; 8.884 + wc.height = ev->height; 8.885 + wc.border_width = ev->border_width; 8.886 + wc.sibling = ev->above; 8.887 + wc.stack_mode = ev->detail; 8.888 + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); 8.889 + XSync(dpy, False); 8.890 + } 8.891 +} 8.892 + 8.893 +static void 8.894 +destroynotify(XEvent *e) { 8.895 + Client *c; 8.896 + XDestroyWindowEvent *ev = &e->xdestroywindow; 8.897 + 8.898 + if((c = getclient(ev->window))) 8.899 + unmanage(c); 8.900 +} 8.901 + 8.902 +static void 8.903 +enternotify(XEvent *e) { 8.904 + Client *c; 8.905 + XCrossingEvent *ev = &e->xcrossing; 8.906 + 8.907 + if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) 8.908 + return; 8.909 + if((c = getclient(ev->window)) && isvisible(c)) 8.910 + focus(c); 8.911 + else if(ev->window == root) { 8.912 + selscreen = True; 8.913 + for(c = stack; c && !isvisible(c); c = c->snext); 8.914 + focus(c); 8.915 + } 8.916 +} 8.917 + 8.918 +static void 8.919 +expose(XEvent *e) { 8.920 + XExposeEvent *ev = &e->xexpose; 8.921 + 8.922 + if(ev->count == 0) { 8.923 + if(barwin == ev->window) 8.924 + drawstatus(); 8.925 + } 8.926 +} 8.927 + 8.928 +static void 8.929 +keypress(XEvent *e) { 8.930 + static unsigned int len = sizeof key / sizeof key[0]; 8.931 + unsigned int i; 8.932 + KeySym keysym; 8.933 + XKeyEvent *ev = &e->xkey; 8.934 + 8.935 + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); 8.936 + for(i = 0; i < len; i++) { 8.937 + if(keysym == key[i].keysym 8.938 + && CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) 8.939 + { 8.940 + if(key[i].func) 8.941 + key[i].func(&key[i].arg); 8.942 + } 8.943 + } 8.944 +} 8.945 + 8.946 +static void 8.947 +leavenotify(XEvent *e) { 8.948 + XCrossingEvent *ev = &e->xcrossing; 8.949 + 8.950 + if((ev->window == root) && !ev->same_screen) { 8.951 + selscreen = False; 8.952 + focus(NULL); 8.953 + } 8.954 +} 8.955 + 8.956 +static void 8.957 +mappingnotify(XEvent *e) { 8.958 + XMappingEvent *ev = &e->xmapping; 8.959 + 8.960 + XRefreshKeyboardMapping(ev); 8.961 + if(ev->request == MappingKeyboard) 8.962 + grabkeys(); 8.963 +} 8.964 + 8.965 +static void 8.966 +maprequest(XEvent *e) { 8.967 + static XWindowAttributes wa; 8.968 + XMapRequestEvent *ev = &e->xmaprequest; 8.969 + 8.970 + if(!XGetWindowAttributes(dpy, ev->window, &wa)) 8.971 + return; 8.972 + if(wa.override_redirect) { 8.973 + XSelectInput(dpy, ev->window, 8.974 + (StructureNotifyMask | PropertyChangeMask)); 8.975 + return; 8.976 + } 8.977 + if(!getclient(ev->window)) 8.978 + manage(ev->window, &wa); 8.979 +} 8.980 + 8.981 +static void 8.982 +propertynotify(XEvent *e) { 8.983 + Client *c; 8.984 + Window trans; 8.985 + XPropertyEvent *ev = &e->xproperty; 8.986 + 8.987 + if(ev->state == PropertyDelete) 8.988 + return; /* ignore */ 8.989 + if((c = getclient(ev->window))) { 8.990 + switch (ev->atom) { 8.991 + default: break; 8.992 + case XA_WM_TRANSIENT_FOR: 8.993 + XGetTransientForHint(dpy, c->win, &trans); 8.994 + if(!c->isfloat && (c->isfloat = (trans != 0))) 8.995 + arrange(); 8.996 + break; 8.997 + case XA_WM_NORMAL_HINTS: 8.998 + updatesizehints(c); 8.999 + break; 8.1000 + } 8.1001 + if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { 8.1002 + updatetitle(c); 8.1003 + if(c == sel) 8.1004 + drawstatus(); 8.1005 + } 8.1006 + } 8.1007 +} 8.1008 + 8.1009 +static void 8.1010 +unmapnotify(XEvent *e) { 8.1011 + Client *c; 8.1012 + XUnmapEvent *ev = &e->xunmap; 8.1013 + 8.1014 + if((c = getclient(ev->window))) 8.1015 + unmanage(c); 8.1016 +} 8.1017 + 8.1018 + 8.1019 + 8.1020 +void (*handler[LASTEvent]) (XEvent *) = { 8.1021 + [ButtonPress] = buttonpress, 8.1022 + [ConfigureRequest] = configurerequest, 8.1023 + [DestroyNotify] = destroynotify, 8.1024 + [EnterNotify] = enternotify, 8.1025 + [LeaveNotify] = leavenotify, 8.1026 + [Expose] = expose, 8.1027 + [KeyPress] = keypress, 8.1028 + [MappingNotify] = mappingnotify, 8.1029 + [MapRequest] = maprequest, 8.1030 + [PropertyNotify] = propertynotify, 8.1031 + [UnmapNotify] = unmapnotify 8.1032 +}; 8.1033 + 8.1034 +void 8.1035 +grabkeys(void) { 8.1036 + static unsigned int len = sizeof key / sizeof key[0]; 8.1037 + unsigned int i; 8.1038 + KeyCode code; 8.1039 + 8.1040 + XUngrabKey(dpy, AnyKey, AnyModifier, root); 8.1041 + for(i = 0; i < len; i++) { 8.1042 + code = XKeysymToKeycode(dpy, key[i].keysym); 8.1043 + XGrabKey(dpy, code, key[i].mod, root, True, 8.1044 + GrabModeAsync, GrabModeAsync); 8.1045 + XGrabKey(dpy, code, key[i].mod | LockMask, root, True, 8.1046 + GrabModeAsync, GrabModeAsync); 8.1047 + XGrabKey(dpy, code, key[i].mod | numlockmask, root, True, 8.1048 + GrabModeAsync, GrabModeAsync); 8.1049 + XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True, 8.1050 + GrabModeAsync, GrabModeAsync); 8.1051 + } 8.1052 +} 8.1053 + 8.1054 +void 8.1055 +procevent(void) { 8.1056 + XEvent ev; 8.1057 + 8.1058 + while(XPending(dpy)) { 8.1059 + XNextEvent(dpy, &ev); 8.1060 + if(handler[ev.type]) 8.1061 + (handler[ev.type])(&ev); /* call handler */ 8.1062 + } 8.1063 +} 8.1064 + 8.1065 + 8.1066 + 8.1067 + 8.1068 + 8.1069 + 8.1070 + 8.1071 + 8.1072 + 8.1073 + 8.1074 + 8.1075 + 8.1076 + 8.1077 + 8.1078 + 8.1079 +/* from draw.c */ 8.1080 +/* static */ 8.1081 + 8.1082 +static unsigned int 8.1083 +textnw(const char *text, unsigned int len) { 8.1084 + XRectangle r; 8.1085 + 8.1086 + if(dc.font.set) { 8.1087 + XmbTextExtents(dc.font.set, text, len, NULL, &r); 8.1088 + return r.width; 8.1089 + } 8.1090 + return XTextWidth(dc.font.xfont, text, len); 8.1091 +} 8.1092 + 8.1093 +static void 8.1094 +drawtext(const char *text, unsigned long col[ColLast]) { 8.1095 + int x, y, w, h; 8.1096 + static char buf[256]; 8.1097 + unsigned int len, olen; 8.1098 + XGCValues gcv; 8.1099 + XRectangle r = { dc.x, dc.y, dc.w, dc.h }; 8.1100 + 8.1101 + XSetForeground(dpy, dc.gc, col[ColBG]); 8.1102 + XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); 8.1103 + if(!text) 8.1104 + return; 8.1105 + w = 0; 8.1106 + olen = len = strlen(text); 8.1107 + if(len >= sizeof buf) 8.1108 + len = sizeof buf - 1; 8.1109 + memcpy(buf, text, len); 8.1110 + buf[len] = 0; 8.1111 + h = dc.font.ascent + dc.font.descent; 8.1112 + y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; 8.1113 + x = dc.x + (h / 2); 8.1114 + /* shorten text if necessary */ 8.1115 + while(len && (w = textnw(buf, len)) > dc.w - h) 8.1116 + buf[--len] = 0; 8.1117 + if(len < olen) { 8.1118 + if(len > 1) 8.1119 + buf[len - 1] = '.'; 8.1120 + if(len > 2) 8.1121 + buf[len - 2] = '.'; 8.1122 + if(len > 3) 8.1123 + buf[len - 3] = '.'; 8.1124 + } 8.1125 + if(w > dc.w) 8.1126 + return; /* too long */ 8.1127 + gcv.foreground = col[ColFG]; 8.1128 + if(dc.font.set) { 8.1129 + XChangeGC(dpy, dc.gc, GCForeground, &gcv); 8.1130 + XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); 8.1131 + } else { 8.1132 + gcv.font = dc.font.xfont->fid; 8.1133 + XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv); 8.1134 + XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); 8.1135 + } 8.1136 +} 8.1137 + 8.1138 + 8.1139 + 8.1140 +void 8.1141 +drawstatus(void) { 8.1142 + int i, x; 8.1143 + 8.1144 + dc.x = dc.y = 0; 8.1145 + for(i = 0; i < ntags; i++) { 8.1146 + dc.w = textw(tags[i]); 8.1147 + drawtext(tags[i], (seltag[i] ? dc.sel : dc.norm)); 8.1148 + dc.x += dc.w + 1; 8.1149 + } 8.1150 + dc.w = bmw; 8.1151 + drawtext("", dc.norm); 8.1152 + x = dc.x + dc.w; 8.1153 + dc.w = textw(stext); 8.1154 + dc.x = sw - dc.w; 8.1155 + if(dc.x < x) { 8.1156 + dc.x = x; 8.1157 + dc.w = sw - x; 8.1158 + } 8.1159 + drawtext(stext, dc.norm); 8.1160 + if((dc.w = dc.x - x) > bh) { 8.1161 + dc.x = x; 8.1162 + drawtext(sel ? sel->name : NULL, dc.norm); 8.1163 + } 8.1164 + XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); 8.1165 + XSync(dpy, False); 8.1166 +} 8.1167 + 8.1168 +unsigned long 8.1169 +getcolor(const char *colstr) { 8.1170 + Colormap cmap = DefaultColormap(dpy, screen); 8.1171 + XColor color; 8.1172 + 8.1173 + if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) 8.1174 + eprint("error, cannot allocate color '%s'\n", colstr); 8.1175 + return color.pixel; 8.1176 +} 8.1177 + 8.1178 +void 8.1179 +setfont(const char *fontstr) { 8.1180 + char *def, **missing; 8.1181 + int i, n; 8.1182 + 8.1183 + missing = NULL; 8.1184 + if(dc.font.set) 8.1185 + XFreeFontSet(dpy, dc.font.set); 8.1186 + dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); 8.1187 + if(missing) { 8.1188 + while(n--) 8.1189 + fprintf(stderr, "missing fontset: %s\n", missing[n]); 8.1190 + XFreeStringList(missing); 8.1191 + } 8.1192 + if(dc.font.set) { 8.1193 + XFontSetExtents *font_extents; 8.1194 + XFontStruct **xfonts; 8.1195 + char **font_names; 8.1196 + dc.font.ascent = dc.font.descent = 0; 8.1197 + font_extents = XExtentsOfFontSet(dc.font.set); 8.1198 + n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); 8.1199 + for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { 8.1200 + if(dc.font.ascent < (*xfonts)->ascent) 8.1201 + dc.font.ascent = (*xfonts)->ascent; 8.1202 + if(dc.font.descent < (*xfonts)->descent) 8.1203 + dc.font.descent = (*xfonts)->descent; 8.1204 + xfonts++; 8.1205 + } 8.1206 + } else { 8.1207 + if(dc.font.xfont) 8.1208 + XFreeFont(dpy, dc.font.xfont); 8.1209 + dc.font.xfont = NULL; 8.1210 + if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))) 8.1211 + eprint("error, cannot load font: '%s'\n", fontstr); 8.1212 + dc.font.ascent = dc.font.xfont->ascent; 8.1213 + dc.font.descent = dc.font.xfont->descent; 8.1214 + } 8.1215 + dc.font.height = dc.font.ascent + dc.font.descent; 8.1216 +} 8.1217 + 8.1218 +unsigned int 8.1219 +textw(const char *text) { 8.1220 + return textnw(text, strlen(text)) + dc.font.height; 8.1221 +} 8.1222 + 8.1223 + 8.1224 + 8.1225 + 8.1226 + 8.1227 + 8.1228 + 8.1229 + 8.1230 + 8.1231 + 8.1232 + 8.1233 +/* from client.c */ 8.1234 +/* static */ 8.1235 + 8.1236 +static void 8.1237 +detachstack(Client *c) { 8.1238 + Client **tc; 8.1239 + for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); 8.1240 + *tc = c->snext; 8.1241 +} 8.1242 + 8.1243 +static void 8.1244 +grabbuttons(Client *c, Bool focused) { 8.1245 + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); 8.1246 + 8.1247 + if(focused) { 8.1248 + XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, 8.1249 + GrabModeAsync, GrabModeSync, None, None); 8.1250 + XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, 8.1251 + GrabModeAsync, GrabModeSync, None, None); 8.1252 + XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, 8.1253 + GrabModeAsync, GrabModeSync, None, None); 8.1254 + XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 8.1255 + GrabModeAsync, GrabModeSync, None, None); 8.1256 + 8.1257 + XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, 8.1258 + GrabModeAsync, GrabModeSync, None, None); 8.1259 + XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, 8.1260 + GrabModeAsync, GrabModeSync, None, None); 8.1261 + XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, 8.1262 + GrabModeAsync, GrabModeSync, None, None); 8.1263 + XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 8.1264 + GrabModeAsync, GrabModeSync, None, None); 8.1265 + 8.1266 + XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, 8.1267 + GrabModeAsync, GrabModeSync, None, None); 8.1268 + XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, 8.1269 + GrabModeAsync, GrabModeSync, None, None); 8.1270 + XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, 8.1271 + GrabModeAsync, GrabModeSync, None, None); 8.1272 + XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, 8.1273 + GrabModeAsync, GrabModeSync, None, None); 8.1274 + } else { 8.1275 + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, 8.1276 + GrabModeAsync, GrabModeSync, None, None); 8.1277 + } 8.1278 +} 8.1279 + 8.1280 +static void 8.1281 +setclientstate(Client *c, long state) { 8.1282 + long data[] = {state, None}; 8.1283 + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, 8.1284 + PropModeReplace, (unsigned char *)data, 2); 8.1285 +} 8.1286 + 8.1287 +static int 8.1288 +xerrordummy(Display *dsply, XErrorEvent *ee) { 8.1289 + return 0; 8.1290 +} 8.1291 + 8.1292 + 8.1293 + 8.1294 +void 8.1295 +configure(Client *c) { 8.1296 + XEvent synev; 8.1297 + 8.1298 + synev.type = ConfigureNotify; 8.1299 + synev.xconfigure.display = dpy; 8.1300 + synev.xconfigure.event = c->win; 8.1301 + synev.xconfigure.window = c->win; 8.1302 + synev.xconfigure.x = c->x; 8.1303 + synev.xconfigure.y = c->y; 8.1304 + synev.xconfigure.width = c->w; 8.1305 + synev.xconfigure.height = c->h; 8.1306 + synev.xconfigure.border_width = c->border; 8.1307 + synev.xconfigure.above = None; 8.1308 + XSendEvent(dpy, c->win, True, NoEventMask, &synev); 8.1309 +} 8.1310 + 8.1311 +void 8.1312 +focus(Client *c) { 8.1313 + if(c && !isvisible(c)) 8.1314 + return; 8.1315 + if(sel && sel != c) { 8.1316 + grabbuttons(sel, False); 8.1317 + XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); 8.1318 + } 8.1319 + if(c) { 8.1320 + detachstack(c); 8.1321 + c->snext = stack; 8.1322 + stack = c; 8.1323 + grabbuttons(c, True); 8.1324 + } 8.1325 + sel = c; 8.1326 + drawstatus(); 8.1327 + if(!selscreen) 8.1328 + return; 8.1329 + if(c) { 8.1330 + XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); 8.1331 + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); 8.1332 + } else { 8.1333 + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); 8.1334 + } 8.1335 +} 8.1336 + 8.1337 +Client * 8.1338 +getclient(Window w) { 8.1339 + Client *c; 8.1340 + 8.1341 + for(c = clients; c; c = c->next) { 8.1342 + if(c->win == w) { 8.1343 + return c; 8.1344 + } 8.1345 + } 8.1346 + return NULL; 8.1347 +} 8.1348 + 8.1349 +Bool 8.1350 +isprotodel(Client *c) { 8.1351 + int i, n; 8.1352 + Atom *protocols; 8.1353 + Bool ret = False; 8.1354 + 8.1355 + if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { 8.1356 + for(i = 0; !ret && i < n; i++) 8.1357 + if(protocols[i] == wmatom[WMDelete]) 8.1358 + ret = True; 8.1359 + XFree(protocols); 8.1360 + } 8.1361 + return ret; 8.1362 +} 8.1363 + 8.1364 +void 8.1365 +killclient(Arg *arg) { 8.1366 + if(!sel) 8.1367 + return; 8.1368 + if(isprotodel(sel)) 8.1369 + sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); 8.1370 + else 8.1371 + XKillClient(dpy, sel->win); 8.1372 +} 8.1373 + 8.1374 +void 8.1375 +manage(Window w, XWindowAttributes *wa) { 8.1376 + Client *c; 8.1377 + Window trans; 8.1378 + 8.1379 + c = emallocz(sizeof(Client)); 8.1380 + c->tags = emallocz(ntags * sizeof(Bool)); 8.1381 + c->win = w; 8.1382 + c->x = wa->x; 8.1383 + c->y = wa->y; 8.1384 + c->w = wa->width; 8.1385 + c->h = wa->height; 8.1386 + if(c->w == sw && c->h == sh) { 8.1387 + c->border = 0; 8.1388 + c->x = sx; 8.1389 + c->y = sy; 8.1390 + } else { 8.1391 + c->border = BORDERPX; 8.1392 + if(c->x + c->w + 2 * c->border > wax + waw) 8.1393 + c->x = wax + waw - c->w - 2 * c->border; 8.1394 + if(c->y + c->h + 2 * c->border > way + wah) 8.1395 + c->y = way + wah - c->h - 2 * c->border; 8.1396 + if(c->x < wax) 8.1397 + c->x = wax; 8.1398 + if(c->y < way) 8.1399 + c->y = way; 8.1400 + } 8.1401 + updatesizehints(c); 8.1402 + XSelectInput(dpy, c->win, 8.1403 + StructureNotifyMask | PropertyChangeMask | EnterWindowMask); 8.1404 + XGetTransientForHint(dpy, c->win, &trans); 8.1405 + grabbuttons(c, False); 8.1406 + XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); 8.1407 + updatetitle(c); 8.1408 + settags(c, getclient(trans)); 8.1409 + if(!c->isfloat) 8.1410 + c->isfloat = trans || c->isfixed; 8.1411 + if(clients) 8.1412 + clients->prev = c; 8.1413 + c->next = clients; 8.1414 + c->snext = stack; 8.1415 + stack = clients = c; 8.1416 + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 8.1417 + XMapWindow(dpy, c->win); 8.1418 + setclientstate(c, NormalState); 8.1419 + if(isvisible(c)) 8.1420 + focus(c); 8.1421 + arrange(); 8.1422 +} 8.1423 + 8.1424 +void 8.1425 +resize(Client *c, Bool sizehints) { 8.1426 + float actual, dx, dy, max, min; 8.1427 + XWindowChanges wc; 8.1428 + 8.1429 + if(c->w <= 0 || c->h <= 0) 8.1430 + return; 8.1431 + if(sizehints) { 8.1432 + if(c->minw && c->w < c->minw) 8.1433 + c->w = c->minw; 8.1434 + if(c->minh && c->h < c->minh) 8.1435 + c->h = c->minh; 8.1436 + if(c->maxw && c->w > c->maxw) 8.1437 + c->w = c->maxw; 8.1438 + if(c->maxh && c->h > c->maxh) 8.1439 + c->h = c->maxh; 8.1440 + /* inspired by algorithm from fluxbox */ 8.1441 + if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) { 8.1442 + dx = (float)(c->w - c->basew); 8.1443 + dy = (float)(c->h - c->baseh); 8.1444 + min = (float)(c->minax) / (float)(c->minay); 8.1445 + max = (float)(c->maxax) / (float)(c->maxay); 8.1446 + actual = dx / dy; 8.1447 + if(max > 0 && min > 0 && actual > 0) { 8.1448 + if(actual < min) { 8.1449 + dy = (dx * min + dy) / (min * min + 1); 8.1450 + dx = dy * min; 8.1451 + c->w = (int)dx + c->basew; 8.1452 + c->h = (int)dy + c->baseh; 8.1453 + } 8.1454 + else if(actual > max) { 8.1455 + dy = (dx * min + dy) / (max * max + 1); 8.1456 + dx = dy * min; 8.1457 + c->w = (int)dx + c->basew; 8.1458 + c->h = (int)dy + c->baseh; 8.1459 + } 8.1460 + } 8.1461 + } 8.1462 + if(c->incw) 8.1463 + c->w -= (c->w - c->basew) % c->incw; 8.1464 + if(c->inch) 8.1465 + c->h -= (c->h - c->baseh) % c->inch; 8.1466 + } 8.1467 + if(c->w == sw && c->h == sh) 8.1468 + c->border = 0; 8.1469 + else 8.1470 + c->border = BORDERPX; 8.1471 + /* offscreen appearance fixes */ 8.1472 + if(c->x > sw) 8.1473 + c->x = sw - c->w - 2 * c->border; 8.1474 + if(c->y > sh) 8.1475 + c->y = sh - c->h - 2 * c->border; 8.1476 + if(c->x + c->w + 2 * c->border < sx) 8.1477 + c->x = sx; 8.1478 + if(c->y + c->h + 2 * c->border < sy) 8.1479 + c->y = sy; 8.1480 + wc.x = c->x; 8.1481 + wc.y = c->y; 8.1482 + wc.width = c->w; 8.1483 + wc.height = c->h; 8.1484 + wc.border_width = c->border; 8.1485 + XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); 8.1486 + configure(c); 8.1487 + XSync(dpy, False); 8.1488 +} 8.1489 + 8.1490 +void 8.1491 +updatesizehints(Client *c) { 8.1492 + long msize; 8.1493 + XSizeHints size; 8.1494 + 8.1495 + if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) 8.1496 + size.flags = PSize; 8.1497 + c->flags = size.flags; 8.1498 + if(c->flags & PBaseSize) { 8.1499 + c->basew = size.base_width; 8.1500 + c->baseh = size.base_height; 8.1501 + } else { 8.1502 + c->basew = c->baseh = 0; 8.1503 + } 8.1504 + if(c->flags & PResizeInc) { 8.1505 + c->incw = size.width_inc; 8.1506 + c->inch = size.height_inc; 8.1507 + } else { 8.1508 + c->incw = c->inch = 0; 8.1509 + } 8.1510 + if(c->flags & PMaxSize) { 8.1511 + c->maxw = size.max_width; 8.1512 + c->maxh = size.max_height; 8.1513 + } else { 8.1514 + c->maxw = c->maxh = 0; 8.1515 + } 8.1516 + if(c->flags & PMinSize) { 8.1517 + c->minw = size.min_width; 8.1518 + c->minh = size.min_height; 8.1519 + } else { 8.1520 + c->minw = c->minh = 0; 8.1521 + } 8.1522 + if(c->flags & PAspect) { 8.1523 + c->minax = size.min_aspect.x; 8.1524 + c->minay = size.min_aspect.y; 8.1525 + c->maxax = size.max_aspect.x; 8.1526 + c->maxay = size.max_aspect.y; 8.1527 + } else { 8.1528 + c->minax = c->minay = c->maxax = c->maxay = 0; 8.1529 + } 8.1530 + c->isfixed = (c->maxw && c->minw && c->maxh && c->minh && 8.1531 + c->maxw == c->minw && c->maxh == c->minh); 8.1532 +} 8.1533 + 8.1534 +void 8.1535 +updatetitle(Client *c) { 8.1536 + char **list = NULL; 8.1537 + int n; 8.1538 + XTextProperty name; 8.1539 + 8.1540 + name.nitems = 0; 8.1541 + c->name[0] = 0; 8.1542 + XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); 8.1543 + if(!name.nitems) 8.1544 + XGetWMName(dpy, c->win, &name); 8.1545 + if(!name.nitems) 8.1546 + return; 8.1547 + if(name.encoding == XA_STRING) 8.1548 + strncpy(c->name, (char *)name.value, sizeof c->name); 8.1549 + else { 8.1550 + if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { 8.1551 + strncpy(c->name, *list, sizeof c->name); 8.1552 + XFreeStringList(list); 8.1553 + } 8.1554 + } 8.1555 + XFree(name.value); 8.1556 +} 8.1557 + 8.1558 +void 8.1559 +unmanage(Client *c) { 8.1560 + Client *nc; 8.1561 + 8.1562 + /* The server grab construct avoids race conditions. */ 8.1563 + XGrabServer(dpy); 8.1564 + XSetErrorHandler(xerrordummy); 8.1565 + detach(c); 8.1566 + detachstack(c); 8.1567 + if(sel == c) { 8.1568 + for(nc = stack; nc && !isvisible(nc); nc = nc->snext); 8.1569 + focus(nc); 8.1570 + } 8.1571 + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); 8.1572 + setclientstate(c, WithdrawnState); 8.1573 + free(c->tags); 8.1574 + free(c); 8.1575 + XSync(dpy, False); 8.1576 + XSetErrorHandler(xerror); 8.1577 + XUngrabServer(dpy); 8.1578 + arrange(); 8.1579 +} 8.1580 + 8.1581 + 8.1582 + 8.1583 + 8.1584 + 8.1585 + 8.1586 + 8.1587 + 8.1588 + 8.1589 + 8.1590 + 8.1591 + 8.1592 + 8.1593 + 8.1594 + 8.1595 + 8.1596 + 8.1597 + 8.1598 + 8.1599 +/* static */ 8.1600 + 8.1601 + 8.1602 +static void 8.1603 +cleanup(void) { 8.1604 + close(STDIN_FILENO); 8.1605 + while(stack) { 8.1606 + resize(stack, True); 8.1607 + unmanage(stack); 8.1608 + } 8.1609 + if(dc.font.set) 8.1610 + XFreeFontSet(dpy, dc.font.set); 8.1611 + else 8.1612 + XFreeFont(dpy, dc.font.xfont); 8.1613 + XUngrabKey(dpy, AnyKey, AnyModifier, root); 8.1614 + XFreePixmap(dpy, dc.drawable); 8.1615 + XFreeGC(dpy, dc.gc); 8.1616 + XDestroyWindow(dpy, barwin); 8.1617 + XFreeCursor(dpy, cursor[CurNormal]); 8.1618 + XFreeCursor(dpy, cursor[CurResize]); 8.1619 + XFreeCursor(dpy, cursor[CurMove]); 8.1620 + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 8.1621 + XSync(dpy, False); 8.1622 + free(seltag); 8.1623 +} 8.1624 + 8.1625 +static void 8.1626 +scan(void) { 8.1627 + unsigned int i, num; 8.1628 + Window *wins, d1, d2; 8.1629 + XWindowAttributes wa; 8.1630 + 8.1631 + wins = NULL; 8.1632 + if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { 8.1633 + for(i = 0; i < num; i++) { 8.1634 + if(!XGetWindowAttributes(dpy, wins[i], &wa)) 8.1635 + continue; 8.1636 + if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) 8.1637 + continue; 8.1638 + if(wa.map_state == IsViewable) 8.1639 + manage(wins[i], &wa); 8.1640 + } 8.1641 + } 8.1642 + if(wins) 8.1643 + XFree(wins); 8.1644 +} 8.1645 + 8.1646 +static void 8.1647 +setup(void) { 8.1648 + int i, j; 8.1649 + unsigned int mask; 8.1650 + Window w; 8.1651 + XModifierKeymap *modmap; 8.1652 + XSetWindowAttributes wa; 8.1653 + 8.1654 + /* init atoms */ 8.1655 + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); 8.1656 + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 8.1657 + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); 8.1658 + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 8.1659 + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 8.1660 + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, 8.1661 + PropModeReplace, (unsigned char *) netatom, NetLast); 8.1662 + /* init cursors */ 8.1663 + cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); 8.1664 + cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); 8.1665 + cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); 8.1666 + /* init modifier map */ 8.1667 + numlockmask = 0; 8.1668 + modmap = XGetModifierMapping(dpy); 8.1669 + for (i = 0; i < 8; i++) { 8.1670 + for (j = 0; j < modmap->max_keypermod; j++) { 8.1671 + if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) 8.1672 + numlockmask = (1 << i); 8.1673 + } 8.1674 + } 8.1675 + XFreeModifiermap(modmap); 8.1676 + /* select for events */ 8.1677 + wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask 8.1678 + | EnterWindowMask | LeaveWindowMask; 8.1679 + wa.cursor = cursor[CurNormal]; 8.1680 + XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); 8.1681 + grabkeys(); 8.1682 + initrregs(); 8.1683 + for(ntags = 0; tags[ntags]; ntags++); 8.1684 + seltag = emallocz(sizeof(Bool) * ntags); 8.1685 + seltag[0] = True; 8.1686 + /* style */ 8.1687 + dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); 8.1688 + dc.norm[ColBG] = getcolor(NORMBGCOLOR); 8.1689 + dc.norm[ColFG] = getcolor(NORMFGCOLOR); 8.1690 + dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); 8.1691 + dc.sel[ColBG] = getcolor(SELBGCOLOR); 8.1692 + dc.sel[ColFG] = getcolor(SELFGCOLOR); 8.1693 + setfont(FONT); 8.1694 + /* geometry */ 8.1695 + sx = sy = 0; 8.1696 + sw = DisplayWidth(dpy, screen); 8.1697 + sh = DisplayHeight(dpy, screen); 8.1698 + nmaster = NMASTER; 8.1699 + bmw = 1; 8.1700 + /* bar */ 8.1701 + dc.h = bh = dc.font.height + 2; 8.1702 + wa.override_redirect = 1; 8.1703 + wa.background_pixmap = ParentRelative; 8.1704 + wa.event_mask = ButtonPressMask | ExposureMask; 8.1705 + barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0, 8.1706 + DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), 8.1707 + CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 8.1708 + XDefineCursor(dpy, barwin, cursor[CurNormal]); 8.1709 + XMapRaised(dpy, barwin); 8.1710 + strcpy(stext, "dwm-"VERSION); 8.1711 + /* windowarea */ 8.1712 + wax = sx; 8.1713 + way = sy + bh; 8.1714 + wah = sh - bh; 8.1715 + waw = sw; 8.1716 + /* pixmap for everything */ 8.1717 + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); 8.1718 + dc.gc = XCreateGC(dpy, root, 0, 0); 8.1719 + XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); 8.1720 + /* multihead support */ 8.1721 + selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); 8.1722 +} 8.1723 + 8.1724 +/* 8.1725 + * Startup Error handler to check if another window manager 8.1726 + * is already running. 8.1727 + */ 8.1728 +static int 8.1729 +xerrorstart(Display *dsply, XErrorEvent *ee) { 8.1730 + otherwm = True; 8.1731 + return -1; 8.1732 +} 8.1733 + 8.1734 + 8.1735 + 8.1736 +void 8.1737 +sendevent(Window w, Atom a, long value) { 8.1738 + XEvent e; 8.1739 + 8.1740 + e.type = ClientMessage; 8.1741 + e.xclient.window = w; 8.1742 + e.xclient.message_type = a; 8.1743 + e.xclient.format = 32; 8.1744 + e.xclient.data.l[0] = value; 8.1745 + e.xclient.data.l[1] = CurrentTime; 8.1746 + XSendEvent(dpy, w, False, NoEventMask, &e); 8.1747 + XSync(dpy, False); 8.1748 +} 8.1749 + 8.1750 +void 8.1751 +quit(Arg *arg) { 8.1752 + readin = running = False; 8.1753 +} 8.1754 + 8.1755 +/* There's no way to check accesses to destroyed windows, thus those cases are 8.1756 + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs 8.1757 + * default error handler, which may call exit. 8.1758 + */ 8.1759 +int 8.1760 +xerror(Display *dpy, XErrorEvent *ee) { 8.1761 + if(ee->error_code == BadWindow 8.1762 + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) 8.1763 + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) 8.1764 + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) 8.1765 + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) 8.1766 + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) 8.1767 + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) 8.1768 + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) 8.1769 + return 0; 8.1770 + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", 8.1771 + ee->request_code, ee->error_code); 8.1772 + return xerrorxlib(dpy, ee); /* may call exit */ 8.1773 +} 8.1774 + 8.1775 +int 8.1776 +main(int argc, char *argv[]) { 8.1777 + char *p; 8.1778 + int r, xfd; 8.1779 + fd_set rd; 8.1780 + 8.1781 + if(argc == 2 && !strncmp("-v", argv[1], 3)) { 8.1782 + fputs("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n", stdout); 8.1783 + exit(EXIT_SUCCESS); 8.1784 + } 8.1785 + else if(argc != 1) 8.1786 + eprint("usage: dwm [-v]\n"); 8.1787 + setlocale(LC_CTYPE, ""); 8.1788 + dpy = XOpenDisplay(0); 8.1789 + if(!dpy) 8.1790 + eprint("dwm: cannot open display\n"); 8.1791 + xfd = ConnectionNumber(dpy); 8.1792 + screen = DefaultScreen(dpy); 8.1793 + root = RootWindow(dpy, screen); 8.1794 + otherwm = False; 8.1795 + XSetErrorHandler(xerrorstart); 8.1796 + /* this causes an error if some other window manager is running */ 8.1797 + XSelectInput(dpy, root, SubstructureRedirectMask); 8.1798 + XSync(dpy, False); 8.1799 + if(otherwm) 8.1800 + eprint("dwm: another window manager is already running\n"); 8.1801 + 8.1802 + XSync(dpy, False); 8.1803 + XSetErrorHandler(NULL); 8.1804 + xerrorxlib = XSetErrorHandler(xerror); 8.1805 + XSync(dpy, False); 8.1806 + setup(); 8.1807 + drawstatus(); 8.1808 + scan(); 8.1809 + 8.1810 + /* main event loop, also reads status text from stdin */ 8.1811 + XSync(dpy, False); 8.1812 + procevent(); 8.1813 + readin = True; 8.1814 + while(running) { 8.1815 + FD_ZERO(&rd); 8.1816 + if(readin) 8.1817 + FD_SET(STDIN_FILENO, &rd); 8.1818 + FD_SET(xfd, &rd); 8.1819 + if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { 8.1820 + if(errno == EINTR) 8.1821 + continue; 8.1822 + eprint("select failed\n"); 8.1823 + } 8.1824 + if(FD_ISSET(STDIN_FILENO, &rd)) { 8.1825 + switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) { 8.1826 + case -1: 8.1827 + strncpy(stext, strerror(errno), sizeof stext - 1); 8.1828 + stext[sizeof stext - 1] = '\0'; 8.1829 + readin = False; 8.1830 + break; 8.1831 + case 0: 8.1832 + strncpy(stext, "EOF", 4); 8.1833 + readin = False; 8.1834 + break; 8.1835 + default: 8.1836 + for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); 8.1837 + for(; p >= stext && *p != '\n'; --p); 8.1838 + if(p > stext) 8.1839 + strncpy(stext, p + 1, sizeof stext); 8.1840 + } 8.1841 + drawstatus(); 8.1842 + } 8.1843 + if(FD_ISSET(xfd, &rd)) 8.1844 + procevent(); 8.1845 + } 8.1846 + cleanup(); 8.1847 + XCloseDisplay(dpy); 8.1848 + return 0; 8.1849 +}
9.1 --- a/dwm.h Sat Jun 16 21:49:51 2007 +0200 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,157 +0,0 @@ 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 - * dynamic window manager is designed like any other X client as well. It is 9.8 - * driven through handling X events. In contrast to other X clients, a window 9.9 - * manager selects for SubstructureRedirectMask on the root window, to receive 9.10 - * events about window (dis-)appearance. Only one X connection at a time is 9.11 - * allowed to select for this event mask. 9.12 - * 9.13 - * Calls to fetch an X event from the event queue are blocking. Due reading 9.14 - * status text from standard input, a select()-driven main loop has been 9.15 - * implemented which selects for reads on the X connection and STDIN_FILENO to 9.16 - * handle all data smoothly. The event handlers of dwm are organized in an 9.17 - * array which is accessed whenever a new event has been fetched. This allows 9.18 - * event dispatching in O(1) time. 9.19 - * 9.20 - * Each child of the root window is called a client, except windows which have 9.21 - * set the override_redirect flag. Clients are organized in a global 9.22 - * doubly-linked client list, the focus history is remembered through a global 9.23 - * stack list. Each client contains an array of Bools of the same size as the 9.24 - * global tags array to indicate the tags of a client. For each client dwm 9.25 - * creates a small title window, which is resized whenever the (_NET_)WM_NAME 9.26 - * properties are updated or the client is moved/resized. 9.27 - * 9.28 - * Keys and tagging rules are organized as arrays and defined in the config.h 9.29 - * file. These arrays are kept static in event.o and tag.o respectively, 9.30 - * because no other part of dwm needs access to them. The current mode is 9.31 - * represented by the arrange() function pointer, which wether points to 9.32 - * dofloat() or dotile(). 9.33 - * 9.34 - * To understand everything else, start reading main.c:main(). 9.35 - */ 9.36 - 9.37 -#include "config.h" 9.38 -#include <X11/Xlib.h> 9.39 - 9.40 -/* mask shorthands, used in event.c and client.c */ 9.41 -#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) 9.42 - 9.43 -enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ 9.44 -enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ 9.45 -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 9.46 -enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ 9.47 - 9.48 -typedef union { 9.49 - const char *cmd; 9.50 - int i; 9.51 -} Arg; /* argument type */ 9.52 - 9.53 -typedef struct { 9.54 - int ascent; 9.55 - int descent; 9.56 - int height; 9.57 - XFontSet set; 9.58 - XFontStruct *xfont; 9.59 -} Fnt; 9.60 - 9.61 -typedef struct { 9.62 - int x, y, w, h; 9.63 - unsigned long norm[ColLast]; 9.64 - unsigned long sel[ColLast]; 9.65 - Drawable drawable; 9.66 - Fnt font; 9.67 - GC gc; 9.68 -} DC; /* draw context */ 9.69 - 9.70 -typedef struct Client Client; 9.71 -struct Client { 9.72 - char name[256]; 9.73 - int x, y, w, h; 9.74 - int rx, ry, rw, rh; /* revert geometry */ 9.75 - int basew, baseh, incw, inch, maxw, maxh, minw, minh; 9.76 - int minax, minay, maxax, maxay; 9.77 - long flags; 9.78 - unsigned int border; 9.79 - Bool isfixed, isfloat, ismax; 9.80 - Bool *tags; 9.81 - Client *next; 9.82 - Client *prev; 9.83 - Client *snext; 9.84 - Window win; 9.85 -}; 9.86 - 9.87 -extern const char *tags[]; /* all tags */ 9.88 -extern char stext[256]; /* status text */ 9.89 -extern int bh, bmw; /* bar height, bar mode label width */ 9.90 -extern int screen, sx, sy, sw, sh; /* screen geometry */ 9.91 -extern int wax, way, wah, waw; /* windowarea geometry */ 9.92 -extern unsigned int master, nmaster; /* master percent, number of master clients */ 9.93 -extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */ 9.94 -extern void (*handler[LASTEvent])(XEvent *); /* event handler */ 9.95 -extern void (*arrange)(void); /* arrange function, indicates mode */ 9.96 -extern Atom wmatom[WMLast], netatom[NetLast]; 9.97 -extern Bool running, selscreen, *seltag; /* seltag is array of Bool */ 9.98 -extern Client *clients, *sel, *stack; /* global client list and stack */ 9.99 -extern Cursor cursor[CurLast]; 9.100 -extern DC dc; /* global draw context */ 9.101 -extern Display *dpy; 9.102 -extern Window root, barwin; 9.103 - 9.104 -/* client.c */ 9.105 -extern void configure(Client *c); /* send synthetic configure event */ 9.106 -extern void focus(Client *c); /* focus c, c may be NULL */ 9.107 -extern Client *getclient(Window w); /* return client of w */ 9.108 -extern Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */ 9.109 -extern void killclient(Arg *arg); /* kill c nicely */ 9.110 -extern void manage(Window w, XWindowAttributes *wa); /* manage new client */ 9.111 -extern void resize(Client *c, Bool sizehints); /* resize c*/ 9.112 -extern void updatesizehints(Client *c); /* update the size hint variables of c */ 9.113 -extern void updatetitle(Client *c); /* update the name of c */ 9.114 -extern void unmanage(Client *c); /* destroy c */ 9.115 - 9.116 -/* draw.c */ 9.117 -extern void drawstatus(void); /* draw the bar */ 9.118 -extern unsigned long getcolor(const char *colstr); /* return color of colstr */ 9.119 -extern void setfont(const char *fontstr); /* set the font for DC */ 9.120 -extern unsigned int textw(const char *text); /* return the width of text in px*/ 9.121 - 9.122 -/* event.c */ 9.123 -extern void grabkeys(void); /* grab all keys defined in config.h */ 9.124 -extern void procevent(void); /* process pending X events */ 9.125 - 9.126 -/* main.c */ 9.127 -extern void quit(Arg *arg); /* quit dwm nicely */ 9.128 -extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */ 9.129 -extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ 9.130 - 9.131 -/* tag.c */ 9.132 -extern void initrregs(void); /* initialize regexps of rules defined in config.h */ 9.133 -extern Client *getnext(Client *c); /* returns next visible client */ 9.134 -extern Client *getprev(Client *c); /* returns previous visible client */ 9.135 -extern void settags(Client *c, Client *trans); /* sets tags of c */ 9.136 -extern void tag(Arg *arg); /* tags c with arg's index */ 9.137 -extern void toggletag(Arg *arg); /* toggles c tags with arg's index */ 9.138 -extern void viewnext(Arg *arg); /* view next tag(s) */ 9.139 - 9.140 -/* util.c */ 9.141 -extern void *emallocz(unsigned int size); /* allocates zero-initialized memory, exits on error */ 9.142 -extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */ 9.143 -extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */ 9.144 - 9.145 -/* view.c */ 9.146 -extern void detach(Client *c); /* detaches c from global client list */ 9.147 -extern void dofloat(void); /* arranges all windows floating */ 9.148 -extern void dotile(void); /* arranges all windows tiled */ 9.149 -extern void domax(void); /* arranges all windows fullscreen */ 9.150 -extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */ 9.151 -extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */ 9.152 -extern void incnmaster(Arg *arg); /* increments nmaster with arg's index value */ 9.153 -extern Bool isvisible(Client *c); /* returns True if client is visible */ 9.154 -extern void resizemaster(Arg *arg); /* resizes the master percent with arg's index value */ 9.155 -extern void restack(void); /* restores z layers of all clients */ 9.156 -extern void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */ 9.157 -extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */ 9.158 -extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */ 9.159 -extern void view(Arg *arg); /* views the tag with arg's index */ 9.160 -extern void zoom(Arg *arg); /* zooms the focused client to master area, arg is ignored */
10.1 --- a/event.c Sat Jun 16 21:49:51 2007 +0200 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,384 +0,0 @@ 10.4 -/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 10.5 - * See LICENSE file for license details. 10.6 - */ 10.7 -#include "dwm.h" 10.8 -#include <stdlib.h> 10.9 -#include <X11/keysym.h> 10.10 -#include <X11/Xatom.h> 10.11 - 10.12 -/* static */ 10.13 - 10.14 -typedef struct { 10.15 - unsigned long mod; 10.16 - KeySym keysym; 10.17 - void (*func)(Arg *arg); 10.18 - Arg arg; 10.19 -} Key; 10.20 - 10.21 -KEYS 10.22 - 10.23 -#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) 10.24 -#define MOUSEMASK (BUTTONMASK | PointerMotionMask) 10.25 - 10.26 -static void 10.27 -movemouse(Client *c) { 10.28 - int x1, y1, ocx, ocy, di; 10.29 - unsigned int dui; 10.30 - Window dummy; 10.31 - XEvent ev; 10.32 - 10.33 - ocx = c->x; 10.34 - ocy = c->y; 10.35 - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 10.36 - None, cursor[CurMove], CurrentTime) != GrabSuccess) 10.37 - return; 10.38 - c->ismax = False; 10.39 - XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); 10.40 - for(;;) { 10.41 - XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); 10.42 - switch (ev.type) { 10.43 - case ButtonRelease: 10.44 - resize(c, True); 10.45 - XUngrabPointer(dpy, CurrentTime); 10.46 - return; 10.47 - case ConfigureRequest: 10.48 - case Expose: 10.49 - case MapRequest: 10.50 - handler[ev.type](&ev); 10.51 - break; 10.52 - case MotionNotify: 10.53 - XSync(dpy, False); 10.54 - c->x = ocx + (ev.xmotion.x - x1); 10.55 - c->y = ocy + (ev.xmotion.y - y1); 10.56 - if(abs(wax + c->x) < SNAP) 10.57 - c->x = wax; 10.58 - else if(abs((wax + waw) - (c->x + c->w + 2 * c->border)) < SNAP) 10.59 - c->x = wax + waw - c->w - 2 * c->border; 10.60 - if(abs(way - c->y) < SNAP) 10.61 - c->y = way; 10.62 - else if(abs((way + wah) - (c->y + c->h + 2 * c->border)) < SNAP) 10.63 - c->y = way + wah - c->h - 2 * c->border; 10.64 - resize(c, False); 10.65 - break; 10.66 - } 10.67 - } 10.68 -} 10.69 - 10.70 -static void 10.71 -resizemouse(Client *c) { 10.72 - int ocx, ocy; 10.73 - int nw, nh; 10.74 - XEvent ev; 10.75 - 10.76 - ocx = c->x; 10.77 - ocy = c->y; 10.78 - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 10.79 - None, cursor[CurResize], CurrentTime) != GrabSuccess) 10.80 - return; 10.81 - c->ismax = False; 10.82 - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); 10.83 - for(;;) { 10.84 - XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); 10.85 - switch(ev.type) { 10.86 - case ButtonRelease: 10.87 - resize(c, True); 10.88 - XUngrabPointer(dpy, CurrentTime); 10.89 - return; 10.90 - case ConfigureRequest: 10.91 - case Expose: 10.92 - case MapRequest: 10.93 - handler[ev.type](&ev); 10.94 - break; 10.95 - case MotionNotify: 10.96 - XSync(dpy, False); 10.97 - nw = ev.xmotion.x - ocx - 2 * c->border + 1; 10.98 - c->w = nw > 0 ? nw : 1; 10.99 - nh = ev.xmotion.y - ocy - 2 * c->border + 1; 10.100 - c->h = nh > 0 ? nh : 1; 10.101 - resize(c, True); 10.102 - break; 10.103 - } 10.104 - } 10.105 -} 10.106 - 10.107 -static void 10.108 -buttonpress(XEvent *e) { 10.109 - int x; 10.110 - Arg a; 10.111 - Client *c; 10.112 - XButtonPressedEvent *ev = &e->xbutton; 10.113 - 10.114 - if(barwin == ev->window) { 10.115 - x = 0; 10.116 - for(a.i = 0; a.i < ntags; a.i++) { 10.117 - x += textw(tags[a.i]); 10.118 - if(ev->x < x) { 10.119 - if(ev->button == Button1) { 10.120 - if(ev->state & MODKEY) 10.121 - tag(&a); 10.122 - else 10.123 - view(&a); 10.124 - } 10.125 - else if(ev->button == Button3) { 10.126 - if(ev->state & MODKEY) 10.127 - toggletag(&a); 10.128 - else 10.129 - toggleview(&a); 10.130 - } 10.131 - return; 10.132 - } 10.133 - } 10.134 - if(ev->x < x + bmw) 10.135 - switch(ev->button) { 10.136 - case Button1: 10.137 - togglemode(NULL); 10.138 - break; 10.139 - case Button4: 10.140 - a.i = 1; 10.141 - incnmaster(&a); 10.142 - break; 10.143 - case Button5: 10.144 - a.i = -1; 10.145 - incnmaster(&a); 10.146 - break; 10.147 - } 10.148 - } 10.149 - else if((c = getclient(ev->window))) { 10.150 - focus(c); 10.151 - if(CLEANMASK(ev->state) != MODKEY) 10.152 - return; 10.153 - if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) { 10.154 - restack(); 10.155 - movemouse(c); 10.156 - } 10.157 - else if(ev->button == Button2) 10.158 - zoom(NULL); 10.159 - else if(ev->button == Button3 && (arrange == dofloat || c->isfloat) && 10.160 - !c->isfixed) { 10.161 - restack(); 10.162 - resizemouse(c); 10.163 - } 10.164 - } 10.165 -} 10.166 - 10.167 -static void 10.168 -configurerequest(XEvent *e) { 10.169 - unsigned long newmask; 10.170 - Client *c; 10.171 - XConfigureRequestEvent *ev = &e->xconfigurerequest; 10.172 - XWindowChanges wc; 10.173 - 10.174 - if((c = getclient(ev->window))) { 10.175 - c->ismax = False; 10.176 - if(ev->value_mask & CWX) 10.177 - c->x = ev->x; 10.178 - if(ev->value_mask & CWY) 10.179 - c->y = ev->y; 10.180 - if(ev->value_mask & CWWidth) 10.181 - c->w = ev->width; 10.182 - if(ev->value_mask & CWHeight) 10.183 - c->h = ev->height; 10.184 - if(ev->value_mask & CWBorderWidth) 10.185 - c->border = ev->border_width; 10.186 - wc.x = c->x; 10.187 - wc.y = c->y; 10.188 - wc.width = c->w; 10.189 - wc.height = c->h; 10.190 - newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth)); 10.191 - if(newmask) 10.192 - XConfigureWindow(dpy, c->win, newmask, &wc); 10.193 - else 10.194 - configure(c); 10.195 - XSync(dpy, False); 10.196 - if(c->isfloat) { 10.197 - resize(c, False); 10.198 - if(!isvisible(c)) 10.199 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 10.200 - } 10.201 - else 10.202 - arrange(); 10.203 - } 10.204 - else { 10.205 - wc.x = ev->x; 10.206 - wc.y = ev->y; 10.207 - wc.width = ev->width; 10.208 - wc.height = ev->height; 10.209 - wc.border_width = ev->border_width; 10.210 - wc.sibling = ev->above; 10.211 - wc.stack_mode = ev->detail; 10.212 - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); 10.213 - XSync(dpy, False); 10.214 - } 10.215 -} 10.216 - 10.217 -static void 10.218 -destroynotify(XEvent *e) { 10.219 - Client *c; 10.220 - XDestroyWindowEvent *ev = &e->xdestroywindow; 10.221 - 10.222 - if((c = getclient(ev->window))) 10.223 - unmanage(c); 10.224 -} 10.225 - 10.226 -static void 10.227 -enternotify(XEvent *e) { 10.228 - Client *c; 10.229 - XCrossingEvent *ev = &e->xcrossing; 10.230 - 10.231 - if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) 10.232 - return; 10.233 - if((c = getclient(ev->window)) && isvisible(c)) 10.234 - focus(c); 10.235 - else if(ev->window == root) { 10.236 - selscreen = True; 10.237 - for(c = stack; c && !isvisible(c); c = c->snext); 10.238 - focus(c); 10.239 - } 10.240 -} 10.241 - 10.242 -static void 10.243 -expose(XEvent *e) { 10.244 - XExposeEvent *ev = &e->xexpose; 10.245 - 10.246 - if(ev->count == 0) { 10.247 - if(barwin == ev->window) 10.248 - drawstatus(); 10.249 - } 10.250 -} 10.251 - 10.252 -static void 10.253 -keypress(XEvent *e) { 10.254 - static unsigned int len = sizeof key / sizeof key[0]; 10.255 - unsigned int i; 10.256 - KeySym keysym; 10.257 - XKeyEvent *ev = &e->xkey; 10.258 - 10.259 - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); 10.260 - for(i = 0; i < len; i++) { 10.261 - if(keysym == key[i].keysym 10.262 - && CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) 10.263 - { 10.264 - if(key[i].func) 10.265 - key[i].func(&key[i].arg); 10.266 - } 10.267 - } 10.268 -} 10.269 - 10.270 -static void 10.271 -leavenotify(XEvent *e) { 10.272 - XCrossingEvent *ev = &e->xcrossing; 10.273 - 10.274 - if((ev->window == root) && !ev->same_screen) { 10.275 - selscreen = False; 10.276 - focus(NULL); 10.277 - } 10.278 -} 10.279 - 10.280 -static void 10.281 -mappingnotify(XEvent *e) { 10.282 - XMappingEvent *ev = &e->xmapping; 10.283 - 10.284 - XRefreshKeyboardMapping(ev); 10.285 - if(ev->request == MappingKeyboard) 10.286 - grabkeys(); 10.287 -} 10.288 - 10.289 -static void 10.290 -maprequest(XEvent *e) { 10.291 - static XWindowAttributes wa; 10.292 - XMapRequestEvent *ev = &e->xmaprequest; 10.293 - 10.294 - if(!XGetWindowAttributes(dpy, ev->window, &wa)) 10.295 - return; 10.296 - if(wa.override_redirect) { 10.297 - XSelectInput(dpy, ev->window, 10.298 - (StructureNotifyMask | PropertyChangeMask)); 10.299 - return; 10.300 - } 10.301 - if(!getclient(ev->window)) 10.302 - manage(ev->window, &wa); 10.303 -} 10.304 - 10.305 -static void 10.306 -propertynotify(XEvent *e) { 10.307 - Client *c; 10.308 - Window trans; 10.309 - XPropertyEvent *ev = &e->xproperty; 10.310 - 10.311 - if(ev->state == PropertyDelete) 10.312 - return; /* ignore */ 10.313 - if((c = getclient(ev->window))) { 10.314 - switch (ev->atom) { 10.315 - default: break; 10.316 - case XA_WM_TRANSIENT_FOR: 10.317 - XGetTransientForHint(dpy, c->win, &trans); 10.318 - if(!c->isfloat && (c->isfloat = (trans != 0))) 10.319 - arrange(); 10.320 - break; 10.321 - case XA_WM_NORMAL_HINTS: 10.322 - updatesizehints(c); 10.323 - break; 10.324 - } 10.325 - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { 10.326 - updatetitle(c); 10.327 - if(c == sel) 10.328 - drawstatus(); 10.329 - } 10.330 - } 10.331 -} 10.332 - 10.333 -static void 10.334 -unmapnotify(XEvent *e) { 10.335 - Client *c; 10.336 - XUnmapEvent *ev = &e->xunmap; 10.337 - 10.338 - if((c = getclient(ev->window))) 10.339 - unmanage(c); 10.340 -} 10.341 - 10.342 -/* extern */ 10.343 - 10.344 -void (*handler[LASTEvent]) (XEvent *) = { 10.345 - [ButtonPress] = buttonpress, 10.346 - [ConfigureRequest] = configurerequest, 10.347 - [DestroyNotify] = destroynotify, 10.348 - [EnterNotify] = enternotify, 10.349 - [LeaveNotify] = leavenotify, 10.350 - [Expose] = expose, 10.351 - [KeyPress] = keypress, 10.352 - [MappingNotify] = mappingnotify, 10.353 - [MapRequest] = maprequest, 10.354 - [PropertyNotify] = propertynotify, 10.355 - [UnmapNotify] = unmapnotify 10.356 -}; 10.357 - 10.358 -void 10.359 -grabkeys(void) { 10.360 - static unsigned int len = sizeof key / sizeof key[0]; 10.361 - unsigned int i; 10.362 - KeyCode code; 10.363 - 10.364 - XUngrabKey(dpy, AnyKey, AnyModifier, root); 10.365 - for(i = 0; i < len; i++) { 10.366 - code = XKeysymToKeycode(dpy, key[i].keysym); 10.367 - XGrabKey(dpy, code, key[i].mod, root, True, 10.368 - GrabModeAsync, GrabModeAsync); 10.369 - XGrabKey(dpy, code, key[i].mod | LockMask, root, True, 10.370 - GrabModeAsync, GrabModeAsync); 10.371 - XGrabKey(dpy, code, key[i].mod | numlockmask, root, True, 10.372 - GrabModeAsync, GrabModeAsync); 10.373 - XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True, 10.374 - GrabModeAsync, GrabModeAsync); 10.375 - } 10.376 -} 10.377 - 10.378 -void 10.379 -procevent(void) { 10.380 - XEvent ev; 10.381 - 10.382 - while(XPending(dpy)) { 10.383 - XNextEvent(dpy, &ev); 10.384 - if(handler[ev.type]) 10.385 - (handler[ev.type])(&ev); /* call handler */ 10.386 - } 10.387 -}
11.1 --- a/main.c Sat Jun 16 21:49:51 2007 +0200 11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 11.3 @@ -1,288 +0,0 @@ 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 - 11.8 -#include "dwm.h" 11.9 -#include <errno.h> 11.10 -#include <locale.h> 11.11 -#include <stdio.h> 11.12 -#include <stdlib.h> 11.13 -#include <string.h> 11.14 -#include <unistd.h> 11.15 -#include <sys/select.h> 11.16 -#include <X11/cursorfont.h> 11.17 -#include <X11/keysym.h> 11.18 -#include <X11/Xatom.h> 11.19 -#include <X11/Xproto.h> 11.20 - 11.21 -/* extern */ 11.22 - 11.23 -char stext[256]; 11.24 -int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah; 11.25 -unsigned int master, nmaster, ntags, numlockmask; 11.26 -Atom wmatom[WMLast], netatom[NetLast]; 11.27 -Bool running = True; 11.28 -Bool *seltag; 11.29 -Bool selscreen = True; 11.30 -Client *clients = NULL; 11.31 -Client *sel = NULL; 11.32 -Client *stack = NULL; 11.33 -Cursor cursor[CurLast]; 11.34 -Display *dpy; 11.35 -DC dc = {0}; 11.36 -Window root, barwin; 11.37 - 11.38 -/* static */ 11.39 - 11.40 -static int (*xerrorxlib)(Display *, XErrorEvent *); 11.41 -static Bool otherwm, readin; 11.42 - 11.43 -static void 11.44 -cleanup(void) { 11.45 - close(STDIN_FILENO); 11.46 - while(stack) { 11.47 - resize(stack, True); 11.48 - unmanage(stack); 11.49 - } 11.50 - if(dc.font.set) 11.51 - XFreeFontSet(dpy, dc.font.set); 11.52 - else 11.53 - XFreeFont(dpy, dc.font.xfont); 11.54 - XUngrabKey(dpy, AnyKey, AnyModifier, root); 11.55 - XFreePixmap(dpy, dc.drawable); 11.56 - XFreeGC(dpy, dc.gc); 11.57 - XDestroyWindow(dpy, barwin); 11.58 - XFreeCursor(dpy, cursor[CurNormal]); 11.59 - XFreeCursor(dpy, cursor[CurResize]); 11.60 - XFreeCursor(dpy, cursor[CurMove]); 11.61 - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 11.62 - XSync(dpy, False); 11.63 - free(seltag); 11.64 -} 11.65 - 11.66 -static void 11.67 -scan(void) { 11.68 - unsigned int i, num; 11.69 - Window *wins, d1, d2; 11.70 - XWindowAttributes wa; 11.71 - 11.72 - wins = NULL; 11.73 - if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { 11.74 - for(i = 0; i < num; i++) { 11.75 - if(!XGetWindowAttributes(dpy, wins[i], &wa)) 11.76 - continue; 11.77 - if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) 11.78 - continue; 11.79 - if(wa.map_state == IsViewable) 11.80 - manage(wins[i], &wa); 11.81 - } 11.82 - } 11.83 - if(wins) 11.84 - XFree(wins); 11.85 -} 11.86 - 11.87 -static void 11.88 -setup(void) { 11.89 - int i, j; 11.90 - unsigned int mask; 11.91 - Window w; 11.92 - XModifierKeymap *modmap; 11.93 - XSetWindowAttributes wa; 11.94 - 11.95 - /* init atoms */ 11.96 - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); 11.97 - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 11.98 - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); 11.99 - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 11.100 - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 11.101 - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, 11.102 - PropModeReplace, (unsigned char *) netatom, NetLast); 11.103 - /* init cursors */ 11.104 - cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); 11.105 - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); 11.106 - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); 11.107 - /* init modifier map */ 11.108 - numlockmask = 0; 11.109 - modmap = XGetModifierMapping(dpy); 11.110 - for (i = 0; i < 8; i++) { 11.111 - for (j = 0; j < modmap->max_keypermod; j++) { 11.112 - if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) 11.113 - numlockmask = (1 << i); 11.114 - } 11.115 - } 11.116 - XFreeModifiermap(modmap); 11.117 - /* select for events */ 11.118 - wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask 11.119 - | EnterWindowMask | LeaveWindowMask; 11.120 - wa.cursor = cursor[CurNormal]; 11.121 - XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); 11.122 - grabkeys(); 11.123 - initrregs(); 11.124 - for(ntags = 0; tags[ntags]; ntags++); 11.125 - seltag = emallocz(sizeof(Bool) * ntags); 11.126 - seltag[0] = True; 11.127 - /* style */ 11.128 - dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); 11.129 - dc.norm[ColBG] = getcolor(NORMBGCOLOR); 11.130 - dc.norm[ColFG] = getcolor(NORMFGCOLOR); 11.131 - dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); 11.132 - dc.sel[ColBG] = getcolor(SELBGCOLOR); 11.133 - dc.sel[ColFG] = getcolor(SELFGCOLOR); 11.134 - setfont(FONT); 11.135 - /* geometry */ 11.136 - sx = sy = 0; 11.137 - sw = DisplayWidth(dpy, screen); 11.138 - sh = DisplayHeight(dpy, screen); 11.139 - master = MASTER; 11.140 - nmaster = NMASTER; 11.141 - bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL); 11.142 - /* bar */ 11.143 - dc.h = bh = dc.font.height + 2; 11.144 - wa.override_redirect = 1; 11.145 - wa.background_pixmap = ParentRelative; 11.146 - wa.event_mask = ButtonPressMask | ExposureMask; 11.147 - barwin = XCreateWindow(dpy, root, sx, sy + (TOPBAR ? 0 : sh - bh), sw, bh, 0, 11.148 - DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), 11.149 - CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 11.150 - XDefineCursor(dpy, barwin, cursor[CurNormal]); 11.151 - XMapRaised(dpy, barwin); 11.152 - strcpy(stext, "dwm-"VERSION); 11.153 - /* windowarea */ 11.154 - wax = sx; 11.155 - way = sy + (TOPBAR ? bh : 0); 11.156 - wah = sh - bh; 11.157 - waw = sw; 11.158 - /* pixmap for everything */ 11.159 - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); 11.160 - dc.gc = XCreateGC(dpy, root, 0, 0); 11.161 - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); 11.162 - /* multihead support */ 11.163 - selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); 11.164 -} 11.165 - 11.166 -/* 11.167 - * Startup Error handler to check if another window manager 11.168 - * is already running. 11.169 - */ 11.170 -static int 11.171 -xerrorstart(Display *dsply, XErrorEvent *ee) { 11.172 - otherwm = True; 11.173 - return -1; 11.174 -} 11.175 - 11.176 -/* extern */ 11.177 - 11.178 -void 11.179 -sendevent(Window w, Atom a, long value) { 11.180 - XEvent e; 11.181 - 11.182 - e.type = ClientMessage; 11.183 - e.xclient.window = w; 11.184 - e.xclient.message_type = a; 11.185 - e.xclient.format = 32; 11.186 - e.xclient.data.l[0] = value; 11.187 - e.xclient.data.l[1] = CurrentTime; 11.188 - XSendEvent(dpy, w, False, NoEventMask, &e); 11.189 - XSync(dpy, False); 11.190 -} 11.191 - 11.192 -void 11.193 -quit(Arg *arg) { 11.194 - readin = running = False; 11.195 -} 11.196 - 11.197 -/* There's no way to check accesses to destroyed windows, thus those cases are 11.198 - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs 11.199 - * default error handler, which may call exit. 11.200 - */ 11.201 -int 11.202 -xerror(Display *dpy, XErrorEvent *ee) { 11.203 - if(ee->error_code == BadWindow 11.204 - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) 11.205 - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) 11.206 - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) 11.207 - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) 11.208 - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) 11.209 - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) 11.210 - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) 11.211 - return 0; 11.212 - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", 11.213 - ee->request_code, ee->error_code); 11.214 - return xerrorxlib(dpy, ee); /* may call exit */ 11.215 -} 11.216 - 11.217 -int 11.218 -main(int argc, char *argv[]) { 11.219 - char *p; 11.220 - int r, xfd; 11.221 - fd_set rd; 11.222 - 11.223 - if(argc == 2 && !strncmp("-v", argv[1], 3)) { 11.224 - fputs("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n", stdout); 11.225 - exit(EXIT_SUCCESS); 11.226 - } 11.227 - else if(argc != 1) 11.228 - eprint("usage: dwm [-v]\n"); 11.229 - setlocale(LC_CTYPE, ""); 11.230 - dpy = XOpenDisplay(0); 11.231 - if(!dpy) 11.232 - eprint("dwm: cannot open display\n"); 11.233 - xfd = ConnectionNumber(dpy); 11.234 - screen = DefaultScreen(dpy); 11.235 - root = RootWindow(dpy, screen); 11.236 - otherwm = False; 11.237 - XSetErrorHandler(xerrorstart); 11.238 - /* this causes an error if some other window manager is running */ 11.239 - XSelectInput(dpy, root, SubstructureRedirectMask); 11.240 - XSync(dpy, False); 11.241 - if(otherwm) 11.242 - eprint("dwm: another window manager is already running\n"); 11.243 - 11.244 - XSync(dpy, False); 11.245 - XSetErrorHandler(NULL); 11.246 - xerrorxlib = XSetErrorHandler(xerror); 11.247 - XSync(dpy, False); 11.248 - setup(); 11.249 - drawstatus(); 11.250 - scan(); 11.251 - 11.252 - /* main event loop, also reads status text from stdin */ 11.253 - XSync(dpy, False); 11.254 - procevent(); 11.255 - readin = True; 11.256 - while(running) { 11.257 - FD_ZERO(&rd); 11.258 - if(readin) 11.259 - FD_SET(STDIN_FILENO, &rd); 11.260 - FD_SET(xfd, &rd); 11.261 - if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { 11.262 - if(errno == EINTR) 11.263 - continue; 11.264 - eprint("select failed\n"); 11.265 - } 11.266 - if(FD_ISSET(STDIN_FILENO, &rd)) { 11.267 - switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) { 11.268 - case -1: 11.269 - strncpy(stext, strerror(errno), sizeof stext - 1); 11.270 - stext[sizeof stext - 1] = '\0'; 11.271 - readin = False; 11.272 - break; 11.273 - case 0: 11.274 - strncpy(stext, "EOF", 4); 11.275 - readin = False; 11.276 - break; 11.277 - default: 11.278 - for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); 11.279 - for(; p >= stext && *p != '\n'; --p); 11.280 - if(p > stext) 11.281 - strncpy(stext, p + 1, sizeof stext); 11.282 - } 11.283 - drawstatus(); 11.284 - } 11.285 - if(FD_ISSET(xfd, &rd)) 11.286 - procevent(); 11.287 - } 11.288 - cleanup(); 11.289 - XCloseDisplay(dpy); 11.290 - return 0; 11.291 -}
12.1 --- a/tag.c Sat Jun 16 21:49:51 2007 +0200 12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 12.3 @@ -1,148 +0,0 @@ 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 <regex.h> 12.9 -#include <stdio.h> 12.10 -#include <stdlib.h> 12.11 -#include <string.h> 12.12 -#include <sys/types.h> 12.13 -#include <X11/Xutil.h> 12.14 - 12.15 - 12.16 -typedef struct { 12.17 - const char *clpattern; 12.18 - const char *tpattern; 12.19 - Bool isfloat; 12.20 -} Rule; 12.21 - 12.22 -typedef struct { 12.23 - regex_t *clregex; 12.24 - regex_t *tregex; 12.25 -} RReg; 12.26 - 12.27 -/* static */ 12.28 - 12.29 -TAGS 12.30 -RULES 12.31 - 12.32 -static RReg *rreg = NULL; 12.33 -static unsigned int len = 0; 12.34 - 12.35 -/* extern */ 12.36 - 12.37 -Client * 12.38 -getnext(Client *c) { 12.39 - for(; c && !isvisible(c); c = c->next); 12.40 - return c; 12.41 -} 12.42 - 12.43 -Client * 12.44 -getprev(Client *c) { 12.45 - for(; c && !isvisible(c); c = c->prev); 12.46 - return c; 12.47 -} 12.48 - 12.49 -void 12.50 -initrregs(void) { 12.51 - unsigned int i; 12.52 - regex_t *reg; 12.53 - 12.54 - if(rreg) 12.55 - return; 12.56 - len = sizeof rule / sizeof rule[0]; 12.57 - rreg = emallocz(len * sizeof(RReg)); 12.58 - for(i = 0; i < len; i++) { 12.59 - if(rule[i].clpattern) { 12.60 - reg = emallocz(sizeof(regex_t)); 12.61 - if(regcomp(reg, rule[i].clpattern, REG_EXTENDED)) 12.62 - free(reg); 12.63 - else 12.64 - rreg[i].clregex = reg; 12.65 - } 12.66 - if(rule[i].tpattern) { 12.67 - reg = emallocz(sizeof(regex_t)); 12.68 - if(regcomp(reg, rule[i].tpattern, REG_EXTENDED)) 12.69 - free(reg); 12.70 - else 12.71 - rreg[i].tregex = reg; 12.72 - } 12.73 - } 12.74 -} 12.75 - 12.76 -void 12.77 -settags(Client *c, Client *trans) { 12.78 - char prop[512]; 12.79 - unsigned int i, j; 12.80 - regmatch_t tmp; 12.81 - Bool matched = trans != NULL; 12.82 - XClassHint ch = { 0 }; 12.83 - 12.84 - if(matched) { 12.85 - for(i = 0; i < ntags; i++) 12.86 - c->tags[i] = trans->tags[i]; 12.87 - } 12.88 - else { 12.89 - XGetClassHint(dpy, c->win, &ch); 12.90 - snprintf(prop, sizeof prop, "%s:%s:%s", 12.91 - ch.res_class ? ch.res_class : "", 12.92 - ch.res_name ? ch.res_name : "", c->name); 12.93 - for(i = 0; i < len; i++) 12.94 - if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) { 12.95 - c->isfloat = rule[i].isfloat; 12.96 - for(j = 0; rreg[i].tregex && j < ntags; j++) { 12.97 - if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) { 12.98 - matched = True; 12.99 - c->tags[j] = True; 12.100 - } 12.101 - } 12.102 - break; /* perform only the first rule matching */ 12.103 - } 12.104 - if(ch.res_class) 12.105 - XFree(ch.res_class); 12.106 - if(ch.res_name) 12.107 - XFree(ch.res_name); 12.108 - } 12.109 - if(!matched) 12.110 - for(i = 0; i < ntags; i++) 12.111 - c->tags[i] = seltag[i]; 12.112 -} 12.113 - 12.114 -void 12.115 -tag(Arg *arg) { 12.116 - unsigned int i; 12.117 - 12.118 - if(!sel) 12.119 - return; 12.120 - for(i = 0; i < ntags; i++) 12.121 - sel->tags[i] = (arg->i == -1) ? True : False; 12.122 - if(arg->i >= 0 && arg->i < ntags) 12.123 - sel->tags[arg->i] = True; 12.124 - arrange(); 12.125 -} 12.126 - 12.127 -void 12.128 -toggletag(Arg *arg) { 12.129 - unsigned int i; 12.130 - 12.131 - if(!sel) 12.132 - return; 12.133 - sel->tags[arg->i] = !sel->tags[arg->i]; 12.134 - for(i = 0; i < ntags && !sel->tags[i]; i++); 12.135 - if(i == ntags) 12.136 - sel->tags[arg->i] = True; 12.137 - arrange(); 12.138 -} 12.139 - 12.140 -/* begin code by jukka */ 12.141 -void 12.142 -viewnext(Arg *arg) { 12.143 - unsigned int i; 12.144 - Bool last = seltag[ntags-1]; 12.145 - 12.146 - for (i=ntags-1; i>0; --i) 12.147 - seltag[i] = seltag[i-1]; 12.148 - seltag[0] = last; 12.149 - arrange(); 12.150 -} 12.151 -/* end code by jukka */
13.1 --- a/util.c Sat Jun 16 21:49:51 2007 +0200 13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 13.3 @@ -1,54 +0,0 @@ 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 -#include <stdarg.h> 13.9 -#include <stdio.h> 13.10 -#include <stdlib.h> 13.11 -#include <sys/wait.h> 13.12 -#include <unistd.h> 13.13 - 13.14 -/* extern */ 13.15 - 13.16 -void * 13.17 -emallocz(unsigned int size) { 13.18 - void *res = calloc(1, size); 13.19 - 13.20 - if(!res) 13.21 - eprint("fatal: could not malloc() %u bytes\n", size); 13.22 - return res; 13.23 -} 13.24 - 13.25 -void 13.26 -eprint(const char *errstr, ...) { 13.27 - va_list ap; 13.28 - 13.29 - va_start(ap, errstr); 13.30 - vfprintf(stderr, errstr, ap); 13.31 - va_end(ap); 13.32 - exit(EXIT_FAILURE); 13.33 -} 13.34 - 13.35 -void 13.36 -spawn(Arg *arg) { 13.37 - static char *shell = NULL; 13.38 - 13.39 - if(!shell && !(shell = getenv("SHELL"))) 13.40 - shell = "/bin/sh"; 13.41 - if(!arg->cmd) 13.42 - return; 13.43 - /* The double-fork construct avoids zombie processes and keeps the code 13.44 - * clean from stupid signal handlers. */ 13.45 - if(fork() == 0) { 13.46 - if(fork() == 0) { 13.47 - if(dpy) 13.48 - close(ConnectionNumber(dpy)); 13.49 - setsid(); 13.50 - execl(shell, shell, "-c", arg->cmd, (char *)NULL); 13.51 - fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd); 13.52 - perror(" failed"); 13.53 - } 13.54 - exit(0); 13.55 - } 13.56 - wait(0); 13.57 -}
14.1 --- a/view.c Sat Jun 16 21:49:51 2007 +0200 14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 14.3 @@ -1,324 +0,0 @@ 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 -#include "dwm.h" 14.8 -#include <stdio.h> 14.9 - 14.10 -/* static */ 14.11 - 14.12 -static Client * 14.13 -nexttiled(Client *c) { 14.14 - for(c = getnext(c); c && c->isfloat; c = getnext(c->next)); 14.15 - return c; 14.16 -} 14.17 - 14.18 -static void 14.19 -togglemax(Client *c) { 14.20 - XEvent ev; 14.21 - 14.22 - if(c->isfixed) 14.23 - return; 14.24 - 14.25 - if((c->ismax = !c->ismax)) { 14.26 - c->rx = c->x; c->x = wax; 14.27 - c->ry = c->y; c->y = way; 14.28 - c->rw = c->w; c->w = waw - 2 * BORDERPX; 14.29 - c->rh = c->h; c->h = wah - 2 * BORDERPX; 14.30 - } 14.31 - else { 14.32 - c->x = c->rx; 14.33 - c->y = c->ry; 14.34 - c->w = c->rw; 14.35 - c->h = c->rh; 14.36 - } 14.37 - resize(c, True); 14.38 - while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 14.39 -} 14.40 - 14.41 -/* extern */ 14.42 - 14.43 -void (*arrange)(void) = DEFMODE; 14.44 - 14.45 -void 14.46 -detach(Client *c) { 14.47 - if(c->prev) 14.48 - c->prev->next = c->next; 14.49 - if(c->next) 14.50 - c->next->prev = c->prev; 14.51 - if(c == clients) 14.52 - clients = c->next; 14.53 - c->next = c->prev = NULL; 14.54 -} 14.55 - 14.56 -void 14.57 -dofloat(void) { 14.58 - Client *c; 14.59 - 14.60 - for(c = clients; c; c = c->next) { 14.61 - if(isvisible(c)) { 14.62 - resize(c, True); 14.63 - } 14.64 - else 14.65 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 14.66 - } 14.67 - if(!sel || !isvisible(sel)) { 14.68 - for(c = stack; c && !isvisible(c); c = c->snext); 14.69 - focus(c); 14.70 - } 14.71 - restack(); 14.72 -} 14.73 - 14.74 -void 14.75 -dotile(void) { 14.76 - unsigned int i, n, mw, mh, tw, th; 14.77 - Client *c; 14.78 - 14.79 - for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) 14.80 - n++; 14.81 - /* window geoms */ 14.82 - mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1); 14.83 - mw = (n > nmaster) ? (waw * master) / 1000 : waw; 14.84 - th = (n > nmaster) ? wah / (n - nmaster) : 0; 14.85 - tw = waw - mw; 14.86 - 14.87 - for(i = 0, c = clients; c; c = c->next) 14.88 - if(isvisible(c)) { 14.89 - if(c->isfloat) { 14.90 - resize(c, True); 14.91 - continue; 14.92 - } 14.93 - c->ismax = False; 14.94 - c->x = wax; 14.95 - c->y = way; 14.96 - if(i < nmaster) { 14.97 - c->y += i * mh; 14.98 - c->w = mw - 2 * BORDERPX; 14.99 - c->h = mh - 2 * BORDERPX; 14.100 - } 14.101 - else { /* tile window */ 14.102 - c->x += mw; 14.103 - c->w = tw - 2 * BORDERPX; 14.104 - if(th > 2 * BORDERPX) { 14.105 - c->y += (i - nmaster) * th; 14.106 - c->h = th - 2 * BORDERPX; 14.107 - } 14.108 - else /* fallback if th <= 2 * BORDERPX */ 14.109 - c->h = wah - 2 * BORDERPX; 14.110 - } 14.111 - resize(c, False); 14.112 - i++; 14.113 - } 14.114 - else 14.115 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 14.116 - if(!sel || !isvisible(sel)) { 14.117 - for(c = stack; c && !isvisible(c); c = c->snext); 14.118 - focus(c); 14.119 - } 14.120 - restack(); 14.121 -} 14.122 - 14.123 -/* begin code by mitch */ 14.124 -void 14.125 -arrangemax(Client *c) { 14.126 - if(c == sel) { 14.127 - c->ismax = True; 14.128 - c->x = sx; 14.129 - c->y = bh; 14.130 - c->w = sw - 2 * BORDERPX; 14.131 - c->h = sh - bh - 2 * BORDERPX; 14.132 - XRaiseWindow(dpy, c->win); 14.133 - } else { 14.134 - c->ismax = False; 14.135 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 14.136 - XLowerWindow(dpy, c->win); 14.137 - } 14.138 -} 14.139 - 14.140 -void 14.141 -domax(void) { 14.142 - Client *c; 14.143 - 14.144 - for(c = clients; c; c = c->next) { 14.145 - if(isvisible(c)) { 14.146 - if(c->isfloat) { 14.147 - resize(c, True); 14.148 - continue; 14.149 - } 14.150 - arrangemax(c); 14.151 - resize(c, False); 14.152 - } else { 14.153 - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); 14.154 - } 14.155 - 14.156 - } 14.157 - if(!sel || !isvisible(sel)) { 14.158 - for(c = stack; c && !isvisible(c); c = c->snext); 14.159 - focus(c); 14.160 - } 14.161 - restack(); 14.162 -} 14.163 -/* end code by mitch */ 14.164 - 14.165 -void 14.166 -focusnext(Arg *arg) { 14.167 - Client *c; 14.168 - 14.169 - if(!sel) 14.170 - return; 14.171 - if(!(c = getnext(sel->next))) 14.172 - c = getnext(clients); 14.173 - if(c) { 14.174 - focus(c); 14.175 - restack(); 14.176 - } 14.177 -} 14.178 - 14.179 -void 14.180 -focusprev(Arg *arg) { 14.181 - Client *c; 14.182 - 14.183 - if(!sel) 14.184 - return; 14.185 - if(!(c = getprev(sel->prev))) { 14.186 - for(c = clients; c && c->next; c = c->next); 14.187 - c = getprev(c); 14.188 - } 14.189 - if(c) { 14.190 - focus(c); 14.191 - restack(); 14.192 - } 14.193 -} 14.194 - 14.195 -void 14.196 -incnmaster(Arg *arg) { 14.197 - if((arrange == dofloat) || (nmaster + arg->i < 1) 14.198 - || (wah / (nmaster + arg->i) <= 2 * BORDERPX)) 14.199 - return; 14.200 - nmaster += arg->i; 14.201 - if(sel) 14.202 - arrange(); 14.203 - else 14.204 - drawstatus(); 14.205 -} 14.206 - 14.207 -Bool 14.208 -isvisible(Client *c) { 14.209 - unsigned int i; 14.210 - 14.211 - for(i = 0; i < ntags; i++) 14.212 - if(c->tags[i] && seltag[i]) 14.213 - return True; 14.214 - return False; 14.215 -} 14.216 - 14.217 -void 14.218 -resizemaster(Arg *arg) { 14.219 - if(arg->i == 0) 14.220 - master = MASTER; 14.221 - else { 14.222 - if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX 14.223 - || waw * (master + arg->i) / 1000 <= 2 * BORDERPX) 14.224 - return; 14.225 - master += arg->i; 14.226 - } 14.227 - arrange(); 14.228 -} 14.229 - 14.230 -void 14.231 -restack(void) { 14.232 - Client *c; 14.233 - XEvent ev; 14.234 - 14.235 - drawstatus(); 14.236 - if(!sel) 14.237 - return; 14.238 - if(sel->isfloat || arrange == dofloat) 14.239 - XRaiseWindow(dpy, sel->win); 14.240 - 14.241 - /* begin code by mitch */ 14.242 - if(arrange == domax) { 14.243 - for(c = nexttiled(clients); c; c = nexttiled(c->next)) { 14.244 - arrangemax(c); 14.245 - resize(c, False); 14.246 - } 14.247 - 14.248 - } else if (arrange == dotile) { 14.249 - /* end code by mitch */ 14.250 - 14.251 - if(!sel->isfloat) 14.252 - XLowerWindow(dpy, sel->win); 14.253 - for(c = nexttiled(clients); c; c = nexttiled(c->next)) { 14.254 - if(c == sel) 14.255 - continue; 14.256 - XLowerWindow(dpy, c->win); 14.257 - } 14.258 - } 14.259 - XSync(dpy, False); 14.260 - while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 14.261 -} 14.262 - 14.263 -void 14.264 -togglefloat(Arg *arg) { 14.265 - if (!sel || arrange == dofloat) 14.266 - return; 14.267 - sel->isfloat = !sel->isfloat; 14.268 - arrange(); 14.269 -} 14.270 - 14.271 -void 14.272 -togglemode(Arg *arg) { 14.273 - /* only toggle between tile and max - float is just available through togglefloat */ 14.274 - arrange = (arrange == dotile) ? domax : dotile; 14.275 - if(sel) 14.276 - arrange(); 14.277 - else 14.278 - drawstatus(); 14.279 -} 14.280 - 14.281 -void 14.282 -toggleview(Arg *arg) { 14.283 - unsigned int i; 14.284 - 14.285 - seltag[arg->i] = !seltag[arg->i]; 14.286 - for(i = 0; i < ntags && !seltag[i]; i++); 14.287 - if(i == ntags) 14.288 - seltag[arg->i] = True; /* cannot toggle last view */ 14.289 - arrange(); 14.290 -} 14.291 - 14.292 -void 14.293 -view(Arg *arg) { 14.294 - unsigned int i; 14.295 - 14.296 - for(i = 0; i < ntags; i++) 14.297 - seltag[i] = (arg->i == -1) ? True : False; 14.298 - if(arg->i >= 0 && arg->i < ntags) 14.299 - seltag[arg->i] = True; 14.300 - arrange(); 14.301 -} 14.302 - 14.303 -void 14.304 -zoom(Arg *arg) { 14.305 - unsigned int n; 14.306 - Client *c; 14.307 - 14.308 - if(!sel) 14.309 - return; 14.310 - if(sel->isfloat || (arrange == dofloat)) { 14.311 - togglemax(sel); 14.312 - return; 14.313 - } 14.314 - for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) 14.315 - n++; 14.316 - 14.317 - if((c = sel) == nexttiled(clients)) 14.318 - if(!(c = nexttiled(c->next))) 14.319 - return; 14.320 - detach(c); 14.321 - if(clients) 14.322 - clients->prev = c; 14.323 - c->next = clients; 14.324 - clients = c; 14.325 - focus(c); 14.326 - arrange(); 14.327 -}