dwm.c
changeset 1088 06fbc117e7d8
parent 1087 197bfedb953c
child 1089 bd14fa197cf6
equal deleted inserted replaced
1087:197bfedb953c 1088:06fbc117e7d8
   115 	regex_t *propregex;
   115 	regex_t *propregex;
   116 	regex_t *tagregex;
   116 	regex_t *tagregex;
   117 } Regs;
   117 } Regs;
   118 
   118 
   119 typedef struct {
   119 typedef struct {
   120 	int screen;
   120 	int monitor;
   121 	Window barwin;
   121 	Window barwin;
   122 	int sx, sy, sw, sh, wax, way, wah, waw;
   122 	int sx, sy, sw, sh, wax, way, wah, waw;
   123 	DC dc;
       
   124 	Bool *seltags;
   123 	Bool *seltags;
   125 	Bool *prevtags;
   124 	Bool *prevtags;
   126 	Layout *layout;
   125 	Layout *layout;
   127 	double mwfact;
   126 	double mwfact;
   128 } Monitor;
   127 } Monitor;
   154 void focus(Client *c);
   153 void focus(Client *c);
   155 void focusin(XEvent *e);
   154 void focusin(XEvent *e);
   156 void focusnext(const char *arg);
   155 void focusnext(const char *arg);
   157 void focusprev(const char *arg);
   156 void focusprev(const char *arg);
   158 Client *getclient(Window w);
   157 Client *getclient(Window w);
   159 unsigned long getcolor(const char *colstr, int screen);
   158 unsigned long getcolor(const char *colstr);
   160 long getstate(Window w);
   159 long getstate(Window w);
   161 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   160 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   162 void grabbuttons(Client *c, Bool focused);
   161 void grabbuttons(Client *c, Bool focused);
   163 void grabkeys(void);
   162 void grabkeys(void);
   164 unsigned int idxoftag(const char *tag);
   163 unsigned int idxoftag(const char *tag);
   165 void initfont(Monitor*, const char *fontstr);
   164 void initfont(const char *fontstr);
   166 Bool isoccupied(unsigned int monitor, unsigned int t);
   165 Bool isoccupied(unsigned int monitor, unsigned int t);
   167 Bool isprotodel(Client *c);
   166 Bool isprotodel(Client *c);
   168 Bool isurgent(unsigned int monitor, unsigned int t);
   167 Bool isurgent(unsigned int monitor, unsigned int t);
   169 Bool isvisible(Client *c, int monitor);
   168 Bool isvisible(Client *c, int monitor);
   170 void keypress(XEvent *e);
   169 void keypress(XEvent *e);
   186 void setlayout(const char *arg);
   185 void setlayout(const char *arg);
   187 void setmwfact(const char *arg);
   186 void setmwfact(const char *arg);
   188 void setup(void);
   187 void setup(void);
   189 void spawn(const char *arg);
   188 void spawn(const char *arg);
   190 void tag(const char *arg);
   189 void tag(const char *arg);
   191 unsigned int textnw(Monitor*, const char *text, unsigned int len);
   190 unsigned int textnw(const char *text, unsigned int len);
   192 unsigned int textw(Monitor*, const char *text);
   191 unsigned int textw(const char *text);
   193 void tile(void);
   192 void tile(void);
   194 void togglebar(const char *arg);
   193 void togglebar(const char *arg);
   195 void togglefloating(const char *arg);
   194 void togglefloating(const char *arg);
   196 void toggletag(const char *arg);
   195 void toggletag(const char *arg);
   197 void toggleview(const char *arg);
   196 void toggleview(const char *arg);
   214 
   213 
   215 /* variables */
   214 /* variables */
   216 char stext[256];
   215 char stext[256];
   217 int mcount = 1;
   216 int mcount = 1;
   218 int selmonitor = 0;
   217 int selmonitor = 0;
       
   218 int screen;
   219 int (*xerrorxlib)(Display *, XErrorEvent *);
   219 int (*xerrorxlib)(Display *, XErrorEvent *);
   220 unsigned int bh, bpos;
   220 unsigned int bh, bpos;
   221 unsigned int blw = 0;
   221 unsigned int blw = 0;
   222 unsigned int numlockmask = 0;
   222 unsigned int numlockmask = 0;
   223 void (*handler[LASTEvent]) (XEvent *) = {
   223 void (*handler[LASTEvent]) (XEvent *) = {
   341 	Monitor *m = &monitors[monitorat()];
   341 	Monitor *m = &monitors[monitorat()];
   342 
   342 
   343 	if(ev->window == m->barwin) {
   343 	if(ev->window == m->barwin) {
   344 		x = 0;
   344 		x = 0;
   345 		for(i = 0; i < LENGTH(tags); i++) {
   345 		for(i = 0; i < LENGTH(tags); i++) {
   346 			x += textw(m, tags[i]);
   346 			x += textw(tags[i]);
   347 			if(ev->x < x) {
   347 			if(ev->x < x) {
   348 				if(ev->button == Button1) {
   348 				if(ev->button == Button1) {
   349 					if(ev->state & MODKEY)
   349 					if(ev->state & MODKEY)
   350 						tag(tags[i]);
   350 						tag(tags[i]);
   351 					else
   351 					else
   406 	close(STDIN_FILENO);
   406 	close(STDIN_FILENO);
   407 	while(stack) {
   407 	while(stack) {
   408 		unban(stack);
   408 		unban(stack);
   409 		unmanage(stack);
   409 		unmanage(stack);
   410 	}
   410 	}
   411 	for(i = 0; i < mcount; i++) {
   411 	if(dc.font.set)
   412 		Monitor *m = &monitors[i];
   412 		XFreeFontSet(dpy, dc.font.set);
   413 		if(m->dc.font.set)
   413 	else
   414 			XFreeFontSet(dpy, m->dc.font.set);
   414 		XFreeFont(dpy, dc.font.xfont);
   415 		else
   415 
   416 			XFreeFont(dpy, m->dc.font.xfont);
   416 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   417 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
   417 	XFreePixmap(dpy, dc.drawable);
   418 		XFreePixmap(dpy, m->dc.drawable);
   418 	XFreeGC(dpy, dc.gc);
   419 		XFreeGC(dpy, m->dc.gc);
   419 	XFreeCursor(dpy, cursor[CurNormal]);
   420 		XDestroyWindow(dpy, m->barwin);
   420 	XFreeCursor(dpy, cursor[CurResize]);
   421 		XFreeCursor(dpy, cursor[CurNormal]);
   421 	XFreeCursor(dpy, cursor[CurMove]);
   422 		XFreeCursor(dpy, cursor[CurResize]);
   422 	for(i = 0; i < mcount; i++)
   423 		XFreeCursor(dpy, cursor[CurMove]);
   423 		XDestroyWindow(dpy, monitors[i].barwin);
   424 		XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   424 	XSync(dpy, False);
   425 		XSync(dpy, False);
   425 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   426 	}
       
   427 }
   426 }
   428 
   427 
   429 void
   428 void
   430 compileregs(void) {
   429 compileregs(void) {
   431 	unsigned int i;
   430 	unsigned int i;
   474 configurenotify(XEvent *e) {
   473 configurenotify(XEvent *e) {
   475 	XConfigureEvent *ev = &e->xconfigure;
   474 	XConfigureEvent *ev = &e->xconfigure;
   476 	Monitor *m = &monitors[selmonitor];
   475 	Monitor *m = &monitors[selmonitor];
   477 
   476 
   478 	if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) {
   477 	if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) {
       
   478 		/* TODO -- update Xinerama dimensions here */
   479 		m->sw = ev->width;
   479 		m->sw = ev->width;
   480 		m->sh = ev->height;
   480 		m->sh = ev->height;
   481 		XFreePixmap(dpy, dc.drawable);
   481 		XFreePixmap(dpy, dc.drawable);
   482 		dc.drawable = XCreatePixmap(dpy, root, m->sw, bh, DefaultDepth(dpy, m->screen));
   482 		dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen));
   483 		XResizeWindow(dpy, m->barwin, m->sw, bh);
   483 		XResizeWindow(dpy, m->barwin, m->sw, bh);
   484 		updatebarpos(m);
   484 		updatebarpos(m);
   485 		arrange();
   485 		arrange();
   486 	}
   486 	}
   487 }
   487 }
   564 	int i, j, x;
   564 	int i, j, x;
   565 	Client *c;
   565 	Client *c;
   566 
   566 
   567 	for(i = 0; i < mcount; i++) {
   567 	for(i = 0; i < mcount; i++) {
   568 		Monitor *m = &monitors[i];
   568 		Monitor *m = &monitors[i];
   569 		m->dc.x = 0;
   569 		dc.x = 0;
   570 		for(c = stack; c && !isvisible(c, i); c = c->snext);
   570 		for(c = stack; c && !isvisible(c, i); c = c->snext);
   571 		fprintf(stderr, "m%d %s\n", i, c ? c->name : "NIL");
   571 		fprintf(stderr, "m%d %s\n", i, c ? c->name : "NIL");
   572 		for(j = 0; j < LENGTH(tags); j++) {
   572 		for(j = 0; j < LENGTH(tags); j++) {
   573 			m->dc.w = textw(m, tags[j]);
   573 			dc.w = textw(tags[j]);
   574 			if(m->seltags[j]) {
   574 			if(m->seltags[j]) {
   575 				drawtext(m, tags[j], m->dc.sel, isurgent(i, j));
   575 				drawtext(m, tags[j], dc.sel, isurgent(i, j));
   576 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   576 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   577 						isoccupied(i, j), isurgent(i, j), m->dc.sel);
   577 						isoccupied(i, j), isurgent(i, j), dc.sel);
   578 			}
   578 			}
   579 			else {
   579 			else {
   580 				drawtext(m, tags[j], m->dc.norm, isurgent(i, j));
   580 				drawtext(m, tags[j], dc.norm, isurgent(i, j));
   581 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   581 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   582 						isoccupied(i, j), isurgent(i, j), m->dc.norm);
   582 						isoccupied(i, j), isurgent(i, j), dc.norm);
   583 			}
   583 			}
   584 			m->dc.x += m->dc.w;
   584 			dc.x += dc.w;
   585 		}
   585 		}
   586 		m->dc.w = blw;
   586 		dc.w = blw;
   587 		drawtext(m, m->layout->symbol, m->dc.norm, False);
   587 		drawtext(m, m->layout->symbol, dc.norm, False);
   588 		x = m->dc.x + m->dc.w;
   588 		x = dc.x + dc.w;
   589 		if(i == selmonitor) {
   589 		if(i == selmonitor) {
   590 			m->dc.w = textw(m, stext);
   590 			dc.w = textw(stext);
   591 			m->dc.x = m->sw - m->dc.w;
   591 			dc.x = m->sw - dc.w;
   592 			if(m->dc.x < x) {
   592 			if(dc.x < x) {
   593 				m->dc.x = x;
   593 				dc.x = x;
   594 				m->dc.w = m->sw - x;
   594 				dc.w = m->sw - x;
   595 			}
   595 			}
   596 			drawtext(m, stext, m->dc.norm, False);
   596 			drawtext(m, stext, dc.norm, False);
   597 		}
   597 		}
   598 		else
   598 		else
   599 			m->dc.x = m->sw;
   599 			dc.x = m->sw;
   600 		if((m->dc.w = m->dc.x - x) > bh) {
   600 		if((dc.w = dc.x - x) > bh) {
   601 			m->dc.x = x;
   601 			dc.x = x;
   602 			if(c) {
   602 			if(c) {
   603 				drawtext(m, c->name, m->dc.sel, False);
   603 				drawtext(m, c->name, dc.sel, False);
   604 				drawsquare(m, False, c->isfloating, False, m->dc.sel);
   604 				drawsquare(m, False, c->isfloating, False, dc.sel);
   605 			}
   605 			}
   606 			else
   606 			else
   607 				drawtext(m, NULL, m->dc.norm, False);
   607 				drawtext(m, NULL, dc.norm, False);
   608 		}
   608 		}
   609 		XCopyArea(dpy, m->dc.drawable, m->barwin, m->dc.gc, 0, 0, m->sw, bh, 0, 0);
   609 		XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0);
   610 		XSync(dpy, False);
   610 		XSync(dpy, False);
   611 	}
   611 	}
   612 }
   612 }
   613 
   613 
   614 void
   614 void
   615 drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   615 drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   616 	int x;
   616 	int x;
   617 	XGCValues gcv;
   617 	XGCValues gcv;
   618 	XRectangle r = { m->dc.x, m->dc.y, m->dc.w, m->dc.h };
   618 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   619 
   619 
   620 	gcv.foreground = col[invert ? ColBG : ColFG];
   620 	gcv.foreground = col[invert ? ColBG : ColFG];
   621 	XChangeGC(dpy, m->dc.gc, GCForeground, &gcv);
   621 	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
   622 	x = (m->dc.font.ascent + m->dc.font.descent + 2) / 4;
   622 	x = (dc.font.ascent + dc.font.descent + 2) / 4;
   623 	r.x = m->dc.x + 1;
   623 	r.x = dc.x + 1;
   624 	r.y = m->dc.y + 1;
   624 	r.y = dc.y + 1;
   625 	if(filled) {
   625 	if(filled) {
   626 		r.width = r.height = x + 1;
   626 		r.width = r.height = x + 1;
   627 		XFillRectangles(dpy, m->dc.drawable, m->dc.gc, &r, 1);
   627 		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   628 	}
   628 	}
   629 	else if(empty) {
   629 	else if(empty) {
   630 		r.width = r.height = x;
   630 		r.width = r.height = x;
   631 		XDrawRectangles(dpy, m->dc.drawable, m->dc.gc, &r, 1);
   631 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   632 	}
   632 	}
   633 }
   633 }
   634 
   634 
   635 void
   635 void
   636 drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert) {
   636 drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert) {
   637 	int x, y, w, h;
   637 	int x, y, w, h;
   638 	static char buf[256];
   638 	static char buf[256];
   639 	unsigned int len, olen;
   639 	unsigned int len, olen;
   640 	XRectangle r = { m->dc.x, m->dc.y, m->dc.w, m->dc.h };
   640 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   641 
   641 
   642 	XSetForeground(dpy, m->dc.gc, col[invert ? ColFG : ColBG]);
   642 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   643 	XFillRectangles(dpy, m->dc.drawable, m->dc.gc, &r, 1);
   643 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   644 	if(!text)
   644 	if(!text)
   645 		return;
   645 		return;
   646 	w = 0;
   646 	w = 0;
   647 	olen = len = strlen(text);
   647 	olen = len = strlen(text);
   648 	if(len >= sizeof buf)
   648 	if(len >= sizeof buf)
   649 		len = sizeof buf - 1;
   649 		len = sizeof buf - 1;
   650 	memcpy(buf, text, len);
   650 	memcpy(buf, text, len);
   651 	buf[len] = 0;
   651 	buf[len] = 0;
   652 	h = m->dc.font.ascent + m->dc.font.descent;
   652 	h = dc.font.ascent + dc.font.descent;
   653 	y = m->dc.y + (m->dc.h / 2) - (h / 2) + m->dc.font.ascent;
   653 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
   654 	x = m->dc.x + (h / 2);
   654 	x = dc.x + (h / 2);
   655 	/* shorten text if necessary */
   655 	/* shorten text if necessary */
   656 	while(len && (w = textnw(m, buf, len)) > m->dc.w - h)
   656 	while(len && (w = textnw(buf, len)) > dc.w - h)
   657 		buf[--len] = 0;
   657 		buf[--len] = 0;
   658 	if(len < olen) {
   658 	if(len < olen) {
   659 		if(len > 1)
   659 		if(len > 1)
   660 			buf[len - 1] = '.';
   660 			buf[len - 1] = '.';
   661 		if(len > 2)
   661 		if(len > 2)
   662 			buf[len - 2] = '.';
   662 			buf[len - 2] = '.';
   663 		if(len > 3)
   663 		if(len > 3)
   664 			buf[len - 3] = '.';
   664 			buf[len - 3] = '.';
   665 	}
   665 	}
   666 	if(w > m->dc.w)
   666 	if(w > dc.w)
   667 		return; /* too long */
   667 		return; /* too long */
   668 	XSetForeground(dpy, m->dc.gc, col[invert ? ColBG : ColFG]);
   668 	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
   669 	if(m->dc.font.set)
   669 	if(dc.font.set)
   670 		XmbDrawString(dpy, m->dc.drawable, m->dc.font.set, m->dc.gc, x, y, buf, len);
   670 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
   671 	else
   671 	else
   672 		XDrawString(dpy, m->dc.drawable, m->dc.gc, x, y, buf, len);
   672 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   673 }
   673 }
   674 
   674 
   675 void *
   675 void *
   676 emallocz(unsigned int size) {
   676 emallocz(unsigned int size) {
   677 	void *res = calloc(1, size);
   677 	void *res = calloc(1, size);
   738 	m = &monitors[selmonitor];
   738 	m = &monitors[selmonitor];
   739 	if(!c || (c && !isvisible(c, selmonitor)))
   739 	if(!c || (c && !isvisible(c, selmonitor)))
   740 		for(c = stack; c && !isvisible(c, c->monitor); c = c->snext);
   740 		for(c = stack; c && !isvisible(c, c->monitor); c = c->snext);
   741 	if(sel && sel != c) {
   741 	if(sel && sel != c) {
   742 		grabbuttons(sel, False);
   742 		grabbuttons(sel, False);
   743 		XSetWindowBorder(dpy, sel->win, monitors[sel->monitor].dc.norm[ColBorder]);
   743 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   744 	}
   744 	}
   745 	if(c) {
   745 	if(c) {
   746 		detachstack(c);
   746 		detachstack(c);
   747 		attachstack(c);
   747 		attachstack(c);
   748 		grabbuttons(c, True);
   748 		grabbuttons(c, True);
   749 	}
   749 	}
   750 	sel = c;
   750 	sel = c;
   751 	drawbar();
   751 	drawbar();
   752 	if(c) {
   752 	if(c) {
   753 		XSetWindowBorder(dpy, c->win, m->dc.sel[ColBorder]);
   753 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   754 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   754 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   755 		selmonitor = c->monitor;
   755 		selmonitor = c->monitor;
   756 	}
   756 	}
   757 	else {
   757 	else {
   758 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   758 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   807 	for(c = clients; c && c->win != w; c = c->next);
   807 	for(c = clients; c && c->win != w; c = c->next);
   808 	return c;
   808 	return c;
   809 }
   809 }
   810 
   810 
   811 unsigned long
   811 unsigned long
   812 getcolor(const char *colstr, int screen) {
   812 getcolor(const char *colstr) {
   813 	Colormap cmap = DefaultColormap(dpy, screen);
   813 	Colormap cmap = DefaultColormap(dpy, screen);
   814 	XColor color;
   814 	XColor color;
   815 
   815 
   816 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   816 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   817 		eprint("error, cannot allocate color '%s'\n", colstr);
   817 		eprint("error, cannot allocate color '%s'\n", colstr);
   935 	for(i = 0; (i < LENGTH(tags)) && (tags[i] != tag); i++);
   935 	for(i = 0; (i < LENGTH(tags)) && (tags[i] != tag); i++);
   936 	return (i < LENGTH(tags)) ? i : 0;
   936 	return (i < LENGTH(tags)) ? i : 0;
   937 }
   937 }
   938 
   938 
   939 void
   939 void
   940 initfont(Monitor *m, const char *fontstr) {
   940 initfont(const char *fontstr) {
   941 	char *def, **missing;
   941 	char *def, **missing;
   942 	int i, n;
   942 	int i, n;
   943 
   943 
   944 	missing = NULL;
   944 	missing = NULL;
   945 	if(m->dc.font.set)
   945 	if(dc.font.set)
   946 		XFreeFontSet(dpy, m->dc.font.set);
   946 		XFreeFontSet(dpy, dc.font.set);
   947 	m->dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
   947 	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
   948 	if(missing) {
   948 	if(missing) {
   949 		while(n--)
   949 		while(n--)
   950 			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
   950 			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
   951 		XFreeStringList(missing);
   951 		XFreeStringList(missing);
   952 	}
   952 	}
   953 	if(m->dc.font.set) {
   953 	if(dc.font.set) {
   954 		XFontSetExtents *font_extents;
   954 		XFontSetExtents *font_extents;
   955 		XFontStruct **xfonts;
   955 		XFontStruct **xfonts;
   956 		char **font_names;
   956 		char **font_names;
   957 		m->dc.font.ascent = m->dc.font.descent = 0;
   957 		dc.font.ascent = dc.font.descent = 0;
   958 		font_extents = XExtentsOfFontSet(m->dc.font.set);
   958 		font_extents = XExtentsOfFontSet(dc.font.set);
   959 		n = XFontsOfFontSet(m->dc.font.set, &xfonts, &font_names);
   959 		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
   960 		for(i = 0, m->dc.font.ascent = 0, m->dc.font.descent = 0; i < n; i++) {
   960 		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
   961 			if(m->dc.font.ascent < (*xfonts)->ascent)
   961 			if(dc.font.ascent < (*xfonts)->ascent)
   962 				m->dc.font.ascent = (*xfonts)->ascent;
   962 				dc.font.ascent = (*xfonts)->ascent;
   963 			if(m->dc.font.descent < (*xfonts)->descent)
   963 			if(dc.font.descent < (*xfonts)->descent)
   964 				m->dc.font.descent = (*xfonts)->descent;
   964 				dc.font.descent = (*xfonts)->descent;
   965 			xfonts++;
   965 			xfonts++;
   966 		}
   966 		}
   967 	}
   967 	}
   968 	else {
   968 	else {
   969 		if(m->dc.font.xfont)
   969 		if(dc.font.xfont)
   970 			XFreeFont(dpy, m->dc.font.xfont);
   970 			XFreeFont(dpy, dc.font.xfont);
   971 		m->dc.font.xfont = NULL;
   971 		dc.font.xfont = NULL;
   972 		if(!(m->dc.font.xfont = XLoadQueryFont(dpy, fontstr))
   972 		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
   973 		&& !(m->dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
   973 		&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
   974 			eprint("error, cannot load font: '%s'\n", fontstr);
   974 			eprint("error, cannot load font: '%s'\n", fontstr);
   975 		m->dc.font.ascent = m->dc.font.xfont->ascent;
   975 		dc.font.ascent = dc.font.xfont->ascent;
   976 		m->dc.font.descent = m->dc.font.xfont->descent;
   976 		dc.font.descent = dc.font.xfont->descent;
   977 	}
   977 	}
   978 	m->dc.font.height = m->dc.font.ascent + m->dc.font.descent;
   978 	dc.font.height = dc.font.ascent + dc.font.descent;
   979 }
   979 }
   980 
   980 
   981 Bool
   981 Bool
   982 isoccupied(unsigned int monitor, unsigned int t) {
   982 isoccupied(unsigned int monitor, unsigned int t) {
   983 	Client *c;
   983 	Client *c;
  1099 			c->y = m->way;
  1099 			c->y = m->way;
  1100 		c->border = BORDERPX;
  1100 		c->border = BORDERPX;
  1101 	}
  1101 	}
  1102 	wc.border_width = c->border;
  1102 	wc.border_width = c->border;
  1103 	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
  1103 	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
  1104 	XSetWindowBorder(dpy, w, m->dc.norm[ColBorder]);
  1104 	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
  1105 	configure(c); /* propagates border_width, if size doesn't change */
  1105 	configure(c); /* propagates border_width, if size doesn't change */
  1106 	updatesizehints(c);
  1106 	updatesizehints(c);
  1107 	XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
  1107 	XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
  1108 	grabbuttons(c, False);
  1108 	grabbuttons(c, False);
  1109 	updatetitle(c);
  1109 	updatetitle(c);
  1547 	arrange();
  1547 	arrange();
  1548 }
  1548 }
  1549 
  1549 
  1550 void
  1550 void
  1551 setup(void) {
  1551 setup(void) {
  1552 	unsigned int i, j, k;
  1552 	unsigned int i;
  1553 	Monitor *m;
  1553 	Monitor *m;
  1554 	XSetWindowAttributes wa;
  1554 	XSetWindowAttributes wa;
  1555 	XineramaScreenInfo *info = NULL;
  1555 	XineramaScreenInfo *info = NULL;
  1556 
  1556 
  1557 	/* init atoms */
  1557 	/* init atoms */
  1571 	mcount = 1;
  1571 	mcount = 1;
  1572 	if((isxinerama = XineramaIsActive(dpy)))
  1572 	if((isxinerama = XineramaIsActive(dpy)))
  1573 		info = XineramaQueryScreens(dpy, &mcount);
  1573 		info = XineramaQueryScreens(dpy, &mcount);
  1574 	monitors = emallocz(mcount * sizeof(Monitor));
  1574 	monitors = emallocz(mcount * sizeof(Monitor));
  1575 
  1575 
  1576 	root = DefaultRootWindow(dpy);
  1576 	screen = DefaultScreen(dpy);
  1577 
  1577 	root = RootWindow(dpy, screen);
       
  1578 
       
  1579 	/* init appearance */
       
  1580 	dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR);
       
  1581 	dc.norm[ColBG] = getcolor(NORMBGCOLOR);
       
  1582 	dc.norm[ColFG] = getcolor(NORMFGCOLOR);
       
  1583 	dc.sel[ColBorder] = getcolor(SELBORDERCOLOR);
       
  1584 	dc.sel[ColBG] = getcolor(SELBGCOLOR);
       
  1585 	dc.sel[ColFG] = getcolor(SELFGCOLOR);
       
  1586 	initfont(FONT);
       
  1587 	dc.h = bh = dc.font.height + 2;
       
  1588 	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
       
  1589 	dc.gc = XCreateGC(dpy, root, 0, 0);
       
  1590 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
       
  1591 	if(!dc.font.set)
       
  1592 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
       
  1593 
       
  1594 	for(blw = i = 0; i < LENGTH(layouts); i++) {
       
  1595 		i = textw(layouts[i].symbol);
       
  1596 		if(i > blw)
       
  1597 			blw = i;
       
  1598 	}
  1578 	for(i = 0; i < mcount; i++) {
  1599 	for(i = 0; i < mcount; i++) {
  1579 		/* init geometry */
  1600 		/* init geometry */
  1580 		m = &monitors[i];
  1601 		m = &monitors[i];
  1581 
  1602 
  1582 		m->screen = isxinerama ? 0 : i;
  1603 		m->monitor = i;
  1583 
  1604 
  1584 		if (mcount != 1 && isxinerama) {
  1605 		if (mcount != 1 && isxinerama) {
  1585 			m->sx = info[i].x_org;
  1606 			m->sx = info[i].x_org;
  1586 			m->sy = info[i].y_org;
  1607 			m->sy = info[i].y_org;
  1587 			m->sw = info[i].width;
  1608 			m->sw = info[i].width;
  1589 			fprintf(stderr, "monitor[%d]: %d,%d,%d,%d\n", i, m->sx, m->sy, m->sw, m->sh);
  1610 			fprintf(stderr, "monitor[%d]: %d,%d,%d,%d\n", i, m->sx, m->sy, m->sw, m->sh);
  1590 		}
  1611 		}
  1591 		else {
  1612 		else {
  1592 			m->sx = 0;
  1613 			m->sx = 0;
  1593 			m->sy = 0;
  1614 			m->sy = 0;
  1594 			m->sw = DisplayWidth(dpy, m->screen);
  1615 			m->sw = DisplayWidth(dpy, screen);
  1595 			m->sh = DisplayHeight(dpy, m->screen);
  1616 			m->sh = DisplayHeight(dpy, screen);
  1596 		}
  1617 		}
  1597 
  1618 
  1598 		m->seltags = emallocz(sizeof initags);
  1619 		m->seltags = emallocz(sizeof initags);
  1599 		m->prevtags = emallocz(sizeof initags);
  1620 		m->prevtags = emallocz(sizeof initags);
  1600 
  1621 
  1601 		memcpy(m->seltags, initags, sizeof initags);
  1622 		memcpy(m->seltags, initags, sizeof initags);
  1602 		memcpy(m->prevtags, initags, sizeof initags);
  1623 		memcpy(m->prevtags, initags, sizeof initags);
  1603 
       
  1604 		/* init appearance */
       
  1605 		m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, m->screen);
       
  1606 		m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, m->screen);
       
  1607 		m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, m->screen);
       
  1608 		m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, m->screen);
       
  1609 		m->dc.sel[ColBG] = getcolor(SELBGCOLOR, m->screen);
       
  1610 		m->dc.sel[ColFG] = getcolor(SELFGCOLOR, m->screen);
       
  1611 		initfont(m, FONT);
       
  1612 		m->dc.h = bh = m->dc.font.height + 2;
       
  1613 
  1624 
  1614 		/* init layouts */
  1625 		/* init layouts */
  1615 		m->mwfact = MWFACT;
  1626 		m->mwfact = MWFACT;
  1616 		m->layout = &layouts[0];
  1627 		m->layout = &layouts[0];
  1617 		for(blw = k = 0; k < LENGTH(layouts); k++) {
       
  1618 			j = textw(m, layouts[k].symbol);
       
  1619 			if(j > blw)
       
  1620 				blw = j;
       
  1621 		}
       
  1622 
  1628 
  1623 		// TODO: bpos per screen?
  1629 		// TODO: bpos per screen?
  1624 		bpos = BARPOS;
  1630 		bpos = BARPOS;
  1625 		wa.override_redirect = 1;
  1631 		wa.override_redirect = 1;
  1626 		wa.background_pixmap = ParentRelative;
  1632 		wa.background_pixmap = ParentRelative;
  1627 		wa.event_mask = ButtonPressMask | ExposureMask;
  1633 		wa.event_mask = ButtonPressMask | ExposureMask;
  1628 
  1634 
  1629 		/* init bars */
  1635 		/* init bars */
  1630 		m->barwin = XCreateWindow(dpy, root, m->sx, m->sy, m->sw, bh, 0,
  1636 		m->barwin = XCreateWindow(dpy, root, m->sx, m->sy, m->sw, bh, 0,
  1631 				DefaultDepth(dpy, m->screen), CopyFromParent, DefaultVisual(dpy, m->screen),
  1637 				DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
  1632 				CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
  1638 				CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
  1633 		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  1639 		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  1634 		updatebarpos(m);
  1640 		updatebarpos(m);
  1635 		XMapRaised(dpy, m->barwin);
  1641 		XMapRaised(dpy, m->barwin);
  1636 		strcpy(stext, "dwm-"VERSION);
  1642 		strcpy(stext, "dwm-"VERSION);
  1637 		m->dc.drawable = XCreatePixmap(dpy, root, m->sw, bh, DefaultDepth(dpy, m->screen));
       
  1638 		m->dc.gc = XCreateGC(dpy, root, 0, 0);
       
  1639 		XSetLineAttributes(dpy, m->dc.gc, 1, LineSolid, CapButt, JoinMiter);
       
  1640 		if(!m->dc.font.set)
       
  1641 			XSetFont(dpy, m->dc.gc, m->dc.font.xfont->fid);
       
  1642 
  1643 
  1643 		/* EWMH support per monitor */
  1644 		/* EWMH support per monitor */
  1644 		XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1645 		XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1645 				PropModeReplace, (unsigned char *) netatom, NetLast);
  1646 				PropModeReplace, (unsigned char *) netatom, NetLast);
  1646 
  1647 
  1698 	sel->tags[idxoftag(arg)] = True;
  1699 	sel->tags[idxoftag(arg)] = True;
  1699 	arrange();
  1700 	arrange();
  1700 }
  1701 }
  1701 
  1702 
  1702 unsigned int
  1703 unsigned int
  1703 textnw(Monitor *m, const char *text, unsigned int len) {
  1704 textnw(const char *text, unsigned int len) {
  1704 	XRectangle r;
  1705 	XRectangle r;
  1705 
  1706 
  1706 	if(m->dc.font.set) {
  1707 	if(dc.font.set) {
  1707 		XmbTextExtents(m->dc.font.set, text, len, NULL, &r);
  1708 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1708 		return r.width;
  1709 		return r.width;
  1709 	}
  1710 	}
  1710 	return XTextWidth(m->dc.font.xfont, text, len);
  1711 	return XTextWidth(dc.font.xfont, text, len);
  1711 }
  1712 }
  1712 
  1713 
  1713 unsigned int
  1714 unsigned int
  1714 textw(Monitor *m, const char *text) {
  1715 textw(const char *text) {
  1715 	return textnw(m, text, strlen(text)) + m->dc.font.height;
  1716 	return textnw(text, strlen(text)) + dc.font.height;
  1716 }
  1717 }
  1717 
  1718 
  1718 void
  1719 void
  1719 tile(void) {
  1720 tile(void) {
  1720 	unsigned int i, j, n, nx, ny, nw, nh, mw, th;
  1721 	unsigned int i, j, n, nx, ny, nw, nh, mw, th;