made the basics of the tagging concept working -- if people want dynamic tags, that's even possible with this concept, the vtags[] array needs to be modified during runtime for this -- the new code is quite experimental, ugly and needs polishing 7bc272a4
anselm@anselm1 · 2008-02-28 21:38 2 file(s) · +93 −54
config.mk +1 −1
17 17
# flags
18 18
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
19 19
LDFLAGS = -s ${LIBS}
20 -
CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
20 +
CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" -DAIM_XINERAMA
21 21
LDFLAGS = -g ${LIBS}
22 22
23 23
# Solaris
dwm.c +92 −53
71 71
	unsigned int border, oldborder;
72 72
	Bool isbanned, isfixed, isfloating, isurgent;
73 73
	Bool *tags;
74 -
	View *view;
75 74
	Client *next;
76 75
	Client *prev;
77 76
	Client *snext;
120 119
};
121 120
122 121
/* function declarations */
123 -
void addtag(Client *c, const char *t);
124 122
void applyrules(Client *c);
125 123
void arrange(void);
126 124
void attach(Client *c);
132 130
void configure(Client *c);
133 131
void configurenotify(XEvent *e);
134 132
void configurerequest(XEvent *e);
133 +
Bool conflicts(Client *c, unsigned int tidx);
135 134
void destroynotify(XEvent *e);
136 135
void detach(Client *c);
137 136
void detachstack(Client *c);
142 141
void enternotify(XEvent *e);
143 142
void eprint(const char *errstr, ...);
144 143
void expose(XEvent *e);
144 +
unsigned int firstag(View *v);
145 145
void floating(View *v); /* default floating layout */
146 146
void focus(Client *c);
147 147
void focusin(XEvent *e);
149 149
void focusprev(const char *arg);
150 150
Client *getclient(Window w);
151 151
unsigned long getcolor(const char *colstr);
152 +
View *getview(Client *c);
152 153
View *getviewbar(Window barwin);
153 154
long getstate(Window w);
154 155
Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
248 249
#define TAGSZ (LENGTH(tags) * sizeof(Bool))
249 250
250 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 253
void
263 254
applyrules(Client *c) {
264 -
	unsigned int i;
255 +
	unsigned int i, idx;
265 256
	Bool matched = False;
266 257
	Rule *r;
267 258
	XClassHint ch = { 0 };
275 266
		|| (ch.res_name && strstr(ch.res_name, r->prop)))
276 267
		{
277 268
			c->isfloating = r->isfloating;
278 -
			if(r->tag) {
279 -
				addtag(c, r->tag);
269 +
			if(r->tag && !conflicts(c, (idx = idxoftag(r->tag)))) {
270 +
				c->tags[idx] = True;
280 271
				matched = True;
281 272
			}
282 273
		}
286 277
	if(ch.res_name)
287 278
		XFree(ch.res_name);
288 279
	if(!matched) {
289 -
		memcpy(c->tags, seltags, TAGSZ);
290 -
		c->view = selview;
280 +
		for(i = 0; i < LENGTH(tags); i++)
281 +
			if(seltags[i] && vtags[i] == selview->id)
282 +
				c->tags[i] = True;
291 283
	}
292 284
}
293 285
327 319
ban(Client *c) {
328 320
	if(c->isbanned)
329 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 323
	c->isbanned = True;
332 324
}
333 325
367 359
		if(CLEANMASK(ev->state) != MODKEY)
368 360
			return;
369 361
		if(ev->button == Button1) {
370 -
			restack(c->view);
362 +
			restack(getview(c));
371 363
			movemouse(c);
372 364
		}
373 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 367
				togglefloating(NULL);
376 368
			else
377 369
				zoom(NULL);
378 370
		}
379 371
		else if(ev->button == Button3 && !c->isfixed) {
380 -
			restack(c->view);
372 +
			restack(getview(c));
381 373
			resizemouse(c);
382 374
		}
383 375
	}
466 458
	XWindowChanges wc;
