dwm.c
changeset 1402 d0721df4028c
parent 1401 8cee6e329111
child 1403 9bfeee8174c2
equal deleted inserted replaced
1401:8cee6e329111 1402:d0721df4028c
    42 
    42 
    43 /* macros */
    43 /* macros */
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    46 #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))
    47 #define ISVISIBLE(M, C)         ((M) == (&mon[C->mon]) && (C->tags & M->tagset[M->seltags]))
    47 #define ISVISIBLE(M, C)         ((M) == (C->m) && (C->tags & M->tagset[M->seltags]))
    48 #define LENGTH(X)               (sizeof X / sizeof X[0])
    48 #define LENGTH(X)               (sizeof X / sizeof X[0])
    49 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
    49 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
    50 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
    50 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    52 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    52 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    75 	unsigned int button;
    75 	unsigned int button;
    76 	void (*func)(const Arg *arg);
    76 	void (*func)(const Arg *arg);
    77 	const Arg arg;
    77 	const Arg arg;
    78 } Button;
    78 } Button;
    79 
    79 
       
    80 typedef struct Monitor Monitor;
    80 typedef struct Client Client;
    81 typedef struct Client Client;
    81 struct Client {
    82 struct Client {
    82 	char name[256];
    83 	char name[256];
    83 	float mina, maxa;
    84 	float mina, maxa;
    84 	int x, y, w, h;
    85 	int x, y, w, h;
    85 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    86 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    86 	int bw, oldbw;
    87 	int bw, oldbw;
    87 	unsigned int tags;
    88 	unsigned int tags;
    88 	unsigned int mon;
       
    89 	Bool isfixed, isfloating, isurgent;
    89 	Bool isfixed, isfloating, isurgent;
    90 	Client *next;
    90 	Client *next;
    91 	Client *snext;
    91 	Client *snext;
       
    92 	Monitor *m;
    92 	Window win;
    93 	Window win;
    93 };
    94 };
    94 
    95 
    95 typedef struct {
    96 typedef struct {
    96 	int x, y, w, h;
    97 	int x, y, w, h;
   113 	void (*func)(const Arg *);
   114 	void (*func)(const Arg *);
   114 	const Arg arg;
   115 	const Arg arg;
   115 } Key;
   116 } Key;
   116 
   117 
   117 typedef struct {
   118 typedef struct {
   118 	char symbol[4];
   119 	const char *symbol;
       
   120 	void (*arrange)(Monitor *);
       
   121 } Layout;
       
   122 
       
   123 struct Monitor {
       
   124 	int screen_number;
   119 	float mfact;
   125 	float mfact;
   120 	int by, btx;          /* bar geometry */
   126 	int by, btx;          /* bar geometry */
   121 	int wx, wy, ww, wh;   /* window area  */
   127 	int wx, wy, ww, wh;   /* window area  */
   122 	unsigned int seltags;
   128 	unsigned int seltags;
   123 	unsigned int sellt;
   129 	unsigned int sellt;
   124 	unsigned int tagset[2];
   130 	unsigned int tagset[2];
   125 	Bool showbar;
   131 	Bool showbar;
   126 	Bool topbar;
   132 	Bool topbar;
   127 	Window barwin;
   133 	Window barwin;
   128 } Monitor;
   134 	Monitor *next;
   129 
   135 };
   130 typedef struct {
       
   131 	const char *symbol;
       
   132 	void (*arrange)(Monitor *);
       
   133 } Layout;
       
   134 
   136 
   135 typedef struct {
   137 typedef struct {
   136 	const char *class;
   138 	const char *class;
   137 	const char *instance;
   139 	const char *instance;
   138 	const char *title;
   140 	const char *title;
   147 static void attach(Client *c);
   149 static void attach(Client *c);
   148 static void attachstack(Client *c);
   150 static void attachstack(Client *c);
   149 static void buttonpress(XEvent *e);
   151 static void buttonpress(XEvent *e);
   150 static void checkotherwm(void);
   152 static void checkotherwm(void);
   151 static void cleanup(void);
   153 static void cleanup(void);
       
   154 static void cleanupmons(void);
   152 static void clearurgent(Client *c);
   155 static void clearurgent(Client *c);
   153 static void configure(Client *c);
   156 static void configure(Client *c);
   154 static void configurenotify(XEvent *e);
   157 static void configurenotify(XEvent *e);
   155 static void configurerequest(XEvent *e);
   158 static void configurerequest(XEvent *e);
   156 static void destroynotify(XEvent *e);
   159 static void destroynotify(XEvent *e);
   204 static void toggletag(const Arg *arg);
   207 static void toggletag(const Arg *arg);
   205 static void toggleview(const Arg *arg);
   208 static void toggleview(const Arg *arg);
   206 static void unmanage(Client *c);
   209 static void unmanage(Client *c);
   207 static void unmapnotify(XEvent *e);
   210 static void unmapnotify(XEvent *e);
   208 static void updategeom(void);
   211 static void updategeom(void);
       
   212 static void updatebars(void);
   209 static void updatenumlockmask(void);
   213 static void updatenumlockmask(void);
   210 static void updatesizehints(Client *c);
   214 static void updatesizehints(Client *c);
   211 static void updatestatus(void);
   215 static void updatestatus(void);
   212 static void updatetitle(Client *c);
   216 static void updatetitle(Client *c);
   213 static void updatewmhints(Client *c);
   217 static void updatewmhints(Client *c);
   250 static Client *stack = NULL;
   254 static Client *stack = NULL;
   251 static Cursor cursor[CurLast];
   255 static Cursor cursor[CurLast];
   252 static Display *dpy;
   256 static Display *dpy;
   253 static DC dc;
   257 static DC dc;
   254 static Layout *lt[] = { NULL, NULL };
   258 static Layout *lt[] = { NULL, NULL };
   255 static Monitor *mon = NULL, *selmon = NULL;
   259 static Monitor *mons = NULL, *selmon = NULL;
   256 static unsigned int nmons = 0;
       
   257 static Window root;
   260 static Window root;
   258 /* configuration, allows nested code to access above variables */
   261 /* configuration, allows nested code to access above variables */
   259 #include "config.h"
   262 #include "config.h"
   260 
   263 
   261 /* compile-time check if all tags fit into an unsigned int bit array. */
   264 /* compile-time check if all tags fit into an unsigned int bit array. */
   283 		if(ch.res_class)
   286 		if(ch.res_class)
   284 			XFree(ch.res_class);
   287 			XFree(ch.res_class);
   285 		if(ch.res_name)
   288 		if(ch.res_name)
   286 			XFree(ch.res_name);
   289 			XFree(ch.res_name);
   287 	}
   290 	}
   288 	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : mon[c->mon].tagset[mon[c->mon].seltags];
   291 	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->m->tagset[c->m->seltags];
   289 }
   292 }
   290 
   293 
   291 Bool
   294 Bool
   292 applysizehints(Client *c, int *x, int *y, int *w, int *h) {
   295 applysizehints(Client *c, int *x, int *y, int *w, int *h) {
   293 	Bool baseismin;
   296 	Bool baseismin;
   353 	return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
   356 	return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
   354 }
   357 }
   355 
   358 
   356 void
   359 void
   357 arrange(void) {
   360 arrange(void) {
   358 	unsigned int i;
   361 	Monitor *m;
       
   362 
   359 	showhide(stack);
   363 	showhide(stack);
   360 	focus(NULL);
   364 	focus(NULL);
   361 	for(i = 0; i < nmons; i++) {
   365 	for(m = mons; m; m = m->next) {
   362 		if(lt[mon[i].sellt]->arrange)
   366 		if(lt[m->sellt]->arrange)
   363 			lt[mon[i].sellt]->arrange(&mon[i]);
   367 			lt[m->sellt]->arrange(m);
   364 		restack(&mon[i]);
   368 		restack(m);
   365 	}
   369 	}
   366 }
   370 }
   367 
   371 
   368 void
   372 void
   369 attach(Client *c) {
   373 attach(Client *c) {
   427 	XSync(dpy, False);
   431 	XSync(dpy, False);
   428 }
   432 }
   429 
   433 
   430 void
   434 void
   431 cleanup(void) {
   435 cleanup(void) {
   432 	unsigned int i;
       
   433 	Arg a = {.ui = ~0};
   436 	Arg a = {.ui = ~0};
   434 	Layout foo = { "", NULL };
   437 	Layout foo = { "", NULL };
   435 
   438 
   436 	view(&a);
   439 	view(&a);
   437 	lt[selmon->sellt] = &foo;
   440 	lt[selmon->sellt] = &foo;
   445 	XFreePixmap(dpy, dc.drawable);
   448 	XFreePixmap(dpy, dc.drawable);
   446 	XFreeGC(dpy, dc.gc);
   449 	XFreeGC(dpy, dc.gc);
   447 	XFreeCursor(dpy, cursor[CurNormal]);
   450 	XFreeCursor(dpy, cursor[CurNormal]);
   448 	XFreeCursor(dpy, cursor[CurResize]);
   451 	XFreeCursor(dpy, cursor[CurResize]);
   449 	XFreeCursor(dpy, cursor[CurMove]);
   452 	XFreeCursor(dpy, cursor[CurMove]);
   450 	for(i = 0; i < nmons; i++)
   453 	cleanupmons();
   451 		XDestroyWindow(dpy, mon[i].barwin);
       
   452 	free(mon);
       
   453 	XSync(dpy, False);
   454 	XSync(dpy, False);
   454 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   455 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
       
   456 }
       
   457 
       
   458 void
       
   459 cleanupmons(void) {
       
   460 	Monitor *m;
       
   461 
       
   462 	while(mons) {
       
   463 		m = mons->next;
       
   464 		XUnmapWindow(dpy, mons->barwin);
       
   465 		XDestroyWindow(dpy, mons->barwin);
       
   466 		free(mons);
       
   467 		mons = m;
       
   468 	}
   455 }
   469 }
   456 
   470 
   457 void
   471 void
   458 clearurgent(Client *c) {
   472 clearurgent(Client *c) {
   459 	XWMHints *wmh;
   473 	XWMHints *wmh;
   484 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   498 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   485 }
   499 }
   486 
   500 
   487 void
   501 void
   488 configurenotify(XEvent *e) {
   502 configurenotify(XEvent *e) {
   489 	unsigned int i;
   503 	Monitor *m;
   490 	XConfigureEvent *ev = &e->xconfigure;
   504 	XConfigureEvent *ev = &e->xconfigure;
   491 
   505 
   492 	if(ev->window == root && (ev->width != sw || ev->height != sh)) {
   506 	if(ev->window == root && (ev->width != sw || ev->height != sh)) {
   493 		sw = ev->width;
   507 		sw = ev->width;
   494 		sh = ev->height;
   508 		sh = ev->height;
   495 		updategeom();
   509 		updategeom();
   496 		if(dc.drawable != 0)
   510 		if(dc.drawable != 0)
   497 			XFreePixmap(dpy, dc.drawable);
   511 			XFreePixmap(dpy, dc.drawable);
   498 		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
   512 		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
   499 		for(i = 0; i < nmons; i++)
   513 		updatebars();
   500 			XMoveResizeWindow(dpy, mon[i].barwin, mon[i].wx, mon[i].by, mon[i].ww, bh);
   514 		for(m = mons; m; m = m->next)
       
   515 			XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
   501 		arrange();
   516 		arrange();
   502 	}
   517 	}
   503 }
   518 }
   504 
   519 
   505 void
   520 void
   524 				c->x = sx + (sw / 2 - c->w / 2); /* center in x direction */
   539 				c->x = sx + (sw / 2 - c->w / 2); /* center in x direction */
   525 			if((c->y - sy + c->h) > sh && c->isfloating)
   540 			if((c->y - sy + c->h) > sh && c->isfloating)
   526 				c->y = sy + (sh / 2 - c->h / 2); /* center in y direction */
   541 				c->y = sy + (sh / 2 - c->h / 2); /* center in y direction */
   527 			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
   542 			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
   528 				configure(c);
   543 				configure(c);
   529 			if(ISVISIBLE((&mon[c->mon]), c))
   544 			if(ISVISIBLE((c->m), c))
   530 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   545 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   531 		}
   546 		}
   532 		else
   547 		else
   533 			configure(c);
   548 			configure(c);
   534 	}
   549 	}
   586 	unsigned int i, occ = 0, urg = 0;
   601 	unsigned int i, occ = 0, urg = 0;
   587 	unsigned long *col;
   602 	unsigned long *col;
   588 	Client *c;
   603 	Client *c;
   589 
   604 
   590 	for(c = clients; c; c = c->next) {
   605 	for(c = clients; c; c = c->next) {
   591 		if(m == &mon[c->mon]) {
   606 		if(m == c->m) {
   592 			occ |= c->tags;
   607 			occ |= c->tags;
   593 			if(c->isurgent)
   608 			if(c->isurgent)
   594 				urg |= c->tags;
   609 				urg |= c->tags;
   595 		}
   610 		}
   596 	}
   611 	}
   597 
   612 
   598 	dc.x = 0;
   613 	dc.x = 0;
   599 #ifdef XINERAMA
   614 #ifdef XINERAMA
   600 	{
   615 	{
       
   616 		/*
   601 		dc.w = TEXTW(m->symbol);
   617 		dc.w = TEXTW(m->symbol);
   602 		drawtext(m->symbol, selmon == m ? dc.sel : dc.norm, False);
   618 		drawtext(NULL, selmon == m ? dc.sel : dc.norm, False);
   603 		dc.x += dc.w;
   619 		dc.x += dc.w;
       
   620 		*/
   604 	}
   621 	}
   605 #endif /* XINERAMA */
   622 #endif /* XINERAMA */
   606 	m->btx = dc.x;
   623 	m->btx = dc.x;
   607 	for(i = 0; i < LENGTH(tags); i++) {
   624 	for(i = 0; i < LENGTH(tags); i++) {
   608 		dc.w = TEXTW(tags[i]);
   625 		dc.w = TEXTW(tags[i]);
   646 	XSync(dpy, False);
   663 	XSync(dpy, False);
   647 }
   664 }
   648 
   665 
   649 void
   666 void
   650 drawbars() {
   667 drawbars() {
   651 	unsigned int i;
   668 	Monitor *m;
   652 
   669 
   653 	for(i = 0; i < nmons; i++)
   670 	for(m = mons; m; m = m->next)
   654 		drawbar(&mon[i]);
   671 		drawbar(m);
   655 }
   672 }
   656 
   673 
   657 void
   674 void
   658 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   675 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   659 	int x;
   676 	int x;
   716 		focus(NULL);
   733 		focus(NULL);
   717 }
   734 }
   718 
   735 
   719 void
   736 void
   720 expose(XEvent *e) {
   737 expose(XEvent *e) {
   721 	unsigned int i;
   738 	Monitor *m;
   722 	XExposeEvent *ev = &e->xexpose;
   739 	XExposeEvent *ev = &e->xexpose;
   723 
   740 
   724 	if(ev->count == 0)
   741 	if(ev->count == 0)
   725 		for(i = 0; i < nmons; i++)
   742 		for(m = mons; m; m = m->next)
   726 			if(ev->window == mon[i].barwin) {
   743 			if(ev->window == m->barwin) {
   727 				drawbar(&mon[i]);
   744 				drawbar(m);
   728 				break;
   745 				break;
   729 			}
   746 			}
   730 }
   747 }
   731 
   748 
   732 void
   749 void
   733 focus(Client *c) {
   750 focus(Client *c) {
   734 	if(!c || !ISVISIBLE((&mon[c->mon]), c))
   751 	if(!c || !ISVISIBLE((c->m), c))
   735 		for(c = stack; c && !ISVISIBLE(selmon, c); c = c->snext);
   752 		for(c = stack; c && !ISVISIBLE(selmon, c); c = c->snext);
   736 	if(sel && sel != c) {
   753 	if(sel && sel != c) {
   737 		grabbuttons(sel, False);
   754 		grabbuttons(sel, False);
   738 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   755 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
   739 	}
   756 	}
   761 }
   778 }
   762 
   779 
   763 #ifdef XINERAMA
   780 #ifdef XINERAMA
   764 void
   781 void
   765 focusmon(const Arg *arg) {
   782 focusmon(const Arg *arg) {
   766 	if(arg->ui >= nmons)
   783 	unsigned int i;
   767 		return;
   784 	Monitor *m; 
   768 	selmon = &mon[arg->ui];
   785 
   769 	focus(NULL);
   786 	for(i = 0, m = mons; m; m = m->next, i++)
   770 	drawbars();
   787 		if(i == arg->ui) {
       
   788 			selmon = m;
       
   789 			focus(NULL);
       
   790 			drawbars();
       
   791 			break;
       
   792 		}
   771 }
   793 }
   772 #endif /* XINERAMA */
   794 #endif /* XINERAMA */
   773 
   795 
   774 void
   796 void
   775 focusstack(const Arg *arg) {
   797 focusstack(const Arg *arg) {
   991 
  1013 
   992 	if(!(c = malloc(sizeof(Client))))
  1014 	if(!(c = malloc(sizeof(Client))))
   993 		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
  1015 		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
   994 	*c = cz;
  1016 	*c = cz;
   995 	c->win = w;
  1017 	c->win = w;
   996 	for(c->mon = 0; selmon != &mon[c->mon]; c->mon++);
  1018 	c->m = selmon;
   997 
  1019 
   998 	/* geometry */
  1020 	/* geometry */
   999 	c->x = wa->x;
  1021 	c->x = wa->x;
  1000 	c->y = wa->y;
  1022 	c->y = wa->y;
  1001 	c->w = wa->width;
  1023 	c->w = wa->width;
  1354 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
  1376 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
  1355 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  1377 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  1356 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  1378 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  1357 
  1379 
  1358 	/* init cursors */
  1380 	/* init cursors */
  1359 	wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1381 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1360 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1382 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1361 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1383 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1362 
  1384 
  1363 	/* init appearance */
  1385 	/* init appearance */
  1364 	dc.norm[ColBorder] = getcolor(normbordercolor);
  1386 	dc.norm[ColBorder] = getcolor(normbordercolor);
  1372 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1394 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1373 	if(!dc.font.set)
  1395 	if(!dc.font.set)
  1374 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
  1396 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
  1375 
  1397 
  1376 	/* init bars */
  1398 	/* init bars */
  1377 	wa.override_redirect = True;
       
  1378 	wa.background_pixmap = ParentRelative;
       
  1379 	wa.event_mask = ButtonPressMask|ExposureMask;
       
  1380 	for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
  1399 	for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
  1381 		w = TEXTW(layouts[i].symbol);
  1400 		w = TEXTW(layouts[i].symbol);
  1382 		blw = MAX(blw, w);
  1401 		blw = MAX(blw, w);
  1383 	}
  1402 	}
  1384 
  1403 	updatebars();
  1385 	for(i = 0; i < nmons; i++) {
       
  1386 		mon[i].barwin = XCreateWindow(dpy, root, mon[i].wx, mon[i].by, mon[i].ww, bh, 0, DefaultDepth(dpy, screen),
       
  1387 
       
  1388 		                              CopyFromParent, DefaultVisual(dpy, screen),
       
  1389 		                              CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
       
  1390 		XDefineCursor(dpy, mon[i].barwin, cursor[CurNormal]);
       
  1391 		XMapRaised(dpy, mon[i].barwin);
       
  1392 	}
       
  1393 	updatestatus();
  1404 	updatestatus();
  1394 
  1405 
  1395 	/* EWMH support per view */
  1406 	/* EWMH support per view */
  1396 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1407 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1397 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1408 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1408 
  1419 
  1409 void
  1420 void
  1410 showhide(Client *c) {
  1421 showhide(Client *c) {
  1411 	if(!c)
  1422 	if(!c)
  1412 		return;
  1423 		return;
  1413 	if(ISVISIBLE((&mon[c->mon]), c)) { /* show clients top down */
  1424 	if(ISVISIBLE((c->m), c)) { /* show clients top down */
  1414 		XMoveWindow(dpy, c->win, c->x, c->y);
  1425 		XMoveWindow(dpy, c->win, c->x, c->y);
  1415 		if(!lt[mon[c->mon].sellt]->arrange || c->isfloating)
  1426 		if(!lt[c->m->sellt]->arrange || c->isfloating)
  1416 			resize(c, c->x, c->y, c->w, c->h);
  1427 			resize(c, c->x, c->y, c->w, c->h);
  1417 		showhide(c->snext);
  1428 		showhide(c->snext);
  1418 	}
  1429 	}
  1419 	else { /* hide clients bottom up */
  1430 	else { /* hide clients bottom up */
  1420 		showhide(c->snext);
  1431 		showhide(c->snext);
  1451 }
  1462 }
  1452 
  1463 
  1453 #ifdef XINERAMA
  1464 #ifdef XINERAMA
  1454 void
  1465 void
  1455 tagmon(const Arg *arg) {
  1466 tagmon(const Arg *arg) {
  1456 	if(!sel || arg->ui >= nmons)
  1467 	unsigned int i;
  1457 		return;
  1468 	Monitor *m;
  1458 	sel->mon = arg->ui;
  1469 
  1459 	arrange();
  1470 	for(i = 0, m = mons; m; m = m->next, i++)
       
  1471 		if(i == arg->ui) {
       
  1472 			sel->m = m;
       
  1473 			arrange();
       
  1474 			break;
       
  1475 		}
  1460 }
  1476 }
  1461 #endif /* XINERAMA */
  1477 #endif /* XINERAMA */
  1462 
  1478 
  1463 int
  1479 int
  1464 textnw(const char *text, unsigned int len) {
  1480 textnw(const char *text, unsigned int len) {
  1577 	if((c = getclient(ev->window)))
  1593 	if((c = getclient(ev->window)))
  1578 		unmanage(c);
  1594 		unmanage(c);
  1579 }
  1595 }
  1580 
  1596 
  1581 void
  1597 void
       
  1598 updatebars(void) {
       
  1599 	Monitor *m;
       
  1600 	XSetWindowAttributes wa;
       
  1601 
       
  1602 	wa.cursor = cursor[CurNormal];
       
  1603 	wa.override_redirect = True;
       
  1604 	wa.background_pixmap = ParentRelative;
       
  1605 	wa.event_mask = ButtonPressMask|ExposureMask;
       
  1606 
       
  1607 	for(m = mons; m; m = m->next) {
       
  1608 		m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
       
  1609 
       
  1610 		                          CopyFromParent, DefaultVisual(dpy, screen),
       
  1611 		                          CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
       
  1612 		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
       
  1613 		XMapRaised(dpy, m->barwin);
       
  1614 	}
       
  1615 }
       
  1616 
       
  1617 void
  1582 updategeom(void) {
  1618 updategeom(void) {
       
  1619 	int i, n;
       
  1620 	Client *c;
       
  1621 	Monitor *newmons = NULL, *m;
       
  1622 
  1583 #ifdef XINERAMA
  1623 #ifdef XINERAMA
  1584 	int n;
       
  1585 	unsigned int i = 0;
       
  1586 	Client *c;
       
  1587 	XineramaScreenInfo *info = NULL;
  1624 	XineramaScreenInfo *info = NULL;
  1588 
  1625 
  1589 	/* window area geometry */
  1626 	if(XineramaIsActive(dpy))
  1590 	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
  1627 		info = XineramaQueryScreens(dpy, &n);
  1591 		if(n != nmons) {
  1628 #endif
  1592 			for(c = clients; c; c = c->next)
  1629 	/* allocate monitor(s) for the new geometry setup */
  1593 				if(c->mon >= n)
  1630 	for(i = 0; i < n; i++) {
  1594 					c->mon = n - 1;
  1631 		m = (Monitor *)malloc(sizeof(Monitor));
  1595 			if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor) * n)))
  1632 		m->next = newmons;
  1596 				die("fatal: could not realloc() %u bytes\n", sizeof(Monitor) * nmons);
  1633 		newmons = m;
  1597 			selmon = NULL;
  1634 	}
  1598 		}
  1635 
  1599 		for(i = 0; i < n ; i++) {
  1636 	/* initialise monitor(s) */
  1600 			/* TODO: consider re-using XineramaScreenInfo */
  1637 #ifdef XINERAMA
  1601 			mon[i].symbol[0] = '[';
  1638 	if(XineramaIsActive(dpy)) {
  1602 			mon[i].symbol[1] = '0' + info[i].screen_number;
  1639 		for(i = 0, m = newmons; m; m = m->next, i++) {
  1603 			mon[i].symbol[2] = ']';
  1640 			m->screen_number = info[i].screen_number;
  1604 			mon[i].symbol[3] = 0;
  1641 			m->wx = info[i].x_org;
  1605 			if(!selmon) { /* not initialised yet */
  1642 			m->wy = info[i].y_org;
  1606 				mon[i].mfact = mfact;
  1643 			m->ww = info[i].width;
  1607 				mon[i].showbar = showbar;
  1644 			m->wh = info[i].height;
  1608 				mon[i].topbar = topbar;
       
  1609 				mon[i].tagset[0] = mon[i].tagset[1] = 1;
       
  1610 			}
       
  1611 			mon[i].wx = info[i].x_org;
       
  1612 			mon[i].wy = mon[i].showbar && mon[i].topbar ? info[i].y_org + bh : info[i].y_org;
       
  1613 			mon[i].ww = info[i].width;
       
  1614 			mon[i].wh = mon[i].showbar ? info[i].height - bh : info[i].height;
       
  1615 			mon[i].seltags = 0;
       
  1616 			mon[i].sellt = 0;
       
  1617 			if(mon[i].showbar)
       
  1618 				mon[i].by = mon[i].topbar ? info[i].y_org : mon[i].wy + mon[i].wh;
       
  1619 			else
       
  1620 				mon[i].by = -bh;
       
  1621 		}
       
  1622 		nmons = (unsigned int)n;
       
  1623 		if(!selmon) {
       
  1624 			selmon = &mon[0];
       
  1625 			int di, x, y;
       
  1626 			unsigned int dui;
       
  1627 			Window dummy;
       
  1628 			if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) 
       
  1629 				for(i = 0; i < nmons; i++)
       
  1630 					if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) {
       
  1631 						selmon = &mon[i];
       
  1632 						break;
       
  1633 					}
       
  1634 		}
  1645 		}
  1635 		XFree(info);
  1646 		XFree(info);
  1636 	}
  1647 	}
  1637 	else
  1648 	else
  1638 #endif /* XINERAMA */
  1649 #endif
       
  1650 	/* default monitor setup */
  1639 	{
  1651 	{
  1640 		if(!mon) {
  1652 		m->screen_number = 0;
  1641 			nmons = 1;
  1653 		m->wx = sx;
  1642 			if(!(mon = (Monitor *)malloc(sizeof(Monitor))))
  1654 		m->wy = sy;
  1643 				die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
  1655 		m->ww = sw;
  1644 		}
  1656 		m->wh = sh;
  1645 		if(!selmon) {
  1657 	}
  1646 			mon[0].symbol[0] = '[';
  1658 
  1647 			mon[0].symbol[1] = '0';
  1659 	/* bar geometry setup */
  1648 			mon[0].symbol[2] = ']';
  1660 	for(m = newmons; m; m = m->next) {
  1649 			mon[0].symbol[3] = 0;
  1661 		/* TODO: consider removing the following values from config.h */
  1650 			mon[0].mfact = mfact;
  1662 		m->seltags = 0;
  1651 			mon[0].showbar = showbar;
  1663 		m->sellt = 0;
  1652 			mon[0].topbar = topbar;
  1664 		m->tagset[0] = m->tagset[1] = 1;
  1653 			mon[0].tagset[0] = mon[0].tagset[1] = 1;
  1665 		m->mfact = mfact;
  1654 		}
  1666 		m->showbar = showbar;
  1655 		mon[0].wx = sx;
  1667 		m->topbar = topbar;
  1656 		mon[0].wy = mon[0].showbar && mon[0].topbar ? sy + bh : sy;
  1668 		if(m->showbar) {
  1657 		mon[0].ww = sw;
  1669 			m->wh -= bh;
  1658 		mon[0].wh = mon[0].showbar ? sh - bh : sh;
  1670 			m->by = m->topbar ? m->wy : m->wy + m->wh;
  1659 		mon[0].seltags = 0;
  1671 			m->wy = m->topbar ? m->wy + bh : m->wy;
  1660 		mon[0].sellt = 0;
  1672 		}
  1661 		if(mon[0].showbar)
       
  1662 			mon[0].by = mon[0].topbar ? sy : mon[0].wy + mon[0].wh;
       
  1663 		else
  1673 		else
  1664 			mon[0].by = -bh;
  1674 			m->by = -bh;
  1665 		selmon = &mon[0];
  1675 		/* reassign all clients with same screen number */
  1666 	}
  1676 		for(c = clients; c; c = c->next)
       
  1677 			if(c->m->screen_number == m->screen_number)
       
  1678 				c->m = m;
       
  1679 	}
       
  1680 
       
  1681 	/* reassign left over clients with disappeared screen number */
       
  1682 	for(c = clients; c; c = c->next)
       
  1683 		if(c->m->screen_number >= n)
       
  1684 			c->m = newmons;
       
  1685 
       
  1686 	/* select focused monitor */
       
  1687 	if(!selmon) {
       
  1688 		selmon = newmons;
       
  1689 		int di, x, y;
       
  1690 		unsigned int dui;
       
  1691 		Window dummy;
       
  1692 		if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) 
       
  1693 			for(m = newmons; m; m = m->next)
       
  1694 				if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) {
       
  1695 					selmon = m;
       
  1696 					break;
       
  1697 				}
       
  1698 	}
       
  1699 
       
  1700 	/* final assignment of new monitors */
       
  1701 	cleanupmons();
       
  1702 	mons = newmons;
  1667 }
  1703 }
  1668 
  1704 
  1669 void
  1705 void
  1670 updatenumlockmask(void) {
  1706 updatenumlockmask(void) {
  1671 	unsigned int i, j;
  1707 	unsigned int i, j;