finished libsl/drw integration 53646979
Anselm R Garbe · 2013-06-16 15:20 3 file(s) · +184 −263
drw.c +88 −62
8 8
#include "util.h"
9 9
10 10
Drw *
11 -
drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) {
11 +
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
12 12
	Drw *drw = (Drw *)calloc(1, sizeof(Drw));
13 +
	if(!drw)
14 +
		return NULL;
13 15
	drw->dpy = dpy;
14 16
	drw->screen = screen;
15 -
	drw->win = win;
17 +
	drw->root = root;
16 18
	drw->w = w;
17 19
	drw->h = h;
18 -
	drw->drwable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen));
19 -
	drw->gc = XCreateGC(dpy, win, 0, NULL);
20 +
	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
21 +
	drw->gc = XCreateGC(dpy, root, 0, NULL);
20 22
	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
21 23
	return drw;
22 24
}
27 29
		return;
28 30
	drw->w = w;
29 31
	drw->h = h;
30 -
	XFreePixmap(drw->dpy, drw->drwable);
31 -
	drw->drwable = XCreatePixmap(drw->dpy, drw->win, w, h, DefaultDepth(drw->dpy, drw->screen));
32 +
	if(drw->drawable != 0)
33 +
		XFreePixmap(drw->dpy, drw->drawable);
34 +
	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
32 35
}
33 36
34 37
void
35 38
drw_free(Drw *drw) {
36 -
	XFreePixmap(drw->dpy, drw->drwable);
39 +
	XFreePixmap(drw->dpy, drw->drawable);
37 40
	XFreeGC(drw->dpy, drw->gc);
38 41
	free(drw);
39 42
}
40 43
41 44
Fnt *
42 -
drw_font_create(Drw *drw, const char *fontname) {
45 +
drw_font_create(Display *dpy, const char *fontname) {
43 46
	Fnt *font;
44 47
	char *def, **missing;
45 48
	int n;
46 49
47 -
	if(!drw)
48 -
		return NULL;
49 50
	font = (Fnt *)calloc(1, sizeof(Fnt));
50 -
	font->set = XCreateFontSet(drw->dpy, fontname, &missing, &n, &def);
51 +
	if(!font)
52 +
		return NULL;
53 +
	font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
51 54
	if(missing) {
52 55
		while(n--)
53 56
			fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
65 68
		}
66 69
	}
67 70
	else {
68 -
		if(!(font->xfont = XLoadQueryFont(drw->dpy, fontname))
69 -
		&& !(font->xfont = XLoadQueryFont(drw->dpy, "fixed")))
71 +
		if(!(font->xfont = XLoadQueryFont(dpy, fontname))
72 +
		&& !(font->xfont = XLoadQueryFont(dpy, "fixed")))
70 73
			die("error, cannot load font: '%s'\n", fontname);
71 74
		font->ascent = font->xfont->ascent;
72 75
		font->descent = font->xfont->descent;
76 79
}
77 80
78 81
void
79 -
drw_font_free(Drw *drw, Fnt *font) {
80 -
	if(!drw || !font)
82 +
drw_font_free(Display *dpy, Fnt *font) {
83 +
	if(!font)
81 84
		return;
82 85
	if(font->set)
83 -
		XFreeFontSet(drw->dpy, font->set);
86 +
		XFreeFontSet(dpy, font->set);
84 87
	else
85 -
		XFreeFont(drw->dpy, font->xfont);
88 +
		XFreeFont(dpy, font->xfont);
86 89
	free(font);
87 90
}
88 91
89 92
Clr *
90 93
drw_clr_create(Drw *drw, const char *clrname) {
91 -
	Clr *clr = (Clr *)calloc(1, sizeof(Clr));
92 -
	Colormap cmap = DefaultColormap(drw->dpy, drw->screen);
94 +
	Clr *clr;
95 +
	Colormap cmap;
93 96
	XColor color;
94 97
98 +
	if(!drw)
99 +
		return NULL;
100 +
	clr = (Clr *)calloc(1, sizeof(Clr));
101 +
	if(!clr)
102 +
		return NULL;
103 +
	cmap = DefaultColormap(drw->dpy, drw->screen);
95 104
	if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color))
96 105
		die("error, cannot allocate color '%s'\n", clrname);
97 106
	clr->rgb = color.pixel;
99 108
}
100 109
101 110
void
102 -
drw_clr_free(Drw *drw, Clr *clr) {
111 +
drw_clr_free(Clr *clr) {
103 112
	if(!clr)
104 113
		return;
105 114
	free(clr);
107 116
108 117
void
109 118
drw_setfont(Drw *drw, Fnt *font) {
110 -
	if(!drw)
111 -
		return;
112 -
	drw->font = font;
119 +
	if(drw)
120 +
		drw->font = font;
113 121
}
114 122
115 123
void
116 -
drw_setfg(Drw *drw, Clr *clr) {
117 -
	if(!drw) 
124 +
drw_settheme(Drw *drw, Theme *theme) {
125 +
	if(!drw || !theme) 
118 126
		return;
119 -
	drw->fg = clr;
120 -
}
121 -
122 -
void
123 -
drw_setbg(Drw *drw, Clr *clr) {
124 -
	if(!drw)
125 -
		return;
126 -
	drw->bg = clr;
127 +
	drw->theme = theme;
127 128
}
128 129
129 130
void
130 -
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) {
131 +
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) {
131 132
	int dx;
132 133
133 -
	if(!drw || !drw->font || !drw->fg || !drw->bg)
134 +
	if(!drw || !drw->font || !drw->theme)
134 135
		return;
135 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb);
136 +
	XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb);
136 137
	dx = (drw->font->ascent + drw->font->descent + 2) / 4;
137 138
	if(filled)
138 -
		XFillRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx+1, dx+1);
