all repos — dwm @ dba23062bad40afb1a90f60b6897cf9e1ca5035b

fork of suckless dynamic window manager

draw.c (view raw)

  1/*
  2 * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
  3 * See LICENSE file for license details.
  4 */
  5
  6#include <stdio.h>
  7#include <string.h>
  8
  9#include <X11/Xlocale.h>
 10
 11#include "dwm.h"
 12
 13void
 14drawall()
 15{
 16	Client *c;
 17
 18	for(c = clients; c; c = getnext(c->next))
 19		drawtitle(c);
 20	drawstatus();
 21}
 22
 23void
 24drawstatus()
 25{
 26	int i;
 27	Bool istile = arrange == dotile;
 28
 29	dc.x = dc.y = 0;
 30	dc.w = bw;
 31	drawtext(NULL, !istile, False);
 32
 33	dc.w = 0;
 34	for(i = 0; i < TLast; i++) {
 35		dc.x += dc.w;
 36		dc.w = textw(tags[i]);
 37		if(istile)
 38			drawtext(tags[i], (i == tsel), True);
 39		else
 40			drawtext(tags[i], (i != tsel), True);
 41	}
 42	if(sel) {
 43		dc.x += dc.w;
 44		dc.w = textw(sel->name);
 45		drawtext(sel->name, istile, True);
 46	}
 47	dc.w = textw(stext);
 48	dc.x = bx + bw - dc.w;
 49	drawtext(stext, !istile, False);
 50
 51	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
 52	XFlush(dpy);
 53}
 54
 55void
 56drawtitle(Client *c)
 57{
 58	int i;
 59	Bool istile = arrange == dotile;
 60
 61	if(c == sel) {
 62		drawstatus();
 63		XUnmapWindow(dpy, c->title);
 64		XSetWindowBorder(dpy, c->win, dc.fg);
 65		return;
 66	}
 67
 68	XSetWindowBorder(dpy, c->win, dc.bg);
 69	XMapWindow(dpy, c->title);
 70
 71	dc.x = dc.y = 0;
 72
 73	dc.w = 0;
 74	for(i = 0; i < TLast; i++) {
 75		if(c->tags[i]) {
 76			dc.x += dc.w;
 77			dc.w = textw(c->tags[i]);
 78			drawtext(c->tags[i], !istile, True);
 79		}
 80	}
 81	dc.x += dc.w;
 82	dc.w = textw(c->name);
 83	drawtext(c->name, !istile, True);
 84	XCopyArea(dpy, dc.drawable, c->title, dc.gc,
 85			0, 0, c->tw, c->th, 0, 0);
 86	XFlush(dpy);
 87}
 88
 89static void
 90drawborder(void)
 91{
 92	XPoint points[5];
 93	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
 94	XSetForeground(dpy, dc.gc, dc.border);
 95	points[0].x = dc.x;
 96	points[0].y = dc.y;
 97	points[1].x = dc.w - 1;
 98	points[1].y = 0;
 99	points[2].x = 0;
100	points[2].y = dc.h - 1;
101	points[3].x = -(dc.w - 1);
102	points[3].y = 0;
103	points[4].x = 0;
104	points[4].y = -(dc.h - 1);
105	XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
106}
107
108void
109drawtext(const char *text, Bool invert, Bool border)
110{
111	int x, y, w, h;
112	unsigned int len;
113	static char buf[256];
114	XGCValues gcv;
115	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
116
117	XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
118	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
119
120	w = 0;
121	if(border)
122		drawborder();
123
124	if(!text)
125		return;
126
127	len = strlen(text);
128	if(len >= sizeof(buf))
129		len = sizeof(buf) - 1;
130	memcpy(buf, text, len);
131	buf[len] = 0;
132
133	h = dc.font.ascent + dc.font.descent;
134	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
135	x = dc.x + (h / 2);
136
137	/* shorten text if necessary */
138	while(len && (w = textnw(buf, len)) > dc.w - h)
139		buf[--len] = 0;
140
141	if(w > dc.w)
142		return; /* too long */
143
144	gcv.foreground = invert ? dc.bg : dc.fg;
145	gcv.background = invert ? dc.fg : dc.bg;
146	if(dc.font.set) {
147		XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
148		XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
149				x, y, buf, len);
150	}
151	else {
152		gcv.font = dc.font.xfont->fid;
153		XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv);
154		XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);
155	}
156}
157
158unsigned long
159getcolor(const char *colstr)
160{
161	XColor color;
162	Colormap cmap = DefaultColormap(dpy, screen);
163
164	XAllocNamedColor(dpy, cmap, colstr, &color, &color);
165	return color.pixel;
166}
167
168unsigned int
169textnw(char *text, unsigned int len)
170{
171	XRectangle r;
172	if(dc.font.set) {
173		XmbTextExtents(dc.font.set, text, len, NULL, &r);
174		return r.width;
175	}
176	return XTextWidth(dc.font.xfont, text, len);
177}
178
179unsigned int
180textw(char *text)
181{
182	return textnw(text, strlen(text)) + dc.font.height;
183}
184
185void
186setfont(const char *fontstr)
187{
188	char **missing, *def;
189	int i, n;
190
191	missing = NULL;
192	setlocale(LC_ALL, "");
193	if(dc.font.set)
194		XFreeFontSet(dpy, dc.font.set);
195	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
196	if(missing) {
197		while(n--)
198			fprintf(stderr, "missing fontset: %s\n", missing[n]);
199		XFreeStringList(missing);
200		if(dc.font.set) {
201			XFreeFontSet(dpy, dc.font.set);
202			dc.font.set = NULL;
203		}
204	}
205	if(dc.font.set) {
206		XFontSetExtents *font_extents;
207		XFontStruct **xfonts;
208		char **font_names;
209
210		dc.font.ascent = dc.font.descent = 0;
211		font_extents = XExtentsOfFontSet(dc.font.set);
212		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
213		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
214			if(dc.font.ascent < (*xfonts)->ascent)
215				dc.font.ascent = (*xfonts)->ascent;
216			if(dc.font.descent < (*xfonts)->descent)
217				dc.font.descent = (*xfonts)->descent;
218			xfonts++;
219		}
220	}
221	else {
222		if(dc.font.xfont)
223			XFreeFont(dpy, dc.font.xfont);
224		dc.font.xfont = NULL;
225		dc.font.xfont = XLoadQueryFont(dpy, fontstr);
226		if (!dc.font.xfont)
227			dc.font.xfont = XLoadQueryFont(dpy, "fixed");
228		if (!dc.font.xfont)
229			eprint("error, cannot init 'fixed' font\n");
230		dc.font.ascent = dc.font.xfont->ascent;
231		dc.font.descent = dc.font.xfont->descent;
232	}
233	dc.font.height = dc.font.ascent + dc.font.descent;
234}