all repos — dwm @ 2091200c957783deed032380d56c4199a23c6b81

fork of suckless dynamic window manager

bar.c (view raw)

  1/* See LICENSE file for copyright and license details. */
  2#include "dwm.h"
  3#include <string.h>
  4#include <stdio.h>
  5
  6/* static */
  7
  8static void
  9drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
 10	int x;
 11	XGCValues gcv;
 12	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 13
 14	gcv.foreground = col[ColFG];
 15	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
 16	x = (dc.font.ascent + dc.font.descent + 2) / 4;
 17	r.x = dc.x + 1;
 18	r.y = dc.y + 1;
 19	if(filled) {
 20		r.width = r.height = x + 1;
 21		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
 22	}
 23	else if(empty) {
 24		r.width = r.height = x;
 25		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
 26	}
 27}
 28
 29static unsigned long
 30initcolor(const char *colstr) {
 31	Colormap cmap = DefaultColormap(dpy, screen);
 32	XColor color;
 33
 34	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
 35		eprint("error, cannot allocate color '%s'\n", colstr);
 36	return color.pixel;
 37}
 38
 39static void
 40initfont(const char *fontstr) {
 41	char *def, **missing;
 42	int i, n;
 43
 44	missing = NULL;
 45	if(dc.font.set)
 46		XFreeFontSet(dpy, dc.font.set);
 47	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
 48	if(missing) {
 49		while(n--)
 50			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
 51		XFreeStringList(missing);
 52	}
 53	if(dc.font.set) {
 54		XFontSetExtents *font_extents;
 55		XFontStruct **xfonts;
 56		char **font_names;
 57		dc.font.ascent = dc.font.descent = 0;
 58		font_extents = XExtentsOfFontSet(dc.font.set);
 59		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
 60		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
 61			if(dc.font.ascent < (*xfonts)->ascent)
 62				dc.font.ascent = (*xfonts)->ascent;
 63			if(dc.font.descent < (*xfonts)->descent)
 64				dc.font.descent = (*xfonts)->descent;
 65			xfonts++;
 66		}
 67	}
 68	else {
 69		if(dc.font.xfont)
 70			XFreeFont(dpy, dc.font.xfont);
 71		dc.font.xfont = NULL;
 72		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
 73		|| !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
 74			eprint("error, cannot load font: '%s'\n", fontstr);
 75		dc.font.ascent = dc.font.xfont->ascent;
 76		dc.font.descent = dc.font.xfont->descent;
 77	}
 78	dc.font.height = dc.font.ascent + dc.font.descent;
 79}
 80
 81static Bool
 82isoccupied(unsigned int t) {
 83	Client *c;
 84
 85	for(c = clients; c; c = c->next)
 86		if(c->tags[t])
 87			return True;
 88	return False;
 89}
 90
 91static unsigned int
 92textnw(const char *text, unsigned int len) {
 93	XRectangle r;
 94
 95	if(dc.font.set) {
 96		XmbTextExtents(dc.font.set, text, len, NULL, &r);
 97		return r.width;
 98	}
 99	return XTextWidth(dc.font.xfont, text, len);
100}
101
102static void
103drawtext(const char *text, unsigned long col[ColLast]) {
104	int x, y, w, h;
105	static char buf[256];
106	unsigned int len, olen;
107	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
108
109	XSetForeground(dpy, dc.gc, col[ColBG]);
110	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
111	if(!text)
112		return;
113	w = 0;
114	olen = len = strlen(text);
115	if(len >= sizeof buf)
116		len = sizeof buf - 1;
117	memcpy(buf, text, len);
118	buf[len] = 0;
119	h = dc.font.ascent + dc.font.descent;
120	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
121	x = dc.x + (h / 2);
122	/* shorten text if necessary */
123	while(len && (w = textnw(buf, len)) > dc.w - h)
124		buf[--len] = 0;
125	if(len < olen) {
126		if(len > 1)
127			buf[len - 1] = '.';
128		if(len > 2)
129			buf[len - 2] = '.';
130		if(len > 3)
131			buf[len - 3] = '.';
132	}
133	if(w > dc.w)
134		return; /* too long */
135	XSetForeground(dpy, dc.gc, col[ColFG]);
136	if(dc.font.set)
137		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
138	else
139		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
140}
141
142/* extern */
143
144unsigned int bh;
145unsigned int bpos = BARPOS;
146DC dc = {0};
147Window barwin;
148
149void
150drawbar(void) {
151	int i, x;
152
153	dc.x = dc.y = 0;
154	for(i = 0; i < ntags; i++) {
155		dc.w = textw(tags[i]);
156		if(seltags[i]) {
157			drawtext(tags[i], dc.sel);
158			drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
159		}
160		else {
161			drawtext(tags[i], dc.norm);
162			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
163		}
164		dc.x += dc.w;
165	}
166	dc.w = blw;
167	drawtext(getsymbol(), dc.norm);
168	x = dc.x + dc.w;
169	dc.w = textw(stext);
170	dc.x = sw - dc.w;
171	if(dc.x < x) {
172		dc.x = x;
173		dc.w = sw - x;
174	}
175	drawtext(stext, dc.norm);
176	if((dc.w = dc.x - x) > bh) {
177		dc.x = x;
178		if(sel) {
179			drawtext(sel->name, dc.sel);
180			drawsquare(sel->ismax, sel->isfloating, dc.sel);
181		}
182		else
183			drawtext(NULL, dc.norm);
184	}
185	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
186	XSync(dpy, False);
187}
188
189void
190initstyle(void) {
191	dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR);
192	dc.norm[ColBG] = initcolor(NORMBGCOLOR);
193	dc.norm[ColFG] = initcolor(NORMFGCOLOR);
194	dc.sel[ColBorder] = initcolor(SELBORDERCOLOR);
195	dc.sel[ColBG] = initcolor(SELBGCOLOR);
196	dc.sel[ColFG] = initcolor(SELFGCOLOR);
197	initfont(FONT);
198	dc.h = bh = dc.font.height + 2;
199}
200
201void
202initbar(void) {
203	XSetWindowAttributes wa;
204
205	wa.override_redirect = 1;
206	wa.background_pixmap = ParentRelative;
207	wa.event_mask = ButtonPressMask | ExposureMask;
208	barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0,
209			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
210			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
211	XDefineCursor(dpy, barwin, cursor[CurNormal]);
212	updatebarpos();
213	XMapRaised(dpy, barwin);
214	strcpy(stext, "dwm-"VERSION);
215	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
216	dc.gc = XCreateGC(dpy, root, 0, 0);
217	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
218	if(!dc.font.set)
219		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
220}
221
222unsigned int
223textw(const char *text) {
224	return textnw(text, strlen(text)) + dc.font.height;
225}
226
227void
228togglebar(const char *arg) {
229	if(bpos == BarOff)
230		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
231	else
232		bpos = BarOff;
233	updatebarpos();
234	arrange();
235}
236
237void
238updatebarpos(void) {
239	XEvent ev;
240
241	wax = sx;
242	way = sy;
243	wah = sh;
244	waw = sw;
245	switch(bpos) {
246	default:
247		wah -= bh;
248		way += bh;
249		XMoveWindow(dpy, barwin, sx, sy);
250		break;
251	case BarBot:
252		wah -= bh;
253		XMoveWindow(dpy, barwin, sx, sy + wah);
254		break;
255	case BarOff:
256		XMoveWindow(dpy, barwin, sx, sy - bh);
257		break;
258	}
259	XSync(dpy, False);
260	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
261}
262
263