467 459
468 460
	if((c = getclient(ev->window))) {
469 -
		View *v = c->view;
461 +
		View *v = getview(c);
470 462
		if(ev->value_mask & CWBorderWidth)
471 463
			c->border = ev->border_width;
472 464
		if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) {
504 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 509
void
508 510
destroynotify(XEvent *e) {
509 511
	Client *c;
538 540
	Client *c;
539 541
540 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 544
	for(i = 0; i < LENGTH(tags); i++) {
543 545
		if(&views[vtags[i]] != v)
544 546
			continue;
681 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 696
void
685 697
floating(View *v) { /* default floating layout */
686 698
	Client *c;
695 707
focus(Client *c) {
696 708
	View *v = selview;
697 709
	if(c)
698 -
		selview = c->view;
699 -
	else
700 -
		selview = viewat();
710 +
		selview = getview(c);
701 711
	if(selview != v)
702 712
		drawbar(v);
703 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 716
	if(sel && sel != c) {
706 717
		grabbuttons(sel, False);
707 718
		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
715 726
	if(c) {
716 727
		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
717 728
		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
718 -
		selview = c->view;
729 +
		selview = getview(c);
719 730
	}
720 731
	else
721 732
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
741 752
		for(c = clients; c && !isvisible(c); c = c->next);
742 753
	if(c) {
743 754
		focus(c);
744 -
		restack(c->view);
755 +
		restack(getview(c));
745 756
	}
746 757
}
747 758
758 769
	}
759 770
	if(c) {
760 771
		focus(c);
761 -
		restack(c->view);
772 +
		restack(getview(c));
762 773
	}
763 774
}
764 775
781 792
}
782 793
783 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;
802 +
}
803 +
804 +
View *
784 805
getviewbar(Window barwin) {
785 806
	unsigned int i;
786 807
905 926
	unsigned int i;
906 927
907 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 932
void
1045 1066
1046 1067
	applyrules(c);
1047 1068
1048 -
	v = c->view;
1069 +
	v = getview(c);
1049 1070
1050 1071
	c->x = wa->x + v->x;
1051 1072
	c->y = wa->y + v->y;
1124 1145
1125 1146
	ocx = nx = c->x;
1126 1147
	ocy = ny = c->y;
1127 -
	v = c->view;
1148 +
	v = getview(c);
1128 1149
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1129 1150
			None, cursor[CurMove], CurrentTime) != GrabSuccess)
1130 1151
		return;
1163 1184
1164 1185
Client *
1165 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 1188
	return c;
1168 1189
}
1169 1190
1188 1209
			break;
1189 1210
		case XA_WM_HINTS:
1190 1211
			updatewmhints(c);
1191 -
			drawbar(c->view);
1212 +
			drawbar(getview(c));
1192 1213
			break;
1193 1214
		}
1194 1215
		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
1221 1242
	View *v;
1222 1243
	XWindowChanges wc;
1223 1244
1224 -
	v = c->view;
1245 +
	v = getview(c);
1225 1246
	if(sizehints) {
1226 1247
		/* set minimum possible */
1227 1248
		if (w < 1)
1292 1313
1293 1314
	ocx = c->x;
1294 1315
	ocy = c->y;
1295 -
	v = c->view;
1316 +
	v = getview(c);
1296 1317
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1297 1318
			None, cursor[CurResize], CurrentTime) != GrabSuccess)
1298 1319
		return;
1560 1581
	for(i = 0; i < nviews; i++) {
1561 1582
		/* init geometry */
1562 1583
		v = &views[i];
1584 +
		v->id = i;
1563 1585
1564 -
		/* select first tag in each view */
1565 -
		for(j = 0; j < LENGTH(tags); j++)
1566 -
			if(vtags[j] == i) {
1567 -
				seltags[j] = prevtags[j] = True; 
1568 -
				break;
1569 -
			}
1570 -
1586 +
		/* select first tag of view */
1587 +
		j = firstag(v);
1588 +
		seltags[j] = prevtags[j] = True; 
1571 1589
1572 1590
		if(info) {
1573 1591
1661 1679
	if(!sel)
1662 1680
		return;
1663 1681
	for(i = 0; i < LENGTH(tags); i++)
1664 -
		sel->tags[i] = (NULL == arg);
1665 -
	sel->tags[idxoftag(arg)] = True;
1682 +
		sel->tags[i] = (NULL == arg) && (vtags[i] == getview(sel)->id);
1683 +
	i = idxoftag(arg);
1684 +
	if(!conflicts(sel, i))
1685 +
		sel->tags[idxoftag(arg)] = True;
1666 1686
	arrange();
1667 1687
}
1668 1688
1753 1773
	if(!sel)
1754 1774
		return;
1755 1775
	i = idxoftag(arg);
1776 +
	if(conflicts(sel, i))
1777 +
		return;
1756 1778
	sel->tags[i] = !sel->tags[i];
1757 1779
	for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
1758 1780
	if(j == LENGTH(tags))
1908 1930
1909 1931
void
1910 1932
view(const char *arg) {
1911 -
	unsigned int i;
1933 +
	unsigned int i, j;
1912 1934
	Bool tmp[LENGTH(tags)];
1913 1935
1914 -
	for(i = 0; i < LENGTH(tags); i++)
1915 -
		tmp[i] = (NULL == arg);
1916 -
	tmp[idxoftag(arg)] = True;
1917 -
1936 +
	memcpy(tmp, seltags, TAGSZ);
1937 +
	if(arg == NULL) {
1938 +
		for(i = 0; i < LENGTH(tags); i++)
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 1957
	if(memcmp(seltags, tmp, TAGSZ) != 0) {
1919 1958
		memcpy(prevtags, seltags, TAGSZ);
1920 1959
		memcpy(seltags, tmp, TAGSZ);
1985 2024
1986 2025
	if(!sel || !dozoom || sel->isfloating)
1987 2026
		return;
1988 -
	if(c == nexttiled(clients, c->view))
1989 -
		if(!(c = nexttiled(c->next, c->view)))
2027 +
	if(c == nexttiled(clients, getview(c)))
2028 +
		if(!(c = nexttiled(c->next, getview(c))))
1990 2029
			return;
1991 2030
	detach(c);
1992 2031
	attach(c);