139 +
		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1);
139 140
	else if(empty)
140 -
		XDrawRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx, dx);
141 +
		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx);
141 142
}
142 143
143 144
void
144 -
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) {
145 +
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) {
145 146
	char buf[256];
146 -
	int i, tx, ty, len, olen;
147 +
	int i, tx, ty, th, len, olen;
147 148
	Extnts tex;
148 149
149 -
	if(!drw || !drw->fg || !drw->bg)
150 +
	if(!drw || !drw->theme)
150 151
		return;
151 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->fg->rgb : drw->bg->rgb);
152 -
	XFillRectangle(drw->dpy, drw->drwable, drw->gc, x, y, w, h);
152 +
	XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->fg->rgb : drw->theme->bg->rgb);
153 +
	XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
153 154
	if(!text || !drw->font)
154 155
		return;
155 156
	olen = strlen(text);
156 -
	drw_getexts(drw, text, olen, &tex);
157 -
	ty = y + (h / 2) - tex.yOff;
158 -
	tx = x + tex.xOff;
157 +
	drw_font_getexts(drw->font, text, olen, &tex);
158 +
	th = drw->font->ascent + drw->font->descent;
159 +
	ty = y + (h / 2) - (th / 2) + drw->font->ascent;
160 +
	tx = x + (h / 2);
159 161
	/* shorten text if necessary */
160 162
	for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--)
161 -
		drw_getexts(drw, text, len, &tex);
163 +
		drw_font_getexts(drw->font, text, len, &tex);
162 164
	if(!len)
163 165
		return;
164 166
	memcpy(buf, text, len);
165 167
	if(len < olen)
166 168
		for(i = len; i && i > len - 3; buf[--i] = '.');
167 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb);
169 +
	XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb);
168 170
	if(drw->font->set)
169 -
		XmbDrawString(drw->dpy, drw->drwable, drw->font->set, drw->gc, tx, ty, buf, len);
171 +
		XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len);
170 172
	else
171 -
		XDrawString(drw->dpy, drw->drwable, drw->gc, tx, ty, buf, len);
173 +
		XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
