Fixed window finding function, generalized it to find any program, configurable using...
[dwm.git] / dwm-6.0-pango.diff
1 diff --git a/config.def.h b/config.def.h
2 index 77ff358..3bee2e7 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -1,7 +1,7 @@
6 /* See LICENSE file for copyright and license details. */
7
8 /* appearance */
9 -static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
10 +static const char font[] = "Sans 8";
11 static const char normbordercolor[] = "#444444";
12 static const char normbgcolor[] = "#222222";
13 static const char normfgcolor[] = "#bbbbbb";
14 @@ -12,6 +12,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
15 static const unsigned int snap = 32; /* snap pixel */
16 static const Bool showbar = True; /* False means no bar */
17 static const Bool topbar = True; /* False means bottom bar */
18 +static const Bool statusmarkup = True; /* True means use pango markup in status message */
19
20 /* tagging */
21 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
22 diff --git a/config.mk b/config.mk
23 index 484554a..cdfb642 100644
24 --- a/config.mk
25 +++ b/config.mk
26 @@ -15,8 +15,8 @@ XINERAMALIBS = -L${X11LIB} -lXinerama
27 XINERAMAFLAGS = -DXINERAMA
28
29 # includes and libs
30 -INCS = -I. -I/usr/include -I${X11INC}
31 -LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS}
32 +INCS = -I. -I/usr/include -I${X11INC} `pkg-config --cflags xft pango pangoxft`
33 +LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs xft pango pangoxft`
34
35 # flags
36 CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
37 diff --git a/dwm.c b/dwm.c
38 index 1d78655..8fae3ba 100644
39 --- a/dwm.c
40 +++ b/dwm.c
41 @@ -36,6 +36,9 @@
42 #include <X11/Xlib.h>
43 #include <X11/Xproto.h>
44 #include <X11/Xutil.h>
45 +#include <X11/Xft/Xft.h>
46 +#include <pango/pango.h>
47 +#include <pango/pangoxft.h>
48 #ifdef XINERAMA
49 #include <X11/extensions/Xinerama.h>
50 #endif /* XINERAMA */
51 @@ -47,8 +50,12 @@
52 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
53 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
54 #define LENGTH(X) (sizeof X / sizeof X[0])
55 +#ifndef MAX
56 #define MAX(A, B) ((A) > (B) ? (A) : (B))
57 +#endif
58 +#ifndef MIN
59 #define MIN(A, B) ((A) < (B) ? (A) : (B))
60 +#endif
61 #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
62 #define WIDTH(X) ((X)->w + 2 * (X)->bw)
63 #define HEIGHT(X) ((X)->h + 2 * (X)->bw)
64 @@ -104,11 +111,15 @@ typedef struct {
65 Drawable drawable;
66 GC gc;
67 struct {
68 + XftColor norm[ColLast];
69 + XftColor sel[ColLast];
70 + XftDraw *drawable;
71 + } xft;
72 + struct {
73 int ascent;
74 int descent;
75 int height;
76 - XFontSet set;
77 - XFontStruct *xfont;
78 + PangoLayout *layout;
79 } font;
80 } DC; /* draw context */
81
82 @@ -186,7 +197,7 @@ static void focus(Client *c);
83 static void focusin(XEvent *e);
84 static void focusmon(const Arg *arg);
85 static void focusstack(const Arg *arg);
86 -static unsigned long getcolor(const char *colstr);
87 +static unsigned long getcolor(const char *colstr, XftColor *color);
88 static Bool getrootptr(int *x, int *y);
89 static long getstate(Window w);
90 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
91 @@ -254,7 +265,7 @@ static void zoom(const Arg *arg);
92
93 /* variables */
94 static const char broken[] = "broken";
95 -static char stext[256];
96 +static char stext[512];
97 static int screen;
98 static int sw, sh; /* X display screen geometry width, height */
99 static int bh, blw = 0; /* bar geometry */
100 @@ -479,18 +490,21 @@ cleanup(void) {
101 Arg a = {.ui = ~0};
102 Layout foo = { "", NULL };
103 Monitor *m;
104 + int i;
105
106 view(&a);
107 selmon->lt[selmon->sellt] = &foo;
108 for(m = mons; m; m = m->next)
109 while(m->stack)
110 unmanage(m->stack, False);
111 - if(dc.font.set)
112 - XFreeFontSet(dpy, dc.font.set);
113 - else
114 - XFreeFont(dpy, dc.font.xfont);
115 XUngrabKey(dpy, AnyKey, AnyModifier, root);
116 XFreePixmap(dpy, dc.drawable);
117 + for(i = ColBorder; i < ColLast; i++) {
118 + XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), dc.xft.norm + i);
119 + XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), dc.xft.sel + i);
120 + }
121 + XftDrawDestroy(dc.xft.drawable);
122 + g_object_unref(dc.font.layout);
123 XFreeGC(dpy, dc.gc);
124 XFreeCursor(dpy, cursor[CurNormal]);
125 XFreeCursor(dpy, cursor[CurResize]);
126 @@ -581,6 +595,7 @@ configurenotify(XEvent *e) {
127 if(dc.drawable != 0)
128 XFreePixmap(dpy, dc.drawable);
129 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
130 + XftDrawChange(dc.xft.drawable, dc.drawable);
131 updatebars();
132 for(m = mons; m; m = m->next)
133 XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
134 @@ -787,7 +802,7 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
135
136 void
137 drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
138 - char buf[256];
139 + char buf[512];
140 int i, x, y, h, len, olen;
141
142 XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
143 @@ -796,20 +811,25 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
144 return;
145 olen = strlen(text);
146 h = dc.font.ascent + dc.font.descent;
147 - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
148 + y = dc.y + (dc.h / 2) - (h / 2);
149 x = dc.x + (h / 2);
150 - /* shorten text if necessary */
151 + /* shorten text if necessary (this could wreak havoc with pango markup but fortunately
152 + dc.w is adjusted to the width of the status text and not the other way around) */
153 for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
154 if(!len)
155 return;
156 memcpy(buf, text, len);
157 if(len < olen)
158 for(i = len; i && i > len - 3; buf[--i] = '.');
159 - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
160 - if(dc.font.set)
161 - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
162 + if(text == stext && statusmarkup)
163 + pango_layout_set_markup(dc.font.layout, buf, len);
164 else
165 - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
166 + pango_layout_set_text(dc.font.layout, buf, len);
167 + pango_xft_render_layout(dc.xft.drawable,
168 + (col == dc.norm ? dc.xft.norm : dc.xft.sel) + (invert ? ColBG : ColFG),
169 + dc.font.layout, x * PANGO_SCALE, y * PANGO_SCALE);
170 + if(text == stext && statusmarkup) /* clear markup attributes */
171 + pango_layout_set_attributes(dc.font.layout, NULL);
172 }
173
174 void
175 @@ -927,13 +947,13 @@ getatomprop(Client *c, Atom prop) {
176 }
177
178 unsigned long
179 -getcolor(const char *colstr) {
180 +getcolor(const char *colstr, XftColor *color) {
181 Colormap cmap = DefaultColormap(dpy, screen);
182 - XColor color;
183 + Visual *vis = DefaultVisual(dpy, screen);
184
185 - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
186 + if(!XftColorAllocName(dpy, vis, cmap, colstr, color))
187 die("error, cannot allocate color '%s'\n", colstr);
188 - return color.pixel;
189 + return color->pixel;
190 }
191
192 Bool
193 @@ -1034,36 +1054,24 @@ incnmaster(const Arg *arg) {
194
195 void
196 initfont(const char *fontstr) {
197 - char *def, **missing;
198 - int n;
199 -
200 - dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
201 - if(missing) {
202 - while(n--)
203 - fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
204 - XFreeStringList(missing);
205 - }
206 - if(dc.font.set) {
207 - XFontStruct **xfonts;
208 - char **font_names;
209 -
210 - dc.font.ascent = dc.font.descent = 0;
211 - XExtentsOfFontSet(dc.font.set);
212 - n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
213 - while(n--) {
214 - dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
215 - dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
216 - xfonts++;
217 - }
218 - }
219 - else {
220 - if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
221 - && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
222 - die("error, cannot load font: '%s'\n", fontstr);
223 - dc.font.ascent = dc.font.xfont->ascent;
224 - dc.font.descent = dc.font.xfont->descent;
225 - }
226 + PangoFontMap *fontmap;
227 + PangoContext *context;
228 + PangoFontDescription *desc;
229 + PangoFontMetrics *metrics;
230 +
231 + fontmap = pango_xft_get_font_map(dpy, screen);
232 + context = pango_font_map_create_context(fontmap);
233 + desc = pango_font_description_from_string(fontstr);
234 + dc.font.layout = pango_layout_new(context);
235 + pango_layout_set_font_description(dc.font.layout, desc);
236 +
237 + metrics = pango_context_get_metrics(context, desc, NULL);
238 + dc.font.ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
239 + dc.font.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
240 dc.font.height = dc.font.ascent + dc.font.descent;
241 +
242 + pango_font_metrics_unref(metrics);
243 + g_object_unref(context);
244 }
245
246 #ifdef XINERAMA
247 @@ -1612,17 +1620,16 @@ setup(void) {
248 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
249 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
250 /* init appearance */
251 - dc.norm[ColBorder] = getcolor(normbordercolor);
252 - dc.norm[ColBG] = getcolor(normbgcolor);
253 - dc.norm[ColFG] = getcolor(normfgcolor);
254 - dc.sel[ColBorder] = getcolor(selbordercolor);
255 - dc.sel[ColBG] = getcolor(selbgcolor);
256 - dc.sel[ColFG] = getcolor(selfgcolor);
257 + dc.norm[ColBorder] = getcolor(normbordercolor, dc.xft.norm + ColBorder);
258 + dc.norm[ColBG] = getcolor(normbgcolor, dc.xft.norm + ColBG);
259 + dc.norm[ColFG] = getcolor(normfgcolor, dc.xft.norm + ColFG);
260 + dc.sel[ColBorder] = getcolor(selbordercolor, dc.xft.sel + ColBorder);
261 + dc.sel[ColBG] = getcolor(selbgcolor, dc.xft.sel + ColBG);
262 + dc.sel[ColFG] = getcolor(selfgcolor, dc.xft.sel + ColFG);
263 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
264 + dc.xft.drawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen));
265 dc.gc = XCreateGC(dpy, root, 0, NULL);
266 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
267 - if(!dc.font.set)
268 - XSetFont(dpy, dc.gc, dc.font.xfont->fid);
269 /* init bars */
270 updatebars();
271 updatestatus();
272 @@ -1692,13 +1699,15 @@ tagmon(const Arg *arg) {
273
274 int
275 textnw(const char *text, unsigned int len) {
276 - XRectangle r;
277 -
278 - if(dc.font.set) {
279 - XmbTextExtents(dc.font.set, text, len, NULL, &r);
280 - return r.width;
281 - }
282 - return XTextWidth(dc.font.xfont, text, len);
283 + PangoRectangle r;
284 + if(text == stext && statusmarkup)
285 + pango_layout_set_markup(dc.font.layout, text, len);
286 + else
287 + pango_layout_set_text(dc.font.layout, text, len);
288 + pango_layout_get_extents(dc.font.layout, 0, &r);
289 + if(text == stext && statusmarkup) /* clear markup attributes */
290 + pango_layout_set_attributes(dc.font.layout, NULL);
291 + return r.width / PANGO_SCALE;
292 }
293
294 void