dwm.c
changeset 1260 2d3d08d2dd19
parent 1259 f0c900871c87
child 1261 218a33808046
equal deleted inserted replaced
1259:f0c900871c87 1260:2d3d08d2dd19
    66 typedef struct Client Client;
    66 typedef struct Client Client;
    67 struct Client {
    67 struct Client {
    68 	char name[256];
    68 	char name[256];
    69 	int x, y, w, h;
    69 	int x, y, w, h;
    70 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    70 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    71 	int minax, maxax, minay, maxay;
    71 	float mina, maxa;
    72 	int bw, oldbw;
    72 	int bw, oldbw;
    73 	Bool isbanned, isfixed, isfloating, ismoved, isurgent;
    73 	Bool isbanned, isfixed, isfloating, ismoved, isurgent;
    74 	uint tags;
    74 	uint tags;
    75 	Client *next;
    75 	Client *next;
    76 	Client *prev;
       
    77 	Client *snext;
    76 	Client *snext;
    78 	Window win;
    77 	Window win;
    79 };
    78 };
    80 
    79 
    81 typedef struct {
    80 typedef struct {
    91 		XFontSet set;
    90 		XFontSet set;
    92 		XFontStruct *xfont;
    91 		XFontStruct *xfont;
    93 	} font;
    92 	} font;
    94 } DC; /* draw context */
    93 } DC; /* draw context */
    95 
    94 
       
    95 typedef union {
       
    96 	const char *c;
       
    97 	int i;
       
    98 	uint ui;
       
    99 	float f;
       
   100 	void *aux;
       
   101 } Arg;
       
   102 
    96 typedef struct {
   103 typedef struct {
    97 	uint mod;
   104 	uint mod;
    98 	KeySym keysym;
   105 	KeySym keysym;
    99 	void (*func)(const void *arg);
   106 	void (*func)(const Arg *);
   100 	const void *arg;
   107 	const Arg arg;
   101 } Key;
   108 } Key;
   102 
   109 
   103 typedef struct {
   110 typedef struct {
   104 	const char *symbol;
   111 	const char *symbol;
   105 	void (*arrange)(void);
   112 	void (*arrange)(void);
   112 	uint tags;
   119 	uint tags;
   113 	Bool isfloating;
   120 	Bool isfloating;
   114 } Rule;
   121 } Rule;
   115 
   122 
   116 /* function declarations */
   123 /* function declarations */
   117 void applyrules(Client *c);
   124 static void applyrules(Client *c);
   118 void arrange(void);
   125 static void arrange(void);
   119 void attach(Client *c);
   126 static void attach(Client *c);
   120 void attachstack(Client *c);
   127 static void attachstack(Client *c);
   121 void buttonpress(XEvent *e);
   128 static void buttonpress(XEvent *e);
   122 void checkotherwm(void);
   129 static void checkotherwm(void);
   123 void cleanup(void);
   130 static void cleanup(void);
   124 void configure(Client *c);
   131 static void configure(Client *c);
   125 void configurenotify(XEvent *e);
   132 static void configurenotify(XEvent *e);
   126 void configurerequest(XEvent *e);
   133 static void configurerequest(XEvent *e);
   127 void destroynotify(XEvent *e);
   134 static void destroynotify(XEvent *e);
   128 void detach(Client *c);
   135 static void detach(Client *c);
   129 void detachstack(Client *c);
   136 static void detachstack(Client *c);
   130 void drawbar(void);
   137 static void drawbar(void);
   131 void drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]);
   138 static void drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]);
   132 void drawtext(const char *text, ulong col[ColLast], Bool invert);
   139 static void drawtext(const char *text, ulong col[ColLast], Bool invert);
   133 void enternotify(XEvent *e);
   140 static void enternotify(XEvent *e);
   134 void eprint(const char *errstr, ...);
   141 static void eprint(const char *errstr, ...);
   135 void expose(XEvent *e);
   142 static void expose(XEvent *e);
   136 void focus(Client *c);
   143 static void focus(Client *c);
   137 void focusin(XEvent *e);
   144 static void focusin(XEvent *e);
   138 void focusnext(const void *arg);
   145 static void focusstack(const Arg *arg);
   139 void focusprev(const void *arg);
   146 static Client *getclient(Window w);
   140 Client *getclient(Window w);
   147 static ulong getcolor(const char *colstr);
   141 ulong getcolor(const char *colstr);
   148 static long getstate(Window w);
   142 long getstate(Window w);
   149 static Bool gettextprop(Window w, Atom atom, char *text, uint size);
   143 Bool gettextprop(Window w, Atom atom, char *text, uint size);
   150 static void grabbuttons(Client *c, Bool focused);
   144 void grabbuttons(Client *c, Bool focused);
   151 static void grabkeys(void);
   145 void grabkeys(void);
   152 static void initfont(const char *fontstr);
   146 void initfont(const char *fontstr);
   153 static Bool isoccupied(uint t);
   147 Bool isoccupied(uint t);
   154 static Bool isprotodel(Client *c);
   148 Bool isprotodel(Client *c);
   155 static Bool isurgent(uint t);
   149 Bool isurgent(uint t);
   156 static void keypress(XEvent *e);
   150 void keypress(XEvent *e);
   157 static void killclient(const Arg *arg);
   151 void killclient(const void *arg);
   158 static void manage(Window w, XWindowAttributes *wa);
   152 void manage(Window w, XWindowAttributes *wa);
   159 static void mappingnotify(XEvent *e);
   153 void mappingnotify(XEvent *e);
   160 static void maprequest(XEvent *e);
   154 void maprequest(XEvent *e);
   161 static void movemouse(Client *c);
   155 void movemouse(Client *c);
   162 static Client *nexttiled(Client *c);
   156 Client *nexttiled(Client *c);
   163 static void propertynotify(XEvent *e);
   157 void propertynotify(XEvent *e);
   164 static void quit(const Arg *arg);
   158 void quit(const void *arg);
   165 static void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   159 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   166 static void resizemouse(Client *c);
   160 void resizemouse(Client *c);
   167 static void restack(void);
   161 void restack(void);
   168 static void run(void);
   162 void run(void);
   169 static void scan(void);
   163 void scan(void);
   170 static void setclientstate(Client *c, long state);
   164 void setclientstate(Client *c, long state);
   171 static void setmfact(const Arg *arg);
   165 void setmfact(const void *arg);
   172 static void setup(void);
   166 void setup(void);
   173 static void spawn(const Arg *arg);
   167 void spawn(const void *arg);
   174 static void tag(const Arg *arg);
   168 void tag(const void *arg);
   175 static int textnw(const char *text, uint len);
   169 int textnw(const char *text, uint len);
   176 static void tile(void);
   170 void tile(void);
   177 static void togglebar(const Arg *arg);
   171 void togglebar(const void *arg);
   178 static void togglefloating(const Arg *arg);
   172 void togglefloating(const void *arg);
   179 static void togglelayout(const Arg *arg);
   173 void togglelayout(const void *arg);
   180 static void togglemax(const Arg *arg);
   174 void togglemax(const void *arg);
   181 static void toggletag(const Arg *arg);
   175 void toggletag(const void *arg);
   182 static void toggleview(const Arg *arg);
   176 void toggleview(const void *arg);
   183 static void unmanage(Client *c);
   177 void unmanage(Client *c);
   184 static void unmapnotify(XEvent *e);
   178 void unmapnotify(XEvent *e);
   185 static void updatebar(void);
   179 void updatebar(void);
   186 static void updategeom(void);
   180 void updategeom(void);
   187 static void updatesizehints(Client *c);
   181 void updatesizehints(Client *c);
   188 static void updatetitle(Client *c);
   182 void updatetitle(Client *c);
   189 static void updatewmhints(Client *c);
   183 void updatewmhints(Client *c);
   190 static void view(const Arg *arg);
   184 void view(const void *arg);
   191 static int xerror(Display *dpy, XErrorEvent *ee);
   185 int xerror(Display *dpy, XErrorEvent *ee);
   192 static int xerrordummy(Display *dpy, XErrorEvent *ee);
   186 int xerrordummy(Display *dpy, XErrorEvent *ee);
   193 static int xerrorstart(Display *dpy, XErrorEvent *ee);
   187 int xerrorstart(Display *dpy, XErrorEvent *ee);
   194 static void zoom(const Arg *arg);
   188 void zoom(const void *arg);
       
   189 
   195 
   190 /* variables */
   196 /* variables */
   191 char stext[256];
   197 static char stext[256];
   192 int screen, sx, sy, sw, sh;
   198 static int screen, sx, sy, sw, sh;
   193 int by, bh, blw, wx, wy, ww, wh;
   199 static int by, bh, blw, wx, wy, ww, wh;
   194 uint seltags = 0;
   200 static uint seltags = 0;
   195 int (*xerrorxlib)(Display *, XErrorEvent *);
   201 static int (*xerrorxlib)(Display *, XErrorEvent *);
   196 uint numlockmask = 0;
   202 static uint numlockmask = 0;
   197 void (*handler[LASTEvent]) (XEvent *) = {
   203 static void (*handler[LASTEvent]) (XEvent *) = {
   198 	[ButtonPress] = buttonpress,
   204 	[ButtonPress] = buttonpress,
   199 	[ConfigureRequest] = configurerequest,
   205 	[ConfigureRequest] = configurerequest,
   200 	[ConfigureNotify] = configurenotify,
   206 	[ConfigureNotify] = configurenotify,
   201 	[DestroyNotify] = destroynotify,
   207 	[DestroyNotify] = destroynotify,
   202 	[EnterNotify] = enternotify,
   208 	[EnterNotify] = enternotify,
   206 	[MappingNotify] = mappingnotify,
   212 	[MappingNotify] = mappingnotify,
   207 	[MapRequest] = maprequest,
   213 	[MapRequest] = maprequest,
   208 	[PropertyNotify] = propertynotify,
   214 	[PropertyNotify] = propertynotify,
   209 	[UnmapNotify] = unmapnotify
   215 	[UnmapNotify] = unmapnotify
   210 };
   216 };
   211 Atom wmatom[WMLast], netatom[NetLast];
   217 static Atom wmatom[WMLast], netatom[NetLast];
   212 Bool ismax = False;
   218 static Bool ismax = False;
   213 Bool otherwm, readin;
   219 static Bool otherwm, readin;
   214 Bool running = True;
   220 static Bool running = True;
   215 uint tagset[] = {1, 1}; /* after start, first tag is selected */
   221 static uint tagset[] = {1, 1}; /* after start, first tag is selected */
   216 Client *clients = NULL;
   222 static Client *clients = NULL;
   217 Client *sel = NULL;
   223 static Client *sel = NULL;
   218 Client *stack = NULL;
   224 static Client *stack = NULL;
   219 Cursor cursor[CurLast];
   225 static Cursor cursor[CurLast];
   220 Display *dpy;
   226 static Display *dpy;
   221 DC dc = {0};
   227 static DC dc = {0};
   222 Layout layouts[];
   228 static Window root, barwin;
   223 Layout *lt = layouts;
       
   224 Window root, barwin;
       
   225 
   229 
   226 /* configuration, allows nested code to access above variables */
   230 /* configuration, allows nested code to access above variables */
   227 #include "config.h"
   231 #include "config.h"
       
   232 
       
   233 static Layout *lt = layouts;
   228 
   234 
   229 /* compile-time check if all tags fit into an uint bit array. */
   235 /* compile-time check if all tags fit into an uint bit array. */
   230 struct NumTags { char limitexceeded[sizeof(uint) * 8 < LENGTH(tags) ? -1 : 1]; };
   236 struct NumTags { char limitexceeded[sizeof(uint) * 8 < LENGTH(tags) ? -1 : 1]; };
   231 
   237 
   232 /* function implementations */
   238 /* function implementations */
   280 	restack();
   286 	restack();
   281 }
   287 }
   282 
   288 
   283 void
   289 void
   284 attach(Client *c) {
   290 attach(Client *c) {
   285 	if(clients)
       
   286 		clients->prev = c;
       
   287 	c->next = clients;
   291 	c->next = clients;
   288 	clients = c;
   292 	clients = c;
   289 }
   293 }
   290 
   294 
   291 void
   295 void
   307 			x += TEXTW(tags[i]);
   311 			x += TEXTW(tags[i]);
   308 			if(ev->x < x) {
   312 			if(ev->x < x) {
   309 				mask = 1 << i;
   313 				mask = 1 << i;
   310 				if(ev->button == Button1) {
   314 				if(ev->button == Button1) {
   311 					if(ev->state & MODKEY)
   315 					if(ev->state & MODKEY)
   312 						tag(&mask);
   316 						tag((Arg*)&mask);
   313 					else
   317 					else
   314 						view(&mask);
   318 						view((Arg*)&mask);
   315 				}
   319 				}
   316 				else if(ev->button == Button3) {
   320 				else if(ev->button == Button3) {
   317 					if(ev->state & MODKEY)
   321 					if(ev->state & MODKEY)
   318 						toggletag(&mask);
   322 						toggletag((Arg*)&mask);
   319 					else
   323 					else
   320 						toggleview(&mask);
   324 						toggleview((Arg*)&mask);
   321 				}
   325 				}
   322 				return;
   326 				return;
   323 			}
   327 			}
   324 		}
   328 		}
   325 		if(ev->x < x + blw) {
   329 		if(ev->x < x + blw) {
   357 	XSync(dpy, False);
   361 	XSync(dpy, False);
   358 }
   362 }
   359 
   363 
   360 void
   364 void
   361 cleanup(void) {
   365 cleanup(void) {
       
   366 	Arg a = {.i = ~0};
   362 	close(STDIN_FILENO);
   367 	close(STDIN_FILENO);
   363 	view((uint[]){~0});
   368 	view(&a);
   364 	while(stack)
   369 	while(stack)
   365 		unmanage(stack);
   370 		unmanage(stack);
   366 	if(dc.font.set)
   371 	if(dc.font.set)
   367 		XFreeFontSet(dpy, dc.font.set);
   372 		XFreeFontSet(dpy, dc.font.set);
   368 	else
   373 	else
   464 		unmanage(c);
   469 		unmanage(c);
   465 }
   470 }
   466 
   471 
   467 void
   472 void
   468 detach(Client *c) {
   473 detach(Client *c) {
   469 	if(c->prev)
   474 	Client *i;
   470 		c->prev->next = c->next;
   475 
   471 	if(c->next)
   476 	if (c != clients) {
   472 		c->next->prev = c->prev;
   477 		for(i = clients; i->next != c; i = i->next);
   473 	if(c == clients)
   478 		i->next = c->next;
       
   479 	}
       
   480 	else {
   474 		clients = c->next;
   481 		clients = c->next;
   475 	c->next = c->prev = NULL;
   482 	}
       
   483 	c->next =  NULL;
   476 }
   484 }
   477 
   485 
   478 void
   486 void
   479 detachstack(Client *c) {
   487 detachstack(Client *c) {
   480 	Client **tc;
   488 	Client **tc;
   638 	if(sel && ev->window != sel->win)
   646 	if(sel && ev->window != sel->win)
   639 		XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
   647 		XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
   640 }
   648 }
   641 
   649 
   642 void
   650 void
   643 focusnext(const void *arg) {
   651 focusstack(const Arg *arg) {
   644 	Client *c;
   652 	Client *c = NULL, *i;
   645 
   653 
   646 	if(!sel)
   654 	if(!sel)
   647 		return;
   655 		return;
   648 	for(c = sel->next; c && c->isbanned; c = c->next);
   656 	if (arg->i > 0) {
   649 	if(!c)
   657 		for(c = sel->next; c && c->isbanned; c = c->next);
   650 		for(c = clients; c && c->isbanned; c = c->next);
   658 		if(!c)
   651 	if(c) {
   659 			for(c = clients; c && c->isbanned; c = c->next);
   652 		focus(c);
   660 	}
   653 		restack();
   661 	else {
   654 	}
   662 		for(i = clients; i != sel; i = i->next)
   655 }
   663 			if (!i->isbanned)
   656 
   664 				c = i;
   657 void
   665 		if(!c) 
   658 focusprev(const void *arg) {
   666 			for(; i; i = i->next)
   659 	Client *c;
   667 				if (!i->isbanned)
   660 
   668 					c = i;
   661 	if(!sel)
       
   662 		return;
       
   663 	for(c = sel->prev; c && c->isbanned; c = c->prev);
       
   664 	if(!c) {
       
   665 		for(c = clients; c && c->next; c = c->next);
       
   666 		for(; c && c->isbanned; c = c->prev);
       
   667 	}
   669 	}
   668 	if(c) {
   670 	if(c) {
   669 		focus(c);
   671 		focus(c);
   670 		restack();
   672 		restack();
   671 	}
   673 	}
   864 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   866 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   865 	for(i = 0; i < LENGTH(keys); i++)
   867 	for(i = 0; i < LENGTH(keys); i++)
   866 		if(keysym == keys[i].keysym
   868 		if(keysym == keys[i].keysym
   867 		   && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
   869 		   && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
   868 		   && keys[i].func)
   870 		   && keys[i].func)
   869 			keys[i].func(keys[i].arg);
   871 			keys[i].func(&(keys[i].arg));
   870 }
   872 }
   871 
   873 
   872 void
   874 void
   873 killclient(const void *arg) {
   875 killclient(const Arg *arg) {
   874 	XEvent ev;
   876 	XEvent ev;
   875 
   877 
   876 	if(!sel)
   878 	if(!sel)
   877 		return;
   879 		return;
   878 	if(isprotodel(sel)) {
   880 	if(isprotodel(sel)) {
  1054 		}
  1056 		}
  1055 	}
  1057 	}
  1056 }
  1058 }
  1057 
  1059 
  1058 void
  1060 void
  1059 quit(const void *arg) {
  1061 quit(const Arg *arg) {
  1060 	readin = running = False;
  1062 	readin = running = False;
  1061 }
  1063 }
  1062 
  1064 
  1063 void
  1065 void
  1064 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1066 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1072 		/* temporarily remove base dimensions */
  1074 		/* temporarily remove base dimensions */
  1073 		w -= c->basew;
  1075 		w -= c->basew;
  1074 		h -= c->baseh;
  1076 		h -= c->baseh;
  1075 
  1077 
  1076 		/* adjust for aspect limits */
  1078 		/* adjust for aspect limits */
  1077 		if(c->minax != c->maxax && c->minay != c->maxay 
  1079 		if(c->mina > 0 && c->maxa > 0) {
  1078 		&& c->minax > 0 && c->maxax > 0 && c->minay > 0 && c->maxay > 0) {
  1080 			if(c->maxa < (float) w/h)
  1079 			if(w * c->maxay > h * c->maxax)
  1081 				w = h * c->maxa;
  1080 				w = h * c->maxax / c->maxay;
  1082 			else if(c->mina > (float) h/w)
  1081 			else if(w * c->minay < h * c->minax)
  1083 				h = w * c->mina;
  1082 				h = w * c->minay / c->minax;
       
  1083 		}
  1084 		}
  1084 
  1085 
  1085 		/* adjust for increment value */
  1086 		/* adjust for increment value */
  1086 		if(c->incw)
  1087 		if(c->incw)
  1087 			w -= w % c->incw;
  1088 			w -= w % c->incw;
  1293 			PropModeReplace, (unsigned char *)data, 2);
  1294 			PropModeReplace, (unsigned char *)data, 2);
  1294 }
  1295 }
  1295 
  1296 
  1296 /* arg > 1.0 will set mfact absolutly */
  1297 /* arg > 1.0 will set mfact absolutly */
  1297 void
  1298 void
  1298 setmfact(const void *arg) {
  1299 setmfact(const Arg *arg) {
  1299 	double d = *((double*) arg);
  1300 	float f;
  1300 
  1301 
  1301 	if(!d || !lt->arrange)
  1302 	if(!arg || !lt->arrange)
  1302 		return;
  1303 		return;
  1303 	d = d < 1.0 ? d + mfact : d - 1.0;
  1304 	f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
  1304 	if(d < 0.1 || d > 0.9)
  1305 	if(f < 0.1 || f > 0.9)
  1305 		return;
  1306 		return;
  1306 	mfact = d;
  1307 	mfact = f;
  1307 	arrange();
  1308 	arrange();
  1308 }
  1309 }
  1309 
  1310 
  1310 void
  1311 void
  1311 setup(void) {
  1312 setup(void) {
  1384 	/* grab keys */
  1385 	/* grab keys */
  1385 	grabkeys();
  1386 	grabkeys();
  1386 }
  1387 }
  1387 
  1388 
  1388 void
  1389 void
  1389 spawn(const void *arg) {
  1390 spawn(const Arg *arg) {
  1390 	static char *shell = NULL;
  1391 	static char *shell = NULL;
  1391 
  1392 
  1392 	if(!shell && !(shell = getenv("SHELL")))
  1393 	if(!shell && !(shell = getenv("SHELL")))
  1393 		shell = "/bin/sh";
  1394 		shell = "/bin/sh";
  1394 	/* The double-fork construct avoids zombie processes and keeps the code
  1395 	/* The double-fork construct avoids zombie processes and keeps the code
  1396 	if(fork() == 0) {
  1397 	if(fork() == 0) {
  1397 		if(fork() == 0) {
  1398 		if(fork() == 0) {
  1398 			if(dpy)
  1399 			if(dpy)
  1399 				close(ConnectionNumber(dpy));
  1400 				close(ConnectionNumber(dpy));
  1400 			setsid();
  1401 			setsid();
  1401 			execl(shell, shell, "-c", (char *)arg, (char *)NULL);
  1402 			execl(shell, shell, "-c", arg->c, (char *)NULL);
  1402 			fprintf(stderr, "dwm: execl '%s -c %s'", shell, (char *)arg);
  1403 			fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->c);
  1403 			perror(" failed");
  1404 			perror(" failed");
  1404 		}
  1405 		}
  1405 		exit(0);
  1406 		exit(0);
  1406 	}
  1407 	}
  1407 	wait(0);
  1408 	wait(0);
  1408 }
  1409 }
  1409 
  1410 
  1410 void
  1411 void
  1411 tag(const void *arg) {
  1412 tag(const Arg *arg) {
  1412 	if(sel && *(int *)arg & TAGMASK) {
  1413 	if(sel && arg->ui & TAGMASK) {
  1413 		sel->tags = *(int *)arg & TAGMASK;
  1414 		sel->tags = arg->ui & TAGMASK;
  1414 		arrange();
  1415 		arrange();
  1415 	}
  1416 	}
  1416 }
  1417 }
  1417 
  1418 
  1418 int
  1419 int
  1459 			y = c->y + c->h + 2 * c->bw;
  1460 			y = c->y + c->h + 2 * c->bw;
  1460 	}
  1461 	}
  1461 }
  1462 }
  1462 
  1463 
  1463 void
  1464 void
  1464 togglebar(const void *arg) {
  1465 togglebar(const Arg *arg) {
  1465 	showbar = !showbar;
  1466 	showbar = !showbar;
  1466 	updategeom();
  1467 	updategeom();
  1467 	updatebar();
  1468 	updatebar();
  1468 	arrange();
  1469 	arrange();
  1469 }
  1470 }
  1470 
  1471 
  1471 void
  1472 void
  1472 togglefloating(const void *arg) {
  1473 togglefloating(const Arg *arg) {
  1473 	if(!sel)
  1474 	if(!sel)
  1474 		return;
  1475 		return;
  1475 	sel->isfloating = !sel->isfloating || sel->isfixed;
  1476 	sel->isfloating = !sel->isfloating || sel->isfixed;
  1476 	if(sel->isfloating)
  1477 	if(sel->isfloating)
  1477 		resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  1478 		resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  1478 	arrange();
  1479 	arrange();
  1479 }
  1480 }
  1480 
  1481 
  1481 void
  1482 void
  1482 togglelayout(const void *arg) {
  1483 togglelayout(const Arg *arg) {
  1483 	uint i;
  1484 	uint i;
  1484 
  1485 
  1485 	if(!arg) {
  1486 	if(!arg->c) {
  1486 		if(++lt == &layouts[LENGTH(layouts)])
  1487 		if(++lt == &layouts[LENGTH(layouts)])
  1487 			lt = &layouts[0];
  1488 			lt = &layouts[0];
  1488 	}
  1489 	}
  1489 	else {
  1490 	else {
  1490 		for(i = 0; i < LENGTH(layouts); i++)
  1491 		for(i = 0; i < LENGTH(layouts); i++)
  1491 			if(!strcmp((char *)arg, layouts[i].symbol))
  1492 			if(!strcmp(arg->c, layouts[i].symbol))
  1492 				break;
  1493 				break;
  1493 		if(i == LENGTH(layouts))
  1494 		if(i == LENGTH(layouts))
  1494 			return;
  1495 			return;
  1495 		lt = &layouts[i];
  1496 		lt = &layouts[i];
  1496 	}
  1497 	}
  1499 	else
  1500 	else
  1500 		drawbar();
  1501 		drawbar();
  1501 }
  1502 }
  1502 
  1503 
  1503 void
  1504 void
  1504 togglemax(const void *arg) {
  1505 togglemax(const Arg *arg) {
  1505 	ismax = !ismax;
  1506 	ismax = !ismax;
  1506 	arrange();
  1507 	arrange();
  1507 }
  1508 }
  1508 
  1509 
  1509 void
  1510 void
  1510 toggletag(const void *arg) {
  1511 toggletag(const Arg *arg) {
  1511 	if(sel && (sel->tags ^ ((*(int *)arg) & TAGMASK))) {
  1512 	if(sel && (sel->tags ^= (arg->ui & TAGMASK)))
  1512 		sel->tags ^= (*(int *)arg) & TAGMASK;
       
  1513 		arrange();
  1513 		arrange();
  1514 	}
  1514 }
  1515 }
  1515 
  1516 
  1516 void
  1517 void
  1517 toggleview(const Arg *arg) {
  1518 toggleview(const void *arg) {
  1518 	if((tagset[seltags] ^= (arg->ui & TAGMASK)))
  1519 	if((tagset[seltags] ^ ((*(int *)arg) & TAGMASK))) {
       
  1520 		tagset[seltags] ^= (*(int *)arg) & TAGMASK;
       
  1521 		arrange();
  1519 		arrange();
  1522 	}
       
  1523 }
  1520 }
  1524 
  1521 
  1525 void
  1522 void
  1526 unmanage(Client *c) {
  1523 unmanage(Client *c) {
  1527 	XWindowChanges wc;
  1524 	XWindowChanges wc;
  1626 		c->minh = size.base_height;
  1623 		c->minh = size.base_height;
  1627 	}
  1624 	}
  1628 	else
  1625 	else
  1629 		c->minw = c->minh = 0;
  1626 		c->minw = c->minh = 0;
  1630 	if(size.flags & PAspect) {
  1627 	if(size.flags & PAspect) {
  1631 		c->minax = size.min_aspect.x;
  1628 		c->mina = (float)size.min_aspect.y / (float)size.min_aspect.x;
  1632 		c->maxax = size.max_aspect.x;
  1629 		c->maxa = (float)size.max_aspect.x / (float)size.max_aspect.y;
  1633 		c->minay = size.min_aspect.y;
       
  1634 		c->maxay = size.max_aspect.y;
       
  1635 	}
  1630 	}
  1636 	else
  1631 	else
  1637 		c->minax = c->maxax = c->minay = c->maxay = 0;
  1632 		c->maxa = c->mina = 0.0;
  1638 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
  1633 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
  1639 			&& c->maxw == c->minw && c->maxh == c->minh);
  1634 			&& c->maxw == c->minw && c->maxh == c->minh);
  1640 }
  1635 }
  1641 
  1636 
  1642 void
  1637 void
  1657 		XFree(wmh);
  1652 		XFree(wmh);
  1658 	}
  1653 	}
  1659 }
  1654 }
  1660 
  1655 
  1661 void
  1656 void
  1662 view(const void *arg) {
  1657 view(const Arg *arg) {
  1663 	seltags ^= 1; /* toggle sel tagset */
  1658 	seltags ^= 1; /* toggle sel tagset */
  1664 	if(arg && (*(int *)arg & TAGMASK))
  1659 	if(arg && (arg->ui & TAGMASK))
  1665 		tagset[seltags] = *(int *)arg & TAGMASK;
  1660 		tagset[seltags] = arg->i & TAGMASK;
  1666 	arrange();
  1661 	arrange();
  1667 }
  1662 }
  1668 
  1663 
  1669 /* There's no way to check accesses to destroyed windows, thus those cases are
  1664 /* There's no way to check accesses to destroyed windows, thus those cases are
  1670  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1665  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1698 	otherwm = True;
  1693 	otherwm = True;
  1699 	return -1;
  1694 	return -1;
  1700 }
  1695 }
  1701 
  1696 
  1702 void
  1697 void
  1703 zoom(const void *arg) {
  1698 zoom(const Arg *arg) {
  1704 	Client *c = sel;
  1699 	Client *c = sel;
  1705 
  1700 
  1706 	if(ismax || !lt->arrange || (sel && sel->isfloating))
  1701 	if(ismax || !lt->arrange || (sel && sel->isfloating))
  1707 		return;
  1702 		return;
  1708 	if(c == nexttiled(clients))
  1703 	if(c == nexttiled(clients))