172 174
}
173 175
174 176
void
175 -
drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h) {
177 +
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
176 178
	if(!drw)
177 179
		return;
178 -
	XCopyArea(drw->dpy, drw->drwable, drw->win, drw->gc, x, y, w, h, x, y);
180 +
	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
179 181
	XSync(drw->dpy, False);
180 182
}
181 183
182 184
183 185
void
184 -
drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *tex) {
186 +
drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) {
185 187
	XRectangle r;
186 188
187 -
	if(!drw || !drw->font || !text)
189 +
	if(!font || !text)
188 190
		return;
189 -
	if(drw->font->set) {
190 -
		XmbTextExtents(drw->font->set, text, len, NULL, &r);
191 -
		tex->xOff = r.x;
192 -
		tex->yOff = r.y;
191 +
	if(font->set) {
192 +
		XmbTextExtents(font->set, text, len, NULL, &r);
193 193
		tex->w = r.width;
194 194
		tex->h = r.height;
195 195
	}
196 196
	else {
197 -
		tex->h = drw->font->ascent + drw->font->descent;
198 -
		tex->w = XTextWidth(drw->font->xfont, text, len);
199 -
		tex->xOff = tex->h / 2;
200 -
		tex->yOff = (tex->h / 2) + drw->font->ascent;
197 +
		tex->h = font->ascent + font->descent;
198 +
		tex->w = XTextWidth(font->xfont, text, len);
201 199
	}
202 200
}
201 +
202 +
unsigned int
203 +
drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) {
204 +
	Extnts tex;
205 +
206 +
	if(!font)
207 +
		return -1;
208 +
	drw_font_getexts(font, text, len, &tex);
209 +
	return tex.w;
210 +
}
211 +
212 +
Cur *
213 +
drw_cur_create(Drw *drw, int shape) {
214 +
	Cur *cur = (Cur *)calloc(1, sizeof(Cur));
215 +
216 +
	if(!drw || !cur)
217 +
		return NULL;
218 +
	cur->cursor = XCreateFontCursor(drw->dpy, shape);
219 +
	return cur;
220 +
}
221 +
222 +
void
223 +
drw_cur_free(Drw *drw, Cur *cursor) {
224 +
	if(!drw || !cursor)
225 +
		return;
226 +
	XFreeCursor(drw->dpy, cursor->cursor);
227 +
	free(cursor);
228 +
}
drw.h +27 −19
5 5
} Clr;
6 6
7 7
typedef struct {
8 +
	Cursor cursor;
9 +
} Cur;
10 +
11 +
typedef struct {
8 12
	int ascent;
9 13
	int descent;
10 14
	unsigned int h;
13 17
} Fnt;
14 18
15 19
typedef struct {
20 +
	Clr *fg;
21 +
	Clr *bg;
22 +
	Clr *border;
23 +
} Theme;
24 +
25 +
typedef struct {
16 26
	unsigned int w, h;
17 27
	Display *dpy;
18 28
	int screen;
19 -
	Window win;
20 -
	Drawable drwable;
29 +
	Window root;
30 +
	Drawable drawable;
21 31
	GC gc;
22 -
	Clr *fg;
23 -
	Clr *bg;
32 +
	Theme *theme;
24 33
	Fnt *font;
25 34
} Drw;
26 35
27 36
typedef struct {
28 37
	unsigned int w;
29 38
	unsigned int h;
30 -
	int xOff;
31 -
	int yOff;
32 39
} Extnts;
33 40
34 41
/* Drawable abstraction */
37 44
void drw_free(Drw *drw);
38 45
39 46
/* Fnt abstraction */
40 -
Fnt *drw_font_create(Drw *drw, const char *fontname);
41 -
void drw_font_free(Drw *drw, Fnt *font);
47 +
Fnt *drw_font_create(Display *dpy, const char *fontname);
48 +
void drw_font_free(Display *dpy, Fnt *font);
49 +
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts);
50 +
unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len);
42 51
43 -
/* Clrour abstraction */
52 +
/* Colour abstraction */
44 53
Clr *drw_clr_create(Drw *drw, const char *clrname);
45 -
void drw_clr_free(Drw *drw, Clr *clr);
54 +
void drw_clr_free(Clr *clr);
55 +
56 +
/* Cursor abstraction */
57 +
Cur *drw_cur_create(Drw *drw, int shape);
58 +
void drw_cur_free(Drw *drw, Cur *cursor);
46 59
47 60
/* Drawing context manipulation */
48 61
void drw_setfont(Drw *drw, Fnt *font);
49 -
void drw_setfg(Drw *drw, Clr *clr);
50 -
void drw_setbg(Drw *drw, Clr *clr);
62 +
void drw_settheme(Drw *drw, Theme *theme);
51 63
52 64
/* Drawing functions */
53 -
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert);
54 -
void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert);
65 +
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert);
66 +
void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
55 67
56 68
/* Map functions */
57 -
void drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h);
58 -
59 -
/* Text functions */
60 -
void drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *extnts);
61 -
69 +
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
dwm.c +69 −182
54 54
#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
55 55
#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
56 56
#define TAGMASK                 ((1 << LENGTH(tags)) - 1)
57 -
#define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
57 +
#define TEXTW(X)                (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
58 58
59 59
/* enums */
60 60
enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
99 99
};
100 100
101 101
typedef struct {
102 -
	int x, y, w, h;
103 -
	unsigned long norm[ColLast];
104 -
	unsigned long sel[ColLast];
105 -
	Drawable drawable;
106 -
	GC gc;
107 -
	struct {
108 -
		int ascent;
109 -
		int descent;
110 -
		int height;
111 -
		XFontSet set;
112 -
		XFontStruct *xfont;
113 -
	} font;
114 -
} DC; /* draw context */
115 -
116 -
typedef struct {
117 102
	unsigned int mod;
118 103
	KeySym keysym;
119 104
	void (*func)(const Arg *);
178 163
static Monitor *dirtomon(int dir);
179 164
static void drawbar(Monitor *m);
180 165
static void drawbars(void);
181 -
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
182 -
static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
183 166
static void enternotify(XEvent *e);
184 167
static void expose(XEvent *e);
185 168
static void focus(Client *c);
186 169
static void focusin(XEvent *e);
187 170
static void focusmon(const Arg *arg);
188 171
static void focusstack(const Arg *arg);
189 -
static unsigned long getcolor(const char *colstr);
190 172
static Bool getrootptr(int *x, int *y);
191 173
static long getstate(Window w);
192 174
static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
193 175
static void grabbuttons(Client *c, Bool focused);
194 176
static void grabkeys(void);
195 177
static void incnmaster(const Arg *arg);
196 -
static void initfont(const char *fontstr);
197 178
static void keypress(XEvent *e);
198 179
static void killclient(const Arg *arg);
199 180
static void manage(Window w, XWindowAttributes *wa);
226 207
static void spawn(const Arg *arg);
227 208
static void tag(const Arg *arg);
228 209
static void tagmon(const Arg *arg);
229 -
static int textnw(const char *text, unsigned int len);
230 210
static void tile(Monitor *);
231 211
static void togglebar(const Arg *arg);
232 212
static void togglefloating(const Arg *arg);
279 259
};
280 260
static Atom wmatom[WMLast], netatom[NetLast];
281 261
static Bool running = True;
282 -
static Cursor cursor[CurLast];
262 +
static Cur *cursor[CurLast];
263 +
static Theme thmnorm[ColLast];
264 +
static Theme thmsel[ColLast];
283 265
static Display *dpy;
284 -
static DC dc;
285 -
static Monitor *mons = NULL, *selmon = NULL;
266 +
static Drw *drw;
267 +
static Fnt *fnt;
268 +
static Monitor *mons, *selmon;
286 269
static Window root;
287 270
288 271
/* configuration, allows nested code to access above variables */
486 469
	for(m = mons; m; m = m->next)
