Skip to content

Commit 10e6d27

Browse files
committed
Merge remote-tracking branch 'suckless/master'
2 parents 4c3a1af + 5b2e5e7 commit 10e6d27

File tree

7 files changed

+113
-74
lines changed

7 files changed

+113
-74
lines changed

LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ MIT/X Consortium License
1717
© 2015-2016 Quentin Rameau <[email protected]>
1818
© 2015-2016 Eric Pruitt <[email protected]>
1919
© 2016-2017 Markus Teich <[email protected]>
20+
© 2020-2022 Chris Down <[email protected]>
2021

2122
Permission is hereby granted, free of charge, to any person obtaining a
2223
copy of this software and associated documentation files (the "Software"),

config.def.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static const Rule rules[] = {
5656
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
5757
static const int nmaster = 1; /* number of clients in master area */
5858
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
59+
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
5960

6061
static const Layout layouts[] = {
6162
/* symbol arrange function */

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static const Rule rules[] = {
6666
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
6767
static const int nmaster = 1; /* number of clients in master area */
6868
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
69+
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
6970

7071
static const Layout layouts[] = {
7172
/* symbol arrange function */

config.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# dwm version
2-
VERSION = 6.2
2+
VERSION = 6.3
33

44
# Customize below to fit your system
55

@@ -20,6 +20,7 @@ FREETYPEINC = /usr/include/freetype2
2020
# OpenBSD (uncomment)
2121
#FREETYPEINC = ${X11INC}/freetype2
2222
#KVMLIB = -lkvm
23+
#MANPREFIX = ${PREFIX}/man
2324

2425
# includes and libs
2526
INCS = -I${X11INC} -I${FREETYPEINC}

drw.c

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -251,26 +251,28 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
251251
int
252252
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
253253
{
254-
char buf[1024];
255-
int ty;
256-
unsigned int ew;
254+
int i, ty, ellipsis_x = 0;
255+
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
257256
XftDraw *d = NULL;
258257
Fnt *usedfont, *curfont, *nextfont;
259-
size_t i, len;
260258
int utf8strlen, utf8charlen, render = x || y || w || h;
261259
long utf8codepoint = 0;
262260
const char *utf8str;
263261
FcCharSet *fccharset;
264262
FcPattern *fcpattern;
265263
FcPattern *match;
266264
XftResult result;
267-
int charexists = 0;
265+
int charexists = 0, overflow = 0;
266+
/* keep track of a couple codepoints for which we have no match. */
267+
enum { nomatches_len = 64 };
268+
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
269+
static unsigned int ellipsis_width = 0;
268270

269-
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
271+
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
270272
return 0;
271273

272274
if (!render) {
273-
w = ~w;
275+
w = invert ? invert : ~invert;
274276
} else {
275277
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
276278
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@@ -282,55 +284,64 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
282284
}
283285

284286
usedfont = drw->fonts;
287+
if (!ellipsis_width && render)
288+
ellipsis_width = drw_fontset_getwidth(drw, "...");
285289
while (1) {
286-
utf8strlen = 0;
290+
ew = ellipsis_len = utf8strlen = 0;
287291
utf8str = text;
288292
nextfont = NULL;
289293
while (*text) {
290294
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
291295
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
292296
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
293297
if (charexists) {
294-
if (curfont == usedfont) {
298+
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
299+
if (ew + ellipsis_width <= w) {
300+
/* keep track where the ellipsis still fits */
301+
ellipsis_x = x + ew;
302+
ellipsis_w = w - ew;
303+
ellipsis_len = utf8strlen;
304+
}
305+
306+
if (ew + tmpw > w) {
307+
overflow = 1;
308+
/* called from drw_fontset_getwidth_clamp():
309+
* it wants the width AFTER the overflow
310+
*/
311+
if (!render)
312+
x += tmpw;
313+
else
314+
utf8strlen = ellipsis_len;
315+
} else if (curfont == usedfont) {
295316
utf8strlen += utf8charlen;
296317
text += utf8charlen;
318+
ew += tmpw;
297319
} else {
298320
nextfont = curfont;
299321
}
300322
break;
301323
}
302324
}
303325

304-
if (!charexists || nextfont)
326+
if (overflow || !charexists || nextfont)
305327
break;
306328
else
307329
charexists = 0;
308330
}
309331

310332
if (utf8strlen) {
311-
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
312-
/* shorten text if necessary */
313-
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
314-
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
315-
316-
if (len) {
317-
memcpy(buf, utf8str, len);
318-
buf[len] = '\0';
319-
if (len < utf8strlen)
320-
for (i = len; i && i > len - 3; buf[--i] = '.')
321-
; /* NOP */
322-
323-
if (render) {
324-
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
325-
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
326-
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
327-
}
328-
x += ew;
329-
w -= ew;
333+
if (render) {
334+
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
335+
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
336+
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
330337
}
338+
x += ew;
339+
w -= ew;
331340
}
341+
if (render && overflow)
342+
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
332343

333-
if (!*text) {
344+
if (!*text || overflow) {
334345
break;
335346
} else if (nextfont) {
336347
charexists = 0;
@@ -340,6 +351,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
340351
* character must be drawn. */
341352
charexists = 1;
342353

354+
for (i = 0; i < nomatches_len; ++i) {
355+
/* avoid calling XftFontMatch if we know we won't find a match */
356+
if (utf8codepoint == nomatches.codepoint[i])
357+
goto no_match;
358+
}
359+
343360
fccharset = FcCharSetCreate();
344361
FcCharSetAddChar(fccharset, utf8codepoint);
345362

@@ -368,6 +385,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
368385
curfont->next = usedfont;
369386
} else {
370387
xfont_free(usedfont);
388+
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
389+
no_match:
371390
usedfont = drw->fonts;
372391
}
373392
}
@@ -397,6 +416,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
397416
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
398417
}
399418

419+
unsigned int
420+
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
421+
{
422+
unsigned int tmp = 0;
423+
if (drw && drw->fonts && text && n)
424+
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
425+
return MIN(n, tmp);
426+
}
427+
400428
void
401429
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
402430
{

drw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ void drw_free(Drw *drw);
3535
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
3636
void drw_fontset_free(Fnt* set);
3737
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
38+
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
3839
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
3940

4041
/* Colorscheme abstraction */

dwm.c

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ struct Client {
102102
float mina, maxa;
103103
int x, y, w, h;
104104
int oldx, oldy, oldw, oldh;
105-
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
105+
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
106106
int bw, oldbw;
107107
unsigned int tags;
108108
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, needresize, issticky, isterminal, noswallow;
@@ -208,8 +208,8 @@ static void motionnotify(XEvent *e);
208208
static void movemouse(const Arg *arg);
209209
static Client *nexttagged(Client *c);
210210
static Client *nexttiled(Client *c);
211-
static void pop(Client *);
212211
static Client *prevtiled(Client *c);
212+
static void pop(Client *c);
213213
static void propertynotify(XEvent *e);
214214
static void pushdown(const Arg *arg);
215215
static void pushup(const Arg *arg);
@@ -237,7 +237,7 @@ static void spawn(const Arg *arg);
237237
static void swapfocus();
238238
static void tag(const Arg *arg);
239239
static void tagmon(const Arg *arg);
240-
static void tile(Monitor *);
240+
static void tile(Monitor *m);
241241
static void togglebar(const Arg *arg);
242242
static void togglefloating(const Arg *arg);
243243
static void togglefullscr(const Arg *arg);
@@ -407,6 +407,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
407407
if (*w < bh)
408408
*w = bh;
409409
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
410+
if (!c->hintsvalid)
411+
updatesizehints(c);
410412
/* see last two sentences in ICCCM 4.1.2.3 */
411413
baseismin = c->basew == c->minw && c->baseh == c->minh;
412414
if (!baseismin) { /* temporarily remove base dimensions */
@@ -613,6 +615,7 @@ cleanup(void)
613615
drw_cur_free(drw, cursor[i]);
614616
for (i = 0; i < LENGTH(colors); i++)
615617
free(scheme[i]);
618+
free(scheme);
616619
XDestroyWindow(dpy, wmcheckwin);
617620
drw_free(drw);
618621
XSync(dpy, False);
@@ -854,6 +857,9 @@ drawbar(Monitor *m)
854857
unsigned int i, occ = 0, urg = 0;
855858
Client *c;
856859

860+
if (!m->showbar)
861+
return;
862+
857863
/* draw status first so it can be overdrawn by tags later */
858864
if (m == selmon) { /* status is only drawn on selected monitor */
859865
drw_setscheme(drw, scheme[SchemeNorm]);
@@ -1003,7 +1009,7 @@ focusstack(const Arg *arg)
10031009
{
10041010
Client *c = NULL, *i;
10051011

1006-
if (!selmon->sel || selmon->sel->isfullscreen)
1012+
if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
10071013
return;
10081014
if (arg->i > 0) {
10091015
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
@@ -1424,7 +1430,7 @@ propertynotify(XEvent *e)
14241430
arrange(c->mon);
14251431
break;
14261432
case XA_WM_NORMAL_HINTS:
1427-
updatesizehints(c);
1433+
c->hintsvalid = 0;
14281434
break;
14291435
case XA_WM_HINTS:
14301436
updatewmhints(c);
@@ -1927,9 +1933,7 @@ spawn(const Arg *arg)
19271933
close(ConnectionNumber(dpy));
19281934
setsid();
19291935
execvp(((char **)arg->v)[0], (char **)arg->v);
1930-
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
1931-
perror(" failed");
1932-
exit(EXIT_SUCCESS);
1936+
die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
19331937
}
19341938
}
19351939

@@ -2165,6 +2169,7 @@ unmanage(Client *c, int destroyed)
21652169
wc.border_width = c->oldbw;
21662170
XGrabServer(dpy); /* avoid race conditions */
21672171
XSetErrorHandler(xerrordummy);
2172+
XSelectInput(dpy, c->win, NoEventMask);
21682173
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
21692174
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
21702175
setclientstate(c, WithdrawnState);
@@ -2265,43 +2270,43 @@ updategeom(void)
22652270
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
22662271
XFree(info);
22672272
nn = j;
2268-
if (n <= nn) { /* new monitors available */
2269-
for (i = 0; i < (nn - n); i++) {
2270-
for (m = mons; m && m->next; m = m->next);
2271-
if (m)
2272-
m->next = createmon();
2273-
else
2274-
mons = createmon();
2273+
2274+
/* new monitors if nn > n */
2275+
for (i = n; i < nn; i++) {
2276+
for (m = mons; m && m->next; m = m->next);
2277+
if (m)
2278+
m->next = createmon();
2279+
else
2280+
mons = createmon();
2281+
}
2282+
for (i = 0, m = mons; i < nn && m; m = m->next, i++)
2283+
if (i >= n
2284+
|| unique[i].x_org != m->mx || unique[i].y_org != m->my
2285+
|| unique[i].width != m->mw || unique[i].height != m->mh)
2286+
{
2287+
dirty = 1;
2288+
m->num = i;
2289+
m->mx = m->wx = unique[i].x_org;
2290+
m->my = m->wy = unique[i].y_org;
2291+
m->mw = m->ww = unique[i].width;
2292+
m->mh = m->wh = unique[i].height;
2293+
updatebarpos(m);
22752294
}
2276-
for (i = 0, m = mons; i < nn && m; m = m->next, i++)
2277-
if (i >= n
2278-
|| unique[i].x_org != m->mx || unique[i].y_org != m->my
2279-
|| unique[i].width != m->mw || unique[i].height != m->mh)
2280-
{
2281-
dirty = 1;
2282-
m->num = i;
2283-
m->mx = m->wx = unique[i].x_org;
2284-
m->my = m->wy = unique[i].y_org;
2285-
m->mw = m->ww = unique[i].width;
2286-
m->mh = m->wh = unique[i].height;
2287-
updatebarpos(m);
2288-
}
2289-
} else { /* less monitors available nn < n */
2290-
for (i = nn; i < n; i++) {
2291-
for (m = mons; m && m->next; m = m->next);
2292-
while ((c = m->clients)) {
2293-
dirty = 1;
2294-
m->clients = c->next;
2295-
detachstack(c);
2296-
c->mon = mons;
2297-
attach(c);
2298-
attachaside(c);
2299-
attachstack(c);
2300-
}
2301-
if (m == selmon)
2302-
selmon = mons;
2303-
cleanupmon(m);
2295+
/* removed monitors if n > nn */
2296+
for (i = nn; i < n; i++) {
2297+
for (m = mons; m && m->next; m = m->next);
2298+
while ((c = m->clients)) {
2299+
dirty = 1;
2300+
m->clients = c->next;
2301+
detachstack(c);
2302+
c->mon = mons;
2303+
attach(c);
2304+
attachaside(c);
2305+
attachstack(c);
23042306
}
2307+
if (m == selmon)
2308+
selmon = mons;
2309+
cleanupmon(m);
23052310
}
23062311
free(unique);
23072312
} else
@@ -2380,6 +2385,7 @@ updatesizehints(Client *c)
23802385
} else
23812386
c->maxa = c->mina = 0.0;
23822387
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
2388+
c->hintsvalid = 1;
23832389
}
23842390

23852391
void

0 commit comments

Comments
 (0)