dwm.c
changeset 1408 2215f7f11dd9
parent 1407 4cbf60555bd8
child 1409 ed5530a91efe
equal deleted inserted replaced
1407:4cbf60555bd8 1408:2215f7f11dd9
     1 /* TODO: cleanup nexttiled, ISVISIBLE, etc */
       
     2 /* See LICENSE file for copyright and license details.
     1 /* See LICENSE file for copyright and license details.
     3  *
     2  *
     4  * dynamic window manager is designed like any other X client as well. It is
     3  * dynamic window manager is designed like any other X client as well. It is
     5  * driven through handling X events. In contrast to other X clients, a window
     4  * driven through handling X events. In contrast to other X clients, a window
     6  * manager selects for SubstructureRedirectMask on the root window, to receive
     5  * manager selects for SubstructureRedirectMask on the root window, to receive
    43 
    42 
    44 /* macros */
    43 /* macros */
    45 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    46 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    47 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
    46 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
    48 #define ISVISIBLE(M, C)         ((M) == (C->mon) && (C->tags & M->tagset[M->seltags]))
    47 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
    49 #define LENGTH(X)               (sizeof X / sizeof X[0])
    48 #define LENGTH(X)               (sizeof X / sizeof X[0])
    50 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
    49 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
    51 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
    50 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
    52 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    53 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    52 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
   187 static void manage(Window w, XWindowAttributes *wa);
   186 static void manage(Window w, XWindowAttributes *wa);
   188 static void mappingnotify(XEvent *e);
   187 static void mappingnotify(XEvent *e);
   189 static void maprequest(XEvent *e);
   188 static void maprequest(XEvent *e);
   190 static void monocle(Monitor *m);
   189 static void monocle(Monitor *m);
   191 static void movemouse(const Arg *arg);
   190 static void movemouse(const Arg *arg);
   192 static Client *nexttiled(Monitor *m, Client *c);
   191 static Client *nexttiled(Client *c);
   193 static void propertynotify(XEvent *e);
   192 static void propertynotify(XEvent *e);
   194 static void quit(const Arg *arg);
   193 static void quit(const Arg *arg);
   195 static void resize(Client *c, int x, int y, int w, int h);
   194 static void resize(Client *c, int x, int y, int w, int h);
   196 static void resizemouse(const Arg *arg);
   195 static void resizemouse(const Arg *arg);
   197 static void restack(Monitor *m);
   196 static void restack(Monitor *m);
   548 				c->x = sx + (sw / 2 - c->w / 2); /* center in x direction */
   547 				c->x = sx + (sw / 2 - c->w / 2); /* center in x direction */
   549 			if((c->y - sy + c->h) > sh && c->isfloating)
   548 			if((c->y - sy + c->h) > sh && c->isfloating)
   550 				c->y = sy + (sh / 2 - c->h / 2); /* center in y direction */
   549 				c->y = sy + (sh / 2 - c->h / 2); /* center in y direction */
   551 			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
   550 			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
   552 				configure(c);
   551 				configure(c);
   553 			if(ISVISIBLE((c->mon), c))
   552 			if(ISVISIBLE(c))
   554 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   553 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   555 		}
   554 		}
   556 		else
   555 		else
   557 			configure(c);
   556 			configure(c);
   558 	}
   557 	}
   754 			}
   753 			}
   755 }
   754 }
   756 
   755 
   757 void
   756 void
   758 focus(Client *c) {
   757 focus(Client *c) {
   759 	if(!c || !ISVISIBLE((c->mon), c))
   758 	if(!c || !ISVISIBLE(c))
   760 		for(c = selmon->stack; c && !ISVISIBLE(selmon, c); c = c->snext);
   759 		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
   761 	if(selmon->sel && selmon->sel != c) {
   760 	if(selmon->sel && selmon->sel != c) {
   762 		grabbuttons(selmon->sel, False);
   761 		grabbuttons(selmon->sel, False);
   763 		XSetWindowBorder(dpy, selmon->sel->win, dc.norm[ColBorder]);
   762 		XSetWindowBorder(dpy, selmon->sel->win, dc.norm[ColBorder]);
   764 	}
   763 	}
   765 	if(c) {
   764 	if(c) {
   806 	Client *c = NULL, *i;
   805 	Client *c = NULL, *i;
   807 
   806 
   808 	if(!selmon->sel)
   807 	if(!selmon->sel)
   809 		return;
   808 		return;
   810 	if(arg->i > 0) {
   809 	if(arg->i > 0) {
   811 		for(c = selmon->sel->next; c && !ISVISIBLE(selmon, c); c = c->next);
   810 		for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
   812 		if(!c)
   811 		if(!c)
   813 			for(c = selmon->clients; c && !ISVISIBLE(selmon, c); c = c->next);
   812 			for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
   814 	}
   813 	}
   815 	else {
   814 	else {
   816 		for(i = selmon->clients; i != selmon->sel; i = i->next)
   815 		for(i = selmon->clients; i != selmon->sel; i = i->next)
   817 			if(ISVISIBLE(selmon, i))
   816 			if(ISVISIBLE(i))
   818 				c = i;
   817 				c = i;
   819 		if(!c)
   818 		if(!c)
   820 			for(; i; i = i->next)
   819 			for(; i; i = i->next)
   821 				if(ISVISIBLE(selmon, i))
   820 				if(ISVISIBLE(i))
   822 					c = i;
   821 					c = i;
   823 	}
   822 	}
   824 	if(c) {
   823 	if(c) {
   825 		focus(c);
   824 		focus(c);
   826 		restack(selmon);
   825 		restack(selmon);
  1100 
  1099 
  1101 void
  1100 void
  1102 monocle(Monitor *m) {
  1101 monocle(Monitor *m) {
  1103 	Client *c;
  1102 	Client *c;
  1104 
  1103 
  1105 	for(c = nexttiled(m, selmon->clients); c; c = nexttiled(m, c->next))
  1104 	for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
  1106 		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
  1105 		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
  1107 }
  1106 }
  1108 
  1107 
  1109 void
  1108 void
  1110 movemouse(const Arg *arg) {
  1109 movemouse(const Arg *arg) {
  1156 	while(ev.type != ButtonRelease);
  1155 	while(ev.type != ButtonRelease);
  1157 	XUngrabPointer(dpy, CurrentTime);
  1156 	XUngrabPointer(dpy, CurrentTime);
  1158 }
  1157 }
  1159 
  1158 
  1160 Client *
  1159 Client *
  1161 nexttiled(Monitor *m, Client *c) {
  1160 nexttiled(Client *c) {
  1162 	// TODO: m handling
  1161 	// TODO: m handling
  1163 	for(; c && (c->isfloating || !ISVISIBLE(m, c)); c = c->next);
  1162 	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  1164 	return c;
  1163 	return c;
  1165 }
  1164 }
  1166 
  1165 
  1167 void
  1166 void
  1168 propertynotify(XEvent *e) {
  1167 propertynotify(XEvent *e) {
  1278 		XRaiseWindow(dpy, selmon->sel->win);
  1277 		XRaiseWindow(dpy, selmon->sel->win);
  1279 	if(lt[m->sellt]->arrange) {
  1278 	if(lt[m->sellt]->arrange) {
  1280 		wc.stack_mode = Below;
  1279 		wc.stack_mode = Below;
  1281 		wc.sibling = m->barwin;
  1280 		wc.sibling = m->barwin;
  1282 		for(c = m->stack; c; c = c->snext)
  1281 		for(c = m->stack; c; c = c->snext)
  1283 			if(!c->isfloating && ISVISIBLE(m, c)) {
  1282 			if(!c->isfloating && ISVISIBLE(c)) {
  1284 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
  1283 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
  1285 				wc.sibling = c->win;
  1284 				wc.sibling = c->win;
  1286 			}
  1285 			}
  1287 	}
  1286 	}
  1288 	XSync(dpy, False);
  1287 	XSync(dpy, False);
  1430 
  1429 
  1431 void
  1430 void
  1432 showhide(Client *c) {
  1431 showhide(Client *c) {
  1433 	if(!c)
  1432 	if(!c)
  1434 		return;
  1433 		return;
  1435 	if(ISVISIBLE((c->mon), c)) { /* show clients top down */
  1434 	if(ISVISIBLE(c)) { /* show clients top down */
  1436 		XMoveWindow(dpy, c->win, c->x, c->y);
  1435 		XMoveWindow(dpy, c->win, c->x, c->y);
  1437 		if(!lt[c->mon->sellt]->arrange || c->isfloating)
  1436 		if(!lt[c->mon->sellt]->arrange || c->isfloating)
  1438 			resize(c, c->x, c->y, c->w, c->h);
  1437 			resize(c, c->x, c->y, c->w, c->h);
  1439 		showhide(c->snext);
  1438 		showhide(c->snext);
  1440 	}
  1439 	}
  1502 tile(Monitor *m) {
  1501 tile(Monitor *m) {
  1503 	int x, y, h, w, mw;
  1502 	int x, y, h, w, mw;
  1504 	unsigned int i, n;
  1503 	unsigned int i, n;
  1505 	Client *c;
  1504 	Client *c;
  1506 
  1505 
  1507 	for(n = 0, c = nexttiled(m, m->clients); c; c = nexttiled(m, c->next), n++);
  1506 	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  1508 	if(n == 0)
  1507 	if(n == 0)
  1509 		return;
  1508 		return;
  1510 
  1509 
  1511 	/* master */
  1510 	/* master */
  1512 	c = nexttiled(m, m->clients);
  1511 	c = nexttiled(m->clients);
  1513 	mw = m->mfact * m->ww;
  1512 	mw = m->mfact * m->ww;
  1514 	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw);
  1513 	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw);
  1515 
  1514 
  1516 	if(--n == 0)
  1515 	if(--n == 0)
  1517 		return;
  1516 		return;
  1522 	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
  1521 	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
  1523 	h = m->wh / n;
  1522 	h = m->wh / n;
  1524 	if(h < bh)
  1523 	if(h < bh)
  1525 		h = m->wh;
  1524 		h = m->wh;
  1526 
  1525 
  1527 	for(i = 0, c = nexttiled(m, c->next); c; c = nexttiled(m, c->next), i++) {
  1526 	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
  1528 		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
  1527 		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
  1529 		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw));
  1528 		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw));
  1530 		if(h != m->wh)
  1529 		if(h != m->wh)
  1531 			y = c->y + HEIGHT(c);
  1530 			y = c->y + HEIGHT(c);
  1532 	}
  1531 	}
  1881 zoom(const Arg *arg) {
  1880 zoom(const Arg *arg) {
  1882 	Client *c = selmon->sel;
  1881 	Client *c = selmon->sel;
  1883 
  1882 
  1884 	if(!lt[selmon->sellt]->arrange || lt[selmon->sellt]->arrange == monocle || (selmon->sel && selmon->sel->isfloating))
  1883 	if(!lt[selmon->sellt]->arrange || lt[selmon->sellt]->arrange == monocle || (selmon->sel && selmon->sel->isfloating))
  1885 		return;
  1884 		return;
  1886 	if(c == nexttiled(selmon, selmon->clients))
  1885 	if(c == nexttiled(selmon->clients))
  1887 		if(!c || !(c = nexttiled(selmon, c->next)))
  1886 		if(!c || !(c = nexttiled(c->next)))
  1888 			return;
  1887 			return;
  1889 	detach(c);
  1888 	detach(c);
  1890 	attach(c);
  1889 	attach(c);
  1891 	focus(c);
  1890 	focus(c);
  1892 	arrange();
  1891 	arrange();