487 470
		while(m->stack)
488 471
			unmanage(m->stack, False);
489 -
	if(dc.font.set)
490 -
		XFreeFontSet(dpy, dc.font.set);
491 -
	else
492 -
		XFreeFont(dpy, dc.font.xfont);
493 472
	XUngrabKey(dpy, AnyKey, AnyModifier, root);
494 -
	XFreePixmap(dpy, dc.drawable);
495 -
	XFreeGC(dpy, dc.gc);
496 -
	XFreeCursor(dpy, cursor[CurNormal]);
497 -
	XFreeCursor(dpy, cursor[CurResize]);
498 -
	XFreeCursor(dpy, cursor[CurMove]);
499 473
	while(mons)
500 474
		cleanupmon(mons);
475 +
	drw_cur_free(drw, cursor[CurNormal]);
476 +
	drw_cur_free(drw, cursor[CurResize]);
477 +
	drw_cur_free(drw, cursor[CurMove]);
478 +
	drw_font_free(dpy, fnt);
479 +
	drw_clr_free(thmnorm->border);
480 +
	drw_clr_free(thmnorm->bg);
481 +
	drw_clr_free(thmnorm->fg);
482 +
	drw_clr_free(thmsel->border);
483 +
	drw_clr_free(thmsel->bg);
