dwm.c
changeset 1001 2477f818215c
parent 1000 55e4d698f53a
child 1002 5cc2be8efeb4
equal deleted inserted replaced
1000:55e4d698f53a 1001:2477f818215c
    19  * stack list. Each client contains an array of Bools of the same size as the
    19  * stack list. Each client contains an array of Bools of the same size as the
    20  * global tags array to indicate the tags of a client.  For each client dwm
    20  * global tags array to indicate the tags of a client.  For each client dwm
    21  * creates a small title window, which is resized whenever the (_NET_)WM_NAME
    21  * creates a small title window, which is resized whenever the (_NET_)WM_NAME
    22  * properties are updated or the client is moved/resized.
    22  * properties are updated or the client is moved/resized.
    23  *
    23  *
    24  * Keys and tagging rules are organized as arrays and defined in the config.h
    24  * Keys and tagging rules are organized as arrays and defined in config.h.
    25  * file. These arrays are kept static in event.o and tag.o respectively,
       
    26  * because no other part of dwm needs access to them.  The current layout is
       
    27  * represented by the lt pointer.
       
    28  *
    25  *
    29  * To understand everything else, start reading main().
    26  * To understand everything else, start reading main().
    30  */
    27  */
    31 #include <errno.h>
    28 #include <errno.h>
    32 #include <locale.h>
    29 #include <locale.h>
   112 	regex_t *propregex;
   109 	regex_t *propregex;
   113 	regex_t *tagregex;
   110 	regex_t *tagregex;
   114 } Regs;
   111 } Regs;
   115 
   112 
   116 /* forward declarations */
   113 /* forward declarations */
   117 static void applyrules(Client *c);
   114 void applyrules(Client *c);
   118 static void arrange(void);
   115 void arrange(void);
   119 static void attach(Client *c);
   116 void attach(Client *c);
   120 static void attachstack(Client *c);
   117 void attachstack(Client *c);
   121 static void ban(Client *c);
   118 void ban(Client *c);
   122 static void buttonpress(XEvent *e);
   119 void buttonpress(XEvent *e);
   123 static void checkotherwm(void);
   120 void checkotherwm(void);
   124 static void cleanup(void);
   121 void cleanup(void);
   125 static void compileregs(void);
   122 void compileregs(void);
   126 static void configure(Client *c);
   123 void configure(Client *c);
   127 static void configurenotify(XEvent *e);
   124 void configurenotify(XEvent *e);
   128 static void configurerequest(XEvent *e);
   125 void configurerequest(XEvent *e);
   129 static void destroynotify(XEvent *e);
   126 void destroynotify(XEvent *e);
   130 static void detach(Client *c);
   127 void detach(Client *c);
   131 static void detachstack(Client *c);
   128 void detachstack(Client *c);
   132 static void drawbar(void);
   129 void drawbar(void);
   133 static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]);
   130 void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]);
   134 static void drawtext(const char *text, unsigned long col[ColLast]);
   131 void drawtext(const char *text, unsigned long col[ColLast]);
   135 static void *emallocz(unsigned int size);
   132 void *emallocz(unsigned int size);
   136 static void enternotify(XEvent *e);
   133 void enternotify(XEvent *e);
   137 static void eprint(const char *errstr, ...);
   134 void eprint(const char *errstr, ...);
   138 static void expose(XEvent *e);
   135 void expose(XEvent *e);
   139 static void floating(void); /* default floating layout */
   136 void floating(void); /* default floating layout */
   140 static void focus(Client *c);
   137 void focus(Client *c);
   141 static void focusnext(const char *arg);
   138 void focusnext(const char *arg);
   142 static void focusprev(const char *arg);
   139 void focusprev(const char *arg);
   143 static Client *getclient(Window w);
   140 Client *getclient(Window w);
   144 static unsigned long getcolor(const char *colstr);
   141 unsigned long getcolor(const char *colstr);
   145 static long getstate(Window w);
   142 long getstate(Window w);
   146 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   143 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   147 static void grabbuttons(Client *c, Bool focused);
   144 void grabbuttons(Client *c, Bool focused);
   148 static unsigned int idxoftag(const char *tag);
   145 unsigned int idxoftag(const char *tag);
   149 static void initfont(const char *fontstr);
   146 void initfont(const char *fontstr);
   150 static Bool isarrange(void (*func)());
   147 Bool isarrange(void (*func)());
   151 static Bool isoccupied(unsigned int t);
   148 Bool isoccupied(unsigned int t);
   152 static Bool isprotodel(Client *c);
   149 Bool isprotodel(Client *c);
   153 static Bool isvisible(Client *c);
   150 Bool isvisible(Client *c);
   154 static void keypress(XEvent *e);
   151 void keypress(XEvent *e);
   155 static void killclient(const char *arg);
   152 void killclient(const char *arg);
   156 static void leavenotify(XEvent *e);
   153 void leavenotify(XEvent *e);
   157 static void manage(Window w, XWindowAttributes *wa);
   154 void manage(Window w, XWindowAttributes *wa);
   158 static void mappingnotify(XEvent *e);
   155 void mappingnotify(XEvent *e);
   159 static void maprequest(XEvent *e);
   156 void maprequest(XEvent *e);
   160 static void movemouse(Client *c);
   157 void movemouse(Client *c);
   161 static Client *nexttiled(Client *c);
   158 Client *nexttiled(Client *c);
   162 static void propertynotify(XEvent *e);
   159 void propertynotify(XEvent *e);
   163 static void quit(const char *arg);
   160 void quit(const char *arg);
   164 static void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   161 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   165 static void resizemouse(Client *c);
   162 void resizemouse(Client *c);
   166 static void restack(void);
   163 void restack(void);
   167 static void run(void);
   164 void run(void);
   168 static void scan(void);
   165 void scan(void);
   169 static void setclientstate(Client *c, long state);
   166 void setclientstate(Client *c, long state);
   170 static void setlayout(const char *arg);
   167 void setlayout(const char *arg);
   171 static void setmwfact(const char *arg);
   168 void setmwfact(const char *arg);
   172 static void setup(void);
   169 void setup(void);
   173 static void spawn(const char *arg);
   170 void spawn(const char *arg);
   174 static void tag(const char *arg);
   171 void tag(const char *arg);
   175 static unsigned int textnw(const char *text, unsigned int len);
   172 unsigned int textnw(const char *text, unsigned int len);
   176 static unsigned int textw(const char *text);
   173 unsigned int textw(const char *text);
   177 static void tile(void);
   174 void tile(void);
   178 static void togglebar(const char *arg);
   175 void togglebar(const char *arg);
   179 static void togglefloating(const char *arg);
   176 void togglefloating(const char *arg);
   180 static void togglemax(const char *arg);
   177 void togglemax(const char *arg);
   181 static void toggletag(const char *arg);
   178 void toggletag(const char *arg);
   182 static void toggleview(const char *arg);
   179 void toggleview(const char *arg);
   183 static void unban(Client *c);
   180 void unban(Client *c);
   184 static void unmanage(Client *c);
   181 void unmanage(Client *c);
   185 static void unmapnotify(XEvent *e);
   182 void unmapnotify(XEvent *e);
   186 static void updatebarpos(void);
   183 void updatebarpos(void);
   187 static void updatesizehints(Client *c);
   184 void updatesizehints(Client *c);
   188 static void updatetitle(Client *c);
   185 void updatetitle(Client *c);
   189 static void view(const char *arg);
   186 void view(const char *arg);
   190 static int xerror(Display *dpy, XErrorEvent *ee);
   187 int xerror(Display *dpy, XErrorEvent *ee);
   191 static int xerrordummy(Display *dsply, XErrorEvent *ee);
   188 int xerrordummy(Display *dsply, XErrorEvent *ee);
   192 static int xerrorstart(Display *dsply, XErrorEvent *ee);
   189 int xerrorstart(Display *dsply, XErrorEvent *ee);
   193 static void zoom(const char *arg);
   190 void zoom(const char *arg);
   194 
   191 
   195 /* variables */
   192 /* variables */
   196 static char stext[256];
   193 char stext[256];
   197 static double mwfact;
   194 double mwfact;
   198 static int screen, sx, sy, sw, sh, wax, way, waw, wah;
   195 int screen, sx, sy, sw, sh, wax, way, waw, wah;
   199 static int (*xerrorxlib)(Display *, XErrorEvent *);
   196 int (*xerrorxlib)(Display *, XErrorEvent *);
   200 static unsigned int bh, bpos, ntags;
   197 unsigned int bh, bpos, ntags;
   201 static unsigned int blw = 0;
   198 unsigned int blw = 0;
   202 static unsigned int ltidx = 0; /* default */
   199 unsigned int ltidx = 0; /* default */
   203 static unsigned int nlayouts = 0;
   200 unsigned int nlayouts = 0;
   204 static unsigned int nrules = 0;
   201 unsigned int nrules = 0;
   205 static unsigned int numlockmask = 0;
   202 unsigned int numlockmask = 0;
   206 static void (*handler[LASTEvent]) (XEvent *) = {
   203 void (*handler[LASTEvent]) (XEvent *) = {
   207 	[ButtonPress] = buttonpress,
   204 	[ButtonPress] = buttonpress,
   208 	[ConfigureRequest] = configurerequest,
   205 	[ConfigureRequest] = configurerequest,
   209 	[ConfigureNotify] = configurenotify,
   206 	[ConfigureNotify] = configurenotify,
   210 	[DestroyNotify] = destroynotify,
   207 	[DestroyNotify] = destroynotify,
   211 	[EnterNotify] = enternotify,
   208 	[EnterNotify] = enternotify,
   215 	[MappingNotify] = mappingnotify,
   212 	[MappingNotify] = mappingnotify,
   216 	[MapRequest] = maprequest,
   213 	[MapRequest] = maprequest,
   217 	[PropertyNotify] = propertynotify,
   214 	[PropertyNotify] = propertynotify,
   218 	[UnmapNotify] = unmapnotify
   215 	[UnmapNotify] = unmapnotify
   219 };
   216 };
   220 static Atom wmatom[WMLast], netatom[NetLast];
   217 Atom wmatom[WMLast], netatom[NetLast];
   221 static Bool otherwm, readin;
   218 Bool otherwm, readin;
   222 static Bool running = True;
   219 Bool running = True;
   223 static Bool *seltags;
   220 Bool *seltags;
   224 static Bool selscreen = True;
   221 Bool selscreen = True;
   225 static Client *clients = NULL;
   222 Client *clients = NULL;
   226 static Client *sel = NULL;
   223 Client *sel = NULL;
   227 static Client *stack = NULL;
   224 Client *stack = NULL;
   228 static Cursor cursor[CurLast];
   225 Cursor cursor[CurLast];
   229 static Display *dpy;
   226 Display *dpy;
   230 static DC dc = {0};
   227 DC dc = {0};
   231 static Window barwin, root;
   228 Window barwin, root;
   232 static Regs *regs = NULL;
   229 Regs *regs = NULL;
   233 
   230 
   234 /* configuration, allows nested code to access above variables */
   231 /* configuration, allows nested code to access above variables */
   235 #include "config.h"
   232 #include "config.h"
   236 
   233 
   237 /* functions*/
   234 /* functions*/
   238 static void
   235 void
   239 applyrules(Client *c) {
   236 applyrules(Client *c) {
   240 	static char buf[512];
   237 	static char buf[512];
   241 	unsigned int i, j;
   238 	unsigned int i, j;
   242 	regmatch_t tmp;
   239 	regmatch_t tmp;
   243 	Bool matched = False;
   240 	Bool matched = False;
   265 	if(!matched)
   262 	if(!matched)
   266 		for(i = 0; i < ntags; i++)
   263 		for(i = 0; i < ntags; i++)
   267 			c->tags[i] = seltags[i];
   264 			c->tags[i] = seltags[i];
   268 }
   265 }
   269 
   266 
   270 static void
   267 void
   271 arrange(void) {
   268 arrange(void) {
   272 	Client *c;
   269 	Client *c;
   273 
   270 
   274 	for(c = clients; c; c = c->next)
   271 	for(c = clients; c; c = c->next)
   275 		if(isvisible(c))
   272 		if(isvisible(c))
   279 	layouts[ltidx].arrange();
   276 	layouts[ltidx].arrange();
   280 	focus(NULL);
   277 	focus(NULL);
   281 	restack();
   278 	restack();
   282 }
   279 }
   283 
   280 
   284 static void
   281 void
   285 attach(Client *c) {
   282 attach(Client *c) {
   286 	if(clients)
   283 	if(clients)
   287 		clients->prev = c;
   284 		clients->prev = c;
   288 	c->next = clients;
   285 	c->next = clients;
   289 	clients = c;
   286 	clients = c;
   290 }
   287 }
   291 
   288 
   292 static void
   289 void
   293 attachstack(Client *c) {
   290 attachstack(Client *c) {
   294 	c->snext = stack;
   291 	c->snext = stack;
   295 	stack = c;
   292 	stack = c;
   296 }
   293 }
   297 
   294 
   298 static void
   295 void
   299 ban(Client *c) {
   296 ban(Client *c) {
   300 	if(c->isbanned)
   297 	if(c->isbanned)
   301 		return;
   298 		return;
   302 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
   299 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
   303 	c->isbanned = True;
   300 	c->isbanned = True;
   304 }
   301 }
   305 
   302 
   306 static void
   303 void
   307 buttonpress(XEvent *e) {
   304 buttonpress(XEvent *e) {
   308 	unsigned int i, x;
   305 	unsigned int i, x;
   309 	Client *c;
   306 	Client *c;
   310 	XButtonPressedEvent *ev = &e->xbutton;
   307 	XButtonPressedEvent *ev = &e->xbutton;
   311 
   308 
   357 			resizemouse(c);
   354 			resizemouse(c);
   358 		}
   355 		}
   359 	}
   356 	}
   360 }
   357 }
   361 
   358 
   362 static void
   359 void
   363 checkotherwm(void) {
   360 checkotherwm(void) {
   364 	otherwm = False;
   361 	otherwm = False;
   365 	XSetErrorHandler(xerrorstart);
   362 	XSetErrorHandler(xerrorstart);
   366 
   363 
   367 	/* this causes an error if some other window manager is running */
   364 	/* this causes an error if some other window manager is running */
   373 	XSetErrorHandler(NULL);
   370 	XSetErrorHandler(NULL);
   374 	xerrorxlib = XSetErrorHandler(xerror);
   371 	xerrorxlib = XSetErrorHandler(xerror);
   375 	XSync(dpy, False);
   372 	XSync(dpy, False);
   376 }
   373 }
   377 
   374 
   378 static void
   375 void
   379 cleanup(void) {
   376 cleanup(void) {
   380 	close(STDIN_FILENO);
   377 	close(STDIN_FILENO);
   381 	while(stack) {
   378 	while(stack) {
   382 		unban(stack);
   379 		unban(stack);
   383 		unmanage(stack);
   380 		unmanage(stack);
   396 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   393 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   397 	XSync(dpy, False);
   394 	XSync(dpy, False);
   398 	free(seltags);
   395 	free(seltags);
   399 }
   396 }
   400 
   397 
   401 static void
   398 void
   402 compileregs(void) {
   399 compileregs(void) {
   403 	unsigned int i;
   400 	unsigned int i;
   404 	regex_t *reg;
   401 	regex_t *reg;
   405 
   402 
   406 	if(regs)
   403 	if(regs)
   423 				regs[i].tagregex = reg;
   420 				regs[i].tagregex = reg;
   424 		}
   421 		}
   425 	}
   422 	}
   426 }
   423 }
   427 
   424 
   428 static void
   425 void
   429 configure(Client *c) {
   426 configure(Client *c) {
   430 	XConfigureEvent ce;
   427 	XConfigureEvent ce;
   431 
   428 
   432 	ce.type = ConfigureNotify;
   429 	ce.type = ConfigureNotify;
   433 	ce.display = dpy;
   430 	ce.display = dpy;
   441 	ce.above = None;
   438 	ce.above = None;
   442 	ce.override_redirect = False;
   439 	ce.override_redirect = False;
   443 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   440 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   444 }
   441 }
   445 
   442 
   446 static void
   443 void
   447 configurenotify(XEvent *e) {
   444 configurenotify(XEvent *e) {
   448 	XConfigureEvent *ev = &e->xconfigure;
   445 	XConfigureEvent *ev = &e->xconfigure;
   449 
   446 
   450 	if (ev->window == root && (ev->width != sw || ev->height != sh)) {
   447 	if (ev->window == root && (ev->width != sw || ev->height != sh)) {
   451 		sw = ev->width;
   448 		sw = ev->width;
   456 		updatebarpos();
   453 		updatebarpos();
   457 		arrange();
   454 		arrange();
   458 	}
   455 	}
   459 }
   456 }
   460 
   457 
   461 static void
   458 void
   462 configurerequest(XEvent *e) {
   459 configurerequest(XEvent *e) {
   463 	Client *c;
   460 	Client *c;
   464 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   461 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   465 	XWindowChanges wc;
   462 	XWindowChanges wc;
   466 
   463 
   501 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   498 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   502 	}
   499 	}
   503 	XSync(dpy, False);
   500 	XSync(dpy, False);
   504 }
   501 }
   505 
   502 
   506 static void
   503 void
   507 destroynotify(XEvent *e) {
   504 destroynotify(XEvent *e) {
   508 	Client *c;
   505 	Client *c;
   509 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   506 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   510 
   507 
   511 	if((c = getclient(ev->window)))
   508 	if((c = getclient(ev->window)))
   512 		unmanage(c);
   509 		unmanage(c);
   513 }
   510 }
   514 
   511 
   515 static void
   512 void
   516 detach(Client *c) {
   513 detach(Client *c) {
   517 	if(c->prev)
   514 	if(c->prev)
   518 		c->prev->next = c->next;
   515 		c->prev->next = c->next;
   519 	if(c->next)
   516 	if(c->next)
   520 		c->next->prev = c->prev;
   517 		c->next->prev = c->prev;
   521 	if(c == clients)
   518 	if(c == clients)
   522 		clients = c->next;
   519 		clients = c->next;
   523 	c->next = c->prev = NULL;
   520 	c->next = c->prev = NULL;
   524 }
   521 }
   525 
   522 
   526 static void
   523 void
   527 detachstack(Client *c) {
   524 detachstack(Client *c) {
   528 	Client **tc;
   525 	Client **tc;
   529 
   526 
   530 	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
   527 	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
   531 	*tc = c->snext;
   528 	*tc = c->snext;
   532 }
   529 }
   533 
   530 
   534 static void
   531 void
   535 drawbar(void) {
   532 drawbar(void) {
   536 	int i, x;
   533 	int i, x;
   537 
   534 
   538 	dc.x = dc.y = 0;
   535 	dc.x = dc.y = 0;
   539 	for(i = 0; i < ntags; i++) {
   536 	for(i = 0; i < ntags; i++) {
   569 	}
   566 	}
   570 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
   567 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
   571 	XSync(dpy, False);
   568 	XSync(dpy, False);
   572 }
   569 }
   573 
   570 
   574 static void
   571 void
   575 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
   572 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
   576 	int x;
   573 	int x;
   577 	XGCValues gcv;
   574 	XGCValues gcv;
   578 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   575 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   579 
   576 
   590 		r.width = r.height = x;
   587 		r.width = r.height = x;
   591 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   588 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   592 	}
   589 	}
   593 }
   590 }
   594 
   591 
   595 static void
   592 void
   596 drawtext(const char *text, unsigned long col[ColLast]) {
   593 drawtext(const char *text, unsigned long col[ColLast]) {
   597 	int x, y, w, h;
   594 	int x, y, w, h;
   598 	static char buf[256];
   595 	static char buf[256];
   599 	unsigned int len, olen;
   596 	unsigned int len, olen;
   600 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   597 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   630 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
   627 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
   631 	else
   628 	else
   632 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   629 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   633 }
   630 }
   634 
   631 
   635 static void *
   632 void *
   636 emallocz(unsigned int size) {
   633 emallocz(unsigned int size) {
   637 	void *res = calloc(1, size);
   634 	void *res = calloc(1, size);
   638 
   635 
   639 	if(!res)
   636 	if(!res)
   640 		eprint("fatal: could not malloc() %u bytes\n", size);
   637 		eprint("fatal: could not malloc() %u bytes\n", size);
   641 	return res;
   638 	return res;
   642 }
   639 }
   643 
   640 
   644 static void
   641 void
   645 enternotify(XEvent *e) {
   642 enternotify(XEvent *e) {
   646 	Client *c;
   643 	Client *c;
   647 	XCrossingEvent *ev = &e->xcrossing;
   644 	XCrossingEvent *ev = &e->xcrossing;
   648 
   645 
   649 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
   646 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
   654 		selscreen = True;
   651 		selscreen = True;
   655 		focus(NULL);
   652 		focus(NULL);
   656 	}
   653 	}
   657 }
   654 }
   658 
   655 
   659 static void
   656 void
   660 eprint(const char *errstr, ...) {
   657 eprint(const char *errstr, ...) {
   661 	va_list ap;
   658 	va_list ap;
   662 
   659 
   663 	va_start(ap, errstr);
   660 	va_start(ap, errstr);
   664 	vfprintf(stderr, errstr, ap);
   661 	vfprintf(stderr, errstr, ap);
   665 	va_end(ap);
   662 	va_end(ap);
   666 	exit(EXIT_FAILURE);
   663 	exit(EXIT_FAILURE);
   667 }
   664 }
   668 
   665 
   669 static void
   666 void
   670 expose(XEvent *e) {
   667 expose(XEvent *e) {
   671 	XExposeEvent *ev = &e->xexpose;
   668 	XExposeEvent *ev = &e->xexpose;
   672 
   669 
   673 	if(ev->count == 0) {
   670 	if(ev->count == 0) {
   674 		if(barwin == ev->window)
   671 		if(barwin == ev->window)
   675 			drawbar();
   672 			drawbar();
   676 	}
   673 	}
   677 }
   674 }
   678 
   675 
   679 static void
   676 void
   680 floating(void) { /* default floating layout */
   677 floating(void) { /* default floating layout */
   681 	Client *c;
   678 	Client *c;
   682 
   679 
   683 	for(c = clients; c; c = c->next)
   680 	for(c = clients; c; c = c->next)
   684 		if(isvisible(c))
   681 		if(isvisible(c))
   685 			resize(c, c->x, c->y, c->w, c->h, True);
   682 			resize(c, c->x, c->y, c->w, c->h, True);
   686 }
   683 }
   687 
   684 
   688 static void
   685 void
   689 focus(Client *c) {
   686 focus(Client *c) {
   690 	if((!c && selscreen) || (c && !isvisible(c)))
   687 	if((!c && selscreen) || (c && !isvisible(c)))
   691 		for(c = stack; c && !isvisible(c); c = c->snext);
   688 		for(c = stack; c && !isvisible(c); c = c->snext);
   692 	if(sel && sel != c) {
   689 	if(sel && sel != c) {
   693 		grabbuttons(sel, False);
   690 		grabbuttons(sel, False);
   708 	}
   705 	}
   709 	else
   706 	else
   710 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   707 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   711 }
   708 }
   712 
   709 
   713 static void
   710 void
   714 focusnext(const char *arg) {
   711 focusnext(const char *arg) {
   715 	Client *c;
   712 	Client *c;
   716 
   713 
   717 	if(!sel)
   714 	if(!sel)
   718 		return;
   715 		return;
   723 		focus(c);
   720 		focus(c);
   724 		restack();
   721 		restack();
   725 	}
   722 	}
   726 }
   723 }
   727 
   724 
   728 static void
   725 void
   729 focusprev(const char *arg) {
   726 focusprev(const char *arg) {
   730 	Client *c;
   727 	Client *c;
   731 
   728 
   732 	if(!sel)
   729 	if(!sel)
   733 		return;
   730 		return;
   740 		focus(c);
   737 		focus(c);
   741 		restack();
   738 		restack();
   742 	}
   739 	}
   743 }
   740 }
   744 
   741 
   745 static Client *
   742 Client *
   746 getclient(Window w) {
   743 getclient(Window w) {
   747 	Client *c;
   744 	Client *c;
   748 
   745 
   749 	for(c = clients; c && c->win != w; c = c->next);
   746 	for(c = clients; c && c->win != w; c = c->next);
   750 	return c;
   747 	return c;
   751 }
   748 }
   752 
   749 
   753 static unsigned long
   750 unsigned long
   754 getcolor(const char *colstr) {
   751 getcolor(const char *colstr) {
   755 	Colormap cmap = DefaultColormap(dpy, screen);
   752 	Colormap cmap = DefaultColormap(dpy, screen);
   756 	XColor color;
   753 	XColor color;
   757 
   754 
   758 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   755 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   759 		eprint("error, cannot allocate color '%s'\n", colstr);
   756 		eprint("error, cannot allocate color '%s'\n", colstr);
   760 	return color.pixel;
   757 	return color.pixel;
   761 }
   758 }
   762 
   759 
   763 static long
   760 long
   764 getstate(Window w) {
   761 getstate(Window w) {
   765 	int format, status;
   762 	int format, status;
   766 	long result = -1;
   763 	long result = -1;
   767 	unsigned char *p = NULL;
   764 	unsigned char *p = NULL;
   768 	unsigned long n, extra;
   765 	unsigned long n, extra;
   776 		result = *p;
   773 		result = *p;
   777 	XFree(p);
   774 	XFree(p);
   778 	return result;
   775 	return result;
   779 }
   776 }
   780 
   777 
   781 static Bool
   778 Bool
   782 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
   779 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
   783 	char **list = NULL;
   780 	char **list = NULL;
   784 	int n;
   781 	int n;
   785 	XTextProperty name;
   782 	XTextProperty name;
   786 
   783 
   803 	text[size - 1] = '\0';
   800 	text[size - 1] = '\0';
   804 	XFree(name.value);
   801 	XFree(name.value);
   805 	return True;
   802 	return True;
   806 }
   803 }
   807 
   804 
   808 static void
   805 void
   809 grabbuttons(Client *c, Bool focused) {
   806 grabbuttons(Client *c, Bool focused) {
   810 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   807 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   811 
   808 
   812 	if(focused) {
   809 	if(focused) {
   813 		XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
   810 		XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
   840 	else
   837 	else
   841 		XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
   838 		XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
   842 				GrabModeAsync, GrabModeSync, None, None);
   839 				GrabModeAsync, GrabModeSync, None, None);
   843 }
   840 }
   844 
   841 
   845 static unsigned int
   842 unsigned int
   846 idxoftag(const char *tag) {
   843 idxoftag(const char *tag) {
   847 	unsigned int i;
   844 	unsigned int i;
   848 
   845 
   849 	for(i = 0; i < ntags; i++)
   846 	for(i = 0; i < ntags; i++)
   850 		if(tags[i] == tag)
   847 		if(tags[i] == tag)
   851 			return i;
   848 			return i;
   852 	return 0;
   849 	return 0;
   853 }
   850 }
   854 
   851 
   855 static void
   852 void
   856 initfont(const char *fontstr) {
   853 initfont(const char *fontstr) {
   857 	char *def, **missing;
   854 	char *def, **missing;
   858 	int i, n;
   855 	int i, n;
   859 
   856 
   860 	missing = NULL;
   857 	missing = NULL;
   892 		dc.font.descent = dc.font.xfont->descent;
   889 		dc.font.descent = dc.font.xfont->descent;
   893 	}
   890 	}
   894 	dc.font.height = dc.font.ascent + dc.font.descent;
   891 	dc.font.height = dc.font.ascent + dc.font.descent;
   895 }
   892 }
   896 
   893 
   897 static Bool
   894 Bool
   898 isarrange(void (*func)())
   895 isarrange(void (*func)())
   899 {
   896 {
   900 	return func == layouts[ltidx].arrange;
   897 	return func == layouts[ltidx].arrange;
   901 }
   898 }
   902 
   899 
   903 static Bool
   900 Bool
   904 isoccupied(unsigned int t) {
   901 isoccupied(unsigned int t) {
   905 	Client *c;
   902 	Client *c;
   906 
   903 
   907 	for(c = clients; c; c = c->next)
   904 	for(c = clients; c; c = c->next)
   908 		if(c->tags[t])
   905 		if(c->tags[t])
   909 			return True;
   906 			return True;
   910 	return False;
   907 	return False;
   911 }
   908 }
   912 
   909 
   913 static Bool
   910 Bool
   914 isprotodel(Client *c) {
   911 isprotodel(Client *c) {
   915 	int i, n;
   912 	int i, n;
   916 	Atom *protocols;
   913 	Atom *protocols;
   917 	Bool ret = False;
   914 	Bool ret = False;
   918 
   915 
   923 		XFree(protocols);
   920 		XFree(protocols);
   924 	}
   921 	}
   925 	return ret;
   922 	return ret;
   926 }
   923 }
   927 
   924 
   928 static Bool
   925 Bool
   929 isvisible(Client *c) {
   926 isvisible(Client *c) {
   930 	unsigned int i;
   927 	unsigned int i;
   931 
   928 
   932 	for(i = 0; i < ntags; i++)
   929 	for(i = 0; i < ntags; i++)
   933 		if(c->tags[i] && seltags[i])
   930 		if(c->tags[i] && seltags[i])
   934 			return True;
   931 			return True;
   935 	return False;
   932 	return False;
   936 }
   933 }
   937 
   934 
   938 static void
   935 void
   939 keypress(XEvent *e) {
   936 keypress(XEvent *e) {
   940 	KEYS
   937 	KEYS
   941 	unsigned int len = sizeof keys / sizeof keys[0];
   938 	unsigned int len = sizeof keys / sizeof keys[0];
   942 	unsigned int i;
   939 	unsigned int i;
   943 	KeyCode code;
   940 	KeyCode code;
   968 			if(keys[i].func)
   965 			if(keys[i].func)
   969 				keys[i].func(keys[i].arg);
   966 				keys[i].func(keys[i].arg);
   970 		}
   967 		}
   971 }
   968 }
   972 
   969 
   973 static void
   970 void
   974 killclient(const char *arg) {
   971 killclient(const char *arg) {
   975 	XEvent ev;
   972 	XEvent ev;
   976 
   973 
   977 	if(!sel)
   974 	if(!sel)
   978 		return;
   975 		return;
   987 	}
   984 	}
   988 	else
   985 	else
   989 		XKillClient(dpy, sel->win);
   986 		XKillClient(dpy, sel->win);
   990 }
   987 }
   991 
   988 
   992 static void
   989 void
   993 leavenotify(XEvent *e) {
   990 leavenotify(XEvent *e) {
   994 	XCrossingEvent *ev = &e->xcrossing;
   991 	XCrossingEvent *ev = &e->xcrossing;
   995 
   992 
   996 	if((ev->window == root) && !ev->same_screen) {
   993 	if((ev->window == root) && !ev->same_screen) {
   997 		selscreen = False;
   994 		selscreen = False;
   998 		focus(NULL);
   995 		focus(NULL);
   999 	}
   996 	}
  1000 }
   997 }
  1001 
   998 
  1002 static void
   999 void
  1003 manage(Window w, XWindowAttributes *wa) {
  1000 manage(Window w, XWindowAttributes *wa) {
  1004 	unsigned int i;
  1001 	unsigned int i;
  1005 	Client *c, *t = NULL;
  1002 	Client *c, *t = NULL;
  1006 	Window trans;
  1003 	Window trans;
  1007 	Status rettrans;
  1004 	Status rettrans;
  1055 	XMapWindow(dpy, c->win);
  1052 	XMapWindow(dpy, c->win);
  1056 	setclientstate(c, NormalState);
  1053 	setclientstate(c, NormalState);
  1057 	arrange();
  1054 	arrange();
  1058 }
  1055 }
  1059 
  1056 
  1060 static void
  1057 void
  1061 mappingnotify(XEvent *e) {
  1058 mappingnotify(XEvent *e) {
  1062 	XMappingEvent *ev = &e->xmapping;
  1059 	XMappingEvent *ev = &e->xmapping;
  1063 
  1060 
  1064 	XRefreshKeyboardMapping(ev);
  1061 	XRefreshKeyboardMapping(ev);
  1065 	if(ev->request == MappingKeyboard)
  1062 	if(ev->request == MappingKeyboard)
  1066 		keypress(NULL);
  1063 		keypress(NULL);
  1067 }
  1064 }
  1068 
  1065 
  1069 static void
  1066 void
  1070 maprequest(XEvent *e) {
  1067 maprequest(XEvent *e) {
  1071 	static XWindowAttributes wa;
  1068 	static XWindowAttributes wa;
  1072 	XMapRequestEvent *ev = &e->xmaprequest;
  1069 	XMapRequestEvent *ev = &e->xmaprequest;
  1073 
  1070 
  1074 	if(!XGetWindowAttributes(dpy, ev->window, &wa))
  1071 	if(!XGetWindowAttributes(dpy, ev->window, &wa))
  1077 		return;
  1074 		return;
  1078 	if(!getclient(ev->window))
  1075 	if(!getclient(ev->window))
  1079 		manage(ev->window, &wa);
  1076 		manage(ev->window, &wa);
  1080 }
  1077 }
  1081 
  1078 
  1082 static void
  1079 void
  1083 movemouse(Client *c) {
  1080 movemouse(Client *c) {
  1084 	int x1, y1, ocx, ocy, di, nx, ny;
  1081 	int x1, y1, ocx, ocy, di, nx, ny;
  1085 	unsigned int dui;
  1082 	unsigned int dui;
  1086 	Window dummy;
  1083 	Window dummy;
  1087 	XEvent ev;
  1084 	XEvent ev;
  1120 			break;
  1117 			break;
  1121 		}
  1118 		}
  1122 	}
  1119 	}
  1123 }
  1120 }
  1124 
  1121 
  1125 static Client *
  1122 Client *
  1126 nexttiled(Client *c) {
  1123 nexttiled(Client *c) {
  1127 	for(; c && (c->isfloating || !isvisible(c)); c = c->next);
  1124 	for(; c && (c->isfloating || !isvisible(c)); c = c->next);
  1128 	return c;
  1125 	return c;
  1129 }
  1126 }
  1130 
  1127 
  1131 static void
  1128 void
  1132 propertynotify(XEvent *e) {
  1129 propertynotify(XEvent *e) {
  1133 	Client *c;
  1130 	Client *c;
  1134 	Window trans;
  1131 	Window trans;
  1135 	XPropertyEvent *ev = &e->xproperty;
  1132 	XPropertyEvent *ev = &e->xproperty;
  1136 
  1133 
  1154 				drawbar();
  1151 				drawbar();
  1155 		}
  1152 		}
  1156 	}
  1153 	}
  1157 }
  1154 }
  1158 
  1155 
  1159 static void
  1156 void
  1160 quit(const char *arg) {
  1157 quit(const char *arg) {
  1161 	readin = running = False;
  1158 	readin = running = False;
  1162 }
  1159 }
  1163 
  1160 
  1164 static void
  1161 void
  1165 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1162 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1166 	double dx, dy, max, min, ratio;
  1163 	double dx, dy, max, min, ratio;
  1167 	XWindowChanges wc; 
  1164 	XWindowChanges wc; 
  1168 
  1165 
  1169 	if(sizehints) {
  1166 	if(sizehints) {
  1222 		configure(c);
  1219 		configure(c);
  1223 		XSync(dpy, False);
  1220 		XSync(dpy, False);
  1224 	}
  1221 	}
  1225 }
  1222 }
  1226 
  1223 
  1227 static void
  1224 void
  1228 resizemouse(Client *c) {
  1225 resizemouse(Client *c) {
  1229 	int ocx, ocy;
  1226 	int ocx, ocy;
  1230 	int nw, nh;
  1227 	int nw, nh;
  1231 	XEvent ev;
  1228 	XEvent ev;
  1232 
  1229 
  1261 			break;
  1258 			break;
  1262 		}
  1259 		}
  1263 	}
  1260 	}
  1264 }
  1261 }
  1265 
  1262 
  1266 static void
  1263 void
  1267 restack(void) {
  1264 restack(void) {
  1268 	Client *c;
  1265 	Client *c;
  1269 	XEvent ev;
  1266 	XEvent ev;
  1270 	XWindowChanges wc;
  1267 	XWindowChanges wc;
  1271 
  1268 
  1290 	}
  1287 	}
  1291 	XSync(dpy, False);
  1288 	XSync(dpy, False);
  1292 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1289 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1293 }
  1290 }
  1294 
  1291 
  1295 static void
  1292 void
  1296 run(void) {
  1293 run(void) {
  1297 	char *p;
  1294 	char *p;
  1298 	int r, xfd;
  1295 	int r, xfd;
  1299 	fd_set rd;
  1296 	fd_set rd;
  1300 	XEvent ev;
  1297 	XEvent ev;
  1338 				(handler[ev.type])(&ev); /* call handler */
  1335 				(handler[ev.type])(&ev); /* call handler */
  1339 		}
  1336 		}
  1340 	}
  1337 	}
  1341 }
  1338 }
  1342 
  1339 
  1343 static void
  1340 void
  1344 scan(void) {
  1341 scan(void) {
  1345 	unsigned int i, num;
  1342 	unsigned int i, num;
  1346 	Window *wins, d1, d2;
  1343 	Window *wins, d1, d2;
  1347 	XWindowAttributes wa;
  1344 	XWindowAttributes wa;
  1348 
  1345 
  1365 	}
  1362 	}
  1366 	if(wins)
  1363 	if(wins)
  1367 		XFree(wins);
  1364 		XFree(wins);
  1368 }
  1365 }
  1369 
  1366 
  1370 static void
  1367 void
  1371 setclientstate(Client *c, long state) {
  1368 setclientstate(Client *c, long state) {
  1372 	long data[] = {state, None};
  1369 	long data[] = {state, None};
  1373 
  1370 
  1374 	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
  1371 	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
  1375 			PropModeReplace, (unsigned char *)data, 2);
  1372 			PropModeReplace, (unsigned char *)data, 2);
  1376 }
  1373 }
  1377 
  1374 
  1378 static void
  1375 void
  1379 setlayout(const char *arg) {
  1376 setlayout(const char *arg) {
  1380 	unsigned int i;
  1377 	unsigned int i;
  1381 
  1378 
  1382 	if(!arg) {
  1379 	if(!arg) {
  1383 		if(++ltidx == nlayouts)
  1380 		if(++ltidx == nlayouts)
  1395 		arrange();
  1392 		arrange();
  1396 	else
  1393 	else
  1397 		drawbar();
  1394 		drawbar();
  1398 }
  1395 }
  1399 
  1396 
  1400 static void
  1397 void
  1401 setmwfact(const char *arg) {
  1398 setmwfact(const char *arg) {
  1402 	double delta;
  1399 	double delta;
  1403 
  1400 
  1404 	if(!isarrange(tile))
  1401 	if(!isarrange(tile))
  1405 		return;
  1402 		return;
  1417 			mwfact = 0.9;
  1414 			mwfact = 0.9;
  1418 	}
  1415 	}
  1419 	arrange();
  1416 	arrange();
  1420 }
  1417 }
  1421 
  1418 
  1422 static void
  1419 void
  1423 setup(void) {
  1420 setup(void) {
  1424 	unsigned int i, j, mask;
  1421 	unsigned int i, j, mask;
  1425 	Window w;
  1422 	Window w;
  1426 	XModifierKeymap *modmap;
  1423 	XModifierKeymap *modmap;
  1427 	XSetWindowAttributes wa;
  1424 	XSetWindowAttributes wa;
  1511 
  1508 
  1512 	/* multihead support */
  1509 	/* multihead support */
  1513 	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
  1510 	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
  1514 }
  1511 }
  1515 
  1512 
  1516 static void
  1513 void
  1517 spawn(const char *arg) {
  1514 spawn(const char *arg) {
  1518 	static char *shell = NULL;
  1515 	static char *shell = NULL;
  1519 
  1516 
  1520 	if(!shell && !(shell = getenv("SHELL")))
  1517 	if(!shell && !(shell = getenv("SHELL")))
  1521 		shell = "/bin/sh";
  1518 		shell = "/bin/sh";
  1535 		exit(0);
  1532 		exit(0);
  1536 	}
  1533 	}
  1537 	wait(0);
  1534 	wait(0);
  1538 }
  1535 }
  1539 
  1536 
  1540 static void
  1537 void
  1541 tag(const char *arg) {
  1538 tag(const char *arg) {
  1542 	unsigned int i;
  1539 	unsigned int i;
  1543 
  1540 
  1544 	if(!sel)
  1541 	if(!sel)
  1545 		return;
  1542 		return;
  1549 	if(i >= 0 && i < ntags)
  1546 	if(i >= 0 && i < ntags)
  1550 		sel->tags[i] = True;
  1547 		sel->tags[i] = True;
  1551 	arrange();
  1548 	arrange();
  1552 }
  1549 }
  1553 
  1550 
  1554 static unsigned int
  1551 unsigned int
  1555 textnw(const char *text, unsigned int len) {
  1552 textnw(const char *text, unsigned int len) {
  1556 	XRectangle r;
  1553 	XRectangle r;
  1557 
  1554 
  1558 	if(dc.font.set) {
  1555 	if(dc.font.set) {
  1559 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1556 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1560 		return r.width;
  1557 		return r.width;
  1561 	}
  1558 	}
  1562 	return XTextWidth(dc.font.xfont, text, len);
  1559 	return XTextWidth(dc.font.xfont, text, len);
  1563 }
  1560 }
  1564 
  1561 
  1565 static unsigned int
  1562 unsigned int
  1566 textw(const char *text) {
  1563 textw(const char *text) {
  1567 	return textnw(text, strlen(text)) + dc.font.height;
  1564 	return textnw(text, strlen(text)) + dc.font.height;
  1568 }
  1565 }
  1569 
  1566 
  1570 static void
  1567 void
  1571 tile(void) {
  1568 tile(void) {
  1572 	unsigned int i, n, nx, ny, nw, nh, mw, th;
  1569 	unsigned int i, n, nx, ny, nw, nh, mw, th;
  1573 	Client *c;
  1570 	Client *c;
  1574 
  1571 
  1575 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  1572 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  1604 		if(n > 1 && th != wah)
  1601 		if(n > 1 && th != wah)
  1605 			ny += nh + 2 * c->border;
  1602 			ny += nh + 2 * c->border;
  1606 	}
  1603 	}
  1607 }
  1604 }
  1608 
  1605 
  1609 static void
  1606 void
  1610 togglebar(const char *arg) {
  1607 togglebar(const char *arg) {
  1611 	if(bpos == BarOff)
  1608 	if(bpos == BarOff)
  1612 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
  1609 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
  1613 	else
  1610 	else
  1614 		bpos = BarOff;
  1611 		bpos = BarOff;
  1615 	updatebarpos();
  1612 	updatebarpos();
  1616 	arrange();
  1613 	arrange();
  1617 }
  1614 }
  1618 
  1615 
  1619 static void
  1616 void
  1620 togglefloating(const char *arg) {
  1617 togglefloating(const char *arg) {
  1621 	if(!sel)
  1618 	if(!sel)
  1622 		return;
  1619 		return;
  1623 	sel->isfloating = !sel->isfloating;
  1620 	sel->isfloating = !sel->isfloating;
  1624 	if(sel->isfloating)
  1621 	if(sel->isfloating)
  1625 		resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  1622 		resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  1626 	arrange();
  1623 	arrange();
  1627 }
  1624 }
  1628 
  1625 
  1629 static void
  1626 void
  1630 togglemax(const char *arg) {
  1627 togglemax(const char *arg) {
  1631 	XEvent ev;
  1628 	XEvent ev;
  1632 
  1629 
  1633 	if(!sel || (!isarrange(floating) && !sel->isfloating) || sel->isfixed)
  1630 	if(!sel || (!isarrange(floating) && !sel->isfloating) || sel->isfixed)
  1634 		return;
  1631 		return;
  1643 		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
  1640 		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
  1644 	drawbar();
  1641 	drawbar();
  1645 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1642 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1646 }
  1643 }
  1647 
  1644 
  1648 static void
  1645 void
  1649 toggletag(const char *arg) {
  1646 toggletag(const char *arg) {
  1650 	unsigned int i, j;
  1647 	unsigned int i, j;
  1651 
  1648 
  1652 	if(!sel)
  1649 	if(!sel)
  1653 		return;
  1650 		return;
  1657 	if(j == ntags)
  1654 	if(j == ntags)
  1658 		sel->tags[i] = True;
  1655 		sel->tags[i] = True;
  1659 	arrange();
  1656 	arrange();
  1660 }
  1657 }
  1661 
  1658 
  1662 static void
  1659 void
  1663 toggleview(const char *arg) {
  1660 toggleview(const char *arg) {
  1664 	unsigned int i, j;
  1661 	unsigned int i, j;
  1665 
  1662 
  1666 	i = idxoftag(arg);
  1663 	i = idxoftag(arg);
  1667 	seltags[i] = !seltags[i];
  1664 	seltags[i] = !seltags[i];
  1669 	if(j == ntags)
  1666 	if(j == ntags)
  1670 		seltags[i] = True; /* cannot toggle last view */
  1667 		seltags[i] = True; /* cannot toggle last view */
  1671 	arrange();
  1668 	arrange();
  1672 }
  1669 }
  1673 
  1670 
  1674 static void
  1671 void
  1675 unban(Client *c) {
  1672 unban(Client *c) {
  1676 	if(!c->isbanned)
  1673 	if(!c->isbanned)
  1677 		return;
  1674 		return;
  1678 	XMoveWindow(dpy, c->win, c->x, c->y);
  1675 	XMoveWindow(dpy, c->win, c->x, c->y);
  1679 	c->isbanned = False;
  1676 	c->isbanned = False;
  1680 }
  1677 }
  1681 
  1678 
  1682 static void
  1679 void
  1683 unmanage(Client *c) {
  1680 unmanage(Client *c) {
  1684 	XWindowChanges wc;
  1681 	XWindowChanges wc;
  1685 
  1682 
  1686 	wc.border_width = c->oldborder;
  1683 	wc.border_width = c->oldborder;
  1687 	/* The server grab construct avoids race conditions. */
  1684 	/* The server grab construct avoids race conditions. */
  1700 	XSetErrorHandler(xerror);
  1697 	XSetErrorHandler(xerror);
  1701 	XUngrabServer(dpy);
  1698 	XUngrabServer(dpy);
  1702 	arrange();
  1699 	arrange();
  1703 }
  1700 }
  1704 
  1701 
  1705 static void
  1702 void
  1706 unmapnotify(XEvent *e) {
  1703 unmapnotify(XEvent *e) {
  1707 	Client *c;
  1704 	Client *c;
  1708 	XUnmapEvent *ev = &e->xunmap;
  1705 	XUnmapEvent *ev = &e->xunmap;
  1709 
  1706 
  1710 	if((c = getclient(ev->window)))
  1707 	if((c = getclient(ev->window)))
  1711 		unmanage(c);
  1708 		unmanage(c);
  1712 }
  1709 }
  1713 
  1710 
  1714 static void
  1711 void
  1715 updatebarpos(void) {
  1712 updatebarpos(void) {
  1716 	XEvent ev;
  1713 	XEvent ev;
  1717 
  1714 
  1718 	wax = sx;
  1715 	wax = sx;
  1719 	way = sy;
  1716 	way = sy;
  1735 	}
  1732 	}
  1736 	XSync(dpy, False);
  1733 	XSync(dpy, False);
  1737 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1734 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1738 }
  1735 }
  1739 
  1736 
  1740 static void
  1737 void
  1741 updatesizehints(Client *c) {
  1738 updatesizehints(Client *c) {
  1742 	long msize;
  1739 	long msize;
  1743 	XSizeHints size;
  1740 	XSizeHints size;
  1744 
  1741 
  1745 	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
  1742 	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
  1787 		c->minax = c->maxax = c->minay = c->maxay = 0;
  1784 		c->minax = c->maxax = c->minay = c->maxay = 0;
  1788 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
  1785 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
  1789 			&& c->maxw == c->minw && c->maxh == c->minh);
  1786 			&& c->maxw == c->minw && c->maxh == c->minh);
  1790 }
  1787 }
  1791 
  1788 
  1792 static void
  1789 void
  1793 updatetitle(Client *c) {
  1790 updatetitle(Client *c) {
  1794 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
  1791 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
  1795 		gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name);
  1792 		gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name);
  1796 }
  1793 }
  1797 
  1794 
  1798 /* There's no way to check accesses to destroyed windows, thus those cases are
  1795 /* There's no way to check accesses to destroyed windows, thus those cases are
  1799  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1796  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1800  * default error handler, which may call exit.  */
  1797  * default error handler, which may call exit.  */
  1801 static int
  1798 int
  1802 xerror(Display *dpy, XErrorEvent *ee) {
  1799 xerror(Display *dpy, XErrorEvent *ee) {
  1803 	if(ee->error_code == BadWindow
  1800 	if(ee->error_code == BadWindow
  1804 	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
  1801 	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
  1805 	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
  1802 	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
  1806 	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
  1803 	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
  1812 	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
  1809 	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
  1813 		ee->request_code, ee->error_code);
  1810 		ee->request_code, ee->error_code);
  1814 	return xerrorxlib(dpy, ee); /* may call exit */
  1811 	return xerrorxlib(dpy, ee); /* may call exit */
  1815 }
  1812 }
  1816 
  1813 
  1817 static int
  1814 int
  1818 xerrordummy(Display *dsply, XErrorEvent *ee) {
  1815 xerrordummy(Display *dsply, XErrorEvent *ee) {
  1819 	return 0;
  1816 	return 0;
  1820 }
  1817 }
  1821 
  1818 
  1822 /* Startup Error handler to check if another window manager
  1819 /* Startup Error handler to check if another window manager
  1823  * is already running. */
  1820  * is already running. */
  1824 static int
  1821 int
  1825 xerrorstart(Display *dsply, XErrorEvent *ee) {
  1822 xerrorstart(Display *dsply, XErrorEvent *ee) {
  1826 	otherwm = True;
  1823 	otherwm = True;
  1827 	return -1;
  1824 	return -1;
  1828 }
  1825 }
  1829 
  1826 
  1830 static void
  1827 void
  1831 view(const char *arg) {
  1828 view(const char *arg) {
  1832 	unsigned int i;
  1829 	unsigned int i;
  1833 
  1830 
  1834 	for(i = 0; i < ntags; i++)
  1831 	for(i = 0; i < ntags; i++)
  1835 		seltags[i] = arg == NULL;
  1832 		seltags[i] = arg == NULL;
  1837 	if(i >= 0 && i < ntags)
  1834 	if(i >= 0 && i < ntags)
  1838 		seltags[i] = True;
  1835 		seltags[i] = True;
  1839 	arrange();
  1836 	arrange();
  1840 }
  1837 }
  1841 
  1838 
  1842 static void
  1839 void
  1843 zoom(const char *arg) {
  1840 zoom(const char *arg) {
  1844 	Client *c;
  1841 	Client *c;
  1845 
  1842 
  1846 	if(!sel || !isarrange(tile) || sel->isfloating)
  1843 	if(!sel || !isarrange(tile) || sel->isfloating)
  1847 		return;
  1844 		return;