dwm.c
changeset 1110 227f2d07c63f
parent 1109 55e2f7e96b71
child 1112 27d2e0f4ff82
equal deleted inserted replaced
1109:55e2f7e96b71 1110:227f2d07c63f
    69 	int minax, maxax, minay, maxay;
    69 	int minax, maxax, minay, maxay;
    70 	long flags;
    70 	long flags;
    71 	unsigned int border, oldborder;
    71 	unsigned int border, oldborder;
    72 	Bool isbanned, isfixed, isfloating, isurgent;
    72 	Bool isbanned, isfixed, isfloating, isurgent;
    73 	Bool *tags;
    73 	Bool *tags;
    74 	View *view;
       
    75 	Client *next;
    74 	Client *next;
    76 	Client *prev;
    75 	Client *prev;
    77 	Client *snext;
    76 	Client *snext;
    78 	Window win;
    77 	Window win;
    79 };
    78 };
   118 	Layout *layout;
   117 	Layout *layout;
   119 	Window barwin;
   118 	Window barwin;
   120 };
   119 };
   121 
   120 
   122 /* function declarations */
   121 /* function declarations */
   123 void addtag(Client *c, const char *t);
       
   124 void applyrules(Client *c);
   122 void applyrules(Client *c);
   125 void arrange(void);
   123 void arrange(void);
   126 void attach(Client *c);
   124 void attach(Client *c);
   127 void attachstack(Client *c);
   125 void attachstack(Client *c);
   128 void ban(Client *c);
   126 void ban(Client *c);
   130 void checkotherwm(void);
   128 void checkotherwm(void);
   131 void cleanup(void);
   129 void cleanup(void);
   132 void configure(Client *c);
   130 void configure(Client *c);
   133 void configurenotify(XEvent *e);
   131 void configurenotify(XEvent *e);
   134 void configurerequest(XEvent *e);
   132 void configurerequest(XEvent *e);
       
   133 Bool conflicts(Client *c, unsigned int tidx);
   135 void destroynotify(XEvent *e);
   134 void destroynotify(XEvent *e);
   136 void detach(Client *c);
   135 void detach(Client *c);
   137 void detachstack(Client *c);
   136 void detachstack(Client *c);
   138 void drawbar(View *v);
   137 void drawbar(View *v);
   139 void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   138 void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   140 void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   139 void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   141 void *emallocz(unsigned int size);
   140 void *emallocz(unsigned int size);
   142 void enternotify(XEvent *e);
   141 void enternotify(XEvent *e);
   143 void eprint(const char *errstr, ...);
   142 void eprint(const char *errstr, ...);
   144 void expose(XEvent *e);
   143 void expose(XEvent *e);
       
   144 unsigned int firstag(View *v);
   145 void floating(View *v); /* default floating layout */
   145 void floating(View *v); /* default floating layout */
   146 void focus(Client *c);
   146 void focus(Client *c);
   147 void focusin(XEvent *e);
   147 void focusin(XEvent *e);
   148 void focusnext(const char *arg);
   148 void focusnext(const char *arg);
   149 void focusprev(const char *arg);
   149 void focusprev(const char *arg);
   150 Client *getclient(Window w);
   150 Client *getclient(Window w);
   151 unsigned long getcolor(const char *colstr);
   151 unsigned long getcolor(const char *colstr);
       
   152 View *getview(Client *c);
   152 View *getviewbar(Window barwin);
   153 View *getviewbar(Window barwin);
   153 long getstate(Window w);
   154 long getstate(Window w);
   154 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   155 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   155 void grabbuttons(Client *c, Bool focused);
   156 void grabbuttons(Client *c, Bool focused);
   156 void grabkeys(void);
   157 void grabkeys(void);
   246 /* configuration, allows nested code to access above variables */
   247 /* configuration, allows nested code to access above variables */
   247 #include "config.h"
   248 #include "config.h"
   248 #define TAGSZ (LENGTH(tags) * sizeof(Bool))
   249 #define TAGSZ (LENGTH(tags) * sizeof(Bool))
   249 
   250 
   250 /* function implementations */
   251 /* function implementations */
   251 void
       
   252 addtag(Client *c, const char *t) {
       
   253 	unsigned int i, tidx = idxoftag(t);
       
   254 
       
   255 	for(i = 0; i < LENGTH(tags); i++)
       
   256 		if(c->tags[i] && vtags[i] != vtags[tidx])
       
   257 			return; /* conflict */
       
   258 	c->tags[tidx] = True;
       
   259 	c->view = &views[vtags[tidx]];
       
   260 }
       
   261 
   252 
   262 void
   253 void
   263 applyrules(Client *c) {
   254 applyrules(Client *c) {
   264 	unsigned int i;
   255 	unsigned int i, idx;
   265 	Bool matched = False;
   256 	Bool matched = False;
   266 	Rule *r;
   257 	Rule *r;
   267 	XClassHint ch = { 0 };
   258 	XClassHint ch = { 0 };
   268 
   259 
   269 	/* rule matching */
   260 	/* rule matching */
   273 		if(strstr(c->name, r->prop)
   264 		if(strstr(c->name, r->prop)
   274 		|| (ch.res_class && strstr(ch.res_class, r->prop))
   265 		|| (ch.res_class && strstr(ch.res_class, r->prop))
   275 		|| (ch.res_name && strstr(ch.res_name, r->prop)))
   266 		|| (ch.res_name && strstr(ch.res_name, r->prop)))
   276 		{
   267 		{
   277 			c->isfloating = r->isfloating;
   268 			c->isfloating = r->isfloating;
   278 			if(r->tag) {
   269 			if(r->tag && !conflicts(c, (idx = idxoftag(r->tag)))) {
   279 				addtag(c, r->tag);
   270 				c->tags[idx] = True;
   280 				matched = True;
   271 				matched = True;
   281 			}
   272 			}
   282 		}
   273 		}
   283 	}
   274 	}
   284 	if(ch.res_class)
   275 	if(ch.res_class)
   285 		XFree(ch.res_class);
   276 		XFree(ch.res_class);
   286 	if(ch.res_name)
   277 	if(ch.res_name)
   287 		XFree(ch.res_name);
   278 		XFree(ch.res_name);
   288 	if(!matched) {
   279 	if(!matched) {
   289 		memcpy(c->tags, seltags, TAGSZ);
   280 		for(i = 0; i < LENGTH(tags); i++)
   290 		c->view = selview;
   281 			if(seltags[i] && vtags[i] == selview->id)
       
   282 				c->tags[i] = True;
   291 	}
   283 	}
   292 }
   284 }
   293 
   285 
   294 void
   286 void
   295 arrange(void) {
   287 arrange(void) {
   325 
   317 
   326 void
   318 void
   327 ban(Client *c) {
   319 ban(Client *c) {
   328 	if(c->isbanned)
   320 	if(c->isbanned)
   329 		return;
   321 		return;
   330 	XMoveWindow(dpy, c->win, c->x + 3 * c->view->w, c->y);
   322 	XMoveWindow(dpy, c->win, c->x + 3 * getview(c)->w, c->y);
   331 	c->isbanned = True;
   323 	c->isbanned = True;
   332 }
   324 }
   333 
   325 
   334 void
   326 void
   335 buttonpress(XEvent *e) {
   327 buttonpress(XEvent *e) {
   365 	else if((c = getclient(ev->window))) {
   357 	else if((c = getclient(ev->window))) {
   366 		focus(c);
   358 		focus(c);
   367 		if(CLEANMASK(ev->state) != MODKEY)
   359 		if(CLEANMASK(ev->state) != MODKEY)
   368 			return;
   360 			return;
   369 		if(ev->button == Button1) {
   361 		if(ev->button == Button1) {
   370 			restack(c->view);
   362 			restack(getview(c));
   371 			movemouse(c);
   363 			movemouse(c);
   372 		}
   364 		}
   373 		else if(ev->button == Button2) {
   365 		else if(ev->button == Button2) {
   374 			if((floating != c->view->layout->arrange) && c->isfloating)
   366 			if((floating != getview(c)->layout->arrange) && c->isfloating)
   375 				togglefloating(NULL);
   367 				togglefloating(NULL);
   376 			else
   368 			else
   377 				zoom(NULL);
   369 				zoom(NULL);
   378 		}
   370 		}
   379 		else if(ev->button == Button3 && !c->isfixed) {
   371 		else if(ev->button == Button3 && !c->isfixed) {
   380 			restack(c->view);
   372 			restack(getview(c));
   381 			resizemouse(c);
   373 			resizemouse(c);
   382 		}
   374 		}
   383 	}
   375 	}
   384 }
   376 }
   385 
   377 
   464 	Client *c;
   456 	Client *c;
   465 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   457 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   466 	XWindowChanges wc;
   458 	XWindowChanges wc;
   467 
   459 
   468 	if((c = getclient(ev->window))) {
   460 	if((c = getclient(ev->window))) {
   469 		View *v = c->view;
   461 		View *v = getview(c);
   470 		if(ev->value_mask & CWBorderWidth)
   462 		if(ev->value_mask & CWBorderWidth)
   471 			c->border = ev->border_width;
   463 			c->border = ev->border_width;
   472 		if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) {
   464 		if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) {
   473 			if(ev->value_mask & CWX)
   465 			if(ev->value_mask & CWX)
   474 				c->x = v->x + ev->x;
   466 				c->x = v->x + ev->x;
   502 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   494 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   503 	}
   495 	}
   504 	XSync(dpy, False);
   496 	XSync(dpy, False);
   505 }
   497 }
   506 
   498 
       
   499 Bool
       
   500 conflicts(Client *c, unsigned int tidx) {
       
   501 	unsigned int i;
       
   502 
       
   503 	for(i = 0; i < LENGTH(tags); i++)
       
   504 		if(c->tags[i] && vtags[i] != vtags[tidx])
       
   505 			return True; /* conflict */
       
   506 	return False;
       
   507 }
       
   508 
   507 void
   509 void
   508 destroynotify(XEvent *e) {
   510 destroynotify(XEvent *e) {
   509 	Client *c;
   511 	Client *c;
   510 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   512 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   511 
   513 
   536 drawbar(View *v) {
   538 drawbar(View *v) {
   537 	int i, x;
   539 	int i, x;
   538 	Client *c;
   540 	Client *c;
   539 
   541 
   540 	dc.x = 0;
   542 	dc.x = 0;
   541 	for(c = stack; c && (!isvisible(c) || c->view != v); c = c->snext);
   543 	for(c = stack; c && (!isvisible(c) || getview(c) != v); c = c->snext);
   542 	for(i = 0; i < LENGTH(tags); i++) {
   544 	for(i = 0; i < LENGTH(tags); i++) {
   543 		if(&views[vtags[i]] != v)
   545 		if(&views[vtags[i]] != v)
   544 			continue;
   546 			continue;
   545 		dc.w = textw(tags[i]);
   547 		dc.w = textw(tags[i]);
   546 		if(seltags[i]) {
   548 		if(seltags[i]) {
   679 
   681 
   680 	if(ev->count == 0 && ((v = getviewbar(ev->window))))
   682 	if(ev->count == 0 && ((v = getviewbar(ev->window))))
   681 		drawbar(v);
   683 		drawbar(v);
   682 }
   684 }
   683 
   685 
       
   686 unsigned int
       
   687 firstag(View *v) {
       
   688 	unsigned int i;
       
   689 
       
   690 	for(i = 0; i < LENGTH(tags); i++)
       
   691 		if(vtags[i] == v->id)
       
   692 			return i;
       
   693 	return 0; /* safe fallback */
       
   694 }
       
   695 
   684 void
   696 void
   685 floating(View *v) { /* default floating layout */
   697 floating(View *v) { /* default floating layout */
   686 	Client *c;
   698 	Client *c;
   687 
   699 
   688 	domwfact = dozoom = False;
   700 	domwfact = dozoom = False;
   693 
   705 
   694 void
   706 void
   695 focus(Client *c) {
   707 focus(Client *c) {
   696 	View *v = selview;
   708 	View *v = selview;
   697 	if(c)
   709 	if(c)
   698 		selview = c->view;
   710 		selview = getview(c);
   699 	else
       
   700 		selview = viewat();
       
   701 	if(selview != v)
   711 	if(selview != v)
   702 		drawbar(v);
   712 		drawbar(v);
   703 	if(!c || (c && !isvisible(c)))
   713 	if(!c || (c && !isvisible(c)))
   704 		for(c = stack; c && (!isvisible(c) || c->view != selview); c = c->snext);
   714 		/* TODO: isvisible might take getview(c) as constraint? */
       
   715 		for(c = stack; c && (!isvisible(c) || getview(c) != selview); c = c->snext);
   705 	if(sel && sel != c) {
   716 	if(sel && sel != c) {
   706 		grabbuttons(sel, False);
   717 		grabbuttons(sel, False);
   707 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   718 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   708 	}
   719 	}
   709 	if(c) {
   720 	if(c) {
   713 	}
   724 	}
   714 	sel = c;
   725 	sel = c;
   715 	if(c) {
   726 	if(c) {
   716 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   727 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   717 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   728 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   718 		selview = c->view;
   729 		selview = getview(c);
   719 	}
   730 	}
   720 	else
   731 	else
   721 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   732 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   722 	drawbar(selview);
   733 	drawbar(selview);
   723 }
   734 }
   739 	for(c = sel->next; c && !isvisible(c); c = c->next);
   750 	for(c = sel->next; c && !isvisible(c); c = c->next);
   740 	if(!c)
   751 	if(!c)
   741 		for(c = clients; c && !isvisible(c); c = c->next);
   752 		for(c = clients; c && !isvisible(c); c = c->next);
   742 	if(c) {
   753 	if(c) {
   743 		focus(c);
   754 		focus(c);
   744 		restack(c->view);
   755 		restack(getview(c));
   745 	}
   756 	}
   746 }
   757 }
   747 
   758 
   748 void
   759 void
   749 focusprev(const char *arg) {
   760 focusprev(const char *arg) {
   756 		for(c = clients; c && c->next; c = c->next);
   767 		for(c = clients; c && c->next; c = c->next);
   757 		for(; c && !isvisible(c); c = c->prev);
   768 		for(; c && !isvisible(c); c = c->prev);
   758 	}
   769 	}
   759 	if(c) {
   770 	if(c) {
   760 		focus(c);
   771 		focus(c);
   761 		restack(c->view);
   772 		restack(getview(c));
   762 	}
   773 	}
   763 }
   774 }
   764 
   775 
   765 Client *
   776 Client *
   766 getclient(Window w) {
   777 getclient(Window w) {
   776 	XColor color;
   787 	XColor color;
   777 
   788 
   778 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   789 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   779 		eprint("error, cannot allocate color '%s'\n", colstr);
   790 		eprint("error, cannot allocate color '%s'\n", colstr);
   780 	return color.pixel;
   791 	return color.pixel;
       
   792 }
       
   793 
       
   794 View *
       
   795 getview(Client *c) {
       
   796 	unsigned int i;
       
   797 
       
   798 	for(i = 0; i < LENGTH(tags); i++)
       
   799 		if(c->tags[i])
       
   800 			return &views[vtags[i]];
       
   801 	return NULL;
   781 }
   802 }
   782 
   803 
   783 View *
   804 View *
   784 getviewbar(Window barwin) {
   805 getviewbar(Window barwin) {
   785 	unsigned int i;
   806 	unsigned int i;
   903 unsigned int
   924 unsigned int
   904 idxoftag(const char *t) {
   925 idxoftag(const char *t) {
   905 	unsigned int i;
   926 	unsigned int i;
   906 
   927 
   907 	for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++);
   928 	for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++);
   908 	return (i < LENGTH(tags)) ? i : 0;
   929 	return (i < LENGTH(tags)) ? i : firstag(selview);
   909 }
   930 }
   910 
   931 
   911 void
   932 void
   912 initfont(const char *fontstr) {
   933 initfont(const char *fontstr) {
   913 	char *def, **missing;
   934 	char *def, **missing;
  1043 	c->tags = emallocz(TAGSZ);
  1064 	c->tags = emallocz(TAGSZ);
  1044 	c->win = w;
  1065 	c->win = w;
  1045 
  1066 
  1046 	applyrules(c);
  1067 	applyrules(c);
  1047 
  1068 
  1048 	v = c->view;
  1069 	v = getview(c);
  1049 
  1070 
  1050 	c->x = wa->x + v->x;
  1071 	c->x = wa->x + v->x;
  1051 	c->y = wa->y + v->y;
  1072 	c->y = wa->y + v->y;
  1052 	c->w = wa->width;
  1073 	c->w = wa->width;
  1053 	c->h = wa->height;
  1074 	c->h = wa->height;
  1122 	Window dummy;
  1143 	Window dummy;
  1123 	XEvent ev;
  1144 	XEvent ev;
  1124 
  1145 
  1125 	ocx = nx = c->x;
  1146 	ocx = nx = c->x;
  1126 	ocy = ny = c->y;
  1147 	ocy = ny = c->y;
  1127 	v = c->view;
  1148 	v = getview(c);
  1128 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1149 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1129 			None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1150 			None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1130 		return;
  1151 		return;
  1131 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
  1152 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
  1132 	for(;;) {
  1153 	for(;;) {
  1161 	}
  1182 	}
  1162 }
  1183 }
  1163 
  1184 
  1164 Client *
  1185 Client *
  1165 nexttiled(Client *c, View *v) {
  1186 nexttiled(Client *c, View *v) {
  1166 	for(; c && (c->isfloating || c->view != v || !isvisible(c)); c = c->next);
  1187 	for(; c && (c->isfloating || getview(c) != v || !isvisible(c)); c = c->next);
  1167 	return c;
  1188 	return c;
  1168 }
  1189 }
  1169 
  1190 
  1170 void
  1191 void
  1171 propertynotify(XEvent *e) {
  1192 propertynotify(XEvent *e) {
  1186 		case XA_WM_NORMAL_HINTS:
  1207 		case XA_WM_NORMAL_HINTS:
  1187 			updatesizehints(c);
  1208 			updatesizehints(c);
  1188 			break;
  1209 			break;
  1189 		case XA_WM_HINTS:
  1210 		case XA_WM_HINTS:
  1190 			updatewmhints(c);
  1211 			updatewmhints(c);
  1191 			drawbar(c->view);
  1212 			drawbar(getview(c));
  1192 			break;
  1213 			break;
  1193 		}
  1214 		}
  1194 		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
  1215 		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
  1195 			updatetitle(c);
  1216 			updatetitle(c);
  1196 			if(c == sel)
  1217 			if(c == sel)
  1219 void
  1240 void
  1220 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1241 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1221 	View *v;
  1242 	View *v;
  1222 	XWindowChanges wc;
  1243 	XWindowChanges wc;
  1223 
  1244 
  1224 	v = c->view;
  1245 	v = getview(c);
  1225 	if(sizehints) {
  1246 	if(sizehints) {
  1226 		/* set minimum possible */
  1247 		/* set minimum possible */
  1227 		if (w < 1)
  1248 		if (w < 1)
  1228 			w = 1;
  1249 			w = 1;
  1229 		if (h < 1)
  1250 		if (h < 1)
  1290 	View *v;
  1311 	View *v;
  1291 	XEvent ev;
  1312 	XEvent ev;
  1292 
  1313 
  1293 	ocx = c->x;
  1314 	ocx = c->x;
  1294 	ocy = c->y;
  1315 	ocy = c->y;
  1295 	v = c->view;
  1316 	v = getview(c);
  1296 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1317 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1297 			None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1318 			None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1298 		return;
  1319 		return;
  1299 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
  1320 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
  1300 	for(;;) {
  1321 	for(;;) {
  1558 			vtags[i] = 0;
  1579 			vtags[i] = 0;
  1559 
  1580 
  1560 	for(i = 0; i < nviews; i++) {
  1581 	for(i = 0; i < nviews; i++) {
  1561 		/* init geometry */
  1582 		/* init geometry */
  1562 		v = &views[i];
  1583 		v = &views[i];
  1563 
  1584 		v->id = i;
  1564 		/* select first tag in each view */
  1585 
  1565 		for(j = 0; j < LENGTH(tags); j++)
  1586 		/* select first tag of view */
  1566 			if(vtags[j] == i) {
  1587 		j = firstag(v);
  1567 				seltags[j] = prevtags[j] = True; 
  1588 		seltags[j] = prevtags[j] = True; 
  1568 				break;
       
  1569 			}
       
  1570 
       
  1571 
  1589 
  1572 		if(info) {
  1590 		if(info) {
  1573 
  1591 
  1574 #if defined(AIM_XINERAMA)
  1592 #if defined(AIM_XINERAMA)
  1575 v->w = DisplayWidth(dpy, screen) / 2;
  1593 v->w = DisplayWidth(dpy, screen) / 2;
  1659 	unsigned int i;
  1677 	unsigned int i;
  1660 
  1678 
  1661 	if(!sel)
  1679 	if(!sel)
  1662 		return;
  1680 		return;
  1663 	for(i = 0; i < LENGTH(tags); i++)
  1681 	for(i = 0; i < LENGTH(tags); i++)
  1664 		sel->tags[i] = (NULL == arg);
  1682 		sel->tags[i] = (NULL == arg) && (vtags[i] == getview(sel)->id);
  1665 	sel->tags[idxoftag(arg)] = True;
  1683 	i = idxoftag(arg);
       
  1684 	if(!conflicts(sel, i))
       
  1685 		sel->tags[idxoftag(arg)] = True;
  1666 	arrange();
  1686 	arrange();
  1667 }
  1687 }
  1668 
  1688 
  1669 unsigned int
  1689 unsigned int
  1670 textnw(const char *text, unsigned int len) {
  1690 textnw(const char *text, unsigned int len) {
  1751 	unsigned int i, j;
  1771 	unsigned int i, j;
  1752 
  1772 
  1753 	if(!sel)
  1773 	if(!sel)
  1754 		return;
  1774 		return;
  1755 	i = idxoftag(arg);
  1775 	i = idxoftag(arg);
       
  1776 	if(conflicts(sel, i))
       
  1777 		return;
  1756 	sel->tags[i] = !sel->tags[i];
  1778 	sel->tags[i] = !sel->tags[i];
  1757 	for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
  1779 	for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
  1758 	if(j == LENGTH(tags))
  1780 	if(j == LENGTH(tags))
  1759 		sel->tags[i] = True; /* at least one tag must be enabled */
  1781 		sel->tags[i] = True; /* at least one tag must be enabled */
  1760 	arrange();
  1782 	arrange();
  1906 	}
  1928 	}
  1907 }
  1929 }
  1908 
  1930 
  1909 void
  1931 void
  1910 view(const char *arg) {
  1932 view(const char *arg) {
  1911 	unsigned int i;
  1933 	unsigned int i, j;
  1912 	Bool tmp[LENGTH(tags)];
  1934 	Bool tmp[LENGTH(tags)];
  1913 
  1935 
  1914 	for(i = 0; i < LENGTH(tags); i++)
  1936 	memcpy(tmp, seltags, TAGSZ);
  1915 		tmp[i] = (NULL == arg);
  1937 	if(arg == NULL) {
  1916 	tmp[idxoftag(arg)] = True;
  1938 		for(i = 0; i < LENGTH(tags); i++)
  1917 
  1939 			tmp[i] = (vtags[i] == selview->id);
       
  1940 	}
       
  1941 	else {
       
  1942 		i = idxoftag(arg);
       
  1943 		for(j = 0; j < LENGTH(tags); j++)
       
  1944 			if(selview->id == vtags[i]) {
       
  1945 				/* view tag of selview */
       
  1946 				if(selview->id == vtags[j])
       
  1947 					tmp[j] = False;
       
  1948 			}
       
  1949 			else {
       
  1950 				/* only touch the view the focus should go */
       
  1951 				if(vtags[j] == vtags[i])
       
  1952 					tmp[j] = False;
       
  1953 			}
       
  1954 		selview = &views[vtags[i]];
       
  1955 		tmp[i] = True;
       
  1956 	}
  1918 	if(memcmp(seltags, tmp, TAGSZ) != 0) {
  1957 	if(memcmp(seltags, tmp, TAGSZ) != 0) {
  1919 		memcpy(prevtags, seltags, TAGSZ);
  1958 		memcpy(prevtags, seltags, TAGSZ);
  1920 		memcpy(seltags, tmp, TAGSZ);
  1959 		memcpy(seltags, tmp, TAGSZ);
  1921 		arrange();
  1960 		arrange();
  1922 	}
  1961 	}
  1983 zoom(const char *arg) {
  2022 zoom(const char *arg) {
  1984 	Client *c = sel;
  2023 	Client *c = sel;
  1985 
  2024 
  1986 	if(!sel || !dozoom || sel->isfloating)
  2025 	if(!sel || !dozoom || sel->isfloating)
  1987 		return;
  2026 		return;
  1988 	if(c == nexttiled(clients, c->view))
  2027 	if(c == nexttiled(clients, getview(c)))
  1989 		if(!(c = nexttiled(c->next, c->view)))
  2028 		if(!(c = nexttiled(c->next, getview(c))))
  1990 			return;
  2029 			return;
  1991 	detach(c);
  2030 	detach(c);
  1992 	attach(c);
  2031 	attach(c);
  1993 	focus(c);
  2032 	focus(c);
  1994 	arrange();
  2033 	arrange();