484 +
	drw_clr_free(thmsel->fg);
485 +
	drw_free(drw);
501 486
	XSync(dpy, False);
502 487
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
503 488
	XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
581 566
		sw = ev->width;
582 567
		sh = ev->height;
583 568
		if(updategeom() || dirty) {
584 -
			if(dc.drawable != 0)
585 -
				XFreePixmap(dpy, dc.drawable);
586 -
			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
569 +
			drw_resize(drw, sw, bh);
587 570
			updatebars();
588 571
			for(m = mons; m; m = m->next)
589 572
				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
710 693
711 694
void
712 695
drawbar(Monitor *m) {
713 -
	int x;
696 +
	int x, xx, w;
714 697
	unsigned int i, occ = 0, urg = 0;
715 -
	unsigned long *col;
716 698
	Client *c;
717 699
718 700
	for(c = m->clients; c; c = c->next) {
720 702
		if(c->isurgent)
721 703
			urg |= c->tags;
722 704
	}
723 -
	dc.x = 0;
705 +
	x = 0;
724 706
	for(i = 0; i < LENGTH(tags); i++) {
725 -
		dc.w = TEXTW(tags[i]);
726 -
		col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
727 -
		drawtext(tags[i], col, urg & 1 << i);
728 -
		drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
729 -
		           occ & 1 << i, urg & 1 << i, col);
730 -
		dc.x += dc.w;
707 +
		w = TEXTW(tags[i]);
708 +
		drw_settheme(drw, m->tagset[m->seltags] & 1 << i ? thmsel : thmnorm);
709 +
		drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i);
710 +
		drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
711 +
		           occ & 1 << i, urg & 1 << i);
712 +
		x += w;
731 713
	}
732 -
	dc.w = blw = TEXTW(m->ltsymbol);
733 -
	drawtext(m->ltsymbol, dc.norm, False);
734 -
	dc.x += dc.w;
735 -
	x = dc.x;
714 +
	w = blw = TEXTW(m->ltsymbol);
715 +
	drw_settheme(drw, thmnorm);
716 +
	drw_text(drw, x, 0, w, bh, m->ltsymbol, 0);
717 +
	x += w;
718 +
	xx = x;
736 719
	if(m == selmon) { /* status is only drawn on selected monitor */
737 -
		dc.w = TEXTW(stext);
738 -
		dc.x = m->ww - dc.w;
739 -
		if(dc.x < x) {
740 -
			dc.x = x;
741 -
			dc.w = m->ww - x;
720 +
		w = TEXTW(stext);
721 +
		x = m->ww - w;
722 +
		if(x < xx) {
723 +
			x = xx;
724 +
			w = m->ww - xx;
742 725
		}
743 -
		drawtext(stext, dc.norm, False);
726 +
		drw_text(drw, x, 0, w, bh, stext, 0);
744 727
	}
745 728
	else
746 -
		dc.x = m->ww;
747 -
	if((dc.w = dc.x - x) > bh) {
748 -
		dc.x = x;
729 +
		x = m->ww;
730 +
	if((w = x - xx) > bh) {
731 +
		x = xx;
749 732
		if(m->sel) {
750 -
			col = m == selmon ? dc.sel : dc.norm;
751 -
			drawtext(m->sel->name, col, False);
752 -
			drawsquare(m->sel->isfixed, m->sel->isfloating, False, col);
733 +
			drw_settheme(drw, m == selmon ? thmsel : thmnorm);
734 +
			drw_text(drw, x, 0, w, bh, m->sel->name, 0);
735 +
			drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0);
753 736
		}
754 -
		else
755 -
			drawtext(NULL, dc.norm, False);
737 +
		else {
738 +
			drw_settheme(drw, thmnorm);
739 +
			drw_text(drw, x, 0, w, bh, NULL, 0);
740 +
		}
756 741
	}
757 -
	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
758 -
	XSync(dpy, False);
742 +
	drw_map(drw, m->barwin, 0, 0, m->ww, bh);
759 743
}
760 744
761 745
void
767 751
}
768 752
769 753
void
770 -
drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
771 -
	int x;
