+
+ if (XineramaIsActive(dpy)) {
+ info = XineramaQueryScreens(dpy, &s);
+ }
+
+ monitors = emallocz(s*sizeof(Monitor));
+ mcount = s;
+
+ for(i = 0; i < s; i++) {
+ /* init geometry */
+ if (mcount != 1) {
+ monitors[i].sx = info[i].x_org;
+ monitors[i].sy = info[i].y_org;
+ monitors[i].sw = info[i].width;
+ monitors[i].sh = info[i].height;
+ }
+ else {
+ monitors[i].sx = 0;
+ monitors[i].sy = 0;
+ monitors[i].sw = DisplayWidth(dpy, screen);
+ monitors[i].sh = DisplayHeight(dpy, screen);
+ }
+
+ monitors[i].id = i;
+ monitors[i].seltags = emallocz(sizeof initags);
+ monitors[i].prevtags = emallocz(sizeof initags);
+
+ memcpy(monitors[i].seltags, initags, sizeof initags);
+ memcpy(monitors[i].prevtags, initags, sizeof initags);
+
+ /* init appearance */
+ monitors[i].dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR);
+ monitors[i].dc.norm[ColBG] = getcolor(NORMBGCOLOR);
+ monitors[i].dc.norm[ColFG] = getcolor(NORMFGCOLOR);
+ monitors[i].dc.sel[ColBorder] = getcolor(SELBORDERCOLOR);
+ monitors[i].dc.sel[ColBG] = getcolor(SELBGCOLOR);
+ monitors[i].dc.sel[ColFG] = getcolor(SELFGCOLOR);
+ initfont(&(monitors[i]), FONT);
+ monitors[i].dc.h = bh = monitors[i].dc.font.height + 2;
+
+ /* init layouts */
+ monitors[i].mwfact = MWFACT;
+ monitors[i].layout = &layouts[0];
+ for(blw = k = 0; k < LENGTH(layouts); k++) {
+ j = textw(&monitors[i], layouts[k].symbol);
+ if(j > blw)
+ blw = j;
+ }
+
+ bpos = BARPOS;
+ wa.override_redirect = 1;
+ wa.background_pixmap = ParentRelative;
+ wa.event_mask = ButtonPressMask | ExposureMask;
+
+ /* init bars */
+ monitors[i].barwin = XCreateWindow(dpy, root, monitors[i].sx, monitors[i].sy, monitors[i].sw, bh, 0,
+ DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+ XDefineCursor(dpy, monitors[i].barwin, cursor[CurNormal]);
+ updatebarpos(&monitors[i]);
+ XMapRaised(dpy, monitors[i].barwin);
+ strcpy(stext, "dwm-"VERSION);
+ monitors[i].dc.drawable = XCreatePixmap(dpy, root, monitors[i].sw, bh, DefaultDepth(dpy, screen));
+ g = XCreateGC(dpy, root, 0, 0);
+ monitors[i].dc.gc = XCreateGC(dpy, root, 0, 0);
+ XSetLineAttributes(dpy, monitors[i].dc.gc, 1, LineSolid, CapButt, JoinMiter);
+ if(!monitors[i].dc.font.set)
+ XSetFont(dpy, monitors[i].dc.gc, monitors[i].dc.font.xfont->fid);
+ }
+}
+
+void
+spawn(const char *arg) {
+ static char *shell = NULL;
+
+ if(!shell && !(shell = getenv("SHELL")))
+ shell = "/bin/sh";
+ if(!arg)
+ return;
+ /* The double-fork construct avoids zombie processes and keeps the code
+ * clean from stupid signal handlers. */
+ if(fork() == 0) {
+ if(fork() == 0) {
+ if(dpy)
+ close(ConnectionNumber(dpy));
+ setsid();
+ execl(shell, shell, "-c", arg, (char *)NULL);
+ fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg);
+ perror(" failed");
+ }
+ exit(0);
+ }
+ wait(0);
+}
+
+void
+tag(const char *arg) {
+ unsigned int i;
+
+ if(!sel)
+ return;
+ for(i = 0; i < LENGTH(tags); i++)
+ sel->tags[i] = (NULL == arg);
+ sel->tags[idxoftag(arg)] = True;
+ arrange();
+}
+
+unsigned int
+textnw(Monitor *m, const char *text, unsigned int len) {
+ XRectangle r;
+
+ if(m->dc.font.set) {
+ XmbTextExtents(m->dc.font.set, text, len, NULL, &r);
+ return r.width;
+ }
+ return XTextWidth(m->dc.font.xfont, text, len);
+}
+
+unsigned int
+textw(Monitor *m, const char *text) {
+ return textnw(m, text, strlen(text)) + m->dc.font.height;
+}
+
+void
+tile(void) {
+ unsigned int i, n, nx, ny, nw, nh, mw, th;
+ int s;
+ Client *c, *mc;
+
+ domwfact = dozoom = True;
+
+ nw = 0; /* gcc stupidity requires this */
+
+ for (s = 0; s < mcount; s++) {
+ Monitor *m = &monitors[s];
+
+ for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m))
+ n++;
+
+ for(i = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) {
+ /* window geoms */
+ mw = (n == 1) ? m->waw : m->mwfact * m->waw;
+ th = (n > 1) ? m->wah / (n - 1) : 0;
+ if(n > 1 && th < bh)
+ th = m->wah;
+ if(i == 0) { /* master */
+ nx = m->wax;
+ ny = m->way;
+ nw = mw - 2 * c->border;
+ nh = m->wah - 2 * c->border;
+ }
+ else { /* tile window */
+ if(i == 1) {
+ ny = m->way;
+ nx += mc->w + 2 * mc->border;
+ nw = m->waw - mw - 2 * c->border;
+ }
+ if(i + 1 == n) /* remainder */
+ nh = (m->way + m->wah) - ny - 2 * c->border;
+ else
+ nh = th - 2 * c->border;
+ }
+ resize(c, nx, ny, nw, nh, RESIZEHINTS);
+ if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw)))
+ /* client doesn't accept size constraints */
+ resize(c, nx, ny, nw, nh, False);
+ if(n > 1 && th != m->wah)
+ ny = c->y + c->h + 2 * c->border;
+
+ i++;
+ }
+ }
+}
+void
+togglebar(const char *arg) {
+ if(bpos == BarOff)
+ bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
+ else
+ bpos = BarOff;
+ updatebarpos(&monitors[monitorat(-1,-1)]);
+ arrange();
+}
+
+void
+togglefloating(const char *arg) {
+ if(!sel)
+ return;
+ sel->isfloating = !sel->isfloating;
+ if(sel->isfloating)
+ resize(sel, sel->x, sel->y, sel->w, sel->h, True);
+ arrange();
+}
+
+void
+toggletag(const char *arg) {
+ unsigned int i, j;
+
+ if(!sel)
+ return;
+ i = idxoftag(arg);
+ sel->tags[i] = !sel->tags[i];
+ for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
+ if(j == LENGTH(tags))
+ sel->tags[i] = True; /* at least one tag must be enabled */
+ arrange();
+}
+
+void
+toggleview(const char *arg) {
+ unsigned int i, j;
+
+ Monitor *m = &monitors[monitorat(-1, -1)];
+
+ i = idxoftag(arg);
+ m->seltags[i] = !m->seltags[i];
+ for(j = 0; j < LENGTH(tags) && !m->seltags[j]; j++);
+ if(j == LENGTH(tags))
+ m->seltags[i] = True; /* at least one tag must be viewed */
+ arrange();
+}
+
+void
+unban(Client *c) {
+ if(!c->isbanned)
+ return;
+ XMoveWindow(dpy, c->win, c->x, c->y);
+ c->isbanned = False;
+}
+
+void
+unmanage(Client *c) {
+ XWindowChanges wc;
+
+ wc.border_width = c->oldborder;
+ /* The server grab construct avoids race conditions. */
+ XGrabServer(dpy);
+ XSetErrorHandler(xerrordummy);
+ XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
+ detach(c);
+ detachstack(c);
+ if(sel == c)
+ focus(NULL);
+ XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
+ setclientstate(c, WithdrawnState);
+ free(c->tags);
+ free(c);
+ XSync(dpy, False);
+ XSetErrorHandler(xerror);
+ XUngrabServer(dpy);
+ arrange();