dwm.c
branchstil
changeset 1531 606ac98e35df
parent 1530 072c62ed10f2
child 1532 4a1df4ff7ca3
equal deleted inserted replaced
1530:072c62ed10f2 1531:606ac98e35df
    34 #include <X11/keysym.h>
    34 #include <X11/keysym.h>
    35 #include <X11/Xatom.h>
    35 #include <X11/Xatom.h>
    36 #include <X11/Xlib.h>
    36 #include <X11/Xlib.h>
    37 #include <X11/Xproto.h>
    37 #include <X11/Xproto.h>
    38 #include <X11/Xutil.h>
    38 #include <X11/Xutil.h>
       
    39 #include <X11/Xft/Xft.h>
       
    40 #include <pango/pango.h>
       
    41 #include <pango/pangoxft.h>
       
    42 #include <pango/pango-font.h>
    39 #ifdef XINERAMA
    43 #ifdef XINERAMA
    40 #include <X11/extensions/Xinerama.h>
    44 #include <X11/extensions/Xinerama.h>
    41 #endif /* XINERAMA */
    45 #endif /* XINERAMA */
    42 
    46 
    43 /* macros */
    47 /* macros */
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    48 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    49 #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))
    50 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
    47 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
    51 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
    48 #define LENGTH(X)               (sizeof X / sizeof X[0])
    52 #define LENGTH(X)               (sizeof X / sizeof X[0])
       
    53 #ifndef MAX
    49 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
    54 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
       
    55 #endif
       
    56 #ifndef MIN
    50 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
    57 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
       
    58 #endif
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    59 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    52 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    60 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    53 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
    61 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
    54 #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
    62 #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
    55 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
    63 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
    99 	int x, y, w, h;
   107 	int x, y, w, h;
   100 	unsigned long norm[ColLast];
   108 	unsigned long norm[ColLast];
   101 	unsigned long sel[ColLast];
   109 	unsigned long sel[ColLast];
   102 	Drawable drawable;
   110 	Drawable drawable;
   103 	GC gc;
   111 	GC gc;
       
   112 
       
   113 	XftColor  xftnorm[ColLast];
       
   114 	XftColor  xftsel[ColLast];
       
   115 	XftDraw  *xftdrawable;
       
   116 	PangoContext *pgc;
       
   117 	PangoLayout  *plo;
       
   118 	PangoFontDescription *pfd;
       
   119 
   104 	struct {
   120 	struct {
   105 		int ascent;
   121 		int ascent;
   106 		int descent;
   122 		int descent;
   107 		int height;
   123 		int height;
   108 		XFontSet set;
       
   109 		XFontStruct *xfont;
       
   110 	} font;
   124 	} font;
   111 } DC; /* draw context */
   125 } DC; /* draw context */
   112 
   126 
   113 typedef struct {
   127 typedef struct {
   114 	unsigned int mod;
   128 	unsigned int mod;
   119 
   133 
   120 typedef struct {
   134 typedef struct {
   121 	const char *symbol;
   135 	const char *symbol;
   122 	void (*arrange)(Monitor *);
   136 	void (*arrange)(Monitor *);
   123 } Layout;
   137 } Layout;
   124 
       
   125 struct Monitor {
       
   126 	char ltsymbol[16];
       
   127 	float mfact;
       
   128 	int num;
       
   129 	int by;               /* bar geometry */
       
   130 	int mx, my, mw, mh;   /* screen size */
       
   131 	int wx, wy, ww, wh;   /* window area  */
       
   132 	unsigned int seltags;
       
   133 	unsigned int sellt;
       
   134 	unsigned int tagset[2];
       
   135 	Bool showbar;
       
   136 	Bool topbar;
       
   137 	Client *clients;
       
   138 	Client *sel;
       
   139 	Client *stack;
       
   140 	Monitor *next;
       
   141 	Window barwin;
       
   142 	const Layout *lt[2];
       
   143 };
       
   144 
   138 
   145 typedef struct {
   139 typedef struct {
   146 	const char *class;
   140 	const char *class;
   147 	const char *instance;
   141 	const char *instance;
   148 	const char *title;
   142 	const char *title;
   181 static void expose(XEvent *e);
   175 static void expose(XEvent *e);
   182 static void focus(Client *c);
   176 static void focus(Client *c);
   183 static void focusin(XEvent *e);
   177 static void focusin(XEvent *e);
   184 static void focusmon(const Arg *arg);
   178 static void focusmon(const Arg *arg);
   185 static void focusstack(const Arg *arg);
   179 static void focusstack(const Arg *arg);
   186 static unsigned long getcolor(const char *colstr);
   180 static unsigned long getcolor(const char *colstr, XftColor *color);
   187 static Bool getrootptr(int *x, int *y);
   181 static Bool getrootptr(int *x, int *y);
   188 static long getstate(Window w);
   182 static long getstate(Window w);
   189 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   183 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   190 static void grabbuttons(Client *c, Bool focused);
   184 static void grabbuttons(Client *c, Bool focused);
   191 static void grabkeys(void);
   185 static void grabkeys(void);
   275 static Window root;
   269 static Window root;
   276 
   270 
   277 /* configuration, allows nested code to access above variables */
   271 /* configuration, allows nested code to access above variables */
   278 #include "config.h"
   272 #include "config.h"
   279 
   273 
       
   274 struct Monitor {
       
   275 	char ltsymbol[16];
       
   276 	float mfact;
       
   277 	int num;
       
   278 	int by;               /* bar geometry */
       
   279 	int mx, my, mw, mh;   /* screen size */
       
   280 	int wx, wy, ww, wh;   /* window area  */
       
   281 	unsigned int seltags;
       
   282 	unsigned int sellt;
       
   283 	unsigned int tagset[2];
       
   284 	Bool showbar;
       
   285 	Bool topbar;
       
   286 	Client *clients;
       
   287 	Client *sel;
       
   288 	Client *stack;
       
   289 	Monitor *next;
       
   290 	Window barwin;
       
   291 	const Layout *lt[2];
       
   292 	int curtag;
       
   293 	int prevtag;
       
   294 	const Layout *lts[LENGTH(tags) + 1];
       
   295 	double mfacts[LENGTH(tags) + 1];
       
   296 	Bool showbars[LENGTH(tags) + 1];
       
   297 };
       
   298 
   280 /* compile-time check if all tags fit into an unsigned int bit array. */
   299 /* compile-time check if all tags fit into an unsigned int bit array. */
   281 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
   300 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
   282 
   301 
   283 /* function implementations */
   302 /* function implementations */
   284 void
   303 void
   474 	view(&a);
   493 	view(&a);
   475 	selmon->lt[selmon->sellt] = &foo;
   494 	selmon->lt[selmon->sellt] = &foo;
   476 	for(m = mons; m; m = m->next)
   495 	for(m = mons; m; m = m->next)
   477 		while(m->stack)
   496 		while(m->stack)
   478 			unmanage(m->stack, False);
   497 			unmanage(m->stack, False);
   479 	if(dc.font.set)
       
   480 		XFreeFontSet(dpy, dc.font.set);
       
   481 	else
       
   482 		XFreeFont(dpy, dc.font.xfont);
       
   483 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   498 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   484 	XFreePixmap(dpy, dc.drawable);
   499 	XFreePixmap(dpy, dc.drawable);
   485 	XFreeGC(dpy, dc.gc);
   500 	XFreeGC(dpy, dc.gc);
   486 	XFreeCursor(dpy, cursor[CurNormal]);
   501 	XFreeCursor(dpy, cursor[CurNormal]);
   487 	XFreeCursor(dpy, cursor[CurResize]);
   502 	XFreeCursor(dpy, cursor[CurResize]);
   547 		sh = ev->height;
   562 		sh = ev->height;
   548 		if(updategeom()) {
   563 		if(updategeom()) {
   549 			if(dc.drawable != 0)
   564 			if(dc.drawable != 0)
   550 				XFreePixmap(dpy, dc.drawable);
   565 				XFreePixmap(dpy, dc.drawable);
   551 			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
   566 			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
       
   567 			XftDrawChange(dc.xftdrawable, dc.drawable);
   552 			updatebars();
   568 			updatebars();
   553 			for(m = mons; m; m = m->next)
   569 			for(m = mons; m; m = m->next)
   554 				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
   570 				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
   555 			arrange(NULL);
   571 			arrange(NULL);
   556 		}
   572 		}
   603 }
   619 }
   604 
   620 
   605 Monitor *
   621 Monitor *
   606 createmon(void) {
   622 createmon(void) {
   607 	Monitor *m;
   623 	Monitor *m;
       
   624 	unsigned int i;
   608 
   625 
   609 	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
   626 	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
   610 		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
   627 		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
   611 	m->tagset[0] = m->tagset[1] = 1;
   628 	m->tagset[0] = m->tagset[1] = 1;
   612 	m->mfact = mfact;
   629 	m->mfact = mfact;
   613 	m->showbar = showbar;
   630 	m->showbar = showbar;
   614 	m->topbar = topbar;
   631 	m->topbar = topbar;
   615 	m->lt[0] = &layouts[0];
   632 	m->lt[0] = &layouts[0];
   616 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
   633 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
   617 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
   634 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
       
   635 
       
   636 	/* pertag init */
       
   637 	m->curtag = m->prevtag = 1;
       
   638 	for(i=0; i < LENGTH(tags) + 1 ; i++) {
       
   639 		m->mfacts[i] = mfact;
       
   640 		m->lts[i] = i ? &layouts[deflayouts[i-1]] : &layouts[0];
       
   641 		m->showbars[i] = m->showbar;
       
   642 	}
       
   643 
   618 	return m;
   644 	return m;
   619 }
   645 }
   620 
   646 
   621 void
   647 void
   622 destroynotify(XEvent *e) {
   648 destroynotify(XEvent *e) {
   764 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   790 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   765 	if(!text)
   791 	if(!text)
   766 		return;
   792 		return;
   767 	olen = strlen(text);
   793 	olen = strlen(text);
   768 	h = dc.font.ascent + dc.font.descent;
   794 	h = dc.font.ascent + dc.font.descent;
   769 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
   795 	//y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
       
   796 	y = dc.y;
   770 	x = dc.x + (h / 2);
   797 	x = dc.x + (h / 2);
   771 	/* shorten text if necessary */
   798 	/* shorten text if necessary */
   772 	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
   799 	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
   773 	if(!len)
   800 	if(!len)
   774 		return;
   801 		return;
   775 	memcpy(buf, text, len);
   802 	memcpy(buf, text, len);
   776 	if(len < olen)
   803 	if(len < olen)
   777 		for(i = len; i && i > len - 3; buf[--i] = '.');
   804 		for(i = len; i && i > len - 3; buf[--i] = '.');
   778 	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
   805 	pango_layout_set_text(dc.plo, text, len);
   779 	if(dc.font.set)
   806 	pango_xft_render_layout(dc.xftdrawable, (col==dc.norm?dc.xftnorm:dc.xftsel)+(invert?ColBG:ColFG), dc.plo, x * PANGO_SCALE, y * PANGO_SCALE);
   780 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
       
   781 	else
       
   782 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
       
   783 }
   807 }
   784 
   808 
   785 void
   809 void
   786 enternotify(XEvent *e) {
   810 enternotify(XEvent *e) {
   787 	Monitor *m;
   811 	Monitor *m;
   875 		restack(selmon);
   899 		restack(selmon);
   876 	}
   900 	}
   877 }
   901 }
   878 
   902 
   879 unsigned long
   903 unsigned long
   880 getcolor(const char *colstr) {
   904 getcolor(const char *colstr, XftColor *color) {
   881 	Colormap cmap = DefaultColormap(dpy, screen);
   905 	Colormap cmap = DefaultColormap(dpy, screen);
   882 	XColor color;
   906 	Visual *vis = DefaultVisual(dpy, screen);
   883 
   907 
   884 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   908 	if(!XftColorAllocName(dpy,vis,cmap,colstr, color))
   885 		die("error, cannot allocate color '%s'\n", colstr);
   909 		die("error, cannot allocate color '%s'\n", colstr);
   886 	return color.pixel;
   910 	return color->pixel;
   887 }
   911 }
   888 
   912 
   889 Bool
   913 Bool
   890 getrootptr(int *x, int *y) {
   914 getrootptr(int *x, int *y) {
   891 	int di;
   915 	int di;
   977 	}
  1001 	}
   978 }
  1002 }
   979 
  1003 
   980 void
  1004 void
   981 initfont(const char *fontstr) {
  1005 initfont(const char *fontstr) {
   982 	char *def, **missing;
  1006 	PangoFontMetrics *metrics;
   983 	int n;
  1007 
   984 
  1008 	dc.pgc = pango_xft_get_context(dpy, screen);
   985 	missing = NULL;
  1009 	dc.pfd = pango_font_description_from_string(fontstr);
   986 	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
  1010 
   987 	if(missing) {
  1011 	metrics = pango_context_get_metrics(dc.pgc, dc.pfd, pango_language_from_string(setlocale(LC_CTYPE, "")));
   988 		while(n--)
  1012 	dc.font.ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
   989 			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
  1013 	dc.font.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
   990 		XFreeStringList(missing);
  1014 
   991 	}
  1015 	pango_font_metrics_unref(metrics);
   992 	if(dc.font.set) {
  1016 
   993 		XFontStruct **xfonts;
  1017 	dc.plo = pango_layout_new(dc.pgc);
   994 		char **font_names;
  1018 	pango_layout_set_font_description(dc.plo, dc.pfd);
   995 
       
   996 		dc.font.ascent = dc.font.descent = 0;
       
   997 		XExtentsOfFontSet(dc.font.set);
       
   998 		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
       
   999 		while(n--) {
       
  1000 			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
       
  1001 			dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
       
  1002 			xfonts++;
       
  1003 		}
       
  1004 	}
       
  1005 	else {
       
  1006 		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
       
  1007 		&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
       
  1008 			die("error, cannot load font: '%s'\n", fontstr);
       
  1009 		dc.font.ascent = dc.font.xfont->ascent;
       
  1010 		dc.font.descent = dc.font.xfont->descent;
       
  1011 	}
       
  1012 	dc.font.height = dc.font.ascent + dc.font.descent;
  1019 	dc.font.height = dc.font.ascent + dc.font.descent;
  1013 }
  1020 }
  1014 
  1021 
  1015 Bool
  1022 Bool
  1016 isprotodel(Client *c) {
  1023 isprotodel(Client *c) {
  1474 void
  1481 void
  1475 setlayout(const Arg *arg) {
  1482 setlayout(const Arg *arg) {
  1476 	if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
  1483 	if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
  1477 		selmon->sellt ^= 1;
  1484 		selmon->sellt ^= 1;
  1478 	if(arg && arg->v)
  1485 	if(arg && arg->v)
  1479 		selmon->lt[selmon->sellt] = (Layout *)arg->v;
  1486 		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v;
  1480 	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
  1487 	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
  1481 	if(selmon->sel)
  1488 	if(selmon->sel)
  1482 		arrange(selmon);
  1489 		arrange(selmon);
  1483 	else
  1490 	else
  1484 		drawbar(selmon);
  1491 		drawbar(selmon);
  1492 	if(!arg || !selmon->lt[selmon->sellt]->arrange)
  1499 	if(!arg || !selmon->lt[selmon->sellt]->arrange)
  1493 		return;
  1500 		return;
  1494 	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
  1501 	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
  1495 	if(f < 0.1 || f > 0.9)
  1502 	if(f < 0.1 || f > 0.9)
  1496 		return;
  1503 		return;
  1497 	selmon->mfact = f;
  1504 	selmon->mfact = selmon->mfacts[selmon->curtag] = f;
  1498 	arrange(selmon);
  1505 	arrange(selmon);
  1499 }
  1506 }
  1500 
  1507 
  1501 void
  1508 void
  1502 setup(void) {
  1509 setup(void) {
  1524 	/* init cursors */
  1531 	/* init cursors */
  1525 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1532 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1526 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1533 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1527 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1534 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1528 	/* init appearance */
  1535 	/* init appearance */
  1529 	dc.norm[ColBorder] = getcolor(normbordercolor);
  1536 	dc.norm[ColBorder] = getcolor(normbordercolor, dc.xftnorm+ColBorder);
  1530 	dc.norm[ColBG] = getcolor(normbgcolor);
  1537 	dc.norm[ColBG] = getcolor(normbgcolor, dc.xftnorm+ColBG);
  1531 	dc.norm[ColFG] = getcolor(normfgcolor);
  1538 	dc.norm[ColFG] = getcolor(normfgcolor, dc.xftnorm+ColFG);
  1532 	dc.sel[ColBorder] = getcolor(selbordercolor);
  1539 	dc.sel[ColBorder] = getcolor(selbordercolor, dc.xftsel+ColBorder);
  1533 	dc.sel[ColBG] = getcolor(selbgcolor);
  1540 	dc.sel[ColBG] = getcolor(selbgcolor, dc.xftsel+ColBG);
  1534 	dc.sel[ColFG] = getcolor(selfgcolor);
  1541 	dc.sel[ColFG] = getcolor(selfgcolor, dc.xftsel+ColFG);
  1535 	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
  1542 	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
  1536 	dc.gc = XCreateGC(dpy, root, 0, NULL);
  1543 	dc.gc = XCreateGC(dpy, root, 0, NULL);
  1537 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1544 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1538 	if(!dc.font.set)
  1545 	dc.xftdrawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy,screen), DefaultColormap(dpy,screen));
  1539 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
  1546 	if(!dc.xftdrawable)
  1540 	/* init bars */
  1547 		printf("error, cannot create drawable\n");
  1541 	updatebars();
  1548 	updatebars();
  1542 	updatestatus();
  1549 	updatestatus();
  1543 	/* EWMH support per view */
  1550 	/* EWMH support per view */
  1544 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1551 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1545 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1552 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1604 	sendmon(selmon->sel, dirtomon(arg->i));
  1611 	sendmon(selmon->sel, dirtomon(arg->i));
  1605 }
  1612 }
  1606 
  1613 
  1607 int
  1614 int
  1608 textnw(const char *text, unsigned int len) {
  1615 textnw(const char *text, unsigned int len) {
  1609 	XRectangle r;
  1616 	PangoRectangle r;
  1610 
  1617 	pango_layout_set_text(dc.plo, text, len);
  1611 	if(dc.font.set) {
  1618 	pango_layout_get_extents(dc.plo, &r, 0);
  1612 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1619 	return r.width / PANGO_SCALE;
  1613 		return r.width;
       
  1614 	}
       
  1615 	return XTextWidth(dc.font.xfont, text, len);
       
  1616 }
  1620 }
  1617 
  1621 
  1618 void
  1622 void
  1619 tile(Monitor *m) {
  1623 tile(Monitor *m) {
  1620 	int x, y, h, w, mw;
  1624 	int x, y, h, w, mw;
  1645 	}
  1649 	}
  1646 }
  1650 }
  1647 
  1651 
  1648 void
  1652 void
  1649 togglebar(const Arg *arg) {
  1653 togglebar(const Arg *arg) {
  1650 	selmon->showbar = !selmon->showbar;
  1654 	selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar;
  1651 	updatebarpos(selmon);
  1655 	updatebarpos(selmon);
  1652 	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
  1656 	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
  1653 	arrange(selmon);
  1657 	arrange(selmon);
  1654 }
  1658 }
  1655 
  1659 
  1665 }
  1669 }
  1666 
  1670 
  1667 void
  1671 void
  1668 toggletag(const Arg *arg) {
  1672 toggletag(const Arg *arg) {
  1669 	unsigned int newtags;
  1673 	unsigned int newtags;
       
  1674 	unsigned int i;
  1670 
  1675 
  1671 	if(!selmon->sel)
  1676 	if(!selmon->sel)
  1672 		return;
  1677 		return;
  1673 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
  1678 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
  1674 	if(newtags) {
  1679 	if(newtags) {
  1675 		selmon->sel->tags = newtags;
  1680 		selmon->sel->tags = newtags;
       
  1681 		if(newtags == ~0) {
       
  1682 			selmon->prevtag = selmon->curtag;
       
  1683 			selmon->curtag = 0;
       
  1684 		}
       
  1685 		if(!(newtags & 1 << (selmon->curtag - 1))) {
       
  1686 			selmon->prevtag = selmon->curtag;
       
  1687 			for (i=0; !(newtags & 1 << i); i++);
       
  1688 			selmon->curtag = i + 1;
       
  1689 		}
       
  1690 		selmon->sel->tags = newtags;
       
  1691 		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
       
  1692 		selmon->mfact = selmon->mfacts[selmon->curtag];
       
  1693 		if (selmon->showbar != selmon->showbars[selmon->curtag])
       
  1694 			togglebar(NULL);
  1676 		arrange(selmon);
  1695 		arrange(selmon);
  1677 	}
  1696 	}
  1678 }
  1697 }
  1679 
  1698 
  1680 void
  1699 void
  1937 	}
  1956 	}
  1938 }
  1957 }
  1939 
  1958 
  1940 void
  1959 void
  1941 view(const Arg *arg) {
  1960 view(const Arg *arg) {
       
  1961 	unsigned int i;
       
  1962 
  1942 	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
  1963 	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
  1943 		return;
  1964 		return;
  1944 	selmon->seltags ^= 1; /* toggle sel tagset */
  1965 	selmon->seltags ^= 1; /* toggle sel tagset */
  1945 	if(arg->ui & TAGMASK)
  1966 	if(arg->ui & TAGMASK) {
  1946 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
  1967 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
       
  1968 		selmon->prevtag = selmon->curtag;
       
  1969 		if(arg->ui == ~0)
       
  1970 			selmon->curtag = 0;
       
  1971 		else {
       
  1972 			for (i=0; !(arg->ui & 1 << i); i++);
       
  1973 			selmon->curtag = i + 1;
       
  1974 		}
       
  1975 	} else {
       
  1976 		selmon->prevtag= selmon->curtag ^ selmon->prevtag;
       
  1977 		selmon->curtag^= selmon->prevtag;
       
  1978 		selmon->prevtag= selmon->curtag ^ selmon->prevtag;
       
  1979 	}
       
  1980 	selmon->lt[selmon->sellt]= selmon->lts[selmon->curtag];
       
  1981 	selmon->mfact = selmon->mfacts[selmon->curtag];
       
  1982 	if(selmon->showbar != selmon->showbars[selmon->curtag])
       
  1983 		togglebar(NULL);
  1947 	arrange(selmon);
  1984 	arrange(selmon);
  1948 }
  1985 }
  1949 
  1986 
  1950 Client *
  1987 Client *
  1951 wintoclient(Window w) {
  1988 wintoclient(Window w) {