772 -
773 -
	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
774 -
	x = (dc.font.ascent + dc.font.descent + 2) / 4;
775 -
	if(filled)
776 -
		XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1);
777 -
	else if(empty)
778 -
		XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x);
779 -
}
780 -
781 -
void
782 -
drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
783 -
	char buf[256];
784 -
	int i, x, y, h, len, olen;
785 -
786 -
	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
787 -
	XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
788 -
	if(!text)
789 -
		return;
790 -
	olen = strlen(text);
791 -
	h = dc.font.ascent + dc.font.descent;
792 -
	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
793 -
	x = dc.x + (h / 2);
794 -
	/* shorten text if necessary */
795 -
	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
796 -
	if(!len)
797 -
		return;
798 -
	memcpy(buf, text, len);
799 -
	if(len < olen)
800 -
		for(i = len; i && i > len - 3; buf[--i] = '.');
801 -
	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
802 -
	if(dc.font.set)
803 -
		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
804 -
	else
805 -
		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
806 -
}
807 -
808 -
void
809 754
enternotify(XEvent *e) {
810 755
	Client *c;
811 756
	Monitor *m;
848 793
		detachstack(c);
849 794
		attachstack(c);
850 795
		grabbuttons(c, True);
851 -
		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
796 +
		XSetWindowBorder(dpy, c->win, thmsel->border->rgb);
852 797
		setfocus(c);
853 798
	}
854 799
	else {
922 867
	return atom;
923 868
}
924 869
925 -
unsigned long
926 -
getcolor(const char *colstr) {
927 -
	Colormap cmap = DefaultColormap(dpy, screen);
928 -
	XColor color;
929 -
930 -
	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
931 -
		die("error, cannot allocate color '%s'\n", colstr);
932 -
	return color.pixel;
933 -
}
934 -
935 870
Bool
936 871
getrootptr(int *x, int *y) {
937 872
	int di;
1028 963
	arrange(selmon);
1029 964
}
1030 965
1031 -
void
1032 -
initfont(const char *fontstr) {
1033 -
	char *def, **missing;
1034 -
	int n;
1035 -
1036 -
	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
1037 -
	if(missing) {
1038 -
		while(n--)
1039 -
			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
1040 -
		XFreeStringList(missing);
1041 -
	}
1042 -
	if(dc.font.set) {
1043 -
		XFontStruct **xfonts;
1044 -
		char **font_names;
1045 -
1046 -
		dc.font.ascent = dc.font.descent = 0;
1047 -
		XExtentsOfFontSet(dc.font.set);
1048 -
		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
1049 -
		while(n--) {
1050 -
			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
1051 -
			dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
1052 -
			xfonts++;
1053 -
		}
1054 -
	}
1055 -
	else {
1056 -
		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
1057 -
		&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
1058 -
			die("error, cannot load font: '%s'\n", fontstr);
1059 -
		dc.font.ascent = dc.font.xfont->ascent;
1060 -
		dc.font.descent = dc.font.xfont->descent;
1061 -
	}
1062 -
	dc.font.height = dc.font.ascent + dc.font.descent;
1063 -
}
1064 -
1065 966
#ifdef XINERAMA
1066 967
static Bool
1067 968
isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) {
1140 1041
1141 1042
	wc.border_width = c->bw;
1142 1043
	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
1143 -
	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
1044 +
	XSetWindowBorder(dpy, w, thmnorm->border->rgb);
1144 1045
	configure(c); /* propagates border_width, if size doesn't change */
1145 1046
	updatewindowtype(c);
1146 1047
	updatesizehints(c);
1232 1133
	ocx = c->x;
1233 1134
	ocy = c->y;
1234 1135
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1235 -
	None, cursor[CurMove], CurrentTime) != GrabSuccess)
1136 +
	None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
1236 1137
		return;
1237 1138
	if(!getrootptr(&x, &y))
1238 1139
		return;
1378 1279
	ocx = c->x;
1379 1280
	ocy = c->y;
1380 1281
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1381 -
	                None, cursor[CurResize], CurrentTime) != GrabSuccess)
1282 +
	                None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
1382 1283
		return;
1383 1284
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
1384 1285
	do {
1597 1498
	/* init screen */
1598 1499
	screen = DefaultScreen(dpy);
1599 1500
	root = RootWindow(dpy, screen);
1600 -
	initfont(font);
1501 +
	fnt = drw_font_create(dpy, font);
1601 1502
	sw = DisplayWidth(dpy, screen);
1602 1503
	sh = DisplayHeight(dpy, screen);
1603 -
	bh = dc.h = dc.font.height + 2;
1504 +
	bh = fnt->h + 2;
1505 +
	drw = drw_create(dpy, screen, root, sw, sh);
1506 +
	drw_setfont(drw, fnt);
1604 1507
	updategeom();
1605 1508
	/* init atoms */
1606 1509
	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
1616 1519
	netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
1617 1520
	netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
1618 1521
	/* init cursors */
1619 -
	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
1620 -
	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
1621 -
	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
1522 +
	cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
1523 +
	cursor[CurResize] = drw_cur_create(drw, XC_sizing);
1524 +
	cursor[CurMove] = drw_cur_create(drw, XC_fleur);
1622 1525
	/* init appearance */
1623 -
	dc.norm[ColBorder] = getcolor(normbordercolor);
1624 -
	dc.norm[ColBG] = getcolor(normbgcolor);
1625 -
	dc.norm[ColFG] = getcolor(normfgcolor);
1626 -
	dc.sel[ColBorder] = getcolor(selbordercolor);
1627 -
	dc.sel[ColBG] = getcolor(selbgcolor);
1628 -
	dc.sel[ColFG] = getcolor(selfgcolor);
1629 -
	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
1630 -
	dc.gc = XCreateGC(dpy, root, 0, NULL);
1631 -
	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
1632 -
	if(!dc.font.set)
1633 -
		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
1526 +
	thmnorm->border = drw_clr_create(drw, normbordercolor);
1527 +
	thmnorm->bg = drw_clr_create(drw, normbgcolor);
1528 +
	thmnorm->fg = drw_clr_create(drw, normfgcolor);
1529 +
	thmsel->border = drw_clr_create(drw, selbordercolor);
1530 +
	thmsel->bg = drw_clr_create(drw, selbgcolor);
1531 +
	thmsel->fg = drw_clr_create(drw, selfgcolor);
1634 1532
	/* init bars */
1635 1533
	updatebars();
1636 1534
	updatestatus();
1639 1537
			PropModeReplace, (unsigned char *) netatom, NetLast);
1640 1538
	XDeleteProperty(dpy, root, netatom[NetClientList]);
1641 1539
	/* select for events */
1642 -
	wa.cursor = cursor[CurNormal];
1540 +
	wa.cursor = cursor[CurNormal]->cursor;
1643 1541
	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask
1644 1542
	                |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
1645 1543
	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
1699 1597
	sendmon(selmon->sel, dirtomon(arg->i));
1700 1598
}
1701 1599
1702 -
int
1703 -
textnw(const char *text, unsigned int len) {
1704 -
	XRectangle r;
1705 -
1706 -
	if(dc.font.set) {
1707 -
		XmbTextExtents(dc.font.set, text, len, NULL, &r);
1708 -
		return r.width;
1709 -
	}
1710 -
	return XTextWidth(dc.font.xfont, text, len);
1711 -
}
1712 -
1713 1600
void
1714 1601
tile(Monitor *m) {
1715 1602
	unsigned int i, n, h, mw, my, ty;
1787 1674
	if(!c)
1788 1675
		return;
1789 1676
	grabbuttons(c, False);
1790 -
	XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
1677 +
	XSetWindowBorder(dpy, c->win, thmnorm->border->rgb);
1791 1678
	if(setfocus) {
1792 1679
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
1793 1680
		XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
1846 1733
		m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
1847 1734
		                          CopyFromParent, DefaultVisual(dpy, screen),
1848 1735
		                          CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
1849 -
		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
1736 +
		XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
1850 1737
		XMapRaised(dpy, m->barwin);
1851 1738
	}
1852 1739
}