From 4e7c469862648420dcca95d7e88dc6cf24eb9ac1 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Mon, 19 Dec 2011 16:09:07 +0100 Subject: [PATCH 001/137] Added tag 6.0 for changeset ec4baab78314 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0034435..d48b951 100644 --- a/.hgtags +++ b/.hgtags @@ -70,3 +70,4 @@ e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 1ed1e75c9c2e395a2c475b52657a430bd95070c7 5.8.1 a043f08008051ca02ae87eb170cd066d8c8315a0 5.8.2 dd74622a4785e55658b05b36834fa0c41084a8c1 5.9 +ec4baab783145b2e9304f436795dc4b02abc5349 6.0 From 907db0a85165f720a7b7d5972736393e4d8ac1b9 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Wed, 4 Jan 2012 13:30:12 +0100 Subject: [PATCH 002/137] config.mk cleanup --- config.mk | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/config.mk b/config.mk index 484554a..7bb1c7c 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.0 +VERSION = 6.0-tip # Customize below to fit your system @@ -10,20 +10,19 @@ MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib -# Xinerama -XINERAMALIBS = -L${X11LIB} -lXinerama +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA # includes and libs -INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} +INCS = -I${X11INC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} # flags -CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -#LDFLAGS = -g ${LIBS} -LDFLAGS = -s ${LIBS} +CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" From 873bcb97a90727be29fe28774fc6b5546660b447 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Thu, 12 Jan 2012 07:36:05 +0100 Subject: [PATCH 003/137] applied Eckehard Berns barwin leak fix and his suggestion to deal with restack() -- the latter aspect needs further investigation. --- LICENSE | 2 +- dwm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index e8e793a..2e53d0a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2011 Anselm R Garbe +© 2006-2012 Anselm R Garbe © 2007-2011 Peter Hartlich © 2010-2011 Connor Lane Smith © 2006-2009 Jukka Salmi diff --git a/dwm.c b/dwm.c index 1d78655..0f946a6 100644 --- a/dwm.c +++ b/dwm.c @@ -1420,8 +1420,6 @@ restack(Monitor *m) { drawbar(m); if(!m->sel) return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); if(m->lt[m->sellt]->arrange) { wc.stack_mode = Below; wc.sibling = m->barwin; @@ -1827,6 +1825,8 @@ updatebars(void) { .event_mask = ButtonPressMask|ExposureMask }; for(m = mons; m; m = m->next) { + if (m->barwin) + continue; m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); @@ -2129,7 +2129,7 @@ zoom(const Arg *arg) { int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2011 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2012 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) From c4b6ac812e09c2dd0bb57ff76e8528b26a6ee9fd Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 22 Jan 2012 20:23:49 +0100 Subject: [PATCH 004/137] added 20h's clarification --- config.def.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.def.h b/config.def.h index 77ff358..8fd5d4a 100644 --- a/config.def.h +++ b/config.def.h @@ -17,6 +17,10 @@ static const Bool topbar = True; /* False means bottom bar */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ /* class instance title tags mask isfloating monitor */ { "Gimp", NULL, NULL, 0, True, -1 }, { "Firefox", NULL, NULL, 1 << 8, False, -1 }, From 51336aa4a38e82cc796edce790a989298e817a5a Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Wed, 8 Feb 2012 19:54:05 +0100 Subject: [PATCH 005/137] applied Eckehard Berns fix fix, sorry that this took so long --- dwm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 0f946a6..d39f11f 100644 --- a/dwm.c +++ b/dwm.c @@ -397,9 +397,10 @@ arrange(Monitor *m) { showhide(m->stack); else for(m = mons; m; m = m->next) showhide(m->stack); - if(m) + if(m) { arrangemon(m); - else for(m = mons; m; m = m->next) + restack(m); + } else for(m = mons; m; m = m->next) arrangemon(m); } @@ -408,7 +409,6 @@ arrangemon(Monitor *m) { strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); if(m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); - restack(m); } void @@ -1420,6 +1420,8 @@ restack(Monitor *m) { drawbar(m); if(!m->sel) return; + if(m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); if(m->lt[m->sellt]->arrange) { wc.stack_mode = Below; wc.sibling = m->barwin; From 54c3044decc9848ba18c137dd3558dc8bdf71f34 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Fri, 10 Feb 2012 00:36:08 +0000 Subject: [PATCH 006/137] unfocus on slow sloppy monitor focus --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index d39f11f..2d44442 100644 --- a/dwm.c +++ b/dwm.c @@ -1212,6 +1212,7 @@ motionnotify(XEvent *e) { if(ev->window != root) return; if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, True); selmon = m; focus(NULL); } From 1b62f8fa58eba3e535134912da2fa305fb7d3021 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 17 Mar 2012 18:14:17 +0100 Subject: [PATCH 007/137] applied Andreas Amann fullscreen fix, some minor modifications --- dwm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 2d44442..10b0d0d 100644 --- a/dwm.c +++ b/dwm.c @@ -1261,8 +1261,11 @@ movemouse(const Arg *arg) { && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) + if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + if(c->isfullscreen) + setfullscreen(c, False); resize(c, nx, ny, c->w, c->h, True); + } break; } } while(ev.type != ButtonRelease); @@ -1397,8 +1400,11 @@ resizemouse(const Arg *arg) { && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) + if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + if(c->isfullscreen) + setfullscreen(c, False); resize(c, c->x, c->y, nw, nh, True); + } break; } } while(ev.type != ButtonRelease); @@ -1744,6 +1750,8 @@ togglefloating(const Arg *arg) { if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, selmon->sel->w, selmon->sel->h, False); + else if(selmon->sel->isfullscreen) + setfullscreen(selmon->sel, False); arrange(selmon); } @@ -2020,7 +2028,6 @@ updatewindowtype(Client *c) { if(state == netatom[NetWMFullscreen]) setfullscreen(c, True); - if(wtype == netatom[NetWMWindowTypeDialog]) c->isfloating = True; } From c1128417a991258b2382a76ec4529b213ee15c91 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 25 Mar 2012 17:46:03 +0200 Subject: [PATCH 008/137] applied Andreas Amann's netwm_active_window patch, thx --- dwm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 10b0d0d..95571f6 100644 --- a/dwm.c +++ b/dwm.c @@ -499,6 +499,7 @@ cleanup(void) { cleanupmon(mons); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); } void @@ -858,8 +859,10 @@ focus(Client *c) { XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); setfocus(c); } - else + else { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } selmon->sel = c; drawbars(); } @@ -1527,8 +1530,12 @@ sendevent(Client *c, Atom proto) { void setfocus(Client *c) { - if(!c->neverfocus) + if(!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } sendevent(c, wmatom[WMTakeFocus]); } @@ -1786,8 +1793,10 @@ unfocus(Client *c, Bool setfocus) { return; grabbuttons(c, False); XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); - if(setfocus) + if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } } void From 3bfc43c3d01d710c4828d75a8a5a9b910ee90dff Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 25 Mar 2012 17:49:35 +0200 Subject: [PATCH 009/137] applied Andreas Amanns' netwm_client_list patch, but with some indentation fixes --- dwm.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 95571f6..9702063 100644 --- a/dwm.c +++ b/dwm.c @@ -60,7 +60,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -238,6 +238,7 @@ static void unmapnotify(XEvent *e); static Bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); +static void updateclientlist(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); @@ -1160,6 +1161,8 @@ manage(Window w, XWindowAttributes *wa) { XRaiseWindow(dpy, c->win); attach(c); attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); if (c->mon == selmon) @@ -1621,6 +1624,7 @@ setup(void) { netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); @@ -1643,6 +1647,7 @@ setup(void) { /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); /* select for events */ wa.cursor = cursor[CurNormal]; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask @@ -1820,6 +1825,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); + updateclientlist(); arrange(m); } @@ -1868,6 +1874,19 @@ updatebarpos(Monitor *m) { m->by = -bh; } +void +updateclientlist() { + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for(m = mons; m; m = m->next) + for(c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + Bool updategeom(void) { Bool dirty = False; From 90f3238301c85ffad459cb871d70ebea569ecbb3 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 15 Apr 2012 11:41:18 +0200 Subject: [PATCH 010/137] =?UTF-8?q?added=20kludge=20to=20fix=20some=20inpu?= =?UTF-8?q?t=20focus=20misbehavior=20in=20gedit=20and=20anjuta,=20thanks?= =?UTF-8?q?=20Martti=20K=C3=BChne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dwm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 9702063..90505b1 100644 --- a/dwm.c +++ b/dwm.c @@ -884,7 +884,8 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, True); + unfocus(selmon->sel, False); /* s/True/False/ fixes input focus issues + in gedit and anjuta */ selmon = m; focus(NULL); } From 820cbb3545e60e4d2bad120fb6e691c80058a98c Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 23 Jun 2012 09:06:00 +0200 Subject: [PATCH 011/137] reversed Andreas Amann's fullscreen fix with the approach proposed by Gary Langshaw: - idea is not supporting movemouse/resizemouse/togglefloating for fullscreen windows - as fullscreen windows are broken anyways, they should only be adjusted by their own means --- dwm.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/dwm.c b/dwm.c index 90505b1..685eb4a 100644 --- a/dwm.c +++ b/dwm.c @@ -575,8 +575,9 @@ configurenotify(XEvent *e) { XConfigureEvent *ev = &e->xconfigure; Bool dirty; + // TODO: updategeom handling sucks, needs to be simplified if(ev->window == root) { - dirty = (sw != ev->width); + dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; if(updategeom() || dirty) { @@ -1235,6 +1236,8 @@ movemouse(const Arg *arg) { if(!(c = selmon->sel)) return; + if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1268,11 +1271,8 @@ movemouse(const Arg *arg) { && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) { - if(c->isfullscreen) - setfullscreen(c, False); + if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, nx, ny, c->w, c->h, True); - } break; } } while(ev.type != ButtonRelease); @@ -1382,6 +1382,8 @@ resizemouse(const Arg *arg) { if(!(c = selmon->sel)) return; + if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1407,11 +1409,8 @@ resizemouse(const Arg *arg) { && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) { - if(c->isfullscreen) - setfullscreen(c, False); + if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, c->x, c->y, nw, nh, True); - } break; } } while(ev.type != ButtonRelease); @@ -1759,12 +1758,12 @@ void togglefloating(const Arg *arg) { if(!selmon->sel) return; + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, selmon->sel->w, selmon->sel->h, False); - else if(selmon->sel->isfullscreen) - setfullscreen(selmon->sel, False); arrange(selmon); } From 20f6917910306bcb5275d726b01b42a3b5e868b4 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 23 Jun 2012 10:12:46 +0200 Subject: [PATCH 012/137] drastically changed updategeom() handling, see comment in updategeom() for details --- config.mk | 2 +- dwm.c | 123 +++++++++++++++++++++++------------------------------- 2 files changed, 54 insertions(+), 71 deletions(-) diff --git a/config.mk b/config.mk index 7bb1c7c..35fd1e3 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.0-tip +VERSION = 6.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 685eb4a..1d79af6 100644 --- a/dwm.c +++ b/dwm.c @@ -235,7 +235,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c, Bool setfocus); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); -static Bool updategeom(void); +static void updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -573,23 +573,18 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - Bool dirty; - // TODO: updategeom handling sucks, needs to be simplified if(ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; - if(updategeom() || dirty) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); - updatebars(); - for(m = mons; m; m = m->next) - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - focus(NULL); - arrange(NULL); - } + if(dc.drawable != 0) + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + updatebars(); + for(m = mons; m; m = m->next) + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); + arrange(NULL); } } @@ -1076,8 +1071,8 @@ initfont(const char *fontstr) { static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) - if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) + /* treat origin (x, y) as fixpoint for uniqueness only, first screen wins */ + if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org) return False; return True; } @@ -1887,86 +1882,74 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -Bool +void updategeom(void) { - Bool dirty = False; + /* Starting with dwm 6.1 this function uses a new (simpler) strategy: + * whenever screen changes are reported, we destroy all monitors + * and recreate all unique origin monitors and add all clients to + * the first monitor, only. In several circumstances this may suck, + * but dealing with all corner-cases sucks even more.*/ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - int i, j, n, nn; + int i, j, n; Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + Monitor *m, *oldmons = mons; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n); XineramaScreenInfo *unique = NULL; - for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ - if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); - for(i = 0, j = 0; i < nn; i++) + if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * n))) + die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * n); + for(i = 0, j = 0; i < n; i++) if(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); - nn = j; - if(n <= nn) { - for(i = 0; i < (nn - n); i++) { /* new monitors available */ - for(m = mons; m && m->next; m = m->next); - if(m) - m->next = createmon(); - else - mons = createmon(); - } - for(i = 0, m = mons; i < nn && m; m = m->next, i++) - if(i >= n - || (unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh)) - { - dirty = True; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } + /* create new monitor structure */ + n = j; + mons = m = createmon(); /* new first monitor */ + for(i = 1; i < n; i++) { + m->next = createmon(); + m = m->next; } - else { /* less monitors available nn < n */ - for(i = nn; i < n; i++) { - for(m = mons; m && m->next; m = m->next); - while(m->clients) { - dirty = True; - c = m->clients; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if(m == selmon) - selmon = mons; - cleanupmon(m); - } + for(i = 0, m = mons; i < n && m; m = m->next, i++) { + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); } free(unique); + /* re-attach old clients and cleanup old monitor structure */ + while(oldmons) { + m = oldmons; + while(m->clients) { + c = m->clients; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + oldmons = m->next; + cleanupmon(m); + } } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) + if(!mons) /* only true if !XINERAMA compile flag */ mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = True; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - if(dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; + selmon = mons; + selmon = wintomon(root); } void From 606b44179dfeec8d31930488aa91c8d4808235a7 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 23 Jun 2012 20:12:49 +0200 Subject: [PATCH 013/137] applied James Turner's XkbKeycodeToKeysym patch, thanks --- dwm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 1d79af6..6b39519 100644 --- a/dwm.c +++ b/dwm.c @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -1085,7 +1086,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) From 940feed3146d6911c79a0a4469f6ede071a4773e Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 8 Jul 2012 09:43:11 +0200 Subject: [PATCH 014/137] reverted to old updategeom() after several complains, we need to optimize the old way --- config.mk | 2 +- dwm.c | 123 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 71 insertions(+), 54 deletions(-) diff --git a/config.mk b/config.mk index 35fd1e3..7bb1c7c 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.1 +VERSION = 6.0-tip # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 6b39519..45191e9 100644 --- a/dwm.c +++ b/dwm.c @@ -236,7 +236,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c, Bool setfocus); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); -static void updategeom(void); +static Bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -574,18 +574,23 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; + Bool dirty; + // TODO: updategeom handling sucks, needs to be simplified if(ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); - updatebars(); - for(m = mons; m; m = m->next) - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - focus(NULL); - arrange(NULL); + if(updategeom() || dirty) { + if(dc.drawable != 0) + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + updatebars(); + for(m = mons; m; m = m->next) + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); + arrange(NULL); + } } } @@ -1072,8 +1077,8 @@ initfont(const char *fontstr) { static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) - /* treat origin (x, y) as fixpoint for uniqueness only, first screen wins */ - if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org) + if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) return False; return True; } @@ -1883,74 +1888,86 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -void +Bool updategeom(void) { - /* Starting with dwm 6.1 this function uses a new (simpler) strategy: - * whenever screen changes are reported, we destroy all monitors - * and recreate all unique origin monitors and add all clients to - * the first monitor, only. In several circumstances this may suck, - * but dealing with all corner-cases sucks even more.*/ + Bool dirty = False; #ifdef XINERAMA if(XineramaIsActive(dpy)) { - int i, j, n; + int i, j, n, nn; Client *c; - Monitor *m, *oldmons = mons; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n); + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; + for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ - if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * n))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * n); - for(i = 0, j = 0; i < n; i++) + if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) + die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); + for(i = 0, j = 0; i < nn; i++) if(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); - /* create new monitor structure */ - n = j; - mons = m = createmon(); /* new first monitor */ - for(i = 1; i < n; i++) { - m->next = createmon(); - m = m->next; + nn = j; + if(n <= nn) { + for(i = 0; i < (nn - n); i++) { /* new monitors available */ + for(m = mons; m && m->next; m = m->next); + if(m) + m->next = createmon(); + else + mons = createmon(); + } + for(i = 0, m = mons; i < nn && m; m = m->next, i++) + if(i >= n + || (unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh)) + { + dirty = True; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } } - for(i = 0, m = mons; i < n && m; m = m->next, i++) { - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); + else { /* less monitors available nn < n */ + for(i = nn; i < n; i++) { + for(m = mons; m && m->next; m = m->next); + while(m->clients) { + dirty = True; + c = m->clients; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if(m == selmon) + selmon = mons; + cleanupmon(m); + } } free(unique); - /* re-attach old clients and cleanup old monitor structure */ - while(oldmons) { - m = oldmons; - while(m->clients) { - c = m->clients; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - oldmons = m->next; - cleanupmon(m); - } } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) /* only true if !XINERAMA compile flag */ + if(!mons) mons = createmon(); if(mons->mw != sw || mons->mh != sh) { + dirty = True; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - selmon = mons; - selmon = wintomon(root); + if(dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; } void From 1bdb393f81541506c9e7d8259855e30523b71238 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 8 Jul 2012 09:45:53 +0200 Subject: [PATCH 015/137] keep 6.1 intact --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 7bb1c7c..35fd1e3 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.0-tip +VERSION = 6.1 # Customize below to fit your system From fd3c19bd550e346d515c8e124c7fa55599a1aa22 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Fri, 2 Nov 2012 12:17:50 +0100 Subject: [PATCH 016/137] incorporating Xft instead of cairo, cairo provides far too many options --- config.def.h | 2 +- config.mk | 4 +-- dwm.c | 100 ++++++++++++++++++--------------------------------- 3 files changed, 38 insertions(+), 68 deletions(-) diff --git a/config.def.h b/config.def.h index 8fd5d4a..7fb4d82 100644 --- a/config.def.h +++ b/config.def.h @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; +static const char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=false"; static const char normbordercolor[] = "#444444"; static const char normbgcolor[] = "#222222"; static const char normfgcolor[] = "#bbbbbb"; diff --git a/config.mk b/config.mk index 35fd1e3..0a737ba 100644 --- a/config.mk +++ b/config.mk @@ -15,8 +15,8 @@ XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA # includes and libs -INCS = -I${X11INC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} +INCS = -I${X11INC} -I/usr/include/freetype2 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lutil -lXext -lXft -lfontconfig # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/dwm.c b/dwm.c index 45191e9..4986b07 100644 --- a/dwm.c +++ b/dwm.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -100,16 +102,15 @@ struct Client { typedef struct { int x, y, w, h; - unsigned long norm[ColLast]; - unsigned long sel[ColLast]; + XftColor norm[ColLast]; + XftColor sel[ColLast]; Drawable drawable; GC gc; struct { int ascent; int descent; int height; - XFontSet set; - XFontStruct *xfont; + XftFont *xfont; } font; } DC; /* draw context */ @@ -179,15 +180,15 @@ static void die(const char *errstr, ...); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); -static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); -static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); +static void drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]); +static void drawtext(const char *text, XftColor col[ColLast], Bool invert); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static unsigned long getcolor(const char *colstr); +static XftColor getcolor(const char *colstr); static Bool getrootptr(int *x, int *y); static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -487,10 +488,6 @@ cleanup(void) { for(m = mons; m; m = m->next) while(m->stack) unmanage(m->stack, False); - if(dc.font.set) - XFreeFontSet(dpy, dc.font.set); - else - XFreeFont(dpy, dc.font.xfont); XUngrabKey(dpy, AnyKey, AnyModifier, root); XFreePixmap(dpy, dc.drawable); XFreeGC(dpy, dc.gc); @@ -723,7 +720,7 @@ void drawbar(Monitor *m) { int x; unsigned int i, occ = 0, urg = 0; - unsigned long *col; + XftColor *col; Client *c; for(c = m->clients; c; c = c->next) { @@ -778,10 +775,10 @@ drawbars(void) { } void -drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { +drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]) { int x; - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); + XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG].pixel); x = (dc.font.ascent + dc.font.descent + 2) / 4; if(filled) XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1); @@ -790,11 +787,12 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { } void -drawtext(const char *text, unsigned long col[ColLast], Bool invert) { +drawtext(const char *text, XftColor col[ColLast], Bool invert) { char buf[256]; int i, x, y, h, len, olen; + XftDraw *d; - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); + XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG].pixel); XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); if(!text) return; @@ -809,11 +807,11 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { memcpy(buf, text, len); if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - if(dc.font.set) - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); - else - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); + + d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy,screen)); + + XftDrawStringUtf8(d, &col[invert ? ColBG : ColFG], dc.font.xfont, x, y, (XftChar8 *) buf, len); + XftDrawDestroy(d); } void @@ -859,7 +857,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); + XSetWindowBorder(dpy, c->win, dc.sel[ColBorder].pixel); setfocus(c); } else { @@ -933,14 +931,14 @@ getatomprop(Client *c, Atom prop) { return atom; } -unsigned long +XftColor getcolor(const char *colstr) { - Colormap cmap = DefaultColormap(dpy, screen); - XColor color; + XftColor color; - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) + if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), colstr, &color)) die("error, cannot allocate color '%s'\n", colstr); - return color.pixel; + + return color; } Bool @@ -1041,35 +1039,13 @@ incnmaster(const Arg *arg) { void initfont(const char *fontstr) { - char *def, **missing; - int n; - dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(dc.font.set) { - XFontStruct **xfonts; - char **font_names; + if(!(dc.font.xfont = XftFontOpenName(dpy,screen,fontstr)) + && !(dc.font.xfont = XftFontOpenName(dpy,screen,"fixed"))) + die("error, cannot load font: '%s'\n", fontstr); - dc.font.ascent = dc.font.descent = 0; - XExtentsOfFontSet(dc.font.set); - n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); - while(n--) { - dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); - dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); - xfonts++; - } - } - else { - if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) - && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) - die("error, cannot load font: '%s'\n", fontstr); - dc.font.ascent = dc.font.xfont->ascent; - dc.font.descent = dc.font.xfont->descent; - } + dc.font.ascent = dc.font.xfont->ascent; + dc.font.descent = dc.font.xfont->descent; dc.font.height = dc.font.ascent + dc.font.descent; } @@ -1151,7 +1127,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, dc.norm[ColBorder]); + XSetWindowBorder(dpy, w, dc.norm[ColBorder].pixel); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1640,8 +1616,6 @@ setup(void) { dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); dc.gc = XCreateGC(dpy, root, 0, NULL); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); /* init bars */ updatebars(); updatestatus(); @@ -1712,13 +1686,9 @@ tagmon(const Arg *arg) { int textnw(const char *text, unsigned int len) { - XRectangle r; - - if(dc.font.set) { - XmbTextExtents(dc.font.set, text, len, NULL, &r); - return r.width; - } - return XTextWidth(dc.font.xfont, text, len); + XGlyphInfo ext; + XftTextExtentsUtf8(dpy, dc.font.xfont, (XftChar8 *) text, len, &ext); + return ext.xOff; } void @@ -1798,7 +1768,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); + XSetWindowBorder(dpy, c->win, dc.norm[ColBorder].pixel); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); From 87adcd263b1fc75f7eb3172dac55ca641fd7a96a Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 17 Nov 2012 19:01:22 +0100 Subject: [PATCH 017/137] starting with initial draw.h --- draw.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dwm.c | 2 ++ 2 files changed, 78 insertions(+) create mode 100644 draw.h diff --git a/draw.h b/draw.h new file mode 100644 index 0000000..955067d --- /dev/null +++ b/draw.h @@ -0,0 +1,76 @@ +/* See LICENSE file for copyright and license details. */ + +/* X11 types - begin */ +struct _XDraw { + unsigned int w, h; + Display *dpy; + Drawable drawable; + GC gc; +}; +typedef struct _XDraw Draw; + +struct _XCol { + unsigned long rgb; +}; +typedef struct _XCol Col; + +struct _XFont { + int ascent; + int descent; + unsigned int h, w; + XFontSet set; + XFontStruct *xfont; +}; +typedef struct _XFont Fnt; +/* X11 types - end */ + +typedef struct { + Draw *draw; + Col *fg; + Col *bg; + Fnt *font; + Bool fill; +} DDC; + +typedef struct { + unsigned int w; + unsigned int h; + int x; + int y; + int xOff; + int yOff; +} TextExtents; + +/* Drawable abstraction */ +Draw *draw_create(Display *dpy, Window win, unsigned int w, unsigned int h); +void draw_resize(Draw *draw, unsigned int w, unsigned int h); +void draw_free(Draw *draw); + +/* Drawing context abstraction */ +DDC *dc_create(Draw *draw); +void dc_free(DDC *dc); + +/* Fnt abstraction */ +Fnt *font_create(const char *fontname); +void font_free(Fnt *font); + +/* Colour abstraction */ +Col *col_create(const char *colname); +void col_free(Col *col); + +/* Drawing context manipulation */ +void dc_setfont(DDC *dc, Fnt *font); +void dc_setfg(DDC *dc, Col col); +void dc_setbg(DDC *dc, Col col); +void dc_setfill(DDC *dc, Bool fill); + +/* Drawing functions */ +void dc_drawrect(DDC *dc, int x, int y, unsigned int w, unsigned int h); +void dc_drawtext(DDC *dc, int x, int y, const char *text); + +/* Map functions */ +void dc_map(DDC *dc, int x, int y, unsigned int w, unsigned int h); + +/* Text functions */ +void dc_getextents(DDC *dc, const char *text, TextExtents *extents); + diff --git a/dwm.c b/dwm.c index 4986b07..95b0a7e 100644 --- a/dwm.c +++ b/dwm.c @@ -43,6 +43,8 @@ #include #endif /* XINERAMA */ +#include "draw.h" + /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) From 344f35f9f55b615e5d7c46f863578f1cc974cc54 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 17 Nov 2012 19:10:39 +0100 Subject: [PATCH 018/137] applied Neil Klopfstein's patch, slightly modified --- dwm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 95b0a7e..32b7b61 100644 --- a/dwm.c +++ b/dwm.c @@ -282,7 +282,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool running = True; +static Bool running = True, usexkb; static Cursor cursor[CurLast]; static Display *dpy; static DC dc; @@ -1069,7 +1069,10 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); + if(usexkb) { + keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); + else + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) @@ -1579,6 +1582,7 @@ setmfact(const Arg *arg) { void setup(void) { XSetWindowAttributes wa; + int dummy = 0, xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion; /* clean up any zombies immediately */ sigchld(0); @@ -1631,6 +1635,8 @@ setup(void) { |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); + /* init xkb */ + usexkb = XkbQueryExtension(dpy, &dummy, &dummy, &dummy, &xkb_major, &xkb_minor); grabkeys(); } From 31451c3ad36cac5275d9a67c24d45887a9810114 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 17 Nov 2012 19:12:10 +0100 Subject: [PATCH 019/137] compile fix --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 32b7b61..7bab478 100644 --- a/dwm.c +++ b/dwm.c @@ -1069,7 +1069,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - if(usexkb) { + if(usexkb) keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); else keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); @@ -1636,7 +1636,7 @@ setup(void) { XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); /* init xkb */ - usexkb = XkbQueryExtension(dpy, &dummy, &dummy, &dummy, &xkb_major, &xkb_minor); + usexkb = XkbQueryExtension(dpy, &dummy, &dummy, &dummy, &xkbmajor, &xkbminor); grabkeys(); } From 917e28163420b643e2d08b26dfba796d8d468d9b Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 17 Nov 2012 20:04:04 +0100 Subject: [PATCH 020/137] removed obsolete bugs from BUGS file --- BUGS | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/BUGS b/BUGS index fd1837f..6c9574a 100644 --- a/BUGS +++ b/BUGS @@ -20,31 +20,6 @@ Donald Allen reported this: starting emacs from dmenu in archlinux results in missing configure of emacs, but mod1-space or mod1-shift-space fix this problem. this problem is new and did not happen in 1.6 xorg servers -Starting emacs from xterm doesnt show this problem, he uses tag 8 for emacs - ---- - -2009/12/7 Alexandr Krylovskiy : -> Fullscreen mode with flash applications (youtube, for example) doesn't -> work properly neither in tiled nor in floating mode. -> Fullscreen window closes immediately after opening. - -This is a known bug (for some curiosity I received the same report via -privmail from 2 other people within one week, really strange). -The quick fix is commenting out the code in lines 817/818 in hg tip -dwm. I cannot confirm this has no side effects (I think it does) and I -will address this issue shortly with a real fix. - ---- - -SDL seems to not like non-reparenting WMs: - -> I would like to mention SDL problems, however SDL is not crucial to -> me anymore; people that really care about it should speak up and -> propose dwm / SDL patch or cooperation scheme in that matter. - -Patching SDL, bugging them? - --- voltaic reports this: From 61fe833a062b0e027ec48ed7c7adeb2ed63089d3 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 18 Nov 2012 10:56:54 +0100 Subject: [PATCH 021/137] reverting to plain X11 fonts in order to implement draw.c default --- config.def.h | 2 +- config.mk | 4 +-- dwm.c | 100 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/config.def.h b/config.def.h index 7fb4d82..8fd5d4a 100644 --- a/config.def.h +++ b/config.def.h @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=false"; +static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; static const char normbordercolor[] = "#444444"; static const char normbgcolor[] = "#222222"; static const char normfgcolor[] = "#bbbbbb"; diff --git a/config.mk b/config.mk index 0a737ba..35fd1e3 100644 --- a/config.mk +++ b/config.mk @@ -15,8 +15,8 @@ XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA # includes and libs -INCS = -I${X11INC} -I/usr/include/freetype2 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lutil -lXext -lXft -lfontconfig +INCS = -I${X11INC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/dwm.c b/dwm.c index 7bab478..6695ddf 100644 --- a/dwm.c +++ b/dwm.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -104,15 +102,16 @@ struct Client { typedef struct { int x, y, w, h; - XftColor norm[ColLast]; - XftColor sel[ColLast]; + unsigned long norm[ColLast]; + unsigned long sel[ColLast]; Drawable drawable; GC gc; struct { int ascent; int descent; int height; - XftFont *xfont; + XFontSet set; + XFontStruct *xfont; } font; } DC; /* draw context */ @@ -182,15 +181,15 @@ static void die(const char *errstr, ...); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); -static void drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]); -static void drawtext(const char *text, XftColor col[ColLast], Bool invert); +static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); +static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static XftColor getcolor(const char *colstr); +static unsigned long getcolor(const char *colstr); static Bool getrootptr(int *x, int *y); static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -490,6 +489,10 @@ cleanup(void) { for(m = mons; m; m = m->next) while(m->stack) unmanage(m->stack, False); + if(dc.font.set) + XFreeFontSet(dpy, dc.font.set); + else + XFreeFont(dpy, dc.font.xfont); XUngrabKey(dpy, AnyKey, AnyModifier, root); XFreePixmap(dpy, dc.drawable); XFreeGC(dpy, dc.gc); @@ -722,7 +725,7 @@ void drawbar(Monitor *m) { int x; unsigned int i, occ = 0, urg = 0; - XftColor *col; + unsigned long *col; Client *c; for(c = m->clients; c; c = c->next) { @@ -777,10 +780,10 @@ drawbars(void) { } void -drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]) { +drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG].pixel); + XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); x = (dc.font.ascent + dc.font.descent + 2) / 4; if(filled) XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1); @@ -789,12 +792,11 @@ drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]) { } void -drawtext(const char *text, XftColor col[ColLast], Bool invert) { +drawtext(const char *text, unsigned long col[ColLast], Bool invert) { char buf[256]; int i, x, y, h, len, olen; - XftDraw *d; - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG].pixel); + XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); if(!text) return; @@ -809,11 +811,11 @@ drawtext(const char *text, XftColor col[ColLast], Bool invert) { memcpy(buf, text, len); if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); - - d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy,screen)); - - XftDrawStringUtf8(d, &col[invert ? ColBG : ColFG], dc.font.xfont, x, y, (XftChar8 *) buf, len); - XftDrawDestroy(d); + XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); + if(dc.font.set) + XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); + else + XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); } void @@ -859,7 +861,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder].pixel); + XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); setfocus(c); } else { @@ -933,14 +935,14 @@ getatomprop(Client *c, Atom prop) { return atom; } -XftColor +unsigned long getcolor(const char *colstr) { - XftColor color; + Colormap cmap = DefaultColormap(dpy, screen); + XColor color; - if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), colstr, &color)) + if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) die("error, cannot allocate color '%s'\n", colstr); - - return color; + return color.pixel; } Bool @@ -1041,13 +1043,35 @@ incnmaster(const Arg *arg) { void initfont(const char *fontstr) { + char *def, **missing; + int n; - if(!(dc.font.xfont = XftFontOpenName(dpy,screen,fontstr)) - && !(dc.font.xfont = XftFontOpenName(dpy,screen,"fixed"))) - die("error, cannot load font: '%s'\n", fontstr); + dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); + if(missing) { + while(n--) + fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); + XFreeStringList(missing); + } + if(dc.font.set) { + XFontStruct **xfonts; + char **font_names; - dc.font.ascent = dc.font.xfont->ascent; - dc.font.descent = dc.font.xfont->descent; + dc.font.ascent = dc.font.descent = 0; + XExtentsOfFontSet(dc.font.set); + n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); + while(n--) { + dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); + dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); + xfonts++; + } + } + else { + if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) + && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) + die("error, cannot load font: '%s'\n", fontstr); + dc.font.ascent = dc.font.xfont->ascent; + dc.font.descent = dc.font.xfont->descent; + } dc.font.height = dc.font.ascent + dc.font.descent; } @@ -1132,7 +1156,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, dc.norm[ColBorder].pixel); + XSetWindowBorder(dpy, w, dc.norm[ColBorder]); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1622,6 +1646,8 @@ setup(void) { dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); dc.gc = XCreateGC(dpy, root, 0, NULL); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); + if(!dc.font.set) + XSetFont(dpy, dc.gc, dc.font.xfont->fid); /* init bars */ updatebars(); updatestatus(); @@ -1694,9 +1720,13 @@ tagmon(const Arg *arg) { int textnw(const char *text, unsigned int len) { - XGlyphInfo ext; - XftTextExtentsUtf8(dpy, dc.font.xfont, (XftChar8 *) text, len, &ext); - return ext.xOff; + XRectangle r; + + if(dc.font.set) { + XmbTextExtents(dc.font.set, text, len, NULL, &r); + return r.width; + } + return XTextWidth(dc.font.xfont, text, len); } void @@ -1776,7 +1806,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, dc.norm[ColBorder].pixel); + XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); From d456617f0eb93df0ec8eb81ff6e04ca988c09c60 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 18 Nov 2012 12:04:29 +0100 Subject: [PATCH 022/137] basic draw.c structure --- Makefile | 2 +- draw.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ draw.h | 14 ++++-- 3 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 draw.c diff --git a/Makefile b/Makefile index b139b54..ce6e508 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = dwm.c +SRC = draw.c dwm.c OBJ = ${SRC:.c=.o} all: options dwm diff --git a/draw.c b/draw.c new file mode 100644 index 0000000..04e7f0d --- /dev/null +++ b/draw.c @@ -0,0 +1,139 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "draw.h" + +Draw * +draw_create(Display *dpy, Window win, unsigned int w, unsigned int h) { + Draw *draw = (Draw *)calloc(1, sizeof(Draw)); + draw->w = w; + draw->h = h; + /* TODO: drawable creation */ + /* TODO: gc allocation */ + return draw; +} + +void +draw_resize(Draw *draw, unsigned int w, unsigned int h) { + if(!draw) + return; + draw->w = w; + draw->h = h; + /* TODO: resize drawable */ +} + +void +draw_free(Draw *draw) { + /* TODO: deallocate DDCs */ + /* TODO: deallocate drawable */ + free(draw); +} + +DDC * +dc_create(Draw *draw) { + DDC *dc = (DDC *)calloc(1, sizeof(DDC)); + dc->draw = draw; + dc->next = draw->dc; + draw->dc = dc; + return dc; +} + +void +dc_free(DDC *dc) { + DDC **tdc; + + if(!dc) + return; + /* remove from dc list */ + for(tdc = &dc->draw->dc; *tdc && *tdc != dc; tdc = &(*tdc)->next); + *tdc = dc->next; + /* TODO: deallocate any resources of this dc, if needed */ + free(dc); +} + +Fnt * +font_create(const char *fontname) { + Fnt *font = (Fnt *)calloc(1, sizeof(Fnt)); + /* TODO: allocate actual font */ + return font; +} + +void +font_free(Fnt *font) { + if(!font) + return; + /* TODO: deallocate any font resources */ + free(font); +} + +Col * +col_create(const char *colname) { + Col *col = (Col *)calloc(1, sizeof(Col)); + /* TODO: allocate color */ + return col; +} + +void +col_free(Col *col) { + if(!col) + return; + /* TODO: deallocate any color resource */ + free(col); +} + +void +dc_setfont(DDC *dc, Fnt *font) { + if(!dc || !font) + return; + dc->font = font; +} + +void +dc_setfg(DDC *dc, Col *col) { + if(!dc || !col) + return; + dc->fg = col; +} + +void +dc_setbg(DDC *dc, Col *col) { + if(!dc || !col) + return; + dc->bg = col; +} + +void +dc_setfill(DDC *dc, Bool fill) { + if(!dc) + return; + dc->fill = fill; +} + +void +dc_drawrect(DDC *dc, int x, int y, unsigned int w, unsigned int h) { + if(!dc) + return; + /* TODO: draw the rectangle */ +} + +void +dc_drawtext(DDC *dc, int x, int y, const char *text) { + if(!dc) + return; + /* TODO: draw the text */ +} + +void +dc_map(DDC *dc, int x, int y, unsigned int w, unsigned int h) { + if(!dc) + return; + /* TODO: map the dc contents in the region */ +} + +void +dc_getextents(DDC *dc, const char *text, TextExtents *extents) { + if(!dc || !extents) + return; + /* TODO: get extents */ +} diff --git a/draw.h b/draw.h index 955067d..9aec43d 100644 --- a/draw.h +++ b/draw.h @@ -1,13 +1,16 @@ /* See LICENSE file for copyright and license details. */ +typedef struct _DDC DDC; + /* X11 types - begin */ +typedef struct _XDraw Draw; struct _XDraw { unsigned int w, h; Display *dpy; Drawable drawable; GC gc; + DDC *dc; }; -typedef struct _XDraw Draw; struct _XCol { unsigned long rgb; @@ -24,13 +27,14 @@ struct _XFont { typedef struct _XFont Fnt; /* X11 types - end */ -typedef struct { +struct _DDC { Draw *draw; Col *fg; Col *bg; Fnt *font; Bool fill; -} DDC; + DDC *next; +}; typedef struct { unsigned int w; @@ -60,8 +64,8 @@ void col_free(Col *col); /* Drawing context manipulation */ void dc_setfont(DDC *dc, Fnt *font); -void dc_setfg(DDC *dc, Col col); -void dc_setbg(DDC *dc, Col col); +void dc_setfg(DDC *dc, Col *col); +void dc_setbg(DDC *dc, Col *col); void dc_setfill(DDC *dc, Bool fill); /* Drawing functions */ From 3aabc08ede9c6496720124be8ee34c8b39735239 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 18 Nov 2012 16:39:56 +0100 Subject: [PATCH 023/137] reverting the xkb dependency, I don't care if this function is deprecated, it seems it breaks other stuff instead. --- dwm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index 6695ddf..8b67cea 100644 --- a/dwm.c +++ b/dwm.c @@ -36,7 +36,6 @@ #include #include #include -#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -281,7 +280,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool running = True, usexkb; +static Bool running = True; static Cursor cursor[CurLast]; static Display *dpy; static DC dc; @@ -1093,10 +1092,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - if(usexkb) - keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); - else - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) @@ -1606,7 +1602,6 @@ setmfact(const Arg *arg) { void setup(void) { XSetWindowAttributes wa; - int dummy = 0, xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion; /* clean up any zombies immediately */ sigchld(0); @@ -1661,8 +1656,6 @@ setup(void) { |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); - /* init xkb */ - usexkb = XkbQueryExtension(dpy, &dummy, &dummy, &dummy, &xkbmajor, &xkbminor); grabkeys(); } From 0a673ad7a37f3a1bdda7cef316bda300f8f181eb Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 18 Nov 2012 17:26:12 +0100 Subject: [PATCH 024/137] continued, distinction of Draw and DDC is bad, needs to be merged --- draw.c | 17 +++++++++++------ draw.h | 4 +++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/draw.c b/draw.c index 04e7f0d..df5aeec 100644 --- a/draw.c +++ b/draw.c @@ -5,12 +5,16 @@ #include "draw.h" Draw * -draw_create(Display *dpy, Window win, unsigned int w, unsigned int h) { +draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { Draw *draw = (Draw *)calloc(1, sizeof(Draw)); + draw->dpy = dpy; + draw->screen = screen; + draw->win = win; draw->w = w; draw->h = h; - /* TODO: drawable creation */ - /* TODO: gc allocation */ + draw->drawable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen)); + draw->gc = XCreateGC(dpy, win, 0, NULL); + XSetLineAttributes(dpy, draw->gc, 1, LineSolid, CapButt, JoinMiter); return draw; } @@ -20,13 +24,14 @@ draw_resize(Draw *draw, unsigned int w, unsigned int h) { return; draw->w = w; draw->h = h; - /* TODO: resize drawable */ + XFreePixmap(draw->dpy, draw->drawable); + draw->drawable = XCreatePixmap(draw->dpy, draw->win, w, h, DefaultDepth(draw->dpy, draw->screen)); } void draw_free(Draw *draw) { - /* TODO: deallocate DDCs */ - /* TODO: deallocate drawable */ + XFreePixmap(draw->dpy, draw->drawable); + XFreeGC(draw->dpy, draw->gc); free(draw); } diff --git a/draw.h b/draw.h index 9aec43d..95242ea 100644 --- a/draw.h +++ b/draw.h @@ -7,6 +7,8 @@ typedef struct _XDraw Draw; struct _XDraw { unsigned int w, h; Display *dpy; + int screen; + Window win; Drawable drawable; GC gc; DDC *dc; @@ -46,7 +48,7 @@ typedef struct { } TextExtents; /* Drawable abstraction */ -Draw *draw_create(Display *dpy, Window win, unsigned int w, unsigned int h); +Draw *draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); void draw_resize(Draw *draw, unsigned int w, unsigned int h); void draw_free(Draw *draw); From c0ba635c50dc53f06e4fc96392415b3d19b25826 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sun, 18 Nov 2012 17:52:42 +0100 Subject: [PATCH 025/137] removed DDC, all is Draw-dependent --- draw.c | 65 ++++++++++++++++------------------------------------------ draw.h | 57 ++++++++++++++++++++------------------------------ 2 files changed, 40 insertions(+), 82 deletions(-) diff --git a/draw.c b/draw.c index df5aeec..01436ea 100644 --- a/draw.c +++ b/draw.c @@ -35,28 +35,6 @@ draw_free(Draw *draw) { free(draw); } -DDC * -dc_create(Draw *draw) { - DDC *dc = (DDC *)calloc(1, sizeof(DDC)); - dc->draw = draw; - dc->next = draw->dc; - draw->dc = dc; - return dc; -} - -void -dc_free(DDC *dc) { - DDC **tdc; - - if(!dc) - return; - /* remove from dc list */ - for(tdc = &dc->draw->dc; *tdc && *tdc != dc; tdc = &(*tdc)->next); - *tdc = dc->next; - /* TODO: deallocate any resources of this dc, if needed */ - free(dc); -} - Fnt * font_create(const char *fontname) { Fnt *font = (Fnt *)calloc(1, sizeof(Fnt)); @@ -88,57 +66,50 @@ col_free(Col *col) { } void -dc_setfont(DDC *dc, Fnt *font) { - if(!dc || !font) +draw_setfont(Draw *draw, Fnt *font) { + if(!draw || !font) return; - dc->font = font; + draw->font = font; } void -dc_setfg(DDC *dc, Col *col) { - if(!dc || !col) +draw_setfg(Draw *draw, Col *col) { + if(!draw || !col) return; - dc->fg = col; + draw->fg = col; } void -dc_setbg(DDC *dc, Col *col) { - if(!dc || !col) +draw_setbg(Draw *draw, Col *col) { + if(!draw || !col) return; - dc->bg = col; + draw->bg = col; } void -dc_setfill(DDC *dc, Bool fill) { - if(!dc) - return; - dc->fill = fill; -} - -void -dc_drawrect(DDC *dc, int x, int y, unsigned int w, unsigned int h) { - if(!dc) +draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h) { + if(!draw) return; /* TODO: draw the rectangle */ } void -dc_drawtext(DDC *dc, int x, int y, const char *text) { - if(!dc) +draw_text(Draw *draw, int x, int y, const char *text) { + if(!draw) return; /* TODO: draw the text */ } void -dc_map(DDC *dc, int x, int y, unsigned int w, unsigned int h) { - if(!dc) +draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h) { + if(!draw) return; - /* TODO: map the dc contents in the region */ + /* TODO: map the draw contents in the region */ } void -dc_getextents(DDC *dc, const char *text, TextExtents *extents) { - if(!dc || !extents) +draw_getextents(Draw *draw, const char *text, TextExtents *extents) { + if(!draw || !extents) return; /* TODO: get extents */ } diff --git a/draw.h b/draw.h index 95242ea..d1a2f37 100644 --- a/draw.h +++ b/draw.h @@ -1,19 +1,5 @@ /* See LICENSE file for copyright and license details. */ -typedef struct _DDC DDC; - -/* X11 types - begin */ -typedef struct _XDraw Draw; -struct _XDraw { - unsigned int w, h; - Display *dpy; - int screen; - Window win; - Drawable drawable; - GC gc; - DDC *dc; -}; - struct _XCol { unsigned long rgb; }; @@ -29,15 +15,6 @@ struct _XFont { typedef struct _XFont Fnt; /* X11 types - end */ -struct _DDC { - Draw *draw; - Col *fg; - Col *bg; - Fnt *font; - Bool fill; - DDC *next; -}; - typedef struct { unsigned int w; unsigned int h; @@ -47,15 +24,26 @@ typedef struct { int yOff; } TextExtents; + +/* X11 types - begin */ +typedef struct _XDraw Draw; +struct _XDraw { + unsigned int w, h; + Display *dpy; + int screen; + Window win; + Drawable drawable; + GC gc; + Col *fg; + Col *bg; + Fnt *font; +}; + /* Drawable abstraction */ Draw *draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); void draw_resize(Draw *draw, unsigned int w, unsigned int h); void draw_free(Draw *draw); -/* Drawing context abstraction */ -DDC *dc_create(Draw *draw); -void dc_free(DDC *dc); - /* Fnt abstraction */ Fnt *font_create(const char *fontname); void font_free(Fnt *font); @@ -65,18 +53,17 @@ Col *col_create(const char *colname); void col_free(Col *col); /* Drawing context manipulation */ -void dc_setfont(DDC *dc, Fnt *font); -void dc_setfg(DDC *dc, Col *col); -void dc_setbg(DDC *dc, Col *col); -void dc_setfill(DDC *dc, Bool fill); +void draw_setfont(Draw *draw, Fnt *font); +void draw_setfg(Draw *draw, Col *col); +void draw_setbg(Draw *draw, Col *col); /* Drawing functions */ -void dc_drawrect(DDC *dc, int x, int y, unsigned int w, unsigned int h); -void dc_drawtext(DDC *dc, int x, int y, const char *text); +void draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h); +void draw_text(Draw *draw, int x, int y, const char *text); /* Map functions */ -void dc_map(DDC *dc, int x, int y, unsigned int w, unsigned int h); +void draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h); /* Text functions */ -void dc_getextents(DDC *dc, const char *text, TextExtents *extents); +void draw_getextents(Draw *draw, const char *text, TextExtents *extents); From f21d46ea7def76221c4173f644eb2188ae9edbb1 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 8 Dec 2012 10:13:01 +0100 Subject: [PATCH 026/137] continued with draw.c abstraction, also started util.{h,c} implementation, that will be used by draw.c as well --- Makefile | 2 +- draw.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++---------- draw.h | 10 +++++----- dwm.c | 14 +------------ util.c | 17 ++++++++++++++++ util.h | 6 ++++++ 6 files changed, 80 insertions(+), 29 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile b/Makefile index ce6e508..b04b79c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = draw.c dwm.c +SRC = util.c draw.c dwm.c OBJ = ${SRC:.c=.o} all: options dwm diff --git a/draw.c b/draw.c index 01436ea..e88a70c 100644 --- a/draw.c +++ b/draw.c @@ -1,8 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include "draw.h" +#include "util.h" Draw * draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { @@ -36,32 +38,70 @@ draw_free(Draw *draw) { } Fnt * -font_create(const char *fontname) { - Fnt *font = (Fnt *)calloc(1, sizeof(Fnt)); - /* TODO: allocate actual font */ +draw_font_create(Draw *draw, const char *fontname) { + Fnt *font; + char *def, **missing; + int n; + + if(!draw) + return NULL; + font = (Fnt *)calloc(1, sizeof(Fnt)); + font->set = XCreateFontSet(draw->dpy, fontname, &missing, &n, &def); + if(missing) { + while(n--) + fprintf(stderr, "draw: missing fontset: %s\n", missing[n]); + XFreeStringList(missing); + } + if(font->set) { + XFontStruct **xfonts; + char **font_names; + + XExtentsOfFontSet(font->set); + n = XFontsOfFontSet(font->set, &xfonts, &font_names); + while(n--) { + font->ascent = MAX(font->ascent, (*xfonts)->ascent); + font->descent = MAX(font->descent,(*xfonts)->descent); + xfonts++; + } + } + else { + if(!(font->xfont = XLoadQueryFont(draw->dpy, fontname)) + && !(font->xfont = XLoadQueryFont(draw->dpy, "fixed"))) + die("error, cannot load font: '%s'\n", fontname); + font->ascent = font->xfont->ascent; + font->descent = font->xfont->descent; + } + font->h = font->ascent + font->descent; return font; } void -font_free(Fnt *font) { - if(!font) +draw_font_free(Draw *draw, Fnt *font) { + if(!draw || !font) return; - /* TODO: deallocate any font resources */ + if(font->set) + XFreeFontSet(draw->dpy, font->set); + else + XFreeFont(draw->dpy, font->xfont); free(font); } Col * -col_create(const char *colname) { +draw_col_create(Draw *draw, const char *colname) { Col *col = (Col *)calloc(1, sizeof(Col)); - /* TODO: allocate color */ + Colormap cmap = DefaultColormap(draw->dpy, draw->screen); + XColor color; + + if(!XAllocNamedColor(draw->dpy, cmap, colname, &color, &color)) + die("error, cannot allocate color '%s'\n", colname); + col->rgb = color.pixel; return col; } void -col_free(Col *col) { +draw_col_free(Draw *draw, Col *col) { if(!col) return; - /* TODO: deallocate any color resource */ free(col); } diff --git a/draw.h b/draw.h index d1a2f37..0c811ab 100644 --- a/draw.h +++ b/draw.h @@ -8,7 +8,7 @@ typedef struct _XCol Col; struct _XFont { int ascent; int descent; - unsigned int h, w; + unsigned int h; XFontSet set; XFontStruct *xfont; }; @@ -45,12 +45,12 @@ void draw_resize(Draw *draw, unsigned int w, unsigned int h); void draw_free(Draw *draw); /* Fnt abstraction */ -Fnt *font_create(const char *fontname); -void font_free(Fnt *font); +Fnt *draw_font_create(Draw *draw, const char *fontname); +void draw_font_free(Draw *draw, Fnt *font); /* Colour abstraction */ -Col *col_create(const char *colname); -void col_free(Col *col); +Col *draw_col_create(Draw *draw, const char *colname); +void draw_col_free(Draw *draw, Col *col); /* Drawing context manipulation */ void draw_setfont(Draw *draw, Fnt *font); diff --git a/dwm.c b/dwm.c index 8b67cea..d9443da 100644 --- a/dwm.c +++ b/dwm.c @@ -41,6 +41,7 @@ #endif /* XINERAMA */ #include "draw.h" +#include "util.h" /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) @@ -49,8 +50,6 @@ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) @@ -176,7 +175,6 @@ static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); -static void die(const char *errstr, ...); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); @@ -695,16 +693,6 @@ detachstack(Client *c) { } } -void -die(const char *errstr, ...) { - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - Monitor * dirtomon(int dir) { Monitor *m = NULL; diff --git a/util.c b/util.c new file mode 100644 index 0000000..51acd1a --- /dev/null +++ b/util.c @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "util.h" + +void +die(const char *errstr, ...) { + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + diff --git a/util.h b/util.h new file mode 100644 index 0000000..033700c --- /dev/null +++ b/util.h @@ -0,0 +1,6 @@ +/* See LICENSE file for copyright and license details. */ + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +void die(const char *errstr, ...); From aafeaf731701e528f4ae9d7c7432b3e92fee4392 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 9 Dec 2012 19:11:11 +0100 Subject: [PATCH 027/137] continued with draw.c and draw.h implementation, now the integration begins --- draw.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++----------- draw.h | 25 ++++++++------------ 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/draw.c b/draw.c index e88a70c..fa340ff 100644 --- a/draw.c +++ b/draw.c @@ -1,6 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include #include +#include #include #include "draw.h" @@ -55,7 +56,6 @@ draw_font_create(Draw *draw, const char *fontname) { if(font->set) { XFontStruct **xfonts; char **font_names; - XExtentsOfFontSet(font->set); n = XFontsOfFontSet(font->set, &xfonts, &font_names); while(n--) { @@ -107,49 +107,96 @@ draw_col_free(Draw *draw, Col *col) { void draw_setfont(Draw *draw, Fnt *font) { - if(!draw || !font) + if(!draw) return; draw->font = font; } void draw_setfg(Draw *draw, Col *col) { - if(!draw || !col) + if(!draw) return; draw->fg = col; } void draw_setbg(Draw *draw, Col *col) { - if(!draw || !col) + if(!draw) return; draw->bg = col; } void -draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h) { - if(!draw) +draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) { + int dx; + + if(!draw || !draw->font || !draw->fg || !draw->bg) return; - /* TODO: draw the rectangle */ + XSetForeground(draw->dpy, draw->gc, invert ? draw->bg->rgb : draw->fg->rgb); + dx = (draw->font->ascent + draw->font->descent + 2) / 4; + if(filled) + XFillRectangle(draw->dpy, draw->drawable, draw->gc, x+1, y+1, dx+1, dx+1); + else if(empty) + XDrawRectangle(draw->dpy, draw->drawable, draw->gc, x+1, y+1, dx, dx); } void -draw_text(Draw *draw, int x, int y, const char *text) { - if(!draw) +draw_text(Draw *draw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) { + char buf[256]; + int i, tx, ty, len, olen; + TextExtents tex; + + if(!draw || !draw->fg || !draw->bg) return; - /* TODO: draw the text */ + XSetForeground(draw->dpy, draw->gc, invert ? draw->fg->rgb : draw->bg->rgb); + XFillRectangle(draw->dpy, draw->drawable, draw->gc, x, y, w, h); + if(!text || !draw->font) + return; + olen = strlen(text); + draw_getextents(draw, text, olen, &tex); + ty = y + (h / 2) - tex.yOff; + tx = x + tex.xOff; + /* shorten text if necessary */ + for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) + draw_getextents(draw, text, len, &tex); + if(!len) + return; + memcpy(buf, text, len); + if(len < olen) + for(i = len; i && i > len - 3; buf[--i] = '.'); + XSetForeground(draw->dpy, draw->gc, invert ? draw->bg->rgb : draw->fg->rgb); + if(draw->font->set) + XmbDrawString(draw->dpy, draw->drawable, draw->font->set, draw->gc, tx, ty, buf, len); + else + XDrawString(draw->dpy, draw->drawable, draw->gc, tx, ty, buf, len); } void draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h) { if(!draw) return; - /* TODO: map the draw contents in the region */ + XCopyArea(draw->dpy, draw->drawable, draw->win, draw->gc, x, y, w, h, x, y); + XSync(draw->dpy, False); } + void -draw_getextents(Draw *draw, const char *text, TextExtents *extents) { - if(!draw || !extents) +draw_getextents(Draw *draw, const char *text, unsigned int len, TextExtents *extents) { + XRectangle r; + + if(!draw || !draw->font || !text) return; - /* TODO: get extents */ + if(draw->font->set) { + XmbTextExtents(draw->font->set, text, len, NULL, &r); + extents->xOff = r.x; + extents->yOff = r.y; + extents->w = r.width; + extents->h = r.height; + } + else { + extents->h = draw->font->ascent + draw->font->descent; + extents->w = XTextWidth(draw->font->xfont, text, len); + extents->xOff = extents->h / 2; + extents->yOff = (extents->h / 2) + draw->font->ascent; + } } diff --git a/draw.h b/draw.h index 0c811ab..17d2c89 100644 --- a/draw.h +++ b/draw.h @@ -13,19 +13,7 @@ struct _XFont { XFontStruct *xfont; }; typedef struct _XFont Fnt; -/* X11 types - end */ -typedef struct { - unsigned int w; - unsigned int h; - int x; - int y; - int xOff; - int yOff; -} TextExtents; - - -/* X11 types - begin */ typedef struct _XDraw Draw; struct _XDraw { unsigned int w, h; @@ -39,6 +27,13 @@ struct _XDraw { Fnt *font; }; +typedef struct { + unsigned int w; + unsigned int h; + int xOff; + int yOff; +} TextExtents; + /* Drawable abstraction */ Draw *draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); void draw_resize(Draw *draw, unsigned int w, unsigned int h); @@ -58,12 +53,12 @@ void draw_setfg(Draw *draw, Col *col); void draw_setbg(Draw *draw, Col *col); /* Drawing functions */ -void draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h); -void draw_text(Draw *draw, int x, int y, const char *text); +void draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert); +void draw_text(Draw *draw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert); /* Map functions */ void draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h); /* Text functions */ -void draw_getextents(Draw *draw, const char *text, TextExtents *extents); +void draw_getextents(Draw *draw, const char *text, unsigned int len, TextExtents *extents); From f2544a331845ad80655c1f79c9dc61922fe3441c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 17 Apr 2013 21:21:47 +0200 Subject: [PATCH 028/137] renamed draw into drw --- Makefile | 2 +- draw.c | 202 ------------------------------------------------------- draw.h | 64 ------------------ drw.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ drw.h | 61 +++++++++++++++++ dwm.c | 2 +- 6 files changed, 265 insertions(+), 268 deletions(-) delete mode 100644 draw.c delete mode 100644 draw.h create mode 100644 drw.c create mode 100644 drw.h diff --git a/Makefile b/Makefile index b04b79c..fd07d59 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = util.c draw.c dwm.c +SRC = drw.c dwm.c util.c OBJ = ${SRC:.c=.o} all: options dwm diff --git a/draw.c b/draw.c deleted file mode 100644 index fa340ff..0000000 --- a/draw.c +++ /dev/null @@ -1,202 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "draw.h" -#include "util.h" - -Draw * -draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { - Draw *draw = (Draw *)calloc(1, sizeof(Draw)); - draw->dpy = dpy; - draw->screen = screen; - draw->win = win; - draw->w = w; - draw->h = h; - draw->drawable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen)); - draw->gc = XCreateGC(dpy, win, 0, NULL); - XSetLineAttributes(dpy, draw->gc, 1, LineSolid, CapButt, JoinMiter); - return draw; -} - -void -draw_resize(Draw *draw, unsigned int w, unsigned int h) { - if(!draw) - return; - draw->w = w; - draw->h = h; - XFreePixmap(draw->dpy, draw->drawable); - draw->drawable = XCreatePixmap(draw->dpy, draw->win, w, h, DefaultDepth(draw->dpy, draw->screen)); -} - -void -draw_free(Draw *draw) { - XFreePixmap(draw->dpy, draw->drawable); - XFreeGC(draw->dpy, draw->gc); - free(draw); -} - -Fnt * -draw_font_create(Draw *draw, const char *fontname) { - Fnt *font; - char *def, **missing; - int n; - - if(!draw) - return NULL; - font = (Fnt *)calloc(1, sizeof(Fnt)); - font->set = XCreateFontSet(draw->dpy, fontname, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "draw: missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(font->set) { - XFontStruct **xfonts; - char **font_names; - XExtentsOfFontSet(font->set); - n = XFontsOfFontSet(font->set, &xfonts, &font_names); - while(n--) { - font->ascent = MAX(font->ascent, (*xfonts)->ascent); - font->descent = MAX(font->descent,(*xfonts)->descent); - xfonts++; - } - } - else { - if(!(font->xfont = XLoadQueryFont(draw->dpy, fontname)) - && !(font->xfont = XLoadQueryFont(draw->dpy, "fixed"))) - die("error, cannot load font: '%s'\n", fontname); - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; - } - font->h = font->ascent + font->descent; - return font; -} - -void -draw_font_free(Draw *draw, Fnt *font) { - if(!draw || !font) - return; - if(font->set) - XFreeFontSet(draw->dpy, font->set); - else - XFreeFont(draw->dpy, font->xfont); - free(font); -} - -Col * -draw_col_create(Draw *draw, const char *colname) { - Col *col = (Col *)calloc(1, sizeof(Col)); - Colormap cmap = DefaultColormap(draw->dpy, draw->screen); - XColor color; - - if(!XAllocNamedColor(draw->dpy, cmap, colname, &color, &color)) - die("error, cannot allocate color '%s'\n", colname); - col->rgb = color.pixel; - return col; -} - -void -draw_col_free(Draw *draw, Col *col) { - if(!col) - return; - free(col); -} - -void -draw_setfont(Draw *draw, Fnt *font) { - if(!draw) - return; - draw->font = font; -} - -void -draw_setfg(Draw *draw, Col *col) { - if(!draw) - return; - draw->fg = col; -} - -void -draw_setbg(Draw *draw, Col *col) { - if(!draw) - return; - draw->bg = col; -} - -void -draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) { - int dx; - - if(!draw || !draw->font || !draw->fg || !draw->bg) - return; - XSetForeground(draw->dpy, draw->gc, invert ? draw->bg->rgb : draw->fg->rgb); - dx = (draw->font->ascent + draw->font->descent + 2) / 4; - if(filled) - XFillRectangle(draw->dpy, draw->drawable, draw->gc, x+1, y+1, dx+1, dx+1); - else if(empty) - XDrawRectangle(draw->dpy, draw->drawable, draw->gc, x+1, y+1, dx, dx); -} - -void -draw_text(Draw *draw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) { - char buf[256]; - int i, tx, ty, len, olen; - TextExtents tex; - - if(!draw || !draw->fg || !draw->bg) - return; - XSetForeground(draw->dpy, draw->gc, invert ? draw->fg->rgb : draw->bg->rgb); - XFillRectangle(draw->dpy, draw->drawable, draw->gc, x, y, w, h); - if(!text || !draw->font) - return; - olen = strlen(text); - draw_getextents(draw, text, olen, &tex); - ty = y + (h / 2) - tex.yOff; - tx = x + tex.xOff; - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) - draw_getextents(draw, text, len, &tex); - if(!len) - return; - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(draw->dpy, draw->gc, invert ? draw->bg->rgb : draw->fg->rgb); - if(draw->font->set) - XmbDrawString(draw->dpy, draw->drawable, draw->font->set, draw->gc, tx, ty, buf, len); - else - XDrawString(draw->dpy, draw->drawable, draw->gc, tx, ty, buf, len); -} - -void -draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h) { - if(!draw) - return; - XCopyArea(draw->dpy, draw->drawable, draw->win, draw->gc, x, y, w, h, x, y); - XSync(draw->dpy, False); -} - - -void -draw_getextents(Draw *draw, const char *text, unsigned int len, TextExtents *extents) { - XRectangle r; - - if(!draw || !draw->font || !text) - return; - if(draw->font->set) { - XmbTextExtents(draw->font->set, text, len, NULL, &r); - extents->xOff = r.x; - extents->yOff = r.y; - extents->w = r.width; - extents->h = r.height; - } - else { - extents->h = draw->font->ascent + draw->font->descent; - extents->w = XTextWidth(draw->font->xfont, text, len); - extents->xOff = extents->h / 2; - extents->yOff = (extents->h / 2) + draw->font->ascent; - } -} diff --git a/draw.h b/draw.h deleted file mode 100644 index 17d2c89..0000000 --- a/draw.h +++ /dev/null @@ -1,64 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -struct _XCol { - unsigned long rgb; -}; -typedef struct _XCol Col; - -struct _XFont { - int ascent; - int descent; - unsigned int h; - XFontSet set; - XFontStruct *xfont; -}; -typedef struct _XFont Fnt; - -typedef struct _XDraw Draw; -struct _XDraw { - unsigned int w, h; - Display *dpy; - int screen; - Window win; - Drawable drawable; - GC gc; - Col *fg; - Col *bg; - Fnt *font; -}; - -typedef struct { - unsigned int w; - unsigned int h; - int xOff; - int yOff; -} TextExtents; - -/* Drawable abstraction */ -Draw *draw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void draw_resize(Draw *draw, unsigned int w, unsigned int h); -void draw_free(Draw *draw); - -/* Fnt abstraction */ -Fnt *draw_font_create(Draw *draw, const char *fontname); -void draw_font_free(Draw *draw, Fnt *font); - -/* Colour abstraction */ -Col *draw_col_create(Draw *draw, const char *colname); -void draw_col_free(Draw *draw, Col *col); - -/* Drawing context manipulation */ -void draw_setfont(Draw *draw, Fnt *font); -void draw_setfg(Draw *draw, Col *col); -void draw_setbg(Draw *draw, Col *col); - -/* Drawing functions */ -void draw_rect(Draw *draw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert); -void draw_text(Draw *draw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert); - -/* Map functions */ -void draw_map(Draw *draw, int x, int y, unsigned int w, unsigned int h); - -/* Text functions */ -void draw_getextents(Draw *draw, const char *text, unsigned int len, TextExtents *extents); - diff --git a/drw.c b/drw.c new file mode 100644 index 0000000..65fd870 --- /dev/null +++ b/drw.c @@ -0,0 +1,202 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +Drw * +drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { + Drw *drw = (Drw *)calloc(1, sizeof(Drw)); + drw->dpy = dpy; + drw->screen = screen; + drw->win = win; + drw->w = w; + drw->h = h; + drw->drwable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, win, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) { + if(!drw) + return; + drw->w = w; + drw->h = h; + XFreePixmap(drw->dpy, drw->drwable); + drw->drwable = XCreatePixmap(drw->dpy, drw->win, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) { + XFreePixmap(drw->dpy, drw->drwable); + XFreeGC(drw->dpy, drw->gc); + free(drw); +} + +Fnt * +drw_font_create(Drw *drw, const char *fontname) { + Fnt *font; + char *def, **missing; + int n; + + if(!drw) + return NULL; + font = (Fnt *)calloc(1, sizeof(Fnt)); + font->set = XCreateFontSet(drw->dpy, fontname, &missing, &n, &def); + if(missing) { + while(n--) + fprintf(stderr, "drw: missing fontset: %s\n", missing[n]); + XFreeStringList(missing); + } + if(font->set) { + XFontStruct **xfonts; + char **font_names; + XExtentsOfFontSet(font->set); + n = XFontsOfFontSet(font->set, &xfonts, &font_names); + while(n--) { + font->ascent = MAX(font->ascent, (*xfonts)->ascent); + font->descent = MAX(font->descent,(*xfonts)->descent); + xfonts++; + } + } + else { + if(!(font->xfont = XLoadQueryFont(drw->dpy, fontname)) + && !(font->xfont = XLoadQueryFont(drw->dpy, "fixed"))) + die("error, cannot load font: '%s'\n", fontname); + font->ascent = font->xfont->ascent; + font->descent = font->xfont->descent; + } + font->h = font->ascent + font->descent; + return font; +} + +void +drw_font_free(Drw *drw, Fnt *font) { + if(!drw || !font) + return; + if(font->set) + XFreeFontSet(drw->dpy, font->set); + else + XFreeFont(drw->dpy, font->xfont); + free(font); +} + +Clr * +drw_clr_create(Drw *drw, const char *clrname) { + Clr *clr = (Clr *)calloc(1, sizeof(Clr)); + Colormap cmap = DefaultColormap(drw->dpy, drw->screen); + XColor color; + + if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) + die("error, cannot allocate color '%s'\n", clrname); + clr->rgb = color.pixel; + return clr; +} + +void +drw_clr_free(Drw *drw, Clr *clr) { + if(!clr) + return; + free(clr); +} + +void +drw_setfont(Drw *drw, Fnt *font) { + if(!drw) + return; + drw->font = font; +} + +void +drw_setfg(Drw *drw, Clr *clr) { + if(!drw) + return; + drw->fg = clr; +} + +void +drw_setbg(Drw *drw, Clr *clr) { + if(!drw) + return; + drw->bg = clr; +} + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) { + int dx; + + if(!drw || !drw->font || !drw->fg || !drw->bg) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); + dx = (drw->font->ascent + drw->font->descent + 2) / 4; + if(filled) + XFillRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx+1, dx+1); + else if(empty) + XDrawRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx, dx); +} + +void +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) { + char buf[256]; + int i, tx, ty, len, olen; + Extnts tex; + + if(!drw || !drw->fg || !drw->bg) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->fg->rgb : drw->bg->rgb); + XFillRectangle(drw->dpy, drw->drwable, drw->gc, x, y, w, h); + if(!text || !drw->font) + return; + olen = strlen(text); + drw_getexts(drw, text, olen, &tex); + ty = y + (h / 2) - tex.yOff; + tx = x + tex.xOff; + /* shorten text if necessary */ + for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) + drw_getexts(drw, text, len, &tex); + if(!len) + return; + memcpy(buf, text, len); + if(len < olen) + for(i = len; i && i > len - 3; buf[--i] = '.'); + XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); + if(drw->font->set) + XmbDrawString(drw->dpy, drw->drwable, drw->font->set, drw->gc, tx, ty, buf, len); + else + XDrawString(drw->dpy, drw->drwable, drw->gc, tx, ty, buf, len); +} + +void +drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h) { + if(!drw) + return; + XCopyArea(drw->dpy, drw->drwable, drw->win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + + +void +drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *tex) { + XRectangle r; + + if(!drw || !drw->font || !text) + return; + if(drw->font->set) { + XmbTextExtents(drw->font->set, text, len, NULL, &r); + tex->xOff = r.x; + tex->yOff = r.y; + tex->w = r.width; + tex->h = r.height; + } + else { + tex->h = drw->font->ascent + drw->font->descent; + tex->w = XTextWidth(drw->font->xfont, text, len); + tex->xOff = tex->h / 2; + tex->yOff = (tex->h / 2) + drw->font->ascent; + } +} diff --git a/drw.h b/drw.h new file mode 100644 index 0000000..819da85 --- /dev/null +++ b/drw.h @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ + +typedef struct { + unsigned long rgb; +} Clr; + +typedef struct { + int ascent; + int descent; + unsigned int h; + XFontSet set; + XFontStruct *xfont; +} Fnt; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window win; + Drawable drwable; + GC gc; + Clr *fg; + Clr *bg; + Fnt *font; +} Drw; + +typedef struct { + unsigned int w; + unsigned int h; + int xOff; + int yOff; +} Extnts; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_font_create(Drw *drw, const char *fontname); +void drw_font_free(Drw *drw, Fnt *font); + +/* Clrour abstraction */ +Clr *drw_clr_create(Drw *drw, const char *clrname); +void drw_clr_free(Drw *drw, Clr *clr); + +/* Drawing context manipulation */ +void drw_setfont(Drw *drw, Fnt *font); +void drw_setfg(Drw *drw, Clr *clr); +void drw_setbg(Drw *drw, Clr *clr); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert); +void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert); + +/* Map functions */ +void drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h); + +/* Text functions */ +void drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *extnts); + diff --git a/dwm.c b/dwm.c index d9443da..7941bd1 100644 --- a/dwm.c +++ b/dwm.c @@ -40,7 +40,7 @@ #include #endif /* XINERAMA */ -#include "draw.h" +#include "drw.h" #include "util.h" /* macros */ From 1479e76f01bf066c441e096ad3f9370b433ce552 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 1 May 2013 15:39:06 +0200 Subject: [PATCH 029/137] shut up about deprecated Xlib functions --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 35fd1e3..bc3d80e 100644 --- a/config.mk +++ b/config.mk @@ -21,7 +21,7 @@ LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = -s ${LIBS} # Solaris From 656882d76f330543b8ecddcf5158e6da575f9202 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 1 May 2013 15:41:44 +0200 Subject: [PATCH 030/137] use st as default terminal from now on --- config.def.h | 2 +- dwm.1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 8fd5d4a..2fde8bc 100644 --- a/config.def.h +++ b/config.def.h @@ -51,7 +51,7 @@ static const Layout layouts[] = { /* commands */ static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = { "uxterm", NULL }; +static const char *termcmd[] = { "st", NULL }; static Key keys[] = { /* modifier key function argument */ diff --git a/dwm.1 b/dwm.1 index 5268a06..7a0ee7c 100644 --- a/dwm.1 +++ b/dwm.1 @@ -57,7 +57,7 @@ click on a tag label adds/removes that tag to/from the focused window. .TP .B Mod1\-Shift\-Return Start -.BR uxterm (1). +.BR st(1). .TP .B Mod1\-, Focus previous screen, if any. From 68b400e95d2622265c26f8992205806eefe9be16 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 1 May 2013 15:45:32 +0200 Subject: [PATCH 031/137] added st to SEE ALSO section --- dwm.1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwm.1 b/dwm.1 index 7a0ee7c..6687011 100644 --- a/dwm.1 +++ b/dwm.1 @@ -150,7 +150,8 @@ Resize focused window while dragging. Tiled windows will be toggled to the float dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. .SH SEE ALSO -.BR dmenu (1) +.BR dmenu (1), +.BR st (1) .SH BUGS Java applications which use the XToolkit/XAWT backend may draw grey windows only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early From 7edc59631193813cf4d64030f8864de36b193cfc Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 2 May 2013 17:31:22 +0200 Subject: [PATCH 032/137] include font argument for st by default --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 2fde8bc..d300687 100644 --- a/config.def.h +++ b/config.def.h @@ -51,7 +51,7 @@ static const Layout layouts[] = { /* commands */ static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = { "st", NULL }; +static const char *termcmd[] = { "st", "-f", font, NULL }; static Key keys[] = { /* modifier key function argument */ From 5364697914fd4272fc1a6494b4fc522d2935427a Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 16 Jun 2013 15:20:29 +0200 Subject: [PATCH 033/137] finished libsl/drw integration --- drw.c | 150 ++++++++++++++++++++--------------- drw.h | 46 ++++++----- dwm.c | 251 ++++++++++++++++------------------------------------------ 3 files changed, 184 insertions(+), 263 deletions(-) diff --git a/drw.c b/drw.c index 65fd870..6e5801c 100644 --- a/drw.c +++ b/drw.c @@ -8,15 +8,17 @@ #include "util.h" Drw * -drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { Drw *drw = (Drw *)calloc(1, sizeof(Drw)); + if(!drw) + return NULL; drw->dpy = dpy; drw->screen = screen; - drw->win = win; + drw->root = root; drw->w = w; drw->h = h; - drw->drwable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, win, 0, NULL); + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, root, 0, NULL); XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; } @@ -27,27 +29,28 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) { return; drw->w = w; drw->h = h; - XFreePixmap(drw->dpy, drw->drwable); - drw->drwable = XCreatePixmap(drw->dpy, drw->win, w, h, DefaultDepth(drw->dpy, drw->screen)); + if(drw->drawable != 0) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); } void drw_free(Drw *drw) { - XFreePixmap(drw->dpy, drw->drwable); + XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); free(drw); } Fnt * -drw_font_create(Drw *drw, const char *fontname) { +drw_font_create(Display *dpy, const char *fontname) { Fnt *font; char *def, **missing; int n; - if(!drw) - return NULL; font = (Fnt *)calloc(1, sizeof(Fnt)); - font->set = XCreateFontSet(drw->dpy, fontname, &missing, &n, &def); + if(!font) + return NULL; + font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); if(missing) { while(n--) fprintf(stderr, "drw: missing fontset: %s\n", missing[n]); @@ -65,8 +68,8 @@ drw_font_create(Drw *drw, const char *fontname) { } } else { - if(!(font->xfont = XLoadQueryFont(drw->dpy, fontname)) - && !(font->xfont = XLoadQueryFont(drw->dpy, "fixed"))) + if(!(font->xfont = XLoadQueryFont(dpy, fontname)) + && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) die("error, cannot load font: '%s'\n", fontname); font->ascent = font->xfont->ascent; font->descent = font->xfont->descent; @@ -76,22 +79,28 @@ drw_font_create(Drw *drw, const char *fontname) { } void -drw_font_free(Drw *drw, Fnt *font) { - if(!drw || !font) +drw_font_free(Display *dpy, Fnt *font) { + if(!font) return; if(font->set) - XFreeFontSet(drw->dpy, font->set); + XFreeFontSet(dpy, font->set); else - XFreeFont(drw->dpy, font->xfont); + XFreeFont(dpy, font->xfont); free(font); } Clr * drw_clr_create(Drw *drw, const char *clrname) { - Clr *clr = (Clr *)calloc(1, sizeof(Clr)); - Colormap cmap = DefaultColormap(drw->dpy, drw->screen); + Clr *clr; + Colormap cmap; XColor color; + if(!drw) + return NULL; + clr = (Clr *)calloc(1, sizeof(Clr)); + if(!clr) + return NULL; + cmap = DefaultColormap(drw->dpy, drw->screen); if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) die("error, cannot allocate color '%s'\n", clrname); clr->rgb = color.pixel; @@ -99,7 +108,7 @@ drw_clr_create(Drw *drw, const char *clrname) { } void -drw_clr_free(Drw *drw, Clr *clr) { +drw_clr_free(Clr *clr) { if(!clr) return; free(clr); @@ -107,96 +116,113 @@ drw_clr_free(Drw *drw, Clr *clr) { void drw_setfont(Drw *drw, Fnt *font) { - if(!drw) - return; - drw->font = font; + if(drw) + drw->font = font; } void -drw_setfg(Drw *drw, Clr *clr) { - if(!drw) +drw_settheme(Drw *drw, Theme *theme) { + if(!drw || !theme) return; - drw->fg = clr; + drw->theme = theme; } void -drw_setbg(Drw *drw, Clr *clr) { - if(!drw) - return; - drw->bg = clr; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) { +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { int dx; - if(!drw || !drw->font || !drw->fg || !drw->bg) + if(!drw || !drw->font || !drw->theme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); dx = (drw->font->ascent + drw->font->descent + 2) / 4; if(filled) - XFillRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx+1, dx+1); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); else if(empty) - XDrawRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx, dx); + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx); } void -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) { +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { char buf[256]; - int i, tx, ty, len, olen; + int i, tx, ty, th, len, olen; Extnts tex; - if(!drw || !drw->fg || !drw->bg) + if(!drw || !drw->theme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->fg->rgb : drw->bg->rgb); - XFillRectangle(drw->dpy, drw->drwable, drw->gc, x, y, w, h); + XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->fg->rgb : drw->theme->bg->rgb); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); if(!text || !drw->font) return; olen = strlen(text); - drw_getexts(drw, text, olen, &tex); - ty = y + (h / 2) - tex.yOff; - tx = x + tex.xOff; + drw_font_getexts(drw->font, text, olen, &tex); + th = drw->font->ascent + drw->font->descent; + ty = y + (h / 2) - (th / 2) + drw->font->ascent; + tx = x + (h / 2); /* shorten text if necessary */ for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) - drw_getexts(drw, text, len, &tex); + drw_font_getexts(drw->font, text, len, &tex); if(!len) return; memcpy(buf, text, len); if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); if(drw->font->set) - XmbDrawString(drw->dpy, drw->drwable, drw->font->set, drw->gc, tx, ty, buf, len); + XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len); else - XDrawString(drw->dpy, drw->drwable, drw->gc, tx, ty, buf, len); + XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len); } void -drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h) { +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { if(!drw) return; - XCopyArea(drw->dpy, drw->drwable, drw->win, drw->gc, x, y, w, h, x, y); + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); XSync(drw->dpy, False); } void -drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *tex) { +drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { XRectangle r; - if(!drw || !drw->font || !text) + if(!font || !text) return; - if(drw->font->set) { - XmbTextExtents(drw->font->set, text, len, NULL, &r); - tex->xOff = r.x; - tex->yOff = r.y; + if(font->set) { + XmbTextExtents(font->set, text, len, NULL, &r); tex->w = r.width; tex->h = r.height; } else { - tex->h = drw->font->ascent + drw->font->descent; - tex->w = XTextWidth(drw->font->xfont, text, len); - tex->xOff = tex->h / 2; - tex->yOff = (tex->h / 2) + drw->font->ascent; + tex->h = font->ascent + font->descent; + tex->w = XTextWidth(font->xfont, text, len); } } + +unsigned int +drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) { + Extnts tex; + + if(!font) + return -1; + drw_font_getexts(font, text, len, &tex); + return tex.w; +} + +Cur * +drw_cur_create(Drw *drw, int shape) { + Cur *cur = (Cur *)calloc(1, sizeof(Cur)); + + if(!drw || !cur) + return NULL; + cur->cursor = XCreateFontCursor(drw->dpy, shape); + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) { + if(!drw || !cursor) + return; + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} diff --git a/drw.h b/drw.h index 819da85..764b9e3 100644 --- a/drw.h +++ b/drw.h @@ -4,6 +4,10 @@ typedef struct { unsigned long rgb; } Clr; +typedef struct { + Cursor cursor; +} Cur; + typedef struct { int ascent; int descent; @@ -12,23 +16,26 @@ typedef struct { XFontStruct *xfont; } Fnt; +typedef struct { + Clr *fg; + Clr *bg; + Clr *border; +} Theme; + typedef struct { unsigned int w, h; Display *dpy; int screen; - Window win; - Drawable drwable; + Window root; + Drawable drawable; GC gc; - Clr *fg; - Clr *bg; + Theme *theme; Fnt *font; } Drw; typedef struct { unsigned int w; unsigned int h; - int xOff; - int yOff; } Extnts; /* Drawable abstraction */ @@ -37,25 +44,26 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ -Fnt *drw_font_create(Drw *drw, const char *fontname); -void drw_font_free(Drw *drw, Fnt *font); +Fnt *drw_font_create(Display *dpy, const char *fontname); +void drw_font_free(Display *dpy, Fnt *font); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); +unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); -/* Clrour abstraction */ +/* Colour abstraction */ Clr *drw_clr_create(Drw *drw, const char *clrname); -void drw_clr_free(Drw *drw, Clr *clr); +void drw_clr_free(Clr *clr); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ void drw_setfont(Drw *drw, Fnt *font); -void drw_setfg(Drw *drw, Clr *clr); -void drw_setbg(Drw *drw, Clr *clr); +void drw_settheme(Drw *drw, Theme *theme); /* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert); -void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert); +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); +void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); /* Map functions */ -void drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h); - -/* Text functions */ -void drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *extnts); - +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/dwm.c b/dwm.c index 7941bd1..7ca1ace 100644 --- a/dwm.c +++ b/dwm.c @@ -54,7 +54,7 @@ #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) +#define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h) /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -98,21 +98,6 @@ struct Client { Window win; }; -typedef struct { - int x, y, w, h; - unsigned long norm[ColLast]; - unsigned long sel[ColLast]; - Drawable drawable; - GC gc; - struct { - int ascent; - int descent; - int height; - XFontSet set; - XFontStruct *xfont; - } font; -} DC; /* draw context */ - typedef struct { unsigned int mod; KeySym keysym; @@ -178,22 +163,18 @@ static void detachstack(Client *c); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); -static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); -static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static unsigned long getcolor(const char *colstr); static Bool getrootptr(int *x, int *y); static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, Bool focused); static void grabkeys(void); static void incnmaster(const Arg *arg); -static void initfont(const char *fontstr); static void keypress(XEvent *e); static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); @@ -226,7 +207,6 @@ static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); -static int textnw(const char *text, unsigned int len); static void tile(Monitor *); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); @@ -279,10 +259,13 @@ static void (*handler[LASTEvent]) (XEvent *) = { }; static Atom wmatom[WMLast], netatom[NetLast]; static Bool running = True; -static Cursor cursor[CurLast]; +static Cur *cursor[CurLast]; +static Theme thmnorm[ColLast]; +static Theme thmsel[ColLast]; static Display *dpy; -static DC dc; -static Monitor *mons = NULL, *selmon = NULL; +static Drw *drw; +static Fnt *fnt; +static Monitor *mons, *selmon; static Window root; /* configuration, allows nested code to access above variables */ @@ -486,18 +469,20 @@ cleanup(void) { for(m = mons; m; m = m->next) while(m->stack) unmanage(m->stack, False); - if(dc.font.set) - XFreeFontSet(dpy, dc.font.set); - else - XFreeFont(dpy, dc.font.xfont); XUngrabKey(dpy, AnyKey, AnyModifier, root); - XFreePixmap(dpy, dc.drawable); - XFreeGC(dpy, dc.gc); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); - XFreeCursor(dpy, cursor[CurMove]); while(mons) cleanupmon(mons); + drw_cur_free(drw, cursor[CurNormal]); + drw_cur_free(drw, cursor[CurResize]); + drw_cur_free(drw, cursor[CurMove]); + drw_font_free(dpy, fnt); + drw_clr_free(thmnorm->border); + drw_clr_free(thmnorm->bg); + drw_clr_free(thmnorm->fg); + drw_clr_free(thmsel->border); + drw_clr_free(thmsel->bg); + drw_clr_free(thmsel->fg); + drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -581,9 +566,7 @@ configurenotify(XEvent *e) { sw = ev->width; sh = ev->height; if(updategeom() || dirty) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + drw_resize(drw, sw, bh); updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); @@ -710,9 +693,8 @@ dirtomon(int dir) { void drawbar(Monitor *m) { - int x; + int x, xx, w; unsigned int i, occ = 0, urg = 0; - unsigned long *col; Client *c; for(c = m->clients; c; c = c->next) { @@ -720,42 +702,44 @@ drawbar(Monitor *m) { if(c->isurgent) urg |= c->tags; } - dc.x = 0; + x = 0; for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); - col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; - drawtext(tags[i], col, urg & 1 << i); - drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - occ & 1 << i, urg & 1 << i, col); - dc.x += dc.w; + w = TEXTW(tags[i]); + drw_settheme(drw, m->tagset[m->seltags] & 1 << i ? thmsel : thmnorm); + drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); + drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + occ & 1 << i, urg & 1 << i); + x += w; } - dc.w = blw = TEXTW(m->ltsymbol); - drawtext(m->ltsymbol, dc.norm, False); - dc.x += dc.w; - x = dc.x; + w = blw = TEXTW(m->ltsymbol); + drw_settheme(drw, thmnorm); + drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); + x += w; + xx = x; if(m == selmon) { /* status is only drawn on selected monitor */ - dc.w = TEXTW(stext); - dc.x = m->ww - dc.w; - if(dc.x < x) { - dc.x = x; - dc.w = m->ww - x; + w = TEXTW(stext); + x = m->ww - w; + if(x < xx) { + x = xx; + w = m->ww - xx; } - drawtext(stext, dc.norm, False); + drw_text(drw, x, 0, w, bh, stext, 0); } else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; + x = m->ww; + if((w = x - xx) > bh) { + x = xx; if(m->sel) { - col = m == selmon ? dc.sel : dc.norm; - drawtext(m->sel->name, col, False); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); + drw_settheme(drw, m == selmon ? thmsel : thmnorm); + drw_text(drw, x, 0, w, bh, m->sel->name, 0); + drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0); + } + else { + drw_settheme(drw, thmnorm); + drw_text(drw, x, 0, w, bh, NULL, 0); } - else - drawtext(NULL, dc.norm, False); } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); + drw_map(drw, m->barwin, 0, 0, m->ww, bh); } void @@ -766,45 +750,6 @@ drawbars(void) { drawbar(m); } -void -drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - int x; - - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - x = (dc.font.ascent + dc.font.descent + 2) / 4; - if(filled) - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1); - else if(empty) - XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); -} - -void -drawtext(const char *text, unsigned long col[ColLast], Bool invert) { - char buf[256]; - int i, x, y, h, len, olen; - - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); - if(!text) - return; - olen = strlen(text); - h = dc.font.ascent + dc.font.descent; - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; - x = dc.x + (h / 2); - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); - if(!len) - return; - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - if(dc.font.set) - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); - else - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); -} - void enternotify(XEvent *e) { Client *c; @@ -848,7 +793,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); + XSetWindowBorder(dpy, c->win, thmsel->border->rgb); setfocus(c); } else { @@ -922,16 +867,6 @@ getatomprop(Client *c, Atom prop) { return atom; } -unsigned long -getcolor(const char *colstr) { - Colormap cmap = DefaultColormap(dpy, screen); - XColor color; - - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) - die("error, cannot allocate color '%s'\n", colstr); - return color.pixel; -} - Bool getrootptr(int *x, int *y) { int di; @@ -1028,40 +963,6 @@ incnmaster(const Arg *arg) { arrange(selmon); } -void -initfont(const char *fontstr) { - char *def, **missing; - int n; - - dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(dc.font.set) { - XFontStruct **xfonts; - char **font_names; - - dc.font.ascent = dc.font.descent = 0; - XExtentsOfFontSet(dc.font.set); - n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); - while(n--) { - dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); - dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); - xfonts++; - } - } - else { - if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) - && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) - die("error, cannot load font: '%s'\n", fontstr); - dc.font.ascent = dc.font.xfont->ascent; - dc.font.descent = dc.font.xfont->descent; - } - dc.font.height = dc.font.ascent + dc.font.descent; -} - #ifdef XINERAMA static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { @@ -1140,7 +1041,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, dc.norm[ColBorder]); + XSetWindowBorder(dpy, w, thmnorm->border->rgb); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1232,7 +1133,7 @@ movemouse(const Arg *arg) { ocx = c->x; ocy = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove], CurrentTime) != GrabSuccess) + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; if(!getrootptr(&x, &y)) return; @@ -1378,7 +1279,7 @@ resizemouse(const Arg *arg) { ocx = c->x; ocy = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize], CurrentTime) != GrabSuccess) + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) return; XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); do { @@ -1597,10 +1498,12 @@ setup(void) { /* init screen */ screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); - initfont(font); + fnt = drw_font_create(dpy, font); sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); - bh = dc.h = dc.font.height + 2; + bh = fnt->h + 2; + drw = drw_create(dpy, screen, root, sw, sh); + drw_setfont(drw, fnt); updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1616,21 +1519,16 @@ setup(void) { netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); /* init cursors */ - cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - dc.norm[ColBorder] = getcolor(normbordercolor); - dc.norm[ColBG] = getcolor(normbgcolor); - dc.norm[ColFG] = getcolor(normfgcolor); - dc.sel[ColBorder] = getcolor(selbordercolor); - dc.sel[ColBG] = getcolor(selbgcolor); - dc.sel[ColFG] = getcolor(selfgcolor); - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); + thmnorm->border = drw_clr_create(drw, normbordercolor); + thmnorm->bg = drw_clr_create(drw, normbgcolor); + thmnorm->fg = drw_clr_create(drw, normfgcolor); + thmsel->border = drw_clr_create(drw, selbordercolor); + thmsel->bg = drw_clr_create(drw, selbgcolor); + thmsel->fg = drw_clr_create(drw, selfgcolor); /* init bars */ updatebars(); updatestatus(); @@ -1639,7 +1537,7 @@ setup(void) { PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); /* select for events */ - wa.cursor = cursor[CurNormal]; + wa.cursor = cursor[CurNormal]->cursor; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); @@ -1699,17 +1597,6 @@ tagmon(const Arg *arg) { sendmon(selmon->sel, dirtomon(arg->i)); } -int -textnw(const char *text, unsigned int len) { - XRectangle r; - - if(dc.font.set) { - XmbTextExtents(dc.font.set, text, len, NULL, &r); - return r.width; - } - return XTextWidth(dc.font.xfont, text, len); -} - void tile(Monitor *m) { unsigned int i, n, h, mw, my, ty; @@ -1787,7 +1674,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); + XSetWindowBorder(dpy, c->win, thmnorm->border->rgb); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -1846,7 +1733,7 @@ updatebars(void) { m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); } } From 33a74489f036600bb80a3c34fcdf10e5f9dafae1 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 19 Jun 2013 19:35:33 +0200 Subject: [PATCH 034/137] applied Julian's enum approach, however renamed theme into scheme resp. Theme into ClrScheme --- drw.c | 22 ++++++++++------------ drw.h | 6 +++--- dwm.c | 49 ++++++++++++++++++++++++------------------------- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/drw.c b/drw.c index 6e5801c..bc4ac41 100644 --- a/drw.c +++ b/drw.c @@ -109,9 +109,8 @@ drw_clr_create(Drw *drw, const char *clrname) { void drw_clr_free(Clr *clr) { - if(!clr) - return; - free(clr); + if(clr) + free(clr); } void @@ -121,19 +120,18 @@ drw_setfont(Drw *drw, Fnt *font) { } void -drw_settheme(Drw *drw, Theme *theme) { - if(!drw || !theme) - return; - drw->theme = theme; +drw_setscheme(Drw *drw, ClrScheme *scheme) { + if(drw && scheme) + drw->scheme = scheme; } void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { int dx; - if(!drw || !drw->font || !drw->theme) + if(!drw || !drw->font || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); dx = (drw->font->ascent + drw->font->descent + 2) / 4; if(filled) XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); @@ -147,9 +145,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex int i, tx, ty, th, len, olen; Extnts tex; - if(!drw || !drw->theme) + if(!drw || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->fg->rgb : drw->theme->bg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); if(!text || !drw->font) return; @@ -166,7 +164,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex memcpy(buf, text, len); if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); if(drw->font->set) XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len); else diff --git a/drw.h b/drw.h index 764b9e3..a5f34e0 100644 --- a/drw.h +++ b/drw.h @@ -20,7 +20,7 @@ typedef struct { Clr *fg; Clr *bg; Clr *border; -} Theme; +} ClrScheme; typedef struct { unsigned int w, h; @@ -29,7 +29,7 @@ typedef struct { Window root; Drawable drawable; GC gc; - Theme *theme; + ClrScheme *scheme; Fnt *font; } Drw; @@ -59,7 +59,7 @@ void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ void drw_setfont(Drw *drw, Fnt *font); -void drw_settheme(Drw *drw, Theme *theme); +void drw_setscheme(Drw *drw, ClrScheme *scheme); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); diff --git a/dwm.c b/dwm.c index 7ca1ace..314adf4 100644 --- a/dwm.c +++ b/dwm.c @@ -57,14 +57,14 @@ #define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h) /* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { int i; @@ -260,8 +260,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { static Atom wmatom[WMLast], netatom[NetLast]; static Bool running = True; static Cur *cursor[CurLast]; -static Theme thmnorm[ColLast]; -static Theme thmsel[ColLast]; +static ClrScheme scheme[SchemeLast]; static Display *dpy; static Drw *drw; static Fnt *fnt; @@ -476,12 +475,12 @@ cleanup(void) { drw_cur_free(drw, cursor[CurResize]); drw_cur_free(drw, cursor[CurMove]); drw_font_free(dpy, fnt); - drw_clr_free(thmnorm->border); - drw_clr_free(thmnorm->bg); - drw_clr_free(thmnorm->fg); - drw_clr_free(thmsel->border); - drw_clr_free(thmsel->bg); - drw_clr_free(thmsel->fg); + drw_clr_free(scheme[SchemeNorm].border); + drw_clr_free(scheme[SchemeNorm].bg); + drw_clr_free(scheme[SchemeNorm].fg); + drw_clr_free(scheme[SchemeSel].border); + drw_clr_free(scheme[SchemeSel].bg); + drw_clr_free(scheme[SchemeSel].fg); drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); @@ -705,14 +704,14 @@ drawbar(Monitor *m) { x = 0; for(i = 0; i < LENGTH(tags); i++) { w = TEXTW(tags[i]); - drw_settheme(drw, m->tagset[m->seltags] & 1 << i ? thmsel : thmnorm); + drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, urg & 1 << i); x += w; } w = blw = TEXTW(m->ltsymbol); - drw_settheme(drw, thmnorm); + drw_setscheme(drw, &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); x += w; xx = x; @@ -730,12 +729,12 @@ drawbar(Monitor *m) { if((w = x - xx) > bh) { x = xx; if(m->sel) { - drw_settheme(drw, m == selmon ? thmsel : thmnorm); + drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, m->sel->name, 0); drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0); } else { - drw_settheme(drw, thmnorm); + drw_setscheme(drw, &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, NULL, 0); } } @@ -793,7 +792,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, thmsel->border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb); setfocus(c); } else { @@ -1041,7 +1040,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, thmnorm->border->rgb); + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1523,12 +1522,12 @@ setup(void) { cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - thmnorm->border = drw_clr_create(drw, normbordercolor); - thmnorm->bg = drw_clr_create(drw, normbgcolor); - thmnorm->fg = drw_clr_create(drw, normfgcolor); - thmsel->border = drw_clr_create(drw, selbordercolor); - thmsel->bg = drw_clr_create(drw, selbgcolor); - thmsel->fg = drw_clr_create(drw, selfgcolor); + scheme[SchemeNorm].border = drw_clr_create(drw, normbordercolor); + scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor); + scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor); + scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor); + scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor); + scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor); /* init bars */ updatebars(); updatestatus(); @@ -1674,7 +1673,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, thmnorm->border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); From b800a1d1366c2ba22b7c934f7527de0b1542fe78 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 23 Jun 2013 21:53:09 +0200 Subject: [PATCH 035/137] applied Jochen's drw_text patch, thanks --- drw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drw.c b/drw.c index bc4ac41..b130405 100644 --- a/drw.c +++ b/drw.c @@ -157,7 +157,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex ty = y + (h / 2) - (th / 2) + drw->font->ascent; tx = x + (h / 2); /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) + for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--) drw_font_getexts(drw->font, text, len, &tex); if(!len) return; From 4fb31e08968c5058362021887fab4bbea746aecf Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 20 Jul 2013 09:08:46 +0200 Subject: [PATCH 036/137] do not take our font declaration as default for st --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index d300687..2fde8bc 100644 --- a/config.def.h +++ b/config.def.h @@ -51,7 +51,7 @@ static const Layout layouts[] = { /* commands */ static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = { "st", "-f", font, NULL }; +static const char *termcmd[] = { "st", NULL }; static Key keys[] = { /* modifier key function argument */ From 6af273771cb0e28e4394c78ab0322f77025a57f3 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 2 Aug 2013 22:40:20 +0200 Subject: [PATCH 037/137] =?UTF-8?q?applied=20improved=20version=20of=20Mar?= =?UTF-8?q?tti=20K=C3=BChne's=20dmenu/multi=20monitor=20approach=20from=20?= =?UTF-8?q?dwm,=20no=20dmenuspawn=20required?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.def.h | 3 ++- dwm.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 2fde8bc..875885b 100644 --- a/config.def.h +++ b/config.def.h @@ -50,7 +50,8 @@ static const Layout layouts[] = { #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ -static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; static const char *termcmd[] = { "st", NULL }; static Key keys[] = { diff --git a/dwm.c b/dwm.c index 314adf4..6f716e9 100644 --- a/dwm.c +++ b/dwm.c @@ -1569,6 +1569,8 @@ sigchld(int unused) { void spawn(const Arg *arg) { + if(arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; if(fork() == 0) { if(dpy) close(ConnectionNumber(dpy)); From cdec9782a1789bd5c3a84772fd59abb9da288597 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 27 Aug 2013 20:39:21 +0200 Subject: [PATCH 038/137] applied Lukas' focus suggestion at startup, thanks --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 6f716e9..1bbb4b3 100644 --- a/dwm.c +++ b/dwm.c @@ -1542,6 +1542,7 @@ setup(void) { XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); grabkeys(); + focus(NULL); } void From b468873b2b71d351ed7b5a4c75f62060999c46eb Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 29 May 2014 18:02:12 +0200 Subject: [PATCH 039/137] updated copyright notice in LICENSE file --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 2e53d0a..dc2326a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2012 Anselm R Garbe +© 2006-2014 Anselm R Garbe © 2007-2011 Peter Hartlich © 2010-2011 Connor Lane Smith © 2006-2009 Jukka Salmi From 18248ebf4b9465b837e717dcd14a5202a98248e0 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 29 May 2014 18:05:17 +0200 Subject: [PATCH 040/137] same as before with dwm.c as well --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 1bbb4b3..ffc8864 100644 --- a/dwm.c +++ b/dwm.c @@ -2046,7 +2046,7 @@ zoom(const Arg *arg) { int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2012 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2014 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) From 3d1090ba896319368c4771b88d325fcee368a608 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 11 Aug 2014 07:24:29 +0200 Subject: [PATCH 041/137] applied Hiltjo's resize/move limitation "Limit the amount of updates when resizing or moving a window in floating mode to 60 times per second. This makes resizing and moving alot smoother and by limiting it it also uses alot less resources on my machine. --- LICENSE | 1 + dwm.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index dc2326a..4fbb67e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT/X Consortium License © 2006-2014 Anselm R Garbe +© 2010-2014 Hiltjo Posthuma © 2007-2011 Peter Hartlich © 2010-2011 Connor Lane Smith © 2006-2009 Jukka Salmi diff --git a/dwm.c b/dwm.c index ffc8864..f896170 100644 --- a/dwm.c +++ b/dwm.c @@ -1123,6 +1123,7 @@ movemouse(const Arg *arg) { Client *c; Monitor *m; XEvent ev; + Time lasttime = 0; if(!(c = selmon->sel)) return; @@ -1145,6 +1146,10 @@ movemouse(const Arg *arg) { handler[ev.type](&ev); break; case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww @@ -1264,11 +1269,11 @@ resizeclient(Client *c, int x, int y, int w, int h) { void resizemouse(const Arg *arg) { - int ocx, ocy; - int nw, nh; + int ocx, ocy, nw, nh; Client *c; Monitor *m; XEvent ev; + Time lasttime = 0; if(!(c = selmon->sel)) return; @@ -1290,6 +1295,10 @@ resizemouse(const Arg *arg) { handler[ev.type](&ev); break; case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww From 35db6d8afc3fd9f80166feac6c1e4adf71d553c3 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 23 Nov 2014 15:25:35 +0100 Subject: [PATCH 042/137] removed .hgtags, thanks Dimitris for spotting --- .hgtags | 73 --------------------------------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 .hgtags diff --git a/.hgtags b/.hgtags deleted file mode 100644 index d48b951..0000000 --- a/.hgtags +++ /dev/null @@ -1,73 +0,0 @@ -d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1 -0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2 -7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3 -eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4 -22213b9a2114167ee8ba019a012e27da0422a61a 0.5 -c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6 -3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7 -cd15de32e173f8ce97bfe1c9b6607937b59056b4 0.8 -fae61afa861755636c4a1070694209ace8efbb6c 0.9 -bbc98e77ae89a7c9232a5be0835f60ea00d8036e 1.0 -44a55e6e46bf6c231780b09d919977d6f01083de 1.1 -e3179ce2b90451d2807cd53b589d768412b8666b 1.2 -f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3 -3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4 -728c9089b079721b43c3347124639a29baa22a97 1.5 -ad3fa2d185426c51fd5deceae809770363f8d33c 1.6 -4dbdb61c8b8ce21dee5c7050a6b103855964ed20 1.7 -d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 1.7.1 -c71952fa3c7ca848ec38a6923b5c6d0e18fff431 1.8 -a5567a0d30112822db2627a04a2e7aa3b6c38148 1.9 -12deea36603da407e3f32640048846a3bd74a9ec 2.0 -a2c465098a3b972bbed00feda9804b6aae1e9531 2.1 -7e92f58754ae6edb3225f26d754bd89c1ff458cf 2.2 -719b37b37b0df829d7cf017ac70e353088fe5849 2.3 -32b246925086910d63147483160281a91a47479f 2.4 -dcbbfabc8ecc5f33a6cc950584de87da1a368045 2.5 -c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1 -5308dd22b6ee8e3218c81d9e7e4125f235bb5778 2.6 -21951c0dfbae5af68ed77821a4d87253ee91803f 2.7 -107719a9ce3bd0c79f9f1f626596eb338a276561 2.8 -3a5910fac3ccb522a98aeeba7af7008530b25092 2.9 -76b58d21ea98257c05565a3b9c850b9b26a32968 3.0 -e1c8bef05e6e48df4f26471ea0712aa43ab9d949 3.1 -4ce65f61f01b055fa6c2901c6d2527ef741aa4bf 3.2 -f2cabc83a18f9b5b548159329ddd4dee904fa31f 3.2.1 -d3876aa792923f9a95f7ad0c7f0134533404df35 3.2.2 -0f91934037b04221ff5d1ba3a6c39c1ff26e3661 3.3 -9ede7b2d2450537e750d5505789fbe63960e97e6 3.4 -63ad05e7f9e1f4f1881fb02f529cb6c6ae81e693 3.5 -75b1b25fe0d7e29400baf30568153f668324928b 3.6 -20ec6976cee1fcfee0c2f354ae382ee3f9f68efa 3.6.1 -baee494346e520f8dee2cee9491b8350064770d2 3.7 -2ea201354cf016407ea93e1e390d1422940d29b0 3.8 -55478328b2422c700c5404a774c85e77322f41a3 3.9 -018c3846842291cb6c009dc087e7fe2f0ef53bea 4.0 -00f4180df72b49aadb2933804fde4bfb33e5666d 4.1 -c13cb8c6b7a56af74cc88346e71d2490470b546f 4.2 -e0ec0d5d8b1ef3ee04a83c7c0fee5853aa2ac6a6 4.3 -408014d2126153d2b0fce26a13ba707db222b7b9 4.4 -7c117df5d202530e85066d8b1ab02cef605c79ad 4.4.1 -2acc60d6dfe28c101a8cd44a8aa710a38ae3607c 4.5 -bcd7e18e196a00cc2e97ff3a4a58f3cdaba13856 4.6 -d6d3085307d8d98b8b012b669e858fd787befeb1 4.7 -607015ddb091d49cbd3457af41713691aa69f4d6 4.8 -22c669b2dd3673785c3476b9976da21e8783f745 4.9 -06eb9644e2dad7667d97495eb7d7bc62aa0429e8 5.0 -ce355cea9bb89e162f61913737a46908cdfa7e45 5.1 -e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2 -4004d61160355d869a7d2672561caad440751ba0 5.3 -335301ed102fec9b1a15d06bfa0184d53b38fa54 5.3.1 -8b7836a471f8f9ee61bec980df00971888d76343 5.4 -85a78d8afa0fe8b106a8223b5327e5bddb5dd5e3 5.4.1 -deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 -5550702215773aad462f22a774dced9b87437c51 5.6 -e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 -257403d4cd962cac03344a871ea56cc742bae38e 5.7 -48c3f87c335d6606e55fbae97267fa6b39ca56e0 5.7.1 -15761ac5e2f1e9010900f891616a24a22d82f128 5.7.2 -60ea8fed13ab750c6717f2764cbf9c13bb6f0d0a 5.8 -1ed1e75c9c2e395a2c475b52657a430bd95070c7 5.8.1 -a043f08008051ca02ae87eb170cd066d8c8315a0 5.8.2 -dd74622a4785e55658b05b36834fa0c41084a8c1 5.9 -ec4baab783145b2e9304f436795dc4b02abc5349 6.0 From 14343e69cc596b847f71f1e825d3019ab1a29aa8 Mon Sep 17 00:00:00 2001 From: Eric Pruitt Date: Thu, 5 Mar 2015 20:26:11 -0800 Subject: [PATCH 043/137] Add Xft and follback-fonts support to graphics lib --- config.def.h | 9 +- config.mk | 4 +- drw.c | 349 +++++++++++++++++++++++++++++++++++++++------------ drw.h | 19 +-- dwm.c | 20 +-- util.h | 1 + 6 files changed, 299 insertions(+), 103 deletions(-) diff --git a/config.def.h b/config.def.h index 875885b..eaae8f3 100644 --- a/config.def.h +++ b/config.def.h @@ -1,7 +1,12 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; +static const char *fonts[] = { + "Sans:size=10.5", + "VL Gothic:size=10.5", + "WenQuanYi Micro Hei:size=10.5", +}; +static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; static const char normbordercolor[] = "#444444"; static const char normbgcolor[] = "#222222"; static const char normfgcolor[] = "#bbbbbb"; @@ -51,7 +56,7 @@ static const Layout layouts[] = { /* commands */ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; static const char *termcmd[] = { "st", NULL }; static Key keys[] = { diff --git a/config.mk b/config.mk index bc3d80e..cf95913 100644 --- a/config.mk +++ b/config.mk @@ -15,8 +15,8 @@ XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA # includes and libs -INCS = -I${X11INC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} +INCS = -I${X11INC} -I/usr/include/freetype2 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/drw.c b/drw.c index b130405..eb3b3c3 100644 --- a/drw.c +++ b/drw.c @@ -3,10 +3,59 @@ #include #include #include +#include #include "drw.h" #include "util.h" +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +static long +utf8decodebyte(const char c, size_t *i) { + for(*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if(((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) { + if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for(i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) { + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if(!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if(!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for(i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if(type != 0) + return j; + } + if(j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + return len; +} + Drw * drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { Drw *drw = (Drw *)calloc(1, sizeof(Drw)); @@ -19,6 +68,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->h = h; drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); drw->gc = XCreateGC(dpy, root, 0, NULL); + drw->fontcount = 0; XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; } @@ -36,56 +86,88 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) { void drw_free(Drw *drw) { + size_t i; + for (i = 0; i < drw->fontcount; i++) { + drw_font_free(drw->fonts[i]); + } XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); free(drw); } -Fnt * -drw_font_create(Display *dpy, const char *fontname) { +/* This function is an implementation detail. Library users should use + * drw_font_create instead. + */ +static Fnt * +drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) { Fnt *font; - char *def, **missing; - int n; - font = (Fnt *)calloc(1, sizeof(Fnt)); - if(!font) + if (!(fontname || fontpattern)) + die("No font specified.\n"); + + if (!(font = (Fnt *)calloc(1, sizeof(Fnt)))) return NULL; - font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "drw: missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(font->set) { - XFontStruct **xfonts; - char **font_names; - XExtentsOfFontSet(font->set); - n = XFontsOfFontSet(font->set, &xfonts, &font_names); - while(n--) { - font->ascent = MAX(font->ascent, (*xfonts)->ascent); - font->descent = MAX(font->descent,(*xfonts)->descent); - xfonts++; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield same + * the same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in + * missing-character-rectangles being drawn, at least with some fonts. + */ + if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) || + !(font->pattern = FcNameParse((FcChar8 *) fontname))) { + if (font->xfont) { + XftFontClose(drw->dpy, font->xfont); + font->xfont = NULL; + } + fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + } + } else if (fontpattern) { + if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font pattern.\n"); + } else { + font->pattern = NULL; } } - else { - if(!(font->xfont = XLoadQueryFont(dpy, fontname)) - && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) - die("error, cannot load font: '%s'\n", fontname); - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; + + if (!font->xfont) { + free(font); + return NULL; } + + font->ascent = font->xfont->ascent; + font->descent = font->xfont->descent; font->h = font->ascent + font->descent; + font->dpy = drw->dpy; return font; } +Fnt* +drw_font_create(Drw *drw, const char *fontname) { + return drw_font_xcreate(drw, fontname, NULL); +} + void -drw_font_free(Display *dpy, Fnt *font) { +drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) { + size_t i; + Fnt *font; + for (i = 0; i < fontcount; i++) { + if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { + die("Font cache exhausted.\n"); + } else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) { + drw->fonts[drw->fontcount++] = font; + } + } +} + +void +drw_font_free(Fnt *font) { if(!font) return; - if(font->set) - XFreeFontSet(dpy, font->set); - else - XFreeFont(dpy, font->xfont); + if(font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); free(font); } @@ -93,7 +175,7 @@ Clr * drw_clr_create(Drw *drw, const char *clrname) { Clr *clr; Colormap cmap; - XColor color; + Visual *vis; if(!drw) return NULL; @@ -101,9 +183,10 @@ drw_clr_create(Drw *drw, const char *clrname) { if(!clr) return NULL; cmap = DefaultColormap(drw->dpy, drw->screen); - if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) + vis = DefaultVisual(drw->dpy, drw->screen); + if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb)) die("error, cannot allocate color '%s'\n", clrname); - clr->rgb = color.pixel; + clr->pix = clr->rgb.pixel; return clr; } @@ -113,15 +196,9 @@ drw_clr_free(Clr *clr) { free(clr); } -void -drw_setfont(Drw *drw, Fnt *font) { - if(drw) - drw->font = font; -} - void drw_setscheme(Drw *drw, ClrScheme *scheme) { - if(drw && scheme) + if(drw && scheme) drw->scheme = scheme; } @@ -129,46 +206,160 @@ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { int dx; - if(!drw || !drw->font || !drw->scheme) + if(!drw || !drw->fontcount || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); - dx = (drw->font->ascent + drw->font->descent + 2) / 4; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); + dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; if(filled) XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); else if(empty) XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx); } -void +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { - char buf[256]; - int i, tx, ty, th, len, olen; + char buf[1024]; + int tx, ty, th; Extnts tex; + Colormap cmap; + Visual *vis; + XftDraw *d; + Fnt *curfont, *nextfont; + size_t i, len; + int utf8strlen, utf8charlen, render; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; - if(!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - if(!text || !drw->font) - return; - olen = strlen(text); - drw_font_getexts(drw->font, text, olen, &tex); - th = drw->font->ascent + drw->font->descent; - ty = y + (h / 2) - (th / 2) + drw->font->ascent; - tx = x + (h / 2); - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--) - drw_font_getexts(drw->font, text, len, &tex); - if(!len) - return; - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); - if(drw->font->set) - XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len); - else - XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len); + if (!(render = x || y || w || h)) { + w = ~w; + } + + if (!drw || !drw->scheme) { + return 0; + } else if (render) { + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->pix : drw->scheme->bg->pix); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + } + + if (!text || !drw->fontcount) { + return 0; + } else if (render) { + cmap = DefaultColormap(drw->dpy, drw->screen); + vis = DefaultVisual(drw->dpy, drw->screen); + d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap); + } + + curfont = drw->fonts[0]; + while (1) { + utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (i = 0; i < drw->fontcount; i++) { + charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint); + if (charexists) { + if (drw->fonts[i] == curfont) { + utf8strlen += utf8charlen; + text += utf8charlen; + } else { + nextfont = drw->fonts[i]; + } + break; + } + } + + if (!charexists || (nextfont && nextfont != curfont)) { + break; + } else { + charexists = 0; + } + } + + if (utf8strlen) { + drw_font_getexts(curfont, utf8str, utf8strlen, &tex); + /* shorten text if necessary */ + for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) + drw_font_getexts(curfont, utf8str, len, &tex); + + if (len) { + memcpy(buf, utf8str, len); + buf[len] = '\0'; + if(len < utf8strlen) + for(i = len; i && i > len - 3; buf[--i] = '.'); + + if (render) { + th = curfont->ascent + curfont->descent; + ty = y + (h / 2) - (th / 2) + curfont->ascent; + tx = x + (h / 2); + XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len); + } + + x += tex.w; + w -= tex.w; + } + } + + if (!*text) { + break; + } else if (nextfont) { + charexists = 0; + curfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. + */ + charexists = 1; + + if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { + continue; + } + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts[0]->pattern) { + /* Refer to the comment in drw_font_xcreate for more + * information. + */ + die("The first font in the cache must be loaded from a font string.\n"); + } + + fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + curfont = drw_font_xcreate(drw, NULL, match); + if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { + drw->fonts[drw->fontcount++] = curfont; + } else { + if (curfont) { + drw_font_free(curfont); + } + curfont = drw->fonts[0]; + } + } + } + } + + if (render) { + XftDrawDestroy(d); + } + + return x; } void @@ -182,19 +373,13 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { - XRectangle r; + XGlyphInfo ext; if(!font || !text) return; - if(font->set) { - XmbTextExtents(font->set, text, len, NULL, &r); - tex->w = r.width; - tex->h = r.height; - } - else { - tex->h = font->ascent + font->descent; - tex->w = XTextWidth(font->xfont, text, len); - } + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + tex->h = font->h; + tex->w = ext.xOff; } unsigned int diff --git a/drw.h b/drw.h index a5f34e0..536171b 100644 --- a/drw.h +++ b/drw.h @@ -1,7 +1,9 @@ /* See LICENSE file for copyright and license details. */ +#define DRW_FONT_CACHE_SIZE 32 typedef struct { - unsigned long rgb; + unsigned long pix; + XftColor rgb; } Clr; typedef struct { @@ -9,11 +11,12 @@ typedef struct { } Cur; typedef struct { + Display *dpy; int ascent; int descent; unsigned int h; - XFontSet set; - XFontStruct *xfont; + XftFont *xfont; + FcPattern *pattern; } Fnt; typedef struct { @@ -30,7 +33,8 @@ typedef struct { Drawable drawable; GC gc; ClrScheme *scheme; - Fnt *font; + size_t fontcount; + Fnt *fonts[DRW_FONT_CACHE_SIZE]; } Drw; typedef struct { @@ -44,8 +48,9 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ -Fnt *drw_font_create(Display *dpy, const char *fontname); -void drw_font_free(Display *dpy, Fnt *font); +Fnt *drw_font_create(Drw *drw, const char *fontname); +void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount); +void drw_font_free(Fnt *font); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); @@ -63,7 +68,7 @@ void drw_setscheme(Drw *drw, ClrScheme *scheme); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); -void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); /* Map functions */ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/dwm.c b/dwm.c index f896170..169adcb 100644 --- a/dwm.c +++ b/dwm.c @@ -39,6 +39,7 @@ #ifdef XINERAMA #include #endif /* XINERAMA */ +#include #include "drw.h" #include "util.h" @@ -54,7 +55,7 @@ #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h) +#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -263,7 +264,6 @@ static Cur *cursor[CurLast]; static ClrScheme scheme[SchemeLast]; static Display *dpy; static Drw *drw; -static Fnt *fnt; static Monitor *mons, *selmon; static Window root; @@ -474,7 +474,6 @@ cleanup(void) { drw_cur_free(drw, cursor[CurNormal]); drw_cur_free(drw, cursor[CurResize]); drw_cur_free(drw, cursor[CurMove]); - drw_font_free(dpy, fnt); drw_clr_free(scheme[SchemeNorm].border); drw_clr_free(scheme[SchemeNorm].bg); drw_clr_free(scheme[SchemeNorm].fg); @@ -792,7 +791,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); } else { @@ -1040,7 +1039,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1505,13 +1504,14 @@ setup(void) { /* init screen */ screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - fnt = drw_font_create(dpy, font); sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); - bh = fnt->h + 2; + root = RootWindow(dpy, screen); drw = drw_create(dpy, screen, root, sw, sh); - drw_setfont(drw, fnt); + drw_load_fonts(drw, fonts, LENGTH(fonts)); + if (!drw->fontcount) + die("No fonts could be loaded.\n"); + bh = drw->fonts[0]->h + 2; updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1685,7 +1685,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); diff --git a/util.h b/util.h index 033700c..f7ce721 100644 --- a/util.h +++ b/util.h @@ -2,5 +2,6 @@ #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *errstr, ...); From 40529e1469b399114048185e1d5b7237b1cc7f3e Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:01:49 +0200 Subject: [PATCH 044/137] config.mk: add $FREETYPELIBS and $FREETYPEINC, simpler to override (ports and *BSDs) --- config.mk | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config.mk b/config.mk index cf95913..4eefb71 100644 --- a/config.mk +++ b/config.mk @@ -14,9 +14,15 @@ X11LIB = /usr/X11R6/lib XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = ${X11INC}/freetype2 + # includes and libs -INCS = -I${X11INC} -I/usr/include/freetype2 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft +INCS = -I${X11INC} -I${FREETYPEINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} From 7e1182ce555985ff2c5860d88403888eabc6ee4b Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:10:54 +0200 Subject: [PATCH 045/137] config.h: use common default font, pass Xft font name to dmenu dmenu uses Xft now (soon to be released). --- config.def.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index eaae8f3..3fde3cf 100644 --- a/config.def.h +++ b/config.def.h @@ -2,11 +2,9 @@ /* appearance */ static const char *fonts[] = { - "Sans:size=10.5", - "VL Gothic:size=10.5", - "WenQuanYi Micro Hei:size=10.5", + "monospace:size=10" }; -static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; +static const char dmenufont[] = "monospace:size=10"; static const char normbordercolor[] = "#444444"; static const char normbgcolor[] = "#222222"; static const char normfgcolor[] = "#bbbbbb"; From 4a4817b3aa84ac61d6071674d3bbc1af7f69cdb7 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:27:31 +0200 Subject: [PATCH 046/137] dwm: cleanup: free schemes and cursors as array --- dwm.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index 169adcb..f9e0c3d 100644 --- a/dwm.c +++ b/dwm.c @@ -462,6 +462,7 @@ cleanup(void) { Arg a = {.ui = ~0}; Layout foo = { "", NULL }; Monitor *m; + size_t i; view(&a); selmon->lt[selmon->sellt] = &foo; @@ -471,15 +472,13 @@ cleanup(void) { XUngrabKey(dpy, AnyKey, AnyModifier, root); while(mons) cleanupmon(mons); - drw_cur_free(drw, cursor[CurNormal]); - drw_cur_free(drw, cursor[CurResize]); - drw_cur_free(drw, cursor[CurMove]); - drw_clr_free(scheme[SchemeNorm].border); - drw_clr_free(scheme[SchemeNorm].bg); - drw_clr_free(scheme[SchemeNorm].fg); - drw_clr_free(scheme[SchemeSel].border); - drw_clr_free(scheme[SchemeSel].bg); - drw_clr_free(scheme[SchemeSel].fg); + for(i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for(i = 0; i < SchemeLast; i++) { + drw_clr_free(scheme[i].border); + drw_clr_free(scheme[i].bg); + drw_clr_free(scheme[i].fg); + } drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); From 04db03a4e69eba88c56c12128340125fb0ef1960 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:28:30 +0200 Subject: [PATCH 047/137] cleanup, dont use c++ style comments - signal: print error string. - die: start message with lower-case (consistency). - bump version to 2015. --- dwm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index f9e0c3d..e2d7423 100644 --- a/dwm.c +++ b/dwm.c @@ -557,7 +557,7 @@ configurenotify(XEvent *e) { XConfigureEvent *ev = &e->xconfigure; Bool dirty; - // TODO: updategeom handling sucks, needs to be simplified + /* TODO: updategeom handling sucks, needs to be simplified */ if(ev->window == root) { dirty = (sw != ev->width || sh != ev->height); sw = ev->width; @@ -1509,7 +1509,7 @@ setup(void) { drw = drw_create(dpy, screen, root, sw, sh); drw_load_fonts(drw, fonts, LENGTH(fonts)); if (!drw->fontcount) - die("No fonts could be loaded.\n"); + die("no fonts could be loaded.\n"); bh = drw->fonts[0]->h + 2; updategeom(); /* init atoms */ @@ -1572,7 +1572,7 @@ showhide(Client *c) { void sigchld(int unused) { if(signal(SIGCHLD, sigchld) == SIG_ERR) - die("Can't install SIGCHLD handler"); + die("can't install SIGCHLD handler:"); while(0 < waitpid(-1, NULL, WNOHANG)); } @@ -2054,7 +2054,7 @@ zoom(const Arg *arg) { int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2014 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2015 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) From e3b7e1d620e18818222c1e5033356ae29dd49e7f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:30:31 +0200 Subject: [PATCH 048/137] dwm: use ecalloc, prevent theoretical overflow --- dwm.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dwm.c b/dwm.c index e2d7423..6295831 100644 --- a/dwm.c +++ b/dwm.c @@ -630,8 +630,7 @@ Monitor * createmon(void) { Monitor *m; - if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); + m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; m->nmaster = nmaster; @@ -1007,8 +1006,7 @@ manage(Window w, XWindowAttributes *wa) { Window trans = None; XWindowChanges wc; - if(!(c = calloc(1, sizeof(Client)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Client)); + c = ecalloc(1, sizeof(Client)); c->win = w; updatetitle(c); if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { @@ -1788,8 +1786,7 @@ updategeom(void) { for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ - if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); for(i = 0, j = 0; i < nn; i++) if(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); From 646b351cc79845f4cc77415dfff474b9ae0053d9 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 20 Oct 2015 23:34:49 +0200 Subject: [PATCH 049/137] sync updated drw code from dmenu important: - drw_rect: didn't use w and h, change the dwm code accordingly. - drw_text: text is NULL is not allowed, use drw_rect(). --- drw.c | 249 +++++++++++++++++++++++++++------------------------------ drw.h | 34 ++++---- dwm.c | 10 ++- util.c | 30 +++++-- util.h | 1 + 5 files changed, 165 insertions(+), 159 deletions(-) diff --git a/drw.c b/drw.c index eb3b3c3..f49200b 100644 --- a/drw.c +++ b/drw.c @@ -9,7 +9,7 @@ #include "util.h" #define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 +#define UTF_SIZ 4 static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; @@ -17,50 +17,55 @@ static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000 static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; static long -utf8decodebyte(const char c, size_t *i) { - for(*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if(((unsigned char)c & utfmask[*i]) == utfbyte[*i]) +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) return (unsigned char)c & ~utfmask[*i]; return 0; } static size_t -utf8validate(long *u, size_t i) { - if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) *u = UTF_INVALID; - for(i = 1; *u > utfmax[i]; ++i) + for (i = 1; *u > utfmax[i]; ++i) ; return i; } static size_t -utf8decode(const char *c, long *u, size_t clen) { +utf8decode(const char *c, long *u, size_t clen) +{ size_t i, j, len, type; long udecoded; *u = UTF_INVALID; - if(!clen) + if (!clen) return 0; udecoded = utf8decodebyte(c[0], &len); - if(!BETWEEN(len, 1, UTF_SIZ)) + if (!BETWEEN(len, 1, UTF_SIZ)) return 1; - for(i = 1, j = 1; i < clen && j < len; ++i, ++j) { + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if(type != 0) + if (type) return j; } - if(j < len) + if (j < len) return 0; *u = udecoded; utf8validate(u, len); + return len; } Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { - Drw *drw = (Drw *)calloc(1, sizeof(Drw)); - if(!drw) - return NULL; +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw; + + drw = ecalloc(1, sizeof(Drw)); drw->dpy = dpy; drw->screen = screen; drw->root = root; @@ -70,26 +75,27 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->gc = XCreateGC(dpy, root, 0, NULL); drw->fontcount = 0; XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + return drw; } void -drw_resize(Drw *drw, unsigned int w, unsigned int h) { - if(!drw) - return; +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ drw->w = w; drw->h = h; - if(drw->drawable != 0) + if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); } void -drw_free(Drw *drw) { +drw_free(Drw *drw) +{ size_t i; - for (i = 0; i < drw->fontcount; i++) { + + for (i = 0; i < drw->fontcount; i++) drw_font_free(drw->fonts[i]); - } XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); free(drw); @@ -99,14 +105,11 @@ drw_free(Drw *drw) { * drw_font_create instead. */ static Fnt * -drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) { +drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ Fnt *font; - - if (!(fontname || fontpattern)) - die("No font specified.\n"); - - if (!(font = (Fnt *)calloc(1, sizeof(Fnt)))) - return NULL; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; if (fontname) { /* Using the pattern found at font->xfont->pattern does not yield same @@ -115,46 +118,50 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) { * behaviour whereas the former just results in * missing-character-rectangles being drawn, at least with some fonts. */ - if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) || - !(font->pattern = FcNameParse((FcChar8 *) fontname))) { - if (font->xfont) { - XftFontClose(drw->dpy, font->xfont); - font->xfont = NULL; - } + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; } } else if (fontpattern) { - if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { fprintf(stderr, "error, cannot load font pattern.\n"); - } else { - font->pattern = NULL; + return NULL; } + } else { + die("no font specified.\n"); } - if (!font->xfont) { - free(font); - return NULL; - } - - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->ascent = xfont->ascent; + font->descent = xfont->descent; font->h = font->ascent + font->descent; font->dpy = drw->dpy; + return font; } Fnt* -drw_font_create(Drw *drw, const char *fontname) { +drw_font_create(Drw *drw, const char *fontname) +{ return drw_font_xcreate(drw, fontname, NULL); } void -drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) { +drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) +{ size_t i; Fnt *font; + for (i = 0; i < fontcount; i++) { if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { - die("Font cache exhausted.\n"); + die("font cache exhausted.\n"); } else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) { drw->fonts[drw->fontcount++] = font; } @@ -162,68 +169,62 @@ drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) { } void -drw_font_free(Fnt *font) { - if(!font) +drw_font_free(Fnt *font) +{ + if (!font) return; - if(font->pattern) + if (font->pattern) FcPatternDestroy(font->pattern); XftFontClose(font->dpy, font->xfont); free(font); } Clr * -drw_clr_create(Drw *drw, const char *clrname) { +drw_clr_create(Drw *drw, const char *clrname) +{ Clr *clr; - Colormap cmap; - Visual *vis; - if(!drw) - return NULL; - clr = (Clr *)calloc(1, sizeof(Clr)); - if(!clr) - return NULL; - cmap = DefaultColormap(drw->dpy, drw->screen); - vis = DefaultVisual(drw->dpy, drw->screen); - if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb)) + clr = ecalloc(1, sizeof(Clr)); + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, &clr->rgb)) die("error, cannot allocate color '%s'\n", clrname); clr->pix = clr->rgb.pixel; + return clr; } void -drw_clr_free(Clr *clr) { - if(clr) - free(clr); +drw_clr_free(Clr *clr) +{ + free(clr); } void -drw_setscheme(Drw *drw, ClrScheme *scheme) { - if(drw && scheme) - drw->scheme = scheme; +drw_setscheme(Drw *drw, ClrScheme *scheme) +{ + drw->scheme = scheme; } void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { - int dx; - - if(!drw || !drw->fontcount || !drw->scheme) +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) +{ + if (!drw->scheme) return; XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); - dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; - if(filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); - else if(empty) - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1); + else if (empty) + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); } int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) +{ char buf[1024]; int tx, ty, th; Extnts tex; - Colormap cmap; - Visual *vis; - XftDraw *d; + XftDraw *d = NULL; Fnt *curfont, *nextfont; size_t i, len; int utf8strlen, utf8charlen, render; @@ -235,23 +236,18 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex XftResult result; int charexists = 0; + if (!drw->scheme || !drw->fontcount) + return 0; + if (!(render = x || y || w || h)) { w = ~w; - } - - if (!drw || !drw->scheme) { - return 0; - } else if (render) { - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->pix : drw->scheme->bg->pix); + } else { + XSetForeground(drw->dpy, drw->gc, invert ? + drw->scheme->fg->pix : drw->scheme->bg->pix); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - } - - if (!text || !drw->fontcount) { - return 0; - } else if (render) { - cmap = DefaultColormap(drw->dpy, drw->screen); - vis = DefaultVisual(drw->dpy, drw->screen); - d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); } curfont = drw->fonts[0]; @@ -274,24 +270,23 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex } } - if (!charexists || (nextfont && nextfont != curfont)) { + if (!charexists || (nextfont && nextfont != curfont)) break; - } else { + else charexists = 0; - } } if (utf8strlen) { drw_font_getexts(curfont, utf8str, utf8strlen, &tex); /* shorten text if necessary */ - for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) + for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) drw_font_getexts(curfont, utf8str, len, &tex); if (len) { memcpy(buf, utf8str, len); buf[len] = '\0'; - if(len < utf8strlen) - for(i = len; i && i > len - 3; buf[--i] = '.'); + if (len < utf8strlen) + for (i = len; i && i > len - 3; buf[--i] = '.'); if (render) { th = curfont->ascent + curfont->descent; @@ -299,7 +294,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex tx = x + (h / 2); XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len); } - x += tex.w; w -= tex.w; } @@ -316,18 +310,16 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex */ charexists = 1; - if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { + if (drw->fontcount >= DRW_FONT_CACHE_SIZE) continue; - } fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); if (!drw->fonts[0]->pattern) { /* Refer to the comment in drw_font_xcreate for more - * information. - */ - die("The first font in the cache must be loaded from a font string.\n"); + * information. */ + die("the first font in the cache must be loaded from a font string.\n"); } fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern); @@ -346,65 +338,60 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { drw->fonts[drw->fontcount++] = curfont; } else { - if (curfont) { - drw_font_free(curfont); - } + drw_font_free(curfont); curfont = drw->fonts[0]; } } } } - - if (render) { + if (d) XftDrawDestroy(d); - } return x; } void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { - if(!drw) - return; +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); XSync(drw->dpy, False); } - void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { +drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) +{ XGlyphInfo ext; - if(!font || !text) - return; XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); tex->h = font->h; tex->w = ext.xOff; } unsigned int -drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) { +drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) +{ Extnts tex; - if(!font) - return -1; drw_font_getexts(font, text, len, &tex); + return tex.w; } Cur * -drw_cur_create(Drw *drw, int shape) { - Cur *cur = (Cur *)calloc(1, sizeof(Cur)); +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; - if(!drw || !cur) - return NULL; + cur = ecalloc(1, sizeof(Cur)); cur->cursor = XCreateFontCursor(drw->dpy, shape); + return cur; } void -drw_cur_free(Drw *drw, Cur *cursor) { - if(!drw || !cursor) +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) return; XFreeCursor(drw->dpy, cursor->cursor); free(cursor); diff --git a/drw.h b/drw.h index 536171b..e3b8515 100644 --- a/drw.h +++ b/drw.h @@ -43,32 +43,32 @@ typedef struct { } Extnts; /* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); +Drw *drw_create(Display *, int, Window, unsigned int, unsigned int); +void drw_resize(Drw *, unsigned int, unsigned int); +void drw_free(Drw *); /* Fnt abstraction */ -Fnt *drw_font_create(Drw *drw, const char *fontname); -void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount); -void drw_font_free(Fnt *font); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); -unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); +Fnt *drw_font_create(Drw *, const char *); +void drw_load_fonts(Drw *, const char *[], size_t); +void drw_font_free(Fnt *); +void drw_font_getexts(Fnt *, const char *, unsigned int, Extnts *); +unsigned int drw_font_getexts_width(Fnt *, const char *, unsigned int); /* Colour abstraction */ -Clr *drw_clr_create(Drw *drw, const char *clrname); -void drw_clr_free(Clr *clr); +Clr *drw_clr_create(Drw *, const char *); +void drw_clr_free(Clr *); /* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); +Cur *drw_cur_create(Drw *, int); +void drw_cur_free(Drw *, Cur *); /* Drawing context manipulation */ -void drw_setfont(Drw *drw, Fnt *font); -void drw_setscheme(Drw *drw, ClrScheme *scheme); +void drw_setfont(Drw *, Fnt *); +void drw_setscheme(Drw *, ClrScheme *); /* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); +void drw_rect(Drw *, int, int, unsigned int, unsigned int, int, int, int); +int drw_text(Drw *, int, int, unsigned int, unsigned int, const char *, int); /* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); +void drw_map(Drw *, Window, int, int, unsigned int, unsigned int); diff --git a/dwm.c b/dwm.c index 6295831..96b43f7 100644 --- a/dwm.c +++ b/dwm.c @@ -689,10 +689,12 @@ dirtomon(int dir) { void drawbar(Monitor *m) { - int x, xx, w; + int x, xx, w, dx; unsigned int i, occ = 0, urg = 0; Client *c; + dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; + for(c = m->clients; c; c = c->next) { occ |= c->tags; if(c->isurgent) @@ -703,7 +705,7 @@ drawbar(Monitor *m) { w = TEXTW(tags[i]); drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); - drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + drw_rect(drw, x + 1, 1, dx, dx, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, urg & 1 << i); x += w; } @@ -728,11 +730,11 @@ drawbar(Monitor *m) { if(m->sel) { drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, m->sel->name, 0); - drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0); + drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0); } else { drw_setscheme(drw, &scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, NULL, 0); + drw_rect(drw, x, 0, w, bh, 1, 0, 1); } } drw_map(drw, m->barwin, 0, 0, m->ww, bh); diff --git a/util.c b/util.c index 51acd1a..6b703e9 100644 --- a/util.c +++ b/util.c @@ -2,16 +2,32 @@ #include #include #include +#include #include "util.h" -void -die(const char *errstr, ...) { - va_list ap; +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); + if (!(p = calloc(nmemb, size))) + perror(NULL); + return p; } +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } + + exit(1); +} diff --git a/util.h b/util.h index f7ce721..cded043 100644 --- a/util.h +++ b/util.h @@ -5,3 +5,4 @@ #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *errstr, ...); +void *ecalloc(size_t, size_t); From dce4fb373757727374d00c857ec0dfd225bbeafd Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Sat, 7 Nov 2015 14:09:08 +0100 Subject: [PATCH 050/137] setfullscreen: don't process the property twice Some clients try to set _NET_WM_STATE_FULLSCREEN even when the window is already in fullscreen. For example, c->oldstate was set two times in a raw and window would then always be floating. We must check that it's not the case before processing it. (original patch modified with suggestion from Markus Teich ) --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 96b43f7..3639165 100644 --- a/dwm.c +++ b/dwm.c @@ -1441,7 +1441,7 @@ setfocus(Client *c) { void setfullscreen(Client *c, Bool fullscreen) { - if(fullscreen) { + if(fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); c->isfullscreen = True; @@ -1452,7 +1452,7 @@ setfullscreen(Client *c, Bool fullscreen) { resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); } - else { + else if(!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); c->isfullscreen = False; From 42cf1c7d8f94e1c51a71761ab24414c2f49dac26 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 8 Nov 2015 16:52:53 +0100 Subject: [PATCH 051/137] Makefile: package all files with make dist --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fd07d59..1ea40b7 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,8 @@ clean: dist: clean @echo creating dist tarball @mkdir -p dwm-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ - dwm.1 ${SRC} dwm-${VERSION} + @cp -R LICENSE TODO BUGS Makefile README config.def.h config.mk \ + dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} @tar -cf dwm-${VERSION}.tar dwm-${VERSION} @gzip dwm-${VERSION}.tar @rm -rf dwm-${VERSION} From 43e82adf0dc37411fdcc6406b3cdf5d572387b9f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 7 Nov 2015 14:04:49 +0100 Subject: [PATCH 052/137] separate program-specific c99 bool and X11 True, False are X11-specific (int), make sure to use c99 stdbool for program-specific things. --- config.def.h | 10 ++-- dwm.c | 142 ++++++++++++++++++++++++++------------------------- 2 files changed, 77 insertions(+), 75 deletions(-) diff --git a/config.def.h b/config.def.h index 3fde3cf..76073a5 100644 --- a/config.def.h +++ b/config.def.h @@ -13,8 +13,8 @@ static const char selbgcolor[] = "#005577"; static const char selfgcolor[] = "#eeeeee"; static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ -static const Bool showbar = True; /* False means no bar */ -static const Bool topbar = True; /* False means bottom bar */ +static const bool showbar = true; /* false means no bar */ +static const bool topbar = true; /* false means bottom bar */ /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; @@ -25,14 +25,14 @@ static const Rule rules[] = { * WM_NAME(STRING) = title */ /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, True, -1 }, - { "Firefox", NULL, NULL, 1 << 8, False, -1 }, + { "Gimp", NULL, NULL, 0, true, -1 }, + { "Firefox", NULL, NULL, 1 << 8, false, -1 }, }; /* layout(s) */ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ static const int nmaster = 1; /* number of clients in master area */ -static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ +static const bool resizehints = true; /* true means respect size hints in tiled resizals */ static const Layout layouts[] = { /* symbol arrange function */ diff --git a/dwm.c b/dwm.c index 3639165..5d64141 100644 --- a/dwm.c +++ b/dwm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -92,7 +93,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; @@ -122,8 +123,8 @@ struct Monitor { unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; - Bool showbar; - Bool topbar; + bool showbar; + bool topbar; Client *clients; Client *sel; Client *stack; @@ -137,13 +138,13 @@ typedef struct { const char *instance; const char *title; unsigned int tags; - Bool isfloating; + bool isfloating; int monitor; } Rule; /* function declarations */ static void applyrules(Client *c); -static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); +static bool applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact); static void arrange(Monitor *m); static void arrangemon(Monitor *m); static void attach(Client *c); @@ -170,10 +171,10 @@ static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static Bool getrootptr(int *x, int *y); +static bool getrootptr(int *x, int *y); static long getstate(Window w); -static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, Bool focused); +static bool gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, bool focused); static void grabkeys(void); static void incnmaster(const Arg *arg); static void keypress(XEvent *e); @@ -189,17 +190,17 @@ static void pop(Client *); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, Bool interact); +static void resize(Client *c, int x, int y, int w, int h, bool interact); static void resizeclient(Client *c, int x, int y, int w, int h); static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); -static Bool sendevent(Client *c, Atom proto); +static bool sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); -static void setfullscreen(Client *c, Bool fullscreen); +static void setfullscreen(Client *c, bool fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -213,10 +214,10 @@ static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); -static void unfocus(Client *c, Bool setfocus); -static void unmanage(Client *c, Bool destroyed); +static void unfocus(Client *c, bool setfocus); +static void unmanage(Client *c, bool destroyed); static void unmapnotify(XEvent *e); -static Bool updategeom(void); +static bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -259,7 +260,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool running = True; +static bool running = true; static Cur *cursor[CurLast]; static ClrScheme scheme[SchemeLast]; static Display *dpy; @@ -283,7 +284,8 @@ applyrules(Client *c) { XClassHint ch = { NULL, NULL }; /* rule matching */ - c->isfloating = c->tags = 0; + c->isfloating = false; + c->tags = 0; XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; @@ -308,9 +310,9 @@ applyrules(Client *c) { c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } -Bool -applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { - Bool baseismin; +bool +applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact) { + bool baseismin; Monitor *m = c->mon; /* set minimum possible */ @@ -417,7 +419,7 @@ buttonpress(XEvent *e) { click = ClkRootWin; /* focus monitor if necessary */ if((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; focus(NULL); } @@ -468,7 +470,7 @@ cleanup(void) { selmon->lt[selmon->sellt] = &foo; for(m = mons; m; m = m->next) while(m->stack) - unmanage(m->stack, False); + unmanage(m->stack, false); XUngrabKey(dpy, AnyKey, AnyModifier, root); while(mons) cleanupmon(mons); @@ -504,7 +506,7 @@ void clearurgent(Client *c) { XWMHints *wmh; - c->isurgent = False; + c->isurgent = false; if(!(wmh = XGetWMHints(dpy, c->win))) return; wmh->flags &= ~XUrgencyHint; @@ -555,7 +557,7 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - Bool dirty; + bool dirty; /* TODO: updategeom handling sucks, needs to be simplified */ if(ev->window == root) { @@ -648,7 +650,7 @@ destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; if((c = wintoclient(ev->window))) - unmanage(c, True); + unmanage(c, true); } void @@ -759,7 +761,7 @@ enternotify(XEvent *e) { c = wintoclient(ev->window); m = c ? c->mon : wintomon(ev->window); if(m != selmon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; } else if(!c || c == selmon->sel) @@ -782,7 +784,7 @@ focus(Client *c) { for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); /* was if(selmon->sel) */ if(selmon->sel && selmon->sel != c) - unfocus(selmon->sel, False); + unfocus(selmon->sel, false); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -790,7 +792,7 @@ focus(Client *c) { clearurgent(c); detachstack(c); attachstack(c); - grabbuttons(c, True); + grabbuttons(c, true); XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); } @@ -818,7 +820,7 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, False); /* s/True/False/ fixes input focus issues + unfocus(selmon->sel, false); /* s/true/false/ fixes input focus issues in gedit and anjuta */ selmon = m; focus(NULL); @@ -865,13 +867,13 @@ getatomprop(Client *c, Atom prop) { return atom; } -Bool +bool getrootptr(int *x, int *y) { int di; unsigned int dui; Window dummy; - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui) == True; } long @@ -891,18 +893,18 @@ getstate(Window w) { return result; } -Bool +bool gettextprop(Window w, Atom atom, char *text, unsigned int size) { char **list = NULL; int n; XTextProperty name; if(!text || size == 0) - return False; + return false; text[0] = '\0'; XGetTextProperty(dpy, w, &name, atom); if(!name.nitems) - return False; + return false; if(name.encoding == XA_STRING) strncpy(text, (char *)name.value, size - 1); else { @@ -913,11 +915,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) { } text[size - 1] = '\0'; XFree(name.value); - return True; + return true; } void -grabbuttons(Client *c, Bool focused) { +grabbuttons(Client *c, bool focused) { updatenumlockmask(); { unsigned int i, j; @@ -962,13 +964,13 @@ incnmaster(const Arg *arg) { } #ifdef XINERAMA -static Bool +static bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org && unique[n].width == info->width && unique[n].height == info->height) - return False; - return True; + return false; + return true; } #endif /* XINERAMA */ @@ -1044,7 +1046,7 @@ manage(Window w, XWindowAttributes *wa) { updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, False); + grabbuttons(c, false); if(!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; if(c->isfloating) @@ -1056,7 +1058,7 @@ manage(Window w, XWindowAttributes *wa) { XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); if (c->mon == selmon) - unfocus(selmon->sel, False); + unfocus(selmon->sel, false); c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); @@ -1096,7 +1098,7 @@ monocle(Monitor *m) { if(n > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, false); } void @@ -1108,7 +1110,7 @@ motionnotify(XEvent *e) { if(ev->window != root) return; if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; focus(NULL); } @@ -1165,7 +1167,7 @@ movemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, True); + resize(c, nx, ny, c->w, c->h, true); break; } } while(ev.type != ButtonRelease); @@ -1229,7 +1231,7 @@ propertynotify(XEvent *e) { void quit(const Arg *arg) { - running = False; + running = false; } Monitor * @@ -1246,7 +1248,7 @@ recttomon(int x, int y, int w, int h) { } void -resize(Client *c, int x, int y, int w, int h, Bool interact) { +resize(Client *c, int x, int y, int w, int h, bool interact) { if(applysizehints(c, &x, &y, &w, &h, interact)) resizeclient(c, x, y, w, h); } @@ -1307,7 +1309,7 @@ resizemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, True); + resize(c, c->x, c->y, nw, nh, true); break; } } while(ev.type != ButtonRelease); @@ -1385,7 +1387,7 @@ void sendmon(Client *c, Monitor *m) { if(c->mon == m) return; - unfocus(c, True); + unfocus(c, true); detach(c); detachstack(c); c->mon = m; @@ -1404,11 +1406,11 @@ setclientstate(Client *c, long state) { PropModeReplace, (unsigned char *)data, 2); } -Bool +bool sendevent(Client *c, Atom proto) { int n; Atom *protocols; - Bool exists = False; + bool exists = false; XEvent ev; if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { @@ -1440,22 +1442,22 @@ setfocus(Client *c) { } void -setfullscreen(Client *c, Bool fullscreen) { +setfullscreen(Client *c, bool fullscreen) { if(fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; + c->isfullscreen = true; c->oldstate = c->isfloating; c->oldbw = c->bw; c->bw = 0; - c->isfloating = True; + c->isfloating = true; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); } else if(!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; + c->isfullscreen = false; c->isfloating = c->oldstate; c->bw = c->oldbw; c->x = c->oldx; @@ -1560,7 +1562,7 @@ showhide(Client *c) { if(ISVISIBLE(c)) { /* show clients top down */ XMoveWindow(dpy, c->win, c->x, c->y); if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, False); + resize(c, c->x, c->y, c->w, c->h, false); showhide(c->snext); } else { /* hide clients bottom up */ @@ -1623,12 +1625,12 @@ tile(Monitor *m) { for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) if(i < m->nmaster) { h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), false); my += HEIGHT(c); } else { h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), false); ty += HEIGHT(c); } } @@ -1650,7 +1652,7 @@ togglefloating(const Arg *arg) { selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, False); + selmon->sel->w, selmon->sel->h, false); arrange(selmon); } @@ -1680,10 +1682,10 @@ toggleview(const Arg *arg) { } void -unfocus(Client *c, Bool setfocus) { +unfocus(Client *c, bool setfocus) { if(!c) return; - grabbuttons(c, False); + grabbuttons(c, false); XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -1692,7 +1694,7 @@ unfocus(Client *c, Bool setfocus) { } void -unmanage(Client *c, Bool destroyed) { +unmanage(Client *c, bool destroyed) { Monitor *m = c->mon; XWindowChanges wc; @@ -1725,7 +1727,7 @@ unmapnotify(XEvent *e) { if(ev->send_event) setclientstate(c, WithdrawnState); else - unmanage(c, False); + unmanage(c, false); } } @@ -1774,9 +1776,9 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -Bool +bool updategeom(void) { - Bool dirty = False; + bool dirty = false; #ifdef XINERAMA if(XineramaIsActive(dpy)) { @@ -1807,7 +1809,7 @@ updategeom(void) { || (unique[i].x_org != m->mx || unique[i].y_org != m->my || unique[i].width != m->mw || unique[i].height != m->mh)) { - dirty = True; + dirty = true; m->num = i; m->mx = m->wx = unique[i].x_org; m->my = m->wy = unique[i].y_org; @@ -1820,7 +1822,7 @@ updategeom(void) { for(i = nn; i < n; i++) { for(m = mons; m && m->next; m = m->next); while(m->clients) { - dirty = True; + dirty = true; c = m->clients; m->clients = c->next; detachstack(c); @@ -1842,7 +1844,7 @@ updategeom(void) { if(!mons) mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = True; + dirty = true; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); @@ -1941,9 +1943,9 @@ updatewindowtype(Client *c) { Atom wtype = getatomprop(c, netatom[NetWMWindowType]); if(state == netatom[NetWMFullscreen]) - setfullscreen(c, True); + setfullscreen(c, true); if(wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = True; + c->isfloating = true; } void @@ -1956,11 +1958,11 @@ updatewmhints(Client *c) { XSetWMHints(dpy, c->win, wmh); } else - c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; + c->isurgent = (wmh->flags & XUrgencyHint) ? true : false; if(wmh->flags & InputHint) c->neverfocus = !wmh->input; else - c->neverfocus = False; + c->neverfocus = false; XFree(wmh); } } From e941181f464e43765bab98509ef6524e688a46ff Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 8 Nov 2015 20:38:00 +0100 Subject: [PATCH 053/137] sort include + whitespace fix --- dwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 5d64141..9f99640 100644 --- a/dwm.c +++ b/dwm.c @@ -22,8 +22,8 @@ */ #include #include -#include #include +#include #include #include #include @@ -1435,8 +1435,8 @@ setfocus(Client *c) { if(!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); } sendevent(c, wmatom[WMTakeFocus]); } From 3c91283ede911916452345d545435b08dce9d556 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 8 Nov 2015 22:48:43 +0100 Subject: [PATCH 054/137] unboolification --- config.def.h | 14 ++--- dwm.c | 141 +++++++++++++++++++++++++-------------------------- 2 files changed, 77 insertions(+), 78 deletions(-) diff --git a/config.def.h b/config.def.h index 76073a5..7054c06 100644 --- a/config.def.h +++ b/config.def.h @@ -13,8 +13,8 @@ static const char selbgcolor[] = "#005577"; static const char selfgcolor[] = "#eeeeee"; static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ -static const bool showbar = true; /* false means no bar */ -static const bool topbar = true; /* false means bottom bar */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; @@ -25,14 +25,14 @@ static const Rule rules[] = { * WM_NAME(STRING) = title */ /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, true, -1 }, - { "Firefox", NULL, NULL, 1 << 8, false, -1 }, + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, }; /* layout(s) */ -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const bool resizehints = true; /* true means respect size hints in tiled resizals */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ static const Layout layouts[] = { /* symbol arrange function */ diff --git a/dwm.c b/dwm.c index 9f99640..fb56d55 100644 --- a/dwm.c +++ b/dwm.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -93,7 +92,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; @@ -123,8 +122,8 @@ struct Monitor { unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; - bool showbar; - bool topbar; + int showbar; + int topbar; Client *clients; Client *sel; Client *stack; @@ -138,13 +137,13 @@ typedef struct { const char *instance; const char *title; unsigned int tags; - bool isfloating; + int isfloating; int monitor; } Rule; /* function declarations */ static void applyrules(Client *c); -static bool applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); static void arrange(Monitor *m); static void arrangemon(Monitor *m); static void attach(Client *c); @@ -171,10 +170,10 @@ static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static bool getrootptr(int *x, int *y); +static int getrootptr(int *x, int *y); static long getstate(Window w); -static bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, bool focused); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); static void grabkeys(void); static void incnmaster(const Arg *arg); static void keypress(XEvent *e); @@ -190,17 +189,17 @@ static void pop(Client *); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, bool interact); +static void resize(Client *c, int x, int y, int w, int h, int interact); static void resizeclient(Client *c, int x, int y, int w, int h); static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); -static bool sendevent(Client *c, Atom proto); +static int sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); -static void setfullscreen(Client *c, bool fullscreen); +static void setfullscreen(Client *c, int fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -214,10 +213,10 @@ static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); -static void unfocus(Client *c, bool setfocus); -static void unmanage(Client *c, bool destroyed); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); static void unmapnotify(XEvent *e); -static bool updategeom(void); +static int updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -260,7 +259,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static bool running = true; +static int running = 1; static Cur *cursor[CurLast]; static ClrScheme scheme[SchemeLast]; static Display *dpy; @@ -284,7 +283,7 @@ applyrules(Client *c) { XClassHint ch = { NULL, NULL }; /* rule matching */ - c->isfloating = false; + c->isfloating = 0; c->tags = 0; XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; @@ -310,9 +309,9 @@ applyrules(Client *c) { c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } -bool -applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact) { - bool baseismin; +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) { + int baseismin; Monitor *m = c->mon; /* set minimum possible */ @@ -419,7 +418,7 @@ buttonpress(XEvent *e) { click = ClkRootWin; /* focus monitor if necessary */ if((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, true); + unfocus(selmon->sel, 1); selmon = m; focus(NULL); } @@ -470,7 +469,7 @@ cleanup(void) { selmon->lt[selmon->sellt] = &foo; for(m = mons; m; m = m->next) while(m->stack) - unmanage(m->stack, false); + unmanage(m->stack, 0); XUngrabKey(dpy, AnyKey, AnyModifier, root); while(mons) cleanupmon(mons); @@ -506,7 +505,7 @@ void clearurgent(Client *c) { XWMHints *wmh; - c->isurgent = false; + c->isurgent = 0; if(!(wmh = XGetWMHints(dpy, c->win))) return; wmh->flags &= ~XUrgencyHint; @@ -557,7 +556,7 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - bool dirty; + int dirty; /* TODO: updategeom handling sucks, needs to be simplified */ if(ev->window == root) { @@ -650,7 +649,7 @@ destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; if((c = wintoclient(ev->window))) - unmanage(c, true); + unmanage(c, 1); } void @@ -761,7 +760,7 @@ enternotify(XEvent *e) { c = wintoclient(ev->window); m = c ? c->mon : wintomon(ev->window); if(m != selmon) { - unfocus(selmon->sel, true); + unfocus(selmon->sel, 1); selmon = m; } else if(!c || c == selmon->sel) @@ -784,7 +783,7 @@ focus(Client *c) { for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); /* was if(selmon->sel) */ if(selmon->sel && selmon->sel != c) - unfocus(selmon->sel, false); + unfocus(selmon->sel, 0); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -792,7 +791,7 @@ focus(Client *c) { clearurgent(c); detachstack(c); attachstack(c); - grabbuttons(c, true); + grabbuttons(c, 1); XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); } @@ -820,7 +819,7 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, false); /* s/true/false/ fixes input focus issues + unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues in gedit and anjuta */ selmon = m; focus(NULL); @@ -867,13 +866,13 @@ getatomprop(Client *c, Atom prop) { return atom; } -bool +int getrootptr(int *x, int *y) { int di; unsigned int dui; Window dummy; - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui) == True; + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); } long @@ -893,18 +892,18 @@ getstate(Window w) { return result; } -bool +int gettextprop(Window w, Atom atom, char *text, unsigned int size) { char **list = NULL; int n; XTextProperty name; if(!text || size == 0) - return false; + return 0; text[0] = '\0'; XGetTextProperty(dpy, w, &name, atom); if(!name.nitems) - return false; + return 0; if(name.encoding == XA_STRING) strncpy(text, (char *)name.value, size - 1); else { @@ -915,11 +914,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) { } text[size - 1] = '\0'; XFree(name.value); - return true; + return 1; } void -grabbuttons(Client *c, bool focused) { +grabbuttons(Client *c, int focused) { updatenumlockmask(); { unsigned int i, j; @@ -964,13 +963,13 @@ incnmaster(const Arg *arg) { } #ifdef XINERAMA -static bool +static int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org && unique[n].width == info->width && unique[n].height == info->height) - return false; - return true; + return 0; + return 1; } #endif /* XINERAMA */ @@ -1046,7 +1045,7 @@ manage(Window w, XWindowAttributes *wa) { updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, false); + grabbuttons(c, 0); if(!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; if(c->isfloating) @@ -1058,7 +1057,7 @@ manage(Window w, XWindowAttributes *wa) { XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); if (c->mon == selmon) - unfocus(selmon->sel, false); + unfocus(selmon->sel, 0); c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); @@ -1098,7 +1097,7 @@ monocle(Monitor *m) { if(n > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, false); + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); } void @@ -1110,7 +1109,7 @@ motionnotify(XEvent *e) { if(ev->window != root) return; if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, true); + unfocus(selmon->sel, 1); selmon = m; focus(NULL); } @@ -1167,7 +1166,7 @@ movemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, true); + resize(c, nx, ny, c->w, c->h, 1); break; } } while(ev.type != ButtonRelease); @@ -1231,7 +1230,7 @@ propertynotify(XEvent *e) { void quit(const Arg *arg) { - running = false; + running = 0; } Monitor * @@ -1248,7 +1247,7 @@ recttomon(int x, int y, int w, int h) { } void -resize(Client *c, int x, int y, int w, int h, bool interact) { +resize(Client *c, int x, int y, int w, int h, int interact) { if(applysizehints(c, &x, &y, &w, &h, interact)) resizeclient(c, x, y, w, h); } @@ -1309,7 +1308,7 @@ resizemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, true); + resize(c, c->x, c->y, nw, nh, 1); break; } } while(ev.type != ButtonRelease); @@ -1387,7 +1386,7 @@ void sendmon(Client *c, Monitor *m) { if(c->mon == m) return; - unfocus(c, true); + unfocus(c, 1); detach(c); detachstack(c); c->mon = m; @@ -1406,11 +1405,11 @@ setclientstate(Client *c, long state) { PropModeReplace, (unsigned char *)data, 2); } -bool +int sendevent(Client *c, Atom proto) { int n; Atom *protocols; - bool exists = false; + int exists = 0; XEvent ev; if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { @@ -1442,22 +1441,22 @@ setfocus(Client *c) { } void -setfullscreen(Client *c, bool fullscreen) { +setfullscreen(Client *c, int fullscreen) { if(fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = true; + c->isfullscreen = 1; c->oldstate = c->isfloating; c->oldbw = c->bw; c->bw = 0; - c->isfloating = true; + c->isfloating = 1; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); } else if(!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = false; + c->isfullscreen = 0; c->isfloating = c->oldstate; c->bw = c->oldbw; c->x = c->oldx; @@ -1562,7 +1561,7 @@ showhide(Client *c) { if(ISVISIBLE(c)) { /* show clients top down */ XMoveWindow(dpy, c->win, c->x, c->y); if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, false); + resize(c, c->x, c->y, c->w, c->h, 0); showhide(c->snext); } else { /* hide clients bottom up */ @@ -1625,12 +1624,12 @@ tile(Monitor *m) { for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) if(i < m->nmaster) { h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), false); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); my += HEIGHT(c); } else { h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), false); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); ty += HEIGHT(c); } } @@ -1652,7 +1651,7 @@ togglefloating(const Arg *arg) { selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, false); + selmon->sel->w, selmon->sel->h, 0); arrange(selmon); } @@ -1682,10 +1681,10 @@ toggleview(const Arg *arg) { } void -unfocus(Client *c, bool setfocus) { +unfocus(Client *c, int setfocus) { if(!c) return; - grabbuttons(c, false); + grabbuttons(c, 0); XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -1694,7 +1693,7 @@ unfocus(Client *c, bool setfocus) { } void -unmanage(Client *c, bool destroyed) { +unmanage(Client *c, int destroyed) { Monitor *m = c->mon; XWindowChanges wc; @@ -1727,7 +1726,7 @@ unmapnotify(XEvent *e) { if(ev->send_event) setclientstate(c, WithdrawnState); else - unmanage(c, false); + unmanage(c, 0); } } @@ -1776,9 +1775,9 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -bool +int updategeom(void) { - bool dirty = false; + int dirty = 0; #ifdef XINERAMA if(XineramaIsActive(dpy)) { @@ -1809,7 +1808,7 @@ updategeom(void) { || (unique[i].x_org != m->mx || unique[i].y_org != m->my || unique[i].width != m->mw || unique[i].height != m->mh)) { - dirty = true; + dirty = 1; m->num = i; m->mx = m->wx = unique[i].x_org; m->my = m->wy = unique[i].y_org; @@ -1822,7 +1821,7 @@ updategeom(void) { for(i = nn; i < n; i++) { for(m = mons; m && m->next; m = m->next); while(m->clients) { - dirty = true; + dirty = 1; c = m->clients; m->clients = c->next; detachstack(c); @@ -1844,7 +1843,7 @@ updategeom(void) { if(!mons) mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = true; + dirty = 1; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); @@ -1943,9 +1942,9 @@ updatewindowtype(Client *c) { Atom wtype = getatomprop(c, netatom[NetWMWindowType]); if(state == netatom[NetWMFullscreen]) - setfullscreen(c, true); + setfullscreen(c, 1); if(wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = true; + c->isfloating = 1; } void @@ -1958,11 +1957,11 @@ updatewmhints(Client *c) { XSetWMHints(dpy, c->win, wmh); } else - c->isurgent = (wmh->flags & XUrgencyHint) ? true : false; + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; if(wmh->flags & InputHint) c->neverfocus = !wmh->input; else - c->neverfocus = false; + c->neverfocus = 0; XFree(wmh); } } From 5ed9c481968a45f5032f1011d92ab8d5237aeba1 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 8 Nov 2015 23:11:48 +0100 Subject: [PATCH 055/137] code-style consistency --- dwm.c | 936 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 503 insertions(+), 433 deletions(-) diff --git a/dwm.c b/dwm.c index fb56d55..0362114 100644 --- a/dwm.c +++ b/dwm.c @@ -275,7 +275,8 @@ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; /* function implementations */ void -applyrules(Client *c) { +applyrules(Client *c) +{ const char *class, *instance; unsigned int i; const Rule *r; @@ -289,126 +290,131 @@ applyrules(Client *c) { class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; - for(i = 0; i < LENGTH(rules); i++) { + for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; - if((!r->title || strstr(c->name, r->title)) + if ((!r->title || strstr(c->name, r->title)) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { c->isfloating = r->isfloating; c->tags |= r->tags; - for(m = mons; m && m->num != r->monitor; m = m->next); - if(m) + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) c->mon = m; } } - if(ch.res_class) + if (ch.res_class) XFree(ch.res_class); - if(ch.res_name) + if (ch.res_name) XFree(ch.res_name); c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) { +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ int baseismin; Monitor *m = c->mon; /* set minimum possible */ *w = MAX(1, *w); *h = MAX(1, *h); - if(interact) { - if(*x > sw) + if (interact) { + if (*x > sw) *x = sw - WIDTH(c); - if(*y > sh) + if (*y > sh) *y = sh - HEIGHT(c); - if(*x + *w + 2 * c->bw < 0) + if (*x + *w + 2 * c->bw < 0) *x = 0; - if(*y + *h + 2 * c->bw < 0) + if (*y + *h + 2 * c->bw < 0) *y = 0; - } - else { - if(*x >= m->wx + m->ww) + } else { + if (*x >= m->wx + m->ww) *x = m->wx + m->ww - WIDTH(c); - if(*y >= m->wy + m->wh) + if (*y >= m->wy + m->wh) *y = m->wy + m->wh - HEIGHT(c); - if(*x + *w + 2 * c->bw <= m->wx) + if (*x + *w + 2 * c->bw <= m->wx) *x = m->wx; - if(*y + *h + 2 * c->bw <= m->wy) + if (*y + *h + 2 * c->bw <= m->wy) *y = m->wy; } - if(*h < bh) + if (*h < bh) *h = bh; - if(*w < bh) + if (*w < bh) *w = bh; - if(resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { /* see last two sentences in ICCCM 4.1.2.3 */ baseismin = c->basew == c->minw && c->baseh == c->minh; - if(!baseismin) { /* temporarily remove base dimensions */ + if (!baseismin) { /* temporarily remove base dimensions */ *w -= c->basew; *h -= c->baseh; } /* adjust for aspect limits */ - if(c->mina > 0 && c->maxa > 0) { - if(c->maxa < (float)*w / *h) + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) *w = *h * c->maxa + 0.5; - else if(c->mina < (float)*h / *w) + else if (c->mina < (float)*h / *w) *h = *w * c->mina + 0.5; } - if(baseismin) { /* increment calculation requires this */ + if (baseismin) { /* increment calculation requires this */ *w -= c->basew; *h -= c->baseh; } /* adjust for increment value */ - if(c->incw) + if (c->incw) *w -= *w % c->incw; - if(c->inch) + if (c->inch) *h -= *h % c->inch; /* restore base dimensions */ *w = MAX(*w + c->basew, c->minw); *h = MAX(*h + c->baseh, c->minh); - if(c->maxw) + if (c->maxw) *w = MIN(*w, c->maxw); - if(c->maxh) + if (c->maxh) *h = MIN(*h, c->maxh); } return *x != c->x || *y != c->y || *w != c->w || *h != c->h; } void -arrange(Monitor *m) { - if(m) +arrange(Monitor *m) +{ + if (m) showhide(m->stack); - else for(m = mons; m; m = m->next) + else for (m = mons; m; m = m->next) showhide(m->stack); - if(m) { + if (m) { arrangemon(m); restack(m); - } else for(m = mons; m; m = m->next) + } else for (m = mons; m; m = m->next) arrangemon(m); } void -arrangemon(Monitor *m) { +arrangemon(Monitor *m) +{ strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) + if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); } void -attach(Client *c) { +attach(Client *c) +{ c->next = c->mon->clients; c->mon->clients = c; } void -attachstack(Client *c) { +attachstack(Client *c) +{ c->snext = c->mon->stack; c->mon->stack = c; } void -buttonpress(XEvent *e) { +buttonpress(XEvent *e) +{ unsigned int i, x, click; Arg arg = {0}; Client *c; @@ -417,39 +423,38 @@ buttonpress(XEvent *e) { click = ClkRootWin; /* focus monitor if necessary */ - if((m = wintomon(ev->window)) && m != selmon) { + if ((m = wintomon(ev->window)) && m != selmon) { unfocus(selmon->sel, 1); selmon = m; focus(NULL); } - if(ev->window == selmon->barwin) { + if (ev->window == selmon->barwin) { i = x = 0; do x += TEXTW(tags[i]); - while(ev->x >= x && ++i < LENGTH(tags)); - if(i < LENGTH(tags)) { + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { click = ClkTagBar; arg.ui = 1 << i; - } - else if(ev->x < x + blw) + } else if (ev->x < x + blw) click = ClkLtSymbol; - else if(ev->x > selmon->ww - TEXTW(stext)) + else if (ev->x > selmon->ww - TEXTW(stext)) click = ClkStatusText; else click = ClkWinTitle; - } - else if((c = wintoclient(ev->window))) { + } else if ((c = wintoclient(ev->window))) { focus(c); click = ClkClientWin; } - for(i = 0; i < LENGTH(buttons); i++) - if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); } void -checkotherwm(void) { +checkotherwm(void) +{ xerrorxlib = XSetErrorHandler(xerrorstart); /* this causes an error if some other window manager is running */ XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); @@ -459,7 +464,8 @@ checkotherwm(void) { } void -cleanup(void) { +cleanup(void) +{ Arg a = {.ui = ~0}; Layout foo = { "", NULL }; Monitor *m; @@ -467,15 +473,15 @@ cleanup(void) { view(&a); selmon->lt[selmon->sellt] = &foo; - for(m = mons; m; m = m->next) - while(m->stack) + for (m = mons; m; m = m->next) + while (m->stack) unmanage(m->stack, 0); XUngrabKey(dpy, AnyKey, AnyModifier, root); - while(mons) + while (mons) cleanupmon(mons); - for(i = 0; i < CurLast; i++) + for (i = 0; i < CurLast; i++) drw_cur_free(drw, cursor[i]); - for(i = 0; i < SchemeLast; i++) { + for (i = 0; i < SchemeLast; i++) { drw_clr_free(scheme[i].border); drw_clr_free(scheme[i].bg); drw_clr_free(scheme[i].fg); @@ -487,13 +493,14 @@ cleanup(void) { } void -cleanupmon(Monitor *mon) { +cleanupmon(Monitor *mon) +{ Monitor *m; - if(mon == mons) + if (mon == mons) mons = mons->next; else { - for(m = mons; m && m->next != mon; m = m->next); + for (m = mons; m && m->next != mon; m = m->next); m->next = mon->next; } XUnmapWindow(dpy, mon->barwin); @@ -502,11 +509,12 @@ cleanupmon(Monitor *mon) { } void -clearurgent(Client *c) { +clearurgent(Client *c) +{ XWMHints *wmh; c->isurgent = 0; - if(!(wmh = XGetWMHints(dpy, c->win))) + if (!(wmh = XGetWMHints(dpy, c->win))) return; wmh->flags &= ~XUrgencyHint; XSetWMHints(dpy, c->win, wmh); @@ -514,19 +522,19 @@ clearurgent(Client *c) { } void -clientmessage(XEvent *e) { +clientmessage(XEvent *e) +{ XClientMessageEvent *cme = &e->xclient; Client *c = wintoclient(cme->window); - if(!c) + if (!c) return; - if(cme->message_type == netatom[NetWMState]) { - if(cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen]) + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen]) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } - else if(cme->message_type == netatom[NetActiveWindow]) { - if(!ISVISIBLE(c)) { + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (!ISVISIBLE(c)) { c->mon->seltags ^= 1; c->mon->tagset[c->mon->seltags] = c->tags; } @@ -535,7 +543,8 @@ clientmessage(XEvent *e) { } void -configure(Client *c) { +configure(Client *c) +{ XConfigureEvent ce; ce.type = ConfigureNotify; @@ -553,20 +562,21 @@ configure(Client *c) { } void -configurenotify(XEvent *e) { +configurenotify(XEvent *e) +{ Monitor *m; XConfigureEvent *ev = &e->xconfigure; int dirty; /* TODO: updategeom handling sucks, needs to be simplified */ - if(ev->window == root) { + if (ev->window == root) { dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; - if(updategeom() || dirty) { + if (updategeom() || dirty) { drw_resize(drw, sw, bh); updatebars(); - for(m = mons; m; m = m->next) + for (m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); focus(NULL); arrange(NULL); @@ -575,46 +585,45 @@ configurenotify(XEvent *e) { } void -configurerequest(XEvent *e) { +configurerequest(XEvent *e) +{ Client *c; Monitor *m; XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; - if((c = wintoclient(ev->window))) { - if(ev->value_mask & CWBorderWidth) + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) c->bw = ev->border_width; - else if(c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { m = c->mon; - if(ev->value_mask & CWX) { + if (ev->value_mask & CWX) { c->oldx = c->x; c->x = m->mx + ev->x; } - if(ev->value_mask & CWY) { + if (ev->value_mask & CWY) { c->oldy = c->y; c->y = m->my + ev->y; } - if(ev->value_mask & CWWidth) { + if (ev->value_mask & CWWidth) { c->oldw = c->w; c->w = ev->width; } - if(ev->value_mask & CWHeight) { + if (ev->value_mask & CWHeight) { c->oldh = c->h; c->h = ev->height; } - if((c->x + c->w) > m->mx + m->mw && c->isfloating) + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if((c->y + c->h) > m->my + m->mh && c->isfloating) + if ((c->y + c->h) > m->my + m->mh && c->isfloating) c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) configure(c); - if(ISVISIBLE(c)) + if (ISVISIBLE(c)) XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } - else + } else configure(c); - } - else { + } else { wc.x = ev->x; wc.y = ev->y; wc.width = ev->width; @@ -628,7 +637,8 @@ configurerequest(XEvent *e) { } Monitor * -createmon(void) { +createmon(void) +{ Monitor *m; m = ecalloc(1, sizeof(Monitor)); @@ -644,65 +654,69 @@ createmon(void) { } void -destroynotify(XEvent *e) { +destroynotify(XEvent *e) +{ Client *c; XDestroyWindowEvent *ev = &e->xdestroywindow; - if((c = wintoclient(ev->window))) + if ((c = wintoclient(ev->window))) unmanage(c, 1); } void -detach(Client *c) { +detach(Client *c) +{ Client **tc; - for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); *tc = c->next; } void -detachstack(Client *c) { +detachstack(Client *c) +{ Client **tc, *t; - for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); *tc = c->snext; - if(c == c->mon->sel) { - for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); c->mon->sel = t; } } Monitor * -dirtomon(int dir) { +dirtomon(int dir) +{ Monitor *m = NULL; - if(dir > 0) { - if(!(m = selmon->next)) + if (dir > 0) { + if (!(m = selmon->next)) m = mons; - } - else if(selmon == mons) - for(m = mons; m->next; m = m->next); + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); else - for(m = mons; m->next != selmon; m = m->next); + for (m = mons; m->next != selmon; m = m->next); return m; } void -drawbar(Monitor *m) { +drawbar(Monitor *m) +{ int x, xx, w, dx; unsigned int i, occ = 0, urg = 0; Client *c; dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; - for(c = m->clients; c; c = c->next) { + for (c = m->clients; c; c = c->next) { occ |= c->tags; - if(c->isurgent) + if (c->isurgent) urg |= c->tags; } x = 0; - for(i = 0; i < LENGTH(tags); i++) { + for (i = 0; i < LENGTH(tags); i++) { w = TEXTW(tags[i]); drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); @@ -715,25 +729,23 @@ drawbar(Monitor *m) { drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); x += w; xx = x; - if(m == selmon) { /* status is only drawn on selected monitor */ + if (m == selmon) { /* status is only drawn on selected monitor */ w = TEXTW(stext); x = m->ww - w; - if(x < xx) { + if (x < xx) { x = xx; w = m->ww - xx; } drw_text(drw, x, 0, w, bh, stext, 0); - } - else + } else x = m->ww; - if((w = x - xx) > bh) { + if ((w = x - xx) > bh) { x = xx; - if(m->sel) { + if (m->sel) { drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]); drw_text(drw, x, 0, w, bh, m->sel->name, 0); drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0); - } - else { + } else { drw_setscheme(drw, &scheme[SchemeNorm]); drw_rect(drw, x, 0, w, bh, 1, 0, 1); } @@ -742,60 +754,62 @@ drawbar(Monitor *m) { } void -drawbars(void) { +drawbars(void) +{ Monitor *m; - for(m = mons; m; m = m->next) + for (m = mons; m; m = m->next) drawbar(m); } void -enternotify(XEvent *e) { +enternotify(XEvent *e) +{ Client *c; Monitor *m; XCrossingEvent *ev = &e->xcrossing; - if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; c = wintoclient(ev->window); m = c ? c->mon : wintomon(ev->window); - if(m != selmon) { + if (m != selmon) { unfocus(selmon->sel, 1); selmon = m; - } - else if(!c || c == selmon->sel) + } else if (!c || c == selmon->sel) return; focus(c); } void -expose(XEvent *e) { +expose(XEvent *e) +{ Monitor *m; XExposeEvent *ev = &e->xexpose; - if(ev->count == 0 && (m = wintomon(ev->window))) + if (ev->count == 0 && (m = wintomon(ev->window))) drawbar(m); } void -focus(Client *c) { - if(!c || !ISVISIBLE(c)) - for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - /* was if(selmon->sel) */ - if(selmon->sel && selmon->sel != c) +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + /* was if (selmon->sel) */ + if (selmon->sel && selmon->sel != c) unfocus(selmon->sel, 0); - if(c) { - if(c->mon != selmon) + if (c) { + if (c->mon != selmon) selmon = c->mon; - if(c->isurgent) + if (c->isurgent) clearurgent(c); detachstack(c); attachstack(c); grabbuttons(c, 1); XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); - } - else { + } else { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); } @@ -803,21 +817,24 @@ focus(Client *c) { drawbars(); } +/* there are some broken focus acquiring clients */ void -focusin(XEvent *e) { /* there are some broken focus acquiring clients */ +focusin(XEvent *e) +{ XFocusChangeEvent *ev = &e->xfocus; - if(selmon->sel && ev->window != selmon->sel->win) + if (selmon->sel && ev->window != selmon->sel->win) setfocus(selmon->sel); } void -focusmon(const Arg *arg) { +focusmon(const Arg *arg) +{ Monitor *m; - if(!mons->next) + if (!mons->next) return; - if((m = dirtomon(arg->i)) == selmon) + if ((m = dirtomon(arg->i)) == selmon) return; unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues in gedit and anjuta */ @@ -826,39 +843,40 @@ focusmon(const Arg *arg) { } void -focusstack(const Arg *arg) { +focusstack(const Arg *arg) +{ Client *c = NULL, *i; - if(!selmon->sel) + if (!selmon->sel) return; - if(arg->i > 0) { - for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if(!c) - for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } - else { - for(i = selmon->clients; i != selmon->sel; i = i->next) - if(ISVISIBLE(i)) + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) c = i; - if(!c) - for(; i; i = i->next) - if(ISVISIBLE(i)) + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) c = i; } - if(c) { + if (c) { focus(c); restack(selmon); } } Atom -getatomprop(Client *c, Atom prop) { +getatomprop(Client *c, Atom prop) +{ int di; unsigned long dl; unsigned char *p = NULL; Atom da, atom = None; - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, &da, &di, &dl, &dl, &p) == Success && p) { atom = *(Atom *)p; XFree(p); @@ -867,7 +885,8 @@ getatomprop(Client *c, Atom prop) { } int -getrootptr(int *x, int *y) { +getrootptr(int *x, int *y) +{ int di; unsigned int dui; Window dummy; @@ -876,38 +895,40 @@ getrootptr(int *x, int *y) { } long -getstate(Window w) { +getstate(Window w) +{ int format; long result = -1; unsigned char *p = NULL; unsigned long n, extra; Atom real; - if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], &real, &format, &n, &extra, (unsigned char **)&p) != Success) return -1; - if(n != 0) + if (n != 0) result = *p; XFree(p); return result; } int -gettextprop(Window w, Atom atom, char *text, unsigned int size) { +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ char **list = NULL; int n; XTextProperty name; - if(!text || size == 0) + if (!text || size == 0) return 0; text[0] = '\0'; XGetTextProperty(dpy, w, &name, atom); - if(!name.nitems) + if (!name.nitems) return 0; - if(name.encoding == XA_STRING) + if (name.encoding == XA_STRING) strncpy(text, (char *)name.value, size - 1); else { - if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { strncpy(text, *list, size - 1); XFreeStringList(list); } @@ -918,29 +939,30 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) { } void -grabbuttons(Client *c, int focused) { +grabbuttons(Client *c, int focused) +{ updatenumlockmask(); { unsigned int i, j; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if(focused) { - for(i = 0; i < LENGTH(buttons); i++) - if(buttons[i].click == ClkClientWin) - for(j = 0; j < LENGTH(modifiers); j++) + if (focused) { + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); - } - else + } else XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } } void -grabkeys(void) { +grabkeys(void) +{ updatenumlockmask(); { unsigned int i, j; @@ -948,25 +970,27 @@ grabkeys(void) { KeyCode code; XUngrabKey(dpy, AnyKey, AnyModifier, root); - for(i = 0; i < LENGTH(keys); i++) - if((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for(j = 0; j < LENGTH(modifiers); j++) + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, True, GrabModeAsync, GrabModeAsync); } } void -incnmaster(const Arg *arg) { +incnmaster(const Arg *arg) +{ selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } #ifdef XINERAMA static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { - while(n--) - if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org && unique[n].width == info->width && unique[n].height == info->height) return 0; return 1; @@ -974,25 +998,27 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { #endif /* XINERAMA */ void -keypress(XEvent *e) { +keypress(XEvent *e) +{ unsigned int i; KeySym keysym; XKeyEvent *ev; ev = &e->xkey; keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for(i = 0; i < LENGTH(keys); i++) - if(keysym == keys[i].keysym + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) && keys[i].func) keys[i].func(&(keys[i].arg)); } void -killclient(const Arg *arg) { - if(!selmon->sel) +killclient(const Arg *arg) +{ + if (!selmon->sel) return; - if(!sendevent(selmon->sel, wmatom[WMDelete])) { + if (!sendevent(selmon->sel, wmatom[WMDelete])) { XGrabServer(dpy); XSetErrorHandler(xerrordummy); XSetCloseDownMode(dpy, DestroyAll); @@ -1004,7 +1030,8 @@ killclient(const Arg *arg) { } void -manage(Window w, XWindowAttributes *wa) { +manage(Window w, XWindowAttributes *wa) +{ Client *c, *t = NULL; Window trans = None; XWindowChanges wc; @@ -1012,11 +1039,10 @@ manage(Window w, XWindowAttributes *wa) { c = ecalloc(1, sizeof(Client)); c->win = w; updatetitle(c); - if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; c->tags = t->tags; - } - else { + } else { c->mon = selmon; applyrules(c); } @@ -1027,9 +1053,9 @@ manage(Window w, XWindowAttributes *wa) { c->h = c->oldh = wa->height; c->oldbw = wa->border_width; - if(c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if(c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) c->y = c->mon->my + c->mon->mh - HEIGHT(c); c->x = MAX(c->x, c->mon->mx); /* only fix client y-offset, if the client center might cover the bar */ @@ -1046,9 +1072,9 @@ manage(Window w, XWindowAttributes *wa) { updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); - if(!c->isfloating) + if (!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; - if(c->isfloating) + if (c->isfloating) XRaiseWindow(dpy, c->win); attach(c); attachstack(c); @@ -1065,50 +1091,54 @@ manage(Window w, XWindowAttributes *wa) { } void -mappingnotify(XEvent *e) { +mappingnotify(XEvent *e) +{ XMappingEvent *ev = &e->xmapping; XRefreshKeyboardMapping(ev); - if(ev->request == MappingKeyboard) + if (ev->request == MappingKeyboard) grabkeys(); } void -maprequest(XEvent *e) { +maprequest(XEvent *e) +{ static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; - if(!XGetWindowAttributes(dpy, ev->window, &wa)) + if (!XGetWindowAttributes(dpy, ev->window, &wa)) return; - if(wa.override_redirect) + if (wa.override_redirect) return; - if(!wintoclient(ev->window)) + if (!wintoclient(ev->window)) manage(ev->window, &wa); } void -monocle(Monitor *m) { +monocle(Monitor *m) +{ unsigned int n = 0; Client *c; - for(c = m->clients; c; c = c->next) - if(ISVISIBLE(c)) + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) n++; - if(n > 0) /* override layout symbol */ + if (n > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); } void -motionnotify(XEvent *e) { +motionnotify(XEvent *e) +{ static Monitor *mon = NULL; Monitor *m; XMotionEvent *ev = &e->xmotion; - if(ev->window != root) + if (ev->window != root) return; - if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { unfocus(selmon->sel, 1); selmon = m; focus(NULL); @@ -1117,24 +1147,25 @@ motionnotify(XEvent *e) { } void -movemouse(const Arg *arg) { +movemouse(const Arg *arg) +{ int x, y, ocx, ocy, nx, ny; Client *c; Monitor *m; XEvent ev; Time lasttime = 0; - if(!(c = selmon->sel)) + if (!(c = selmon->sel)) return; - if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ return; restack(selmon); ocx = c->x; ocy = c->y; - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; - if(!getrootptr(&x, &y)) + if (!getrootptr(&x, &y)) return; do { XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); @@ -1151,27 +1182,27 @@ movemouse(const Arg *arg) { nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); - if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww + if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) { - if(abs(selmon->wx - nx) < snap) + if (abs(selmon->wx - nx) < snap) nx = selmon->wx; - else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) nx = selmon->wx + selmon->ww - WIDTH(c); - if(abs(selmon->wy - ny) < snap) + if (abs(selmon->wy - ny) < snap) ny = selmon->wy; - else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) ny = selmon->wy + selmon->wh - HEIGHT(c); - if(!c->isfloating && selmon->lt[selmon->sellt]->arrange + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, nx, ny, c->w, c->h, 1); break; } - } while(ev.type != ButtonRelease); + } while (ev.type != ButtonRelease); XUngrabPointer(dpy, CurrentTime); - if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { sendmon(c, m); selmon = m; focus(NULL); @@ -1179,13 +1210,15 @@ movemouse(const Arg *arg) { } Client * -nexttiled(Client *c) { - for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); return c; } void -pop(Client *c) { +pop(Client *c) +{ detach(c); attach(c); focus(c); @@ -1193,20 +1226,21 @@ pop(Client *c) { } void -propertynotify(XEvent *e) { +propertynotify(XEvent *e) +{ Client *c; Window trans; XPropertyEvent *ev = &e->xproperty; - if((ev->window == root) && (ev->atom == XA_WM_NAME)) + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) updatestatus(); - else if(ev->state == PropertyDelete) + else if (ev->state == PropertyDelete) return; /* ignore */ - else if((c = wintoclient(ev->window))) { + else if ((c = wintoclient(ev->window))) { switch(ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: - if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && (c->isfloating = (wintoclient(trans)) != NULL)) arrange(c->mon); break; @@ -1218,28 +1252,30 @@ propertynotify(XEvent *e) { drawbars(); break; } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); - if(c == c->mon->sel) + if (c == c->mon->sel) drawbar(c->mon); } - if(ev->atom == netatom[NetWMWindowType]) + if (ev->atom == netatom[NetWMWindowType]) updatewindowtype(c); } } void -quit(const Arg *arg) { +quit(const Arg *arg) +{ running = 0; } Monitor * -recttomon(int x, int y, int w, int h) { +recttomon(int x, int y, int w, int h) +{ Monitor *m, *r = selmon; int a, area = 0; - for(m = mons; m; m = m->next) - if((a = INTERSECT(x, y, w, h, m)) > area) { + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { area = a; r = m; } @@ -1247,13 +1283,15 @@ recttomon(int x, int y, int w, int h) { } void -resize(Client *c, int x, int y, int w, int h, int interact) { - if(applysizehints(c, &x, &y, &w, &h, interact)) +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) resizeclient(c, x, y, w, h); } void -resizeclient(Client *c, int x, int y, int w, int h) { +resizeclient(Client *c, int x, int y, int w, int h) +{ XWindowChanges wc; c->oldx = c->x; c->x = wc.x = x; @@ -1267,21 +1305,22 @@ resizeclient(Client *c, int x, int y, int w, int h) { } void -resizemouse(const Arg *arg) { +resizemouse(const Arg *arg) +{ int ocx, ocy, nw, nh; Client *c; Monitor *m; XEvent ev; Time lasttime = 0; - if(!(c = selmon->sel)) + if (!(c = selmon->sel)) return; - if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ return; restack(selmon); ocx = c->x; ocy = c->y; - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) return; XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); @@ -1300,22 +1339,22 @@ resizemouse(const Arg *arg) { nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) { - if(!c->isfloating && selmon->lt[selmon->sellt]->arrange + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) togglefloating(NULL); } - if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, c->x, c->y, nw, nh, 1); break; } - } while(ev.type != ButtonRelease); + } while (ev.type != ButtonRelease); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); XUngrabPointer(dpy, CurrentTime); - while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { sendmon(c, m); selmon = m; focus(NULL); @@ -1323,68 +1362,72 @@ resizemouse(const Arg *arg) { } void -restack(Monitor *m) { +restack(Monitor *m) +{ Client *c; XEvent ev; XWindowChanges wc; drawbar(m); - if(!m->sel) + if (!m->sel) return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) XRaiseWindow(dpy, m->sel->win); - if(m->lt[m->sellt]->arrange) { + if (m->lt[m->sellt]->arrange) { wc.stack_mode = Below; wc.sibling = m->barwin; - for(c = m->stack; c; c = c->snext) - if(!c->isfloating && ISVISIBLE(c)) { + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); wc.sibling = c->win; } } XSync(dpy, False); - while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); } void -run(void) { +run(void) +{ XEvent ev; /* main event loop */ XSync(dpy, False); - while(running && !XNextEvent(dpy, &ev)) - if(handler[ev.type]) + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) handler[ev.type](&ev); /* call handler */ } void -scan(void) { +scan(void) +{ unsigned int i, num; Window d1, d2, *wins = NULL; XWindowAttributes wa; - if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for(i = 0; i < num; i++) { - if(!XGetWindowAttributes(dpy, wins[i], &wa) + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) continue; - if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); } - for(i = 0; i < num; i++) { /* now the transients */ - if(!XGetWindowAttributes(dpy, wins[i], &wa)) + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) continue; - if(XGetTransientForHint(dpy, wins[i], &d1) + if (XGetTransientForHint(dpy, wins[i], &d1) && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) manage(wins[i], &wa); } - if(wins) + if (wins) XFree(wins); } } void -sendmon(Client *c, Monitor *m) { - if(c->mon == m) +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) return; unfocus(c, 1); detach(c); @@ -1398,7 +1441,8 @@ sendmon(Client *c, Monitor *m) { } void -setclientstate(Client *c, long state) { +setclientstate(Client *c, long state) +{ long data[] = { state, None }; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, @@ -1406,18 +1450,19 @@ setclientstate(Client *c, long state) { } int -sendevent(Client *c, Atom proto) { +sendevent(Client *c, Atom proto) +{ int n; Atom *protocols; int exists = 0; XEvent ev; - if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while(!exists && n--) + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) exists = protocols[n] == proto; XFree(protocols); } - if(exists) { + if (exists) { ev.type = ClientMessage; ev.xclient.window = c->win; ev.xclient.message_type = wmatom[WMProtocols]; @@ -1430,8 +1475,9 @@ sendevent(Client *c, Atom proto) { } void -setfocus(Client *c) { - if(!c->neverfocus) { +setfocus(Client *c) +{ + if (!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], XA_WINDOW, 32, PropModeReplace, @@ -1441,8 +1487,9 @@ setfocus(Client *c) { } void -setfullscreen(Client *c, int fullscreen) { - if(fullscreen && !c->isfullscreen) { +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); c->isfullscreen = 1; @@ -1452,8 +1499,7 @@ setfullscreen(Client *c, int fullscreen) { c->isfloating = 1; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); - } - else if(!fullscreen && c->isfullscreen){ + } else if (!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); c->isfullscreen = 0; @@ -1469,13 +1515,14 @@ setfullscreen(Client *c, int fullscreen) { } void -setlayout(const Arg *arg) { - if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) selmon->sellt ^= 1; - if(arg && arg->v) + if (arg && arg->v) selmon->lt[selmon->sellt] = (Layout *)arg->v; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) + if (selmon->sel) arrange(selmon); else drawbar(selmon); @@ -1483,20 +1530,22 @@ setlayout(const Arg *arg) { /* arg > 1.0 will set mfact absolutly */ void -setmfact(const Arg *arg) { +setmfact(const Arg *arg) +{ float f; - if(!arg || !selmon->lt[selmon->sellt]->arrange) + if (!arg || !selmon->lt[selmon->sellt]->arrange) return; f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) + if (f < 0.1 || f > 0.9) return; selmon->mfact = f; arrange(selmon); } void -setup(void) { +setup(void) +{ XSetWindowAttributes wa; /* clean up any zombies immediately */ @@ -1555,34 +1604,38 @@ setup(void) { } void -showhide(Client *c) { - if(!c) +showhide(Client *c) +{ + if (!c) return; - if(ISVISIBLE(c)) { /* show clients top down */ + if (ISVISIBLE(c)) { + /* show clients top down */ XMoveWindow(dpy, c->win, c->x, c->y); - if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) resize(c, c->x, c->y, c->w, c->h, 0); showhide(c->snext); - } - else { /* hide clients bottom up */ + } else { + /* hide clients bottom up */ showhide(c->snext); XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); } } void -sigchld(int unused) { - if(signal(SIGCHLD, sigchld) == SIG_ERR) +sigchld(int unused) +{ + if (signal(SIGCHLD, sigchld) == SIG_ERR) die("can't install SIGCHLD handler:"); - while(0 < waitpid(-1, NULL, WNOHANG)); + while (0 < waitpid(-1, NULL, WNOHANG)); } void -spawn(const Arg *arg) { - if(arg->v == dmenucmd) +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; - if(fork() == 0) { - if(dpy) + if (fork() == 0) { + if (dpy) close(ConnectionNumber(dpy)); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); @@ -1593,8 +1646,9 @@ spawn(const Arg *arg) { } void -tag(const Arg *arg) { - if(selmon->sel && arg->ui & TAGMASK) { +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; focus(NULL); arrange(selmon); @@ -1602,32 +1656,33 @@ tag(const Arg *arg) { } void -tagmon(const Arg *arg) { - if(!selmon->sel || !mons->next) +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) return; sendmon(selmon->sel, dirtomon(arg->i)); } void -tile(Monitor *m) { +tile(Monitor *m) +{ unsigned int i, n, h, mw, my, ty; Client *c; - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if(n == 0) + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) return; - if(n > m->nmaster) + if (n > m->nmaster) mw = m->nmaster ? m->ww * m->mfact : 0; else mw = m->ww; - for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if(i < m->nmaster) { + for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { h = (m->wh - my) / (MIN(n, m->nmaster) - i); resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); my += HEIGHT(c); - } - else { + } else { h = (m->wh - ty) / (n - i); resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); ty += HEIGHT(c); @@ -1635,7 +1690,8 @@ tile(Monitor *m) { } void -togglebar(const Arg *arg) { +togglebar(const Arg *arg) +{ selmon->showbar = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); @@ -1643,26 +1699,28 @@ togglebar(const Arg *arg) { } void -togglefloating(const Arg *arg) { - if(!selmon->sel) +togglefloating(const Arg *arg) +{ + if (!selmon->sel) return; - if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ return; selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if(selmon->sel->isfloating) + if (selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, selmon->sel->w, selmon->sel->h, 0); arrange(selmon); } void -toggletag(const Arg *arg) { +toggletag(const Arg *arg) +{ unsigned int newtags; - if(!selmon->sel) + if (!selmon->sel) return; newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if(newtags) { + if (newtags) { selmon->sel->tags = newtags; focus(NULL); arrange(selmon); @@ -1670,10 +1728,11 @@ toggletag(const Arg *arg) { } void -toggleview(const Arg *arg) { +toggleview(const Arg *arg) +{ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - if(newtagset) { + if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; focus(NULL); arrange(selmon); @@ -1681,26 +1740,28 @@ toggleview(const Arg *arg) { } void -unfocus(Client *c, int setfocus) { - if(!c) +unfocus(Client *c, int setfocus) +{ + if (!c) return; grabbuttons(c, 0); XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); - if(setfocus) { + if (setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); } } void -unmanage(Client *c, int destroyed) { +unmanage(Client *c, int destroyed) +{ Monitor *m = c->mon; XWindowChanges wc; /* The server grab construct avoids race conditions. */ detach(c); detachstack(c); - if(!destroyed) { + if (!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); XSetErrorHandler(xerrordummy); @@ -1718,12 +1779,13 @@ unmanage(Client *c, int destroyed) { } void -unmapnotify(XEvent *e) { +unmapnotify(XEvent *e) +{ Client *c; XUnmapEvent *ev = &e->xunmap; - if((c = wintoclient(ev->window))) { - if(ev->send_event) + if ((c = wintoclient(ev->window))) { + if (ev->send_event) setclientstate(c, WithdrawnState); else unmanage(c, 0); @@ -1731,14 +1793,15 @@ unmapnotify(XEvent *e) { } void -updatebars(void) { +updatebars(void) +{ Monitor *m; XSetWindowAttributes wa = { .override_redirect = True, .background_pixmap = ParentRelative, .event_mask = ButtonPressMask|ExposureMask }; - for(m = mons; m; m = m->next) { + for (m = mons; m; m = m->next) { if (m->barwin) continue; m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), @@ -1750,61 +1813,63 @@ updatebars(void) { } void -updatebarpos(Monitor *m) { +updatebarpos(Monitor *m) +{ m->wy = m->my; m->wh = m->mh; - if(m->showbar) { + if (m->showbar) { m->wh -= bh; m->by = m->topbar ? m->wy : m->wy + m->wh; m->wy = m->topbar ? m->wy + bh : m->wy; - } - else + } else m->by = -bh; } void -updateclientlist() { +updateclientlist() +{ Client *c; Monitor *m; XDeleteProperty(dpy, root, netatom[NetClientList]); - for(m = mons; m; m = m->next) - for(c = m->clients; c; c = c->next) + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); } int -updategeom(void) { +updategeom(void) +{ int dirty = 0; #ifdef XINERAMA - if(XineramaIsActive(dpy)) { + if (XineramaIsActive(dpy)) { int i, j, n, nn; Client *c; Monitor *m; XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; - for(n = 0, m = mons; m; m = m->next, n++); + for (n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for(i = 0, j = 0; i < nn; i++) - if(isuniquegeom(unique, j, &info[i])) + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); nn = j; - if(n <= nn) { - for(i = 0; i < (nn - n); i++) { /* new monitors available */ - for(m = mons; m && m->next; m = m->next); - if(m) + if (n <= nn) { + for (i = 0; i < (nn - n); i++) { /* new monitors available */ + for (m = mons; m && m->next; m = m->next); + if (m) m->next = createmon(); else mons = createmon(); } - for(i = 0, m = mons; i < nn && m; m = m->next, i++) - if(i >= n + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n || (unique[i].x_org != m->mx || unique[i].y_org != m->my || unique[i].width != m->mw || unique[i].height != m->mh)) { @@ -1816,11 +1881,11 @@ updategeom(void) { m->mh = m->wh = unique[i].height; updatebarpos(m); } - } - else { /* less monitors available nn < n */ - for(i = nn; i < n; i++) { - for(m = mons; m && m->next; m = m->next); - while(m->clients) { + } else { + /* less monitors available nn < n */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while (m->clients) { dirty = 1; c = m->clients; m->clients = c->next; @@ -1829,27 +1894,26 @@ updategeom(void) { attach(c); attachstack(c); } - if(m == selmon) + if (m == selmon) selmon = mons; cleanupmon(m); } } free(unique); - } - else + } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) + if (!mons) mons = createmon(); - if(mons->mw != sw || mons->mh != sh) { + if (mons->mw != sw || mons->mh != sh) { dirty = 1; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - if(dirty) { + if (dirty) { selmon = mons; selmon = wintomon(root); } @@ -1857,108 +1921,106 @@ updategeom(void) { } void -updatenumlockmask(void) { +updatenumlockmask(void) +{ unsigned int i, j; XModifierKeymap *modmap; numlockmask = 0; modmap = XGetModifierMapping(dpy); - for(i = 0; i < 8; i++) - for(j = 0; j < modmap->max_keypermod; j++) - if(modmap->modifiermap[i * modmap->max_keypermod + j] + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) numlockmask = (1 << i); XFreeModifiermap(modmap); } void -updatesizehints(Client *c) { +updatesizehints(Client *c) +{ long msize; XSizeHints size; - if(!XGetWMNormalHints(dpy, c->win, &size, &msize)) + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) /* size is uninitialized, ensure that size.flags aren't used */ size.flags = PSize; - if(size.flags & PBaseSize) { + if (size.flags & PBaseSize) { c->basew = size.base_width; c->baseh = size.base_height; - } - else if(size.flags & PMinSize) { + } else if (size.flags & PMinSize) { c->basew = size.min_width; c->baseh = size.min_height; - } - else + } else c->basew = c->baseh = 0; - if(size.flags & PResizeInc) { + if (size.flags & PResizeInc) { c->incw = size.width_inc; c->inch = size.height_inc; - } - else + } else c->incw = c->inch = 0; - if(size.flags & PMaxSize) { + if (size.flags & PMaxSize) { c->maxw = size.max_width; c->maxh = size.max_height; - } - else + } else c->maxw = c->maxh = 0; - if(size.flags & PMinSize) { + if (size.flags & PMinSize) { c->minw = size.min_width; c->minh = size.min_height; - } - else if(size.flags & PBaseSize) { + } else if (size.flags & PBaseSize) { c->minw = size.base_width; c->minh = size.base_height; - } - else + } else c->minw = c->minh = 0; - if(size.flags & PAspect) { + if (size.flags & PAspect) { c->mina = (float)size.min_aspect.y / size.min_aspect.x; c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } - else + } else c->maxa = c->mina = 0.0; c->isfixed = (c->maxw && c->minw && c->maxh && c->minh && c->maxw == c->minw && c->maxh == c->minh); } void -updatetitle(Client *c) { - if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if(c->name[0] == '\0') /* hack to mark broken clients */ + if (c->name[0] == '\0') /* hack to mark broken clients */ strcpy(c->name, broken); } void -updatestatus(void) { - if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) strcpy(stext, "dwm-"VERSION); drawbar(selmon); } void -updatewindowtype(Client *c) { +updatewindowtype(Client *c) +{ Atom state = getatomprop(c, netatom[NetWMState]); Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - if(state == netatom[NetWMFullscreen]) + if (state == netatom[NetWMFullscreen]) setfullscreen(c, 1); - if(wtype == netatom[NetWMWindowTypeDialog]) + if (wtype == netatom[NetWMWindowTypeDialog]) c->isfloating = 1; } void -updatewmhints(Client *c) { +updatewmhints(Client *c) +{ XWMHints *wmh; - if((wmh = XGetWMHints(dpy, c->win))) { - if(c == selmon->sel && wmh->flags & XUrgencyHint) { + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { wmh->flags &= ~XUrgencyHint; XSetWMHints(dpy, c->win, wmh); - } - else + } else c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if(wmh->flags & InputHint) + if (wmh->flags & InputHint) c->neverfocus = !wmh->input; else c->neverfocus = 0; @@ -1967,40 +2029,43 @@ updatewmhints(Client *c) { } void -view(const Arg *arg) { - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if(arg->ui & TAGMASK) + if (arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; focus(NULL); arrange(selmon); } Client * -wintoclient(Window w) { +wintoclient(Window w) +{ Client *c; Monitor *m; - for(m = mons; m; m = m->next) - for(c = m->clients; c; c = c->next) - if(c->win == w) + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) return c; return NULL; } Monitor * -wintomon(Window w) { +wintomon(Window w) +{ int x, y; Client *c; Monitor *m; - if(w == root && getrootptr(&x, &y)) + if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) - if(w == m->barwin) + for (m = mons; m; m = m->next) + if (w == m->barwin) return m; - if((c = wintoclient(w))) + if ((c = wintoclient(w))) return c->mon; return selmon; } @@ -2009,8 +2074,9 @@ wintomon(Window w) { * ignored (especially on UnmapNotify's). Other types of errors call Xlibs * default error handler, which may call exit. */ int -xerror(Display *dpy, XErrorEvent *ee) { - if(ee->error_code == BadWindow +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) @@ -2026,40 +2092,44 @@ xerror(Display *dpy, XErrorEvent *ee) { } int -xerrordummy(Display *dpy, XErrorEvent *ee) { +xerrordummy(Display *dpy, XErrorEvent *ee) +{ return 0; } /* Startup Error handler to check if another window manager * is already running. */ int -xerrorstart(Display *dpy, XErrorEvent *ee) { +xerrorstart(Display *dpy, XErrorEvent *ee) +{ die("dwm: another window manager is already running\n"); return -1; } void -zoom(const Arg *arg) { +zoom(const Arg *arg) +{ Client *c = selmon->sel; - if(!selmon->lt[selmon->sellt]->arrange + if (!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating)) return; - if(c == nexttiled(selmon->clients)) - if(!c || !(c = nexttiled(c->next))) + if (c == nexttiled(selmon->clients)) + if (!c || !(c = nexttiled(c->next))) return; pop(c); } int -main(int argc, char *argv[]) { - if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2015 dwm engineers, see LICENSE for details\n"); - else if(argc != 1) +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION "\n"); + else if (argc != 1) die("usage: dwm [-v]\n"); - if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fputs("warning: no locale support\n", stderr); - if(!(dpy = XOpenDisplay(NULL))) + if (!(dpy = XOpenDisplay(NULL))) die("dwm: cannot open display\n"); checkotherwm(); setup(); From 4ec3a673ff81275a9157d6801ea4a2b17031e5ba Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Sat, 19 Dec 2015 20:04:19 +0100 Subject: [PATCH 056/137] Shut up glibc about _BSD_SOURCE being deprecated --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 4eefb71..80dc936 100644 --- a/config.mk +++ b/config.mk @@ -25,7 +25,7 @@ INCS = -I${X11INC} -I${FREETYPEINC} LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} # flags -CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = -s ${LIBS} From 3465bed290abc62cb2e69a8096084ba6b8eb4956 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 19 Dec 2015 20:25:26 +0100 Subject: [PATCH 057/137] fix fullscreen clients not resized on X display resolution change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit patch provided by Bert Münnich , thanks! --- dwm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 0362114..ff7e096 100644 --- a/dwm.c +++ b/dwm.c @@ -565,6 +565,7 @@ void configurenotify(XEvent *e) { Monitor *m; + Client *c; XConfigureEvent *ev = &e->xconfigure; int dirty; @@ -576,8 +577,12 @@ configurenotify(XEvent *e) if (updategeom() || dirty) { drw_resize(drw, sw, bh); updatebars(); - for (m = mons; m; m = m->next) + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } focus(NULL); arrange(NULL); } From cd2d7549b3ae5ec234b45d85608f79f4d3aaa851 Mon Sep 17 00:00:00 2001 From: Eric Pruitt Date: Wed, 25 May 2016 16:33:11 -0700 Subject: [PATCH 058/137] Configure geometry before applying rules Configuring geometry before applying rules makes it possible to have more complex constraints in applyrules that depend on the initial window dimensions and location. --- dwm.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dwm.c b/dwm.c index ff7e096..9585683 100644 --- a/dwm.c +++ b/dwm.c @@ -1043,6 +1043,13 @@ manage(Window w, XWindowAttributes *wa) c = ecalloc(1, sizeof(Client)); c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; @@ -1051,12 +1058,6 @@ manage(Window w, XWindowAttributes *wa) c->mon = selmon; applyrules(c); } - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) c->x = c->mon->mx + c->mon->mw - WIDTH(c); From 7af4d439bdb5a2e40aca69446a3367bd71431c45 Mon Sep 17 00:00:00 2001 From: Markus Teich Date: Sun, 22 May 2016 22:33:56 +0200 Subject: [PATCH 059/137] import new drw from libsl and minor fixes. - better scaling for occupied tag squares. - draw statusline first to omitt some complicated calculations. --- config.def.h | 24 ++--- drw.c | 253 ++++++++++++++++++++++++++++----------------------- drw.h | 63 +++++-------- dwm.c | 85 ++++++++--------- util.h | 4 +- 5 files changed, 215 insertions(+), 214 deletions(-) diff --git a/config.def.h b/config.def.h index 7054c06..13ea4b9 100644 --- a/config.def.h +++ b/config.def.h @@ -1,20 +1,22 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const char *fonts[] = { - "monospace:size=10" -}; -static const char dmenufont[] = "monospace:size=10"; -static const char normbordercolor[] = "#444444"; -static const char normbgcolor[] = "#222222"; -static const char normfgcolor[] = "#bbbbbb"; -static const char selbordercolor[] = "#005577"; -static const char selbgcolor[] = "#005577"; -static const char selfgcolor[] = "#eeeeee"; static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=10" }; +static const char dmenufont[] = "monospace:size=10"; +static const char col_gray1[] = "#222222"; +static const char col_gray2[] = "#444444"; +static const char col_gray3[] = "#bbbbbb"; +static const char col_gray4[] = "#eeeeee"; +static const char col_cyan[] = "#005577"; +static const char *colors[][3] = { + /* fg bg border */ + { col_gray3, col_gray1, col_gray2}, /* normal */ + { col_gray4, col_cyan, col_cyan }, /* selected */ +}; /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; @@ -54,7 +56,7 @@ static const Layout layouts[] = { /* commands */ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; static const char *termcmd[] = { "st", NULL }; static Key keys[] = { diff --git a/drw.c b/drw.c index f49200b..987e53b 100644 --- a/drw.c +++ b/drw.c @@ -63,9 +63,8 @@ utf8decode(const char *c, long *u, size_t clen) Drw * drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { - Drw *drw; + Drw *drw = ecalloc(1, sizeof(Drw)); - drw = ecalloc(1, sizeof(Drw)); drw->dpy = dpy; drw->screen = screen; drw->root = root; @@ -73,7 +72,6 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->h = h; drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); drw->gc = XCreateGC(dpy, root, 0, NULL); - drw->fontcount = 0; XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; @@ -82,6 +80,9 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h void drw_resize(Drw *drw, unsigned int w, unsigned int h) { + if (!drw) + return; + drw->w = w; drw->h = h; if (drw->drawable) @@ -92,44 +93,39 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) void drw_free(Drw *drw) { - size_t i; - - for (i = 0; i < drw->fontcount; i++) - drw_font_free(drw->fonts[i]); XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); free(drw); } /* This function is an implementation detail. Library users should use - * drw_font_create instead. + * drw_fontset_create instead. */ static Fnt * -drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) { Fnt *font; XftFont *xfont = NULL; FcPattern *pattern = NULL; if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield same - * the same substitution results as using the pattern returned by + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in - * missing-character-rectangles being drawn, at least with some fonts. - */ + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); return NULL; } if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); XftFontClose(drw->dpy, xfont); return NULL; } } else if (fontpattern) { if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font pattern.\n"); + fprintf(stderr, "error, cannot load font from pattern.\n"); return NULL; } } else { @@ -139,37 +135,14 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; - font->ascent = xfont->ascent; - font->descent = xfont->descent; - font->h = font->ascent + font->descent; + font->h = xfont->ascent + xfont->descent; font->dpy = drw->dpy; return font; } -Fnt* -drw_font_create(Drw *drw, const char *fontname) -{ - return drw_font_xcreate(drw, fontname, NULL); -} - -void -drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) -{ - size_t i; - Fnt *font; - - for (i = 0; i < fontcount; i++) { - if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { - die("font cache exhausted.\n"); - } else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) { - drw->fonts[drw->fontcount++] = font; - } - } -} - -void -drw_font_free(Fnt *font) +static void +xfont_free(Fnt *font) { if (!font) return; @@ -179,55 +152,98 @@ drw_font_free(Fnt *font) free(font); } -Clr * -drw_clr_create(Drw *drw, const char *clrname) +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) { - Clr *clr; + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create(Drw *drw, XftColor *dest, const char *clrname) +{ + if (!drw || !dest || !clrname) + return; - clr = ecalloc(1, sizeof(Clr)); if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen), - clrname, &clr->rgb)) + clrname, dest)) die("error, cannot allocate color '%s'\n", clrname); - clr->pix = clr->rgb.pixel; +} - return clr; +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Scm +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +{ + size_t i; + Scm ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; } void -drw_clr_free(Clr *clr) +drw_setfontset(Drw *drw, Fnt *set) { - free(clr); + if (drw) + drw->fonts = set; } void -drw_setscheme(Drw *drw, ClrScheme *scheme) +drw_setscheme(Drw *drw, Scm scm) { - drw->scheme = scheme; + if (drw) + drw->scheme = scm; } void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) { - if (!drw->scheme) + if (!drw || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1); - else if (empty) - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); } int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { char buf[1024]; - int tx, ty, th; - Extnts tex; + int ty; + unsigned int ew; XftDraw *d = NULL; - Fnt *curfont, *nextfont; + Fnt *usedfont, *curfont, *nextfont; size_t i, len; - int utf8strlen, utf8charlen, render; + int utf8strlen, utf8charlen, render = x || y || w || h; long utf8codepoint = 0; const char *utf8str; FcCharSet *fccharset; @@ -236,66 +252,67 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex XftResult result; int charexists = 0; - if (!drw->scheme || !drw->fontcount) + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0; - if (!(render = x || y || w || h)) { + if (!render) { w = ~w; } else { - XSetForeground(drw->dpy, drw->gc, invert ? - drw->scheme->fg->pix : drw->scheme->bg->pix); + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); d = XftDrawCreate(drw->dpy, drw->drawable, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; } - curfont = drw->fonts[0]; + usedfont = drw->fonts; while (1) { utf8strlen = 0; utf8str = text; nextfont = NULL; while (*text) { utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (i = 0; i < drw->fontcount; i++) { - charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); if (charexists) { - if (drw->fonts[i] == curfont) { + if (curfont == usedfont) { utf8strlen += utf8charlen; text += utf8charlen; } else { - nextfont = drw->fonts[i]; + nextfont = curfont; } break; } } - if (!charexists || (nextfont && nextfont != curfont)) + if (!charexists || nextfont) break; else charexists = 0; } if (utf8strlen) { - drw_font_getexts(curfont, utf8str, utf8strlen, &tex); + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) - drw_font_getexts(curfont, utf8str, len, &tex); + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); if (len) { memcpy(buf, utf8str, len); buf[len] = '\0'; if (len < utf8strlen) - for (i = len; i && i > len - 3; buf[--i] = '.'); + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ if (render) { - th = curfont->ascent + curfont->descent; - ty = y + (h / 2) - (th / 2) + curfont->ascent; - tx = x + (h / 2); - XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len); + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)buf, len); } - x += tex.w; - w -= tex.w; + x += ew; + w -= ew; } } @@ -303,26 +320,21 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex break; } else if (nextfont) { charexists = 0; - curfont = nextfont; + usedfont = nextfont; } else { /* Regardless of whether or not a fallback font is found, the - * character must be drawn. - */ + * character must be drawn. */ charexists = 1; - if (drw->fontcount >= DRW_FONT_CACHE_SIZE) - continue; - fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); - if (!drw->fonts[0]->pattern) { - /* Refer to the comment in drw_font_xcreate for more - * information. */ + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ die("the first font in the cache must be loaded from a font string.\n"); } - fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern); + fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); @@ -334,12 +346,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex FcPatternDestroy(fcpattern); if (match) { - curfont = drw_font_xcreate(drw, NULL, match); - if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { - drw->fonts[drw->fontcount++] = curfont; + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; } else { - drw_font_free(curfont); - curfont = drw->fonts[0]; + xfont_free(usedfont); + usedfont = drw->fonts; } } } @@ -347,34 +361,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex if (d) XftDrawDestroy(d); - return x; + return x + (render ? w : 0); } void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { + if (!drw) + return; + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); XSync(drw->dpy, False); } +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0); +} + void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { XGlyphInfo ext; + if (!font || !text) + return; + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - tex->h = font->h; - tex->w = ext.xOff; -} - -unsigned int -drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) -{ - Extnts tex; - - drw_font_getexts(font, text, len, &tex); - - return tex.w; + if (w) + *w = ext.xOff; + if (h) + *h = font->h; } Cur * @@ -382,7 +402,9 @@ drw_cur_create(Drw *drw, int shape) { Cur *cur; - cur = ecalloc(1, sizeof(Cur)); + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + cur->cursor = XCreateFontCursor(drw->dpy, shape); return cur; @@ -393,6 +415,7 @@ drw_cur_free(Drw *drw, Cur *cursor) { if (!cursor) return; + XFreeCursor(drw->dpy, cursor->cursor); free(cursor); } diff --git a/drw.h b/drw.h index e3b8515..ff4355b 100644 --- a/drw.h +++ b/drw.h @@ -1,29 +1,19 @@ /* See LICENSE file for copyright and license details. */ -#define DRW_FONT_CACHE_SIZE 32 - -typedef struct { - unsigned long pix; - XftColor rgb; -} Clr; typedef struct { Cursor cursor; } Cur; -typedef struct { +typedef struct Fnt { Display *dpy; - int ascent; - int descent; unsigned int h; XftFont *xfont; FcPattern *pattern; + struct Fnt *next; } Fnt; -typedef struct { - Clr *fg; - Clr *bg; - Clr *border; -} ClrScheme; +enum { ColFg, ColBg, ColCount }; /* Scm index */ +typedef XftColor *Scm; typedef struct { unsigned int w, h; @@ -32,43 +22,36 @@ typedef struct { Window root; Drawable drawable; GC gc; - ClrScheme *scheme; - size_t fontcount; - Fnt *fonts[DRW_FONT_CACHE_SIZE]; + Scm scheme; + Fnt *fonts; } Drw; -typedef struct { - unsigned int w; - unsigned int h; -} Extnts; - /* Drawable abstraction */ -Drw *drw_create(Display *, int, Window, unsigned int, unsigned int); -void drw_resize(Drw *, unsigned int, unsigned int); -void drw_free(Drw *); +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); /* Fnt abstraction */ -Fnt *drw_font_create(Drw *, const char *); -void drw_load_fonts(Drw *, const char *[], size_t); -void drw_font_free(Fnt *); -void drw_font_getexts(Fnt *, const char *, unsigned int, Extnts *); -unsigned int drw_font_getexts_width(Fnt *, const char *, unsigned int); +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); -/* Colour abstraction */ -Clr *drw_clr_create(Drw *, const char *); -void drw_clr_free(Clr *); +/* Colorscheme abstraction */ +void drw_clr_create(Drw *drw, XftColor *dest, const char *clrname); +Scm drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); /* Cursor abstraction */ -Cur *drw_cur_create(Drw *, int); -void drw_cur_free(Drw *, Cur *); +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ -void drw_setfont(Drw *, Fnt *); -void drw_setscheme(Drw *, ClrScheme *); +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Scm scm); /* Drawing functions */ -void drw_rect(Drw *, int, int, unsigned int, unsigned int, int, int, int); -int drw_text(Drw *, int, int, unsigned int, unsigned int, const char *, int); +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); /* Map functions */ -void drw_map(Drw *, Window, int, int, unsigned int, unsigned int); +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/dwm.c b/dwm.c index 9585683..b2bc9bd 100644 --- a/dwm.c +++ b/dwm.c @@ -55,7 +55,8 @@ #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#define ColBorder 2 /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -240,6 +241,7 @@ static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { @@ -261,7 +263,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; static Cur *cursor[CurLast]; -static ClrScheme scheme[SchemeLast]; +static Scm scheme[SchemeLast]; static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; @@ -481,11 +483,8 @@ cleanup(void) cleanupmon(mons); for (i = 0; i < CurLast; i++) drw_cur_free(drw, cursor[i]); - for (i = 0; i < SchemeLast; i++) { - drw_clr_free(scheme[i].border); - drw_clr_free(scheme[i].bg); - drw_clr_free(scheme[i].fg); - } + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); @@ -709,11 +708,18 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, xx, w, dx; + int x, w, sw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; Client *c; - dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + sw = TEXTW(stext) - lrpad / 2; /* no right padding so status text hugs the corner */ + drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2 - 2, stext, 0); + } for (c = m->clients; c; c = c->next) { occ |= c->tags; @@ -723,36 +729,27 @@ drawbar(Monitor *m) x = 0; for (i = 0; i < LENGTH(tags); i++) { w = TEXTW(tags[i]); - drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); - drw_rect(drw, x + 1, 1, dx, dx, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - occ & 1 << i, urg & 1 << i); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); x += w; } w = blw = TEXTW(m->ltsymbol); - drw_setscheme(drw, &scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); - x += w; - xx = x; - if (m == selmon) { /* status is only drawn on selected monitor */ - w = TEXTW(stext); - x = m->ww - w; - if (x < xx) { - x = xx; - w = m->ww - xx; - } - drw_text(drw, x, 0, w, bh, stext, 0); - } else - x = m->ww; - if ((w = x - xx) > bh) { - x = xx; + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - sw - x) > bh) { if (m->sel) { - drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, m->sel->name, 0); - drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0); + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); } else { - drw_setscheme(drw, &scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 0, 1); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); } } drw_map(drw, m->barwin, 0, 0, m->ww, bh); @@ -812,7 +809,7 @@ focus(Client *c) detachstack(c); attachstack(c); grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); setfocus(c); } else { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -1071,7 +1068,7 @@ manage(Window w, XWindowAttributes *wa) wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1563,10 +1560,10 @@ setup(void) sh = DisplayHeight(dpy, screen); root = RootWindow(dpy, screen); drw = drw_create(dpy, screen, root, sw, sh); - drw_load_fonts(drw, fonts, LENGTH(fonts)); - if (!drw->fontcount) + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1586,12 +1583,8 @@ setup(void) cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - scheme[SchemeNorm].border = drw_clr_create(drw, normbordercolor); - scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor); - scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor); - scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor); - scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor); - scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor); + scheme[SchemeNorm] = drw_scm_create(drw, colors[SchemeNorm], 3); + scheme[SchemeSel] = drw_scm_create(drw, colors[SchemeSel], 3); /* init bars */ updatebars(); updatestatus(); @@ -1751,7 +1744,7 @@ unfocus(Client *c, int setfocus) if (!c) return; grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); if (setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); diff --git a/util.h b/util.h index cded043..f633b51 100644 --- a/util.h +++ b/util.h @@ -4,5 +4,5 @@ #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) -void die(const char *errstr, ...); -void *ecalloc(size_t, size_t); +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); From 56a31dc4a7be459e3a1ea06d45427e1a4087a1a6 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 28 Jun 2016 18:04:56 +0200 Subject: [PATCH 060/137] config.def.h: style improvement, use color Scheme enum --- config.def.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 13ea4b9..fd77a07 100644 --- a/config.def.h +++ b/config.def.h @@ -12,10 +12,10 @@ static const char col_gray2[] = "#444444"; static const char col_gray3[] = "#bbbbbb"; static const char col_gray4[] = "#eeeeee"; static const char col_cyan[] = "#005577"; -static const char *colors[][3] = { - /* fg bg border */ - { col_gray3, col_gray1, col_gray2}, /* normal */ - { col_gray4, col_cyan, col_cyan }, /* selected */ +static const char *colors[SchemeLast][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, }; /* tagging */ From ab9571bbc5f6fb04fd583238a665a7e830fc1397 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 12 Aug 2016 14:35:25 +0200 Subject: [PATCH 061/137] die() consistency: always add newline --- drw.c | 6 +++--- dwm.c | 10 +++++----- util.c | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drw.c b/drw.c index 987e53b..319eb6b 100644 --- a/drw.c +++ b/drw.c @@ -129,7 +129,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) return NULL; } } else { - die("no font specified.\n"); + die("no font specified."); } font = ecalloc(1, sizeof(Fnt)); @@ -188,7 +188,7 @@ drw_clr_create(Drw *drw, XftColor *dest, const char *clrname) if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen), clrname, dest)) - die("error, cannot allocate color '%s'\n", clrname); + die("error, cannot allocate color '%s'", clrname); } /* Wrapper to create color schemes. The caller has to call free(3) on the @@ -331,7 +331,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (!drw->fonts->pattern) { /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string.\n"); + die("the first font in the cache must be loaded from a font string."); } fcpattern = FcPatternDuplicate(drw->fonts->pattern); diff --git a/dwm.c b/dwm.c index b2bc9bd..421bf27 100644 --- a/dwm.c +++ b/dwm.c @@ -1561,7 +1561,7 @@ setup(void) root = RootWindow(dpy, screen); drw = drw_create(dpy, screen, root, sw, sh); if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded.\n"); + die("no fonts could be loaded."); lrpad = drw->fonts->h; bh = drw->fonts->h + 2; updategeom(); @@ -2101,7 +2101,7 @@ xerrordummy(Display *dpy, XErrorEvent *ee) int xerrorstart(Display *dpy, XErrorEvent *ee) { - die("dwm: another window manager is already running\n"); + die("dwm: another window manager is already running"); return -1; } @@ -2123,13 +2123,13 @@ int main(int argc, char *argv[]) { if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION "\n"); + die("dwm-"VERSION); else if (argc != 1) - die("usage: dwm [-v]\n"); + die("usage: dwm [-v]"); if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display\n"); + die("dwm: cannot open display"); checkotherwm(); setup(); scan(); diff --git a/util.c b/util.c index 6b703e9..b0612af 100644 --- a/util.c +++ b/util.c @@ -27,6 +27,8 @@ die(const char *fmt, ...) { if (fmt[0] && fmt[strlen(fmt)-1] == ':') { fputc(' ', stderr); perror(NULL); + } else { + fputc('\n', stderr); } exit(1); From 24849acada79977cea6acd2d8741d2bd00891ff6 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 5 Nov 2016 11:34:52 +0100 Subject: [PATCH 062/137] die() on calloc failure thanks Markus Teich and David! --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index b0612af..fe044fc 100644 --- a/util.c +++ b/util.c @@ -12,7 +12,7 @@ ecalloc(size_t nmemb, size_t size) void *p; if (!(p = calloc(nmemb, size))) - perror(NULL); + die("calloc:"); return p; } From 7a59cd14573b2ead4e69a609e27992f0b7493b19 Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 14 Nov 2016 11:18:27 +0100 Subject: [PATCH 063/137] dwm.1: add keybinding for spawning dmenu --- dwm.1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dwm.1 b/dwm.1 index 6687011..60ca1d6 100644 --- a/dwm.1 +++ b/dwm.1 @@ -59,6 +59,11 @@ click on a tag label adds/removes that tag to/from the focused window. Start .BR st(1). .TP +.B Mod1\-p +Spawn +.BR dmenu(1) +for launching other programs. +.TP .B Mod1\-, Focus previous screen, if any. .TP From 839c7f6939368fe5784058975ee95062cc88d4c3 Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 14 Nov 2016 11:49:17 +0100 Subject: [PATCH 064/137] LICENSE: update people --- LICENSE | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 4fbb67e..90121f5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,18 +1,22 @@ MIT/X Consortium License © 2006-2014 Anselm R Garbe -© 2010-2014 Hiltjo Posthuma -© 2007-2011 Peter Hartlich -© 2010-2011 Connor Lane Smith © 2006-2009 Jukka Salmi -© 2007-2009 Premysl Hruby +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich © 2007-2009 Szabolcs Nagy © 2007-2009 Christof Musik -© 2009 Mate Nagy +© 2007-2009 Premysl Hruby © 2007-2008 Enno Gottox Boland © 2008 Martin Hurton © 2008 Neale Pickett -© 2006-2007 Sander van Dijk +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016 Markus Teich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), From a137a86a234476bc3c7128fecbf845e6fc1de995 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 5 Dec 2016 09:54:20 +0100 Subject: [PATCH 065/137] applied Markus' clarify status text padding patch --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 421bf27..dbff59b 100644 --- a/dwm.c +++ b/dwm.c @@ -717,8 +717,8 @@ drawbar(Monitor *m) /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext) - lrpad / 2; /* no right padding so status text hugs the corner */ - drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2 - 2, stext, 0); + sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); } for (c = m->clients; c; c = c->next) { From 975c8983762246b50026d43079c60a78b341f81c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 5 Dec 2016 10:01:33 +0100 Subject: [PATCH 066/137] applied Markus' decouple color-scheme patch --- config.def.h | 2 +- dwm.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/config.def.h b/config.def.h index fd77a07..ba9a240 100644 --- a/config.def.h +++ b/config.def.h @@ -12,7 +12,7 @@ static const char col_gray2[] = "#444444"; static const char col_gray3[] = "#bbbbbb"; static const char col_gray4[] = "#eeeeee"; static const char col_cyan[] = "#005577"; -static const char *colors[SchemeLast][3] = { +static const char *colors[][3] = { /* fg bg border */ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, [SchemeSel] = { col_gray4, col_cyan, col_cyan }, diff --git a/dwm.c b/dwm.c index dbff59b..3d6cc28 100644 --- a/dwm.c +++ b/dwm.c @@ -60,7 +60,7 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ @@ -263,7 +263,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; static Cur *cursor[CurLast]; -static Scm scheme[SchemeLast]; +static Scm *scheme; static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; @@ -483,7 +483,7 @@ cleanup(void) cleanupmon(mons); for (i = 0; i < CurLast; i++) drw_cur_free(drw, cursor[i]); - for (i = 0; i < SchemeLast; i++) + for (i = 0; i < LENGTH(colors); i++) free(scheme[i]); drw_free(drw); XSync(dpy, False); @@ -1549,6 +1549,7 @@ setmfact(const Arg *arg) void setup(void) { + int i; XSetWindowAttributes wa; /* clean up any zombies immediately */ @@ -1583,8 +1584,9 @@ setup(void) cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - scheme[SchemeNorm] = drw_scm_create(drw, colors[SchemeNorm], 3); - scheme[SchemeSel] = drw_scm_create(drw, colors[SchemeSel], 3); + scheme = ecalloc(LENGTH(colors), sizeof(Scm)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); /* init bars */ updatebars(); updatestatus(); From 5376947571040a4654384ea8889a54cc2313cca7 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 5 Dec 2016 10:05:00 +0100 Subject: [PATCH 067/137] applied Ian Remmler's man page adjustment suggestions --- dwm.1 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dwm.1 b/dwm.1 index 60ca1d6..e3b2c38 100644 --- a/dwm.1 +++ b/dwm.1 @@ -10,8 +10,9 @@ and floating layouts. Either layout can be applied dynamically, optimising the environment for the application in use and the task performed. .P In tiled layouts windows are managed in a master and stacking area. The master -area contains the window which currently needs most attention, whereas the -stacking area contains all other windows. In monocle layout all windows are +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are maximised to the screen size. In floating layout windows can be resized and moved freely. Dialog windows are always managed floating, regardless of the layout applied. @@ -98,10 +99,10 @@ Focus next window. Focus previous window. .TP .B Mod1\-i -Increase clients in master area. +Increase number of windows in master area. .TP .B Mod1\-d -Decrease clients in master area. +Decrease number of windows in master area. .TP .B Mod1\-l Increase master area size. From e63bf229485a576d68975dd4eb00c210394133ae Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 5 Dec 2016 10:09:49 +0100 Subject: [PATCH 068/137] applied Ivan Delalande's NET_SUPPORTING_WM_CHECK patch for gtk3 compatibility --- dwm.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 3d6cc28..ca6f679 100644 --- a/dwm.c +++ b/dwm.c @@ -61,7 +61,7 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ @@ -267,7 +267,7 @@ static Scm *scheme; static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; -static Window root; +static Window root, wmcheckwin; /* configuration, allows nested code to access above variables */ #include "config.h" @@ -485,6 +485,7 @@ cleanup(void) drw_cur_free(drw, cursor[i]); for (i = 0; i < LENGTH(colors); i++) free(scheme[i]); + XDestroyWindow(dpy, wmcheckwin); drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); @@ -1551,6 +1552,7 @@ setup(void) { int i; XSetWindowAttributes wa; + Atom utf8string; /* clean up any zombies immediately */ sigchld(0); @@ -1567,6 +1569,7 @@ setup(void) bh = drw->fonts->h + 2; updategeom(); /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); @@ -1575,6 +1578,7 @@ setup(void) netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); @@ -1590,6 +1594,14 @@ setup(void) /* init bars */ updatebars(); updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 4); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *) netatom, NetLast); From bb3bd6fec37174e8d4bb9457ca815c00609e5157 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 5 Dec 2016 10:16:46 +0100 Subject: [PATCH 069/137] applied Markus' tagset purge of alternative view on _NET_ACTIVE_WINDOW event --- dwm.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/dwm.c b/dwm.c index ca6f679..d27cb67 100644 --- a/dwm.c +++ b/dwm.c @@ -153,7 +153,6 @@ static void buttonpress(XEvent *e); static void checkotherwm(void); static void cleanup(void); static void cleanupmon(Monitor *mon); -static void clearurgent(Client *c); static void clientmessage(XEvent *e); static void configure(Client *c); static void configurenotify(XEvent *e); @@ -204,6 +203,7 @@ static void setfullscreen(Client *c, int fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); +static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); @@ -508,19 +508,6 @@ cleanupmon(Monitor *mon) free(mon); } -void -clearurgent(Client *c) -{ - XWMHints *wmh; - - c->isurgent = 0; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - void clientmessage(XEvent *e) { @@ -534,11 +521,8 @@ clientmessage(XEvent *e) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); } else if (cme->message_type == netatom[NetActiveWindow]) { - if (!ISVISIBLE(c)) { - c->mon->seltags ^= 1; - c->mon->tagset[c->mon->seltags] = c->tags; - } - pop(c); + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); } } @@ -806,7 +790,7 @@ focus(Client *c) if (c->mon != selmon) selmon = c->mon; if (c->isurgent) - clearurgent(c); + seturgent(c, 0); detachstack(c); attachstack(c); grabbuttons(c, 1); @@ -1616,6 +1600,20 @@ setup(void) focus(NULL); } + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + void showhide(Client *c) { From 2952b68db88f38be8d34b80c7a7d2c7eb5b2484d Mon Sep 17 00:00:00 2001 From: Markus Teich Date: Sat, 7 Jan 2017 17:21:28 +0100 Subject: [PATCH 070/137] cleanup - unify multi-line expression alignment style. - unify multi-line function call alignment style. - simplify client moving on monitor count decrease. - clarify comment for focusin(). - remove old confusing comment about input focus fix in focusmon(). The explanation is already in the old commit message, so no need to keep it in the code. - remove old comment describing even older state of the code in focus(). - unify comment style. - break up some long lines. - fix some typos and grammar. --- LICENSE | 2 +- config.def.h | 2 +- dwm.c | 64 ++++++++++++++++++++++++---------------------------- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/LICENSE b/LICENSE index 90121f5..fc41d77 100644 --- a/LICENSE +++ b/LICENSE @@ -16,7 +16,7 @@ MIT/X Consortium License © 2011 Christoph Lohmann <20h@r-36.net> © 2015-2016 Quentin Rameau © 2015-2016 Eric Pruitt -© 2016 Markus Teich +© 2016-2017 Markus Teich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/config.def.h b/config.def.h index ba9a240..a9ac303 100644 --- a/config.def.h +++ b/config.def.h @@ -15,7 +15,7 @@ static const char col_cyan[] = "#005577"; static const char *colors[][3] = { /* fg bg border */ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, }; /* tagging */ diff --git a/dwm.c b/dwm.c index d27cb67..3f80b63 100644 --- a/dwm.c +++ b/dwm.c @@ -3,7 +3,7 @@ * dynamic window manager is designed like any other X client as well. It is * driven through handling X events. In contrast to other X clients, a window * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is + * events about window (dis-)appearance. Only one X connection at a time is * allowed to select for this event mask. * * The event handlers of dwm are organized in an array which is accessed @@ -11,7 +11,7 @@ * in O(1) time. * * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client + * set the override_redirect flag. Clients are organized in a linked client * list on each monitor, the focus history is remembered through a stack list * on each monitor. Each client contains a bit array to indicate the tags of a * client. @@ -517,7 +517,8 @@ clientmessage(XEvent *e) if (!c) return; if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen]) + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); } else if (cme->message_type == netatom[NetActiveWindow]) { @@ -783,7 +784,6 @@ focus(Client *c) { if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - /* was if (selmon->sel) */ if (selmon->sel && selmon->sel != c) unfocus(selmon->sel, 0); if (c) { @@ -804,7 +804,7 @@ focus(Client *c) drawbars(); } -/* there are some broken focus acquiring clients */ +/* there are some broken focus acquiring clients needing extra handling */ void focusin(XEvent *e) { @@ -823,8 +823,7 @@ focusmon(const Arg *arg) return; if ((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues - in gedit and anjuta */ + unfocus(selmon->sel, 0); selmon = m; focus(NULL); } @@ -961,7 +960,7 @@ grabkeys(void) if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) for (j = 0; j < LENGTH(modifiers); j++) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + True, GrabModeAsync, GrabModeAsync); } } @@ -1151,7 +1150,7 @@ movemouse(const Arg *arg) ocx = c->x; ocy = c->y; if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; if (!getrootptr(&x, &y)) return; @@ -1434,7 +1433,7 @@ setclientstate(Client *c, long state) long data[] = { state, None }; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); + PropModeReplace, (unsigned char *)data, 2); } int @@ -1516,7 +1515,7 @@ setlayout(const Arg *arg) drawbar(selmon); } -/* arg > 1.0 will set mfact absolutly */ +/* arg > 1.0 will set mfact absolutely */ void setmfact(const Arg *arg) { @@ -1581,19 +1580,20 @@ setup(void) /* supporting window for NetWMCheck */ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); + PropModeReplace, (unsigned char *) &wmcheckwin, 1); XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 4); + PropModeReplace, (unsigned char *) "dwm", 4); XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); + PropModeReplace, (unsigned char *) &wmcheckwin, 1); /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); + PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select for events */ + /* select events */ wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask - |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); grabkeys(); @@ -1769,12 +1769,11 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; - /* The server grab construct avoids race conditions. */ detach(c); detachstack(c); if (!destroyed) { wc.border_width = c->oldbw; - XGrabServer(dpy); + XGrabServer(dpy); /* avoid race conditions */ XSetErrorHandler(xerrordummy); XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ XUngrabButton(dpy, AnyButton, AnyModifier, c->win); @@ -1871,8 +1870,8 @@ updategeom(void) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); nn = j; - if (n <= nn) { - for (i = 0; i < (nn - n); i++) { /* new monitors available */ + if (n <= nn) { /* new monitors available */ + for (i = 0; i < (nn - n); i++) { for (m = mons; m && m->next; m = m->next); if (m) m->next = createmon(); @@ -1881,8 +1880,8 @@ updategeom(void) } for (i = 0, m = mons; i < nn && m; m = m->next, i++) if (i >= n - || (unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh)) + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) { dirty = 1; m->num = i; @@ -1892,13 +1891,11 @@ updategeom(void) m->mh = m->wh = unique[i].height; updatebarpos(m); } - } else { - /* less monitors available nn < n */ + } else { /* less monitors available nn < n */ for (i = nn; i < n; i++) { for (m = mons; m && m->next; m = m->next); - while (m->clients) { + while ((c = m->clients)) { dirty = 1; - c = m->clients; m->clients = c->next; detachstack(c); c->mon = mons; @@ -1913,8 +1910,7 @@ updategeom(void) free(unique); } else #endif /* XINERAMA */ - /* default monitor setup */ - { + { /* default monitor setup */ if (!mons) mons = createmon(); if (mons->mw != sw || mons->mh != sh) { @@ -1988,7 +1984,7 @@ updatesizehints(Client *c) } else c->maxa = c->mina = 0.0; c->isfixed = (c->maxw && c->minw && c->maxh && c->minh - && c->maxw == c->minw && c->maxh == c->minh); + && c->maxw == c->minw && c->maxh == c->minh); } void @@ -2082,8 +2078,8 @@ wintomon(Window w) } /* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ int xerror(Display *dpy, XErrorEvent *ee) { @@ -2098,7 +2094,7 @@ xerror(Display *dpy, XErrorEvent *ee) || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) return 0; fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); + ee->request_code, ee->error_code); return xerrorxlib(dpy, ee); /* may call exit */ } From 022d07605412bc5bd9726f74af9355c562ba4957 Mon Sep 17 00:00:00 2001 From: Markus Teich Date: Sat, 7 Jan 2017 17:21:29 +0100 Subject: [PATCH 071/137] Button passthrough when client is not focused Before this change it is not possible to press a button in a client on the first click if the client is not yet focused. The first click on the button would only focus the client and a second click on the button is needed to activate it. This situation can occur when moving the mouse over a client (therefore focusing it) and then moving the focus to another client with keyboard shortcuts. After this commit the behavior is fixed and button presses on unfocused clients are passed to the client correctly. --- dwm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/dwm.c b/dwm.c index 3f80b63..9c01d1a 100644 --- a/dwm.c +++ b/dwm.c @@ -446,6 +446,8 @@ buttonpress(XEvent *e) click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); click = ClkClientWin; } for (i = 0; i < LENGTH(buttons); i++) @@ -932,17 +934,16 @@ grabbuttons(Client *c, int focused) unsigned int i, j; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (focused) { - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } else + if (!focused) XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); } } From 5b238c8dab945023b6a16a6c9f642b11137f2204 Mon Sep 17 00:00:00 2001 From: Markus Teich Date: Sat, 7 Jan 2017 17:21:30 +0100 Subject: [PATCH 072/137] Don't restrict snap in mousemove This also fixes a bug where client windows only switch to floating mode when the mouse is dragged in one specific direction. --- dwm.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/dwm.c b/dwm.c index 9c01d1a..7861512 100644 --- a/dwm.c +++ b/dwm.c @@ -1170,20 +1170,17 @@ movemouse(const Arg *arg) nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); - if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww - && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) { - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - } + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, nx, ny, c->w, c->h, 1); break; From ceac8c91ff3bf45ae53135658d6f560cb2335133 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 8 May 2017 21:08:27 +0200 Subject: [PATCH 073/137] yet another cleanup The previous patches introduced some unclean space-based indentation patterns. This patch fixes them. --- LICENSE | 2 +- dwm.c | 68 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/LICENSE b/LICENSE index fc41d77..954cdc9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2014 Anselm R Garbe +© 2006-2017 Anselm R Garbe © 2006-2009 Jukka Salmi © 2006-2007 Sander van Dijk © 2007-2011 Peter Hartlich diff --git a/dwm.c b/dwm.c index 7861512..a5ce993 100644 --- a/dwm.c +++ b/dwm.c @@ -522,7 +522,7 @@ clientmessage(XEvent *e) if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen]) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); } else if (cme->message_type == netatom[NetActiveWindow]) { if (c != selmon->sel && !c->isurgent) seturgent(c, 1); @@ -721,8 +721,8 @@ drawbar(Monitor *m) drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); if (occ & 1 << i) drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); x += w; } w = blw = TEXTW(m->ltsymbol); @@ -865,7 +865,7 @@ getatomprop(Client *c, Atom prop) Atom da, atom = None; if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { + &da, &di, &dl, &dl, &p) == Success && p) { atom = *(Atom *)p; XFree(p); } @@ -892,7 +892,7 @@ getstate(Window w) Atom real; if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) + &real, &format, &n, &extra, (unsigned char **)&p) != Success) return -1; if (n != 0) result = *p; @@ -936,14 +936,14 @@ grabbuttons(Client *c, int focused) XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if (!focused) XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); for (i = 0; i < LENGTH(buttons); i++) if (buttons[i].click == ClkClientWin) for (j = 0; j < LENGTH(modifiers); j++) XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); } } @@ -961,7 +961,7 @@ grabkeys(void) if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) for (j = 0; j < LENGTH(modifiers); j++) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + True, GrabModeAsync, GrabModeAsync); } } @@ -1048,7 +1048,7 @@ manage(Window w, XWindowAttributes *wa) c->x = MAX(c->x, c->mon->mx); /* only fix client y-offset, if the client center might cover the bar */ c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); c->bw = borderpx; wc.border_width = c->bw; @@ -1067,7 +1067,7 @@ manage(Window w, XWindowAttributes *wa) attach(c); attachstack(c); XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); + (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); if (c->mon == selmon) @@ -1151,7 +1151,7 @@ movemouse(const Arg *arg) ocx = c->x; ocy = c->y; if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; if (!getrootptr(&x, &y)) return; @@ -1226,7 +1226,7 @@ propertynotify(XEvent *e) default: break; case XA_WM_TRANSIENT_FOR: if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) + (c->isfloating = (wintoclient(trans)) != NULL)) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: @@ -1306,7 +1306,7 @@ resizemouse(const Arg *arg) ocx = c->x; ocy = c->y; if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) return; XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); do { @@ -1431,7 +1431,7 @@ setclientstate(Client *c, long state) long data[] = { state, None }; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); + PropModeReplace, (unsigned char *)data, 2); } int @@ -1465,8 +1465,8 @@ setfocus(Client *c) if (!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); } sendevent(c, wmatom[WMTakeFocus]); } @@ -1476,7 +1476,7 @@ setfullscreen(Client *c, int fullscreen) { if (fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); c->isfullscreen = 1; c->oldstate = c->isfloating; c->oldbw = c->bw; @@ -1486,7 +1486,7 @@ setfullscreen(Client *c, int fullscreen) XRaiseWindow(dpy, c->win); } else if (!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); + PropModeReplace, (unsigned char*)0, 0); c->isfullscreen = 0; c->isfloating = c->oldstate; c->bw = c->oldbw; @@ -1578,20 +1578,20 @@ setup(void) /* supporting window for NetWMCheck */ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); + PropModeReplace, (unsigned char *) &wmcheckwin, 1); XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 4); + PropModeReplace, (unsigned char *) "dwm", 4); XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); + PropModeReplace, (unsigned char *) &wmcheckwin, 1); /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); + PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); /* select events */ wa.cursor = cursor[CurNormal]->cursor; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); grabkeys(); @@ -1717,7 +1717,7 @@ togglefloating(const Arg *arg) selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if (selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); + selmon->sel->w, selmon->sel->h, 0); arrange(selmon); } @@ -1813,8 +1813,8 @@ updatebars(void) if (m->barwin) continue; m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); } @@ -1843,8 +1843,8 @@ updateclientlist() for (m = mons; m; m = m->next) for (c = m->clients; c; c = c->next) XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); } int @@ -1936,7 +1936,7 @@ updatenumlockmask(void) for (i = 0; i < 8; i++) for (j = 0; j < modmap->max_keypermod; j++) if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) + == XKeysymToKeycode(dpy, XK_Num_Lock)) numlockmask = (1 << i); XFreeModifiermap(modmap); } @@ -1982,7 +1982,7 @@ updatesizehints(Client *c) } else c->maxa = c->mina = 0.0; c->isfixed = (c->maxw && c->minw && c->maxh && c->minh - && c->maxw == c->minw && c->maxh == c->minh); + && c->maxw == c->minw && c->maxh == c->minh); } void @@ -2092,7 +2092,7 @@ xerror(Display *dpy, XErrorEvent *ee) || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) return 0; fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); + ee->request_code, ee->error_code); return xerrorxlib(dpy, ee); /* may call exit */ } From 6aa8e37efe22c8a2a7713d9a437491c564c04b7e Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Wed, 11 Oct 2017 08:10:45 +1100 Subject: [PATCH 074/137] simplify isfixed conditions --- dwm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index a5ce993..4782343 100644 --- a/dwm.c +++ b/dwm.c @@ -1981,8 +1981,7 @@ updatesizehints(Client *c) c->maxa = (float)size.max_aspect.x / size.max_aspect.y; } else c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh - && c->maxw == c->minw && c->maxh == c->minh); + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); } void From a9b6a312a77b9cc81ca8b08a95c09e9f7948d7a6 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Fri, 3 Nov 2017 09:58:38 -0700 Subject: [PATCH 075/137] Set class name on status bar This is useful for configuring compositors to ignore the status bar window. --- dwm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dwm.c b/dwm.c index 4782343..b0d99c0 100644 --- a/dwm.c +++ b/dwm.c @@ -1809,6 +1809,7 @@ updatebars(void) .background_pixmap = ParentRelative, .event_mask = ButtonPressMask|ExposureMask }; + XClassHint ch = {"dwm", "dwm"}; for (m = mons; m; m = m->next) { if (m->barwin) continue; @@ -1817,6 +1818,7 @@ updatebars(void) CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); } } From 99f78fa553f9ddb23fab73e47a408d66ca7f974c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 3 Nov 2017 16:36:32 +0100 Subject: [PATCH 076/137] gettextprop: check result of XGetTextProperty (undefined behaviour for XFree) --- dwm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index b0d99c0..650d19f 100644 --- a/dwm.c +++ b/dwm.c @@ -910,8 +910,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) if (!text || size == 0) return 0; text[0] = '\0'; - XGetTextProperty(dpy, w, &name, atom); - if (!name.nitems) + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) return 0; if (name.encoding == XA_STRING) strncpy(text, (char *)name.value, size - 1); From 3756f7f6b8dccf7a31789ffaf073a76fd1a87eb9 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 3 Nov 2017 21:20:48 +0100 Subject: [PATCH 077/137] sync dmenu drw.{c,h} code: use Clr* (was Scm) --- drw.c | 10 +++++----- drw.h | 12 ++++++------ dwm.c | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drw.c b/drw.c index 319eb6b..c638323 100644 --- a/drw.c +++ b/drw.c @@ -180,7 +180,7 @@ drw_fontset_free(Fnt *font) } void -drw_clr_create(Drw *drw, XftColor *dest, const char *clrname) +drw_clr_create(Drw *drw, Clr *dest, const char *clrname) { if (!drw || !dest || !clrname) return; @@ -193,14 +193,14 @@ drw_clr_create(Drw *drw, XftColor *dest, const char *clrname) /* Wrapper to create color schemes. The caller has to call free(3) on the * returned color scheme when done using it. */ -Scm +Clr * drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) { size_t i; - Scm ret; + Clr *ret; /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr)))) return NULL; for (i = 0; i < clrcount; i++) @@ -216,7 +216,7 @@ drw_setfontset(Drw *drw, Fnt *set) } void -drw_setscheme(Drw *drw, Scm scm) +drw_setscheme(Drw *drw, Clr *scm) { if (drw) drw->scheme = scm; diff --git a/drw.h b/drw.h index ff4355b..4c67419 100644 --- a/drw.h +++ b/drw.h @@ -12,8 +12,8 @@ typedef struct Fnt { struct Fnt *next; } Fnt; -enum { ColFg, ColBg, ColCount }; /* Scm index */ -typedef XftColor *Scm; +enum { ColFg, ColBg }; /* Clr scheme index */ +typedef XftColor Clr; typedef struct { unsigned int w, h; @@ -22,7 +22,7 @@ typedef struct { Window root; Drawable drawable; GC gc; - Scm scheme; + Clr *scheme; Fnt *fonts; } Drw; @@ -38,8 +38,8 @@ unsigned int drw_fontset_getwidth(Drw *drw, const char *text); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); /* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, XftColor *dest, const char *clrname); -Scm drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); @@ -47,7 +47,7 @@ void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Scm scm); +void drw_setscheme(Drw *drw, Clr *scm); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); diff --git a/dwm.c b/dwm.c index 650d19f..ff893df 100644 --- a/dwm.c +++ b/dwm.c @@ -263,7 +263,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; static Cur *cursor[CurLast]; -static Scm *scheme; +static Clr **scheme; static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; @@ -1568,7 +1568,7 @@ setup(void) cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Scm)); + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); for (i = 0; i < LENGTH(colors); i++) scheme[i] = drw_scm_create(drw, colors[i], 3); /* init bars */ From db2236001c1cb042a2f24052849da96578273b1c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 27 Dec 2017 13:36:53 +0100 Subject: [PATCH 078/137] dont NUL terminate _NET_WM_NAME Reported by Kernc, thanks! "This makes a particular program that uses libwnck [1] fail after: Wnck-WARNING **: Property _NET_WM_NAME contained invalid UTF-8 in this code [2] because the returned string contains a '\0' and the documentation for g_utf8_validate() [3] explicitly states that when string length is provided, no nul bytes are allowed." It is not entirely clear it is incorrect, other WM's seem to not NUL terminate it either though. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index ff893df..ec6a27c 100644 --- a/dwm.c +++ b/dwm.c @@ -1579,7 +1579,7 @@ setup(void) XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, PropModeReplace, (unsigned char *) &wmcheckwin, 1); XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 4); + PropModeReplace, (unsigned char *) "dwm", 3); XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, PropModeReplace, (unsigned char *) &wmcheckwin, 1); /* EWMH support per view */ From 3cb34830eb25ebda15a23d8391fd69cddb4fc024 Mon Sep 17 00:00:00 2001 From: Christopher Drelich Date: Wed, 14 Mar 2018 17:44:53 +0100 Subject: [PATCH 079/137] ColBorder has been moved to the enum with ColFg and ColBg. --- drw.h | 2 +- dwm.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drw.h b/drw.h index 4c67419..4bcd5ad 100644 --- a/drw.h +++ b/drw.h @@ -12,7 +12,7 @@ typedef struct Fnt { struct Fnt *next; } Fnt; -enum { ColFg, ColBg }; /* Clr scheme index */ +enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ typedef XftColor Clr; typedef struct { diff --git a/dwm.c b/dwm.c index ec6a27c..ab16c75 100644 --- a/dwm.c +++ b/dwm.c @@ -56,7 +56,6 @@ #define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -#define ColBorder 2 /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ From 76c8c16d79d4fd2a3e776800637d211e4dc8e50a Mon Sep 17 00:00:00 2001 From: Christopher Drelich Date: Wed, 14 Mar 2018 13:58:06 -0400 Subject: [PATCH 080/137] All functions in alphabetical order except for this one. --- dwm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index ab16c75..c98678d 100644 --- a/dwm.c +++ b/dwm.c @@ -223,8 +223,8 @@ static void updateclientlist(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); -static void updatewindowtype(Client *c); static void updatetitle(Client *c); +static void updatewindowtype(Client *c); static void updatewmhints(Client *c); static void view(const Arg *arg); static Client *wintoclient(Window w); @@ -1984,6 +1984,14 @@ updatesizehints(Client *c) c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); } +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + void updatetitle(Client *c) { @@ -1993,14 +2001,6 @@ updatetitle(Client *c) strcpy(c->name, broken); } -void -updatestatus(void) -{ - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - drawbar(selmon); -} - void updatewindowtype(Client *c) { From 3bd8466e93b2c81be86e67c6ecdda4e1d240fe4b Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 14 Mar 2018 21:03:11 +0100 Subject: [PATCH 081/137] update README: remove mentioning the old dextra repo Thanks Christopher Drelich --- README | 3 --- 1 file changed, 3 deletions(-) diff --git a/README b/README index 7abf1cf..95d4fd0 100644 --- a/README +++ b/README @@ -18,9 +18,6 @@ necessary as root): make clean install -If you are going to use the default bluegray color scheme it is highly -recommended to also install the bluegray files shipped in the dextra package. - Running dwm ----------- From 10dfa65860d770cbce2cdaf67618f44f726a27c3 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 12 May 2018 19:14:19 +0200 Subject: [PATCH 082/137] remove old TODO and BUGS entries the bug in the dwm man page is an (ancient) Java issue. Thanks David and quinq for the patches and feedback! --- BUGS | 44 -------------------------------------------- Makefile | 2 +- TODO | 4 ---- dwm.1 | 12 +++--------- 4 files changed, 4 insertions(+), 58 deletions(-) delete mode 100644 BUGS delete mode 100644 TODO diff --git a/BUGS b/BUGS deleted file mode 100644 index 6c9574a..0000000 --- a/BUGS +++ /dev/null @@ -1,44 +0,0 @@ ---- - -18:17 < Biolunar> when i change my resolution in dwm (to a smaller one) and then back to the native, the top bar is not repainted. that's since 5.7.2, in 5.6 it worked fine -18:19 < Biolunar> is it just happening to me or a (known) bug? -18:24 < Biolunar> and in addition, mplayers fullscreen is limited to the small resolution after i changed it back to the native - -reproducible with xrandr -s but not with --output and --mode, strange - ---- - -yet another corner case: -open a terminal, focus another monitor, but without moving the mouse -pointer there -if there is no client on the other monitor to get the focus, then the -terminal will be unfocused but it will accept input - ---- - -Donald Allen reported this: - -starting emacs from dmenu in archlinux results in missing configure of emacs, but mod1-space or mod1-shift-space fix this problem. this problem is new and did not happen in 1.6 xorg servers - ---- - -voltaic reports this: - -When I use two monitors, one larger in resolution than the other, the -bar is drawn using the smaller x-dimension on both screens. I think -what's happening is that there are two bars drawn, but the short bar -is always on top of the long bar such that I can't see the information -under the short bar. If I switch to the small screen, hide the short -bar, and then switch to the large screen, the long bar is drawn -correctly. - -A similar problem occurs when I have started dwm on a small resolution -monitor (laptop screen) and then I switch to a large external display. -When I do this, the bar itself is drawn for the original smaller -resolution, but the information to be printed on the bar is -right-aligned for a longer bar. So what I see is a bar that has the -right hand side of it cut-off. See attached screenshot. - -I am using standard options for xrandr such as --output VGA1 --auto, etc. - ---- diff --git a/Makefile b/Makefile index 1ea40b7..d7acc01 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ clean: dist: clean @echo creating dist tarball @mkdir -p dwm-${VERSION} - @cp -R LICENSE TODO BUGS Makefile README config.def.h config.mk \ + @cp -R LICENSE Makefile README config.def.h config.mk \ dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} @tar -cf dwm-${VERSION}.tar dwm-${VERSION} @gzip dwm-${VERSION}.tar diff --git a/TODO b/TODO deleted file mode 100644 index b33a08d..0000000 --- a/TODO +++ /dev/null @@ -1,4 +0,0 @@ -- add a flag to Key to execute the command on release (needed for commands - affecting the keyboard grab, see scrot -s for example) -- add updategeom() hook for external tools like dzen -- consider onscreenkeyboard hooks for tablet deployment diff --git a/dwm.1 b/dwm.1 index e3b2c38..13b3729 100644 --- a/dwm.1 +++ b/dwm.1 @@ -158,7 +158,7 @@ code. This keeps it fast, secure and simple. .SH SEE ALSO .BR dmenu (1), .BR st (1) -.SH BUGS +.SH ISSUES Java applications which use the XToolkit/XAWT backend may draw grey windows only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds @@ -172,11 +172,5 @@ or (to pretend that a non-reparenting window manager is running that the XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable .BR _JAVA_AWT_WM_NONREPARENTING=1 . -.P -GTK 2.10.9+ versions contain a broken -.BR Save\-As -file dialog implementation, -which requests to reconfigure its window size in an endless loop. However, its -window is still respondable during this state, so you can simply ignore the flicker -until a new GTK version appears, which will fix this bug, approximately -GTK 2.10.12+ versions. +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. From c8e9479186dd7e3a0d6dc938369ab3bf7dc4a1d0 Mon Sep 17 00:00:00 2001 From: Christopher Drelich Date: Wed, 2 May 2018 18:09:50 -0400 Subject: [PATCH 083/137] Function declarations in correct order. In dwm.c function declarations are in alphabetical order except for updategeom(). There doesn't appear to be any reason for this, so this patch corrects that, and now all function declarations are in alphabetical order. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index c98678d..bb95e26 100644 --- a/dwm.c +++ b/dwm.c @@ -216,10 +216,10 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c, int setfocus); static void unmanage(Client *c, int destroyed); static void unmapnotify(XEvent *e); -static int updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); +static int updategeom(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); From c3a2e016bb65c00bd44b6461b1b1bbaa61f20093 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 25 May 2018 06:56:36 +0200 Subject: [PATCH 084/137] config.def.h: ClkTagBar missing from comment by Christopher Drelich Patch was mangled on the ML, also adjusted the order to be the same as the enum in dwm.c --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index a9ac303..1c0b587 100644 --- a/config.def.h +++ b/config.def.h @@ -97,7 +97,7 @@ static Key keys[] = { }; /* button definitions */ -/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static Button buttons[] = { /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, From f40f86fa873bc4acccdf3d929aa0f786993ae31d Mon Sep 17 00:00:00 2001 From: Klemens Nanni Date: Fri, 25 May 2018 07:56:27 +0200 Subject: [PATCH 085/137] Pledge on OpenBSD --- dwm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwm.c b/dwm.c index bb95e26..09feae3 100644 --- a/dwm.c +++ b/dwm.c @@ -2137,6 +2137,10 @@ main(int argc, char *argv[]) die("dwm: cannot open display"); checkotherwm(); setup(); +#ifdef __OpenBSD__ + if (pledge("stdio proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ scan(); run(); cleanup(); From 3cd4023fb35d0aeb6e888bfdc1845f2f0251ad20 Mon Sep 17 00:00:00 2001 From: Klemens Nanni Date: Sat, 2 Jun 2018 15:12:42 +0200 Subject: [PATCH 086/137] Do not strip at link stage Building with debug symbols is worthless unless LDFLAGS are manually adjusted as well. --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 80dc936..25e2685 100644 --- a/config.mk +++ b/config.mk @@ -28,7 +28,7 @@ LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = -s ${LIBS} +LDFLAGS = ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" From e78b4a9207d92956cee3e5bc3f70b5acabe72e5c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 2 Jun 2018 17:04:44 +0200 Subject: [PATCH 087/137] Makefile: just show the compiler output Don't be fancy and just show the actual output so debugging is simpler. --- Makefile | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index d7acc01..77bcbc0 100644 --- a/Makefile +++ b/Makefile @@ -15,46 +15,37 @@ options: @echo "CC = ${CC}" .c.o: - @echo CC $< - @${CC} -c ${CFLAGS} $< + ${CC} -c ${CFLAGS} $< ${OBJ}: config.h config.mk config.h: - @echo creating $@ from config.def.h - @cp config.def.h $@ + cp config.def.h $@ dwm: ${OBJ} - @echo CC -o $@ - @${CC} -o $@ ${OBJ} ${LDFLAGS} + ${CC} -o $@ ${OBJ} ${LDFLAGS} clean: - @echo cleaning - @rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz dist: clean - @echo creating dist tarball - @mkdir -p dwm-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ + mkdir -p dwm-${VERSION} + cp -R LICENSE Makefile README config.def.h config.mk\ dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} - @tar -cf dwm-${VERSION}.tar dwm-${VERSION} - @gzip dwm-${VERSION}.tar - @rm -rf dwm-${VERSION} + tar -cf dwm-${VERSION}.tar dwm-${VERSION} + gzip dwm-${VERSION}.tar + rm -rf dwm-${VERSION} install: all - @echo installing executable file to ${DESTDIR}${PREFIX}/bin - @mkdir -p ${DESTDIR}${PREFIX}/bin - @cp -f dwm ${DESTDIR}${PREFIX}/bin - @chmod 755 ${DESTDIR}${PREFIX}/bin/dwm - @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 - @mkdir -p ${DESTDIR}${MANPREFIX}/man1 - @sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 - @chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f dwm ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 uninstall: - @echo removing executable file from ${DESTDIR}${PREFIX}/bin - @rm -f ${DESTDIR}${PREFIX}/bin/dwm - @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 - @rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1 + rm -f ${DESTDIR}${PREFIX}/bin/dwm\ + ${DESTDIR}${MANPREFIX}/man1/dwm.1 .PHONY: all options clean dist install uninstall From b69c870a3076d78ab595ed1cd4b41cf6b03b2610 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 2 Jun 2018 17:15:42 +0200 Subject: [PATCH 088/137] pledge: add rpath promise for the ugly Xft font fallback --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 09feae3..4465af1 100644 --- a/dwm.c +++ b/dwm.c @@ -2138,7 +2138,7 @@ main(int argc, char *argv[]) checkotherwm(); setup(); #ifdef __OpenBSD__ - if (pledge("stdio proc exec", NULL) == -1) + if (pledge("stdio rpath proc exec", NULL) == -1) die("pledge"); #endif /* __OpenBSD__ */ scan(); From cb3f58ad06993f7ef3a7d8f61468012e2b786cab Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 2 Feb 2019 04:50:42 -0800 Subject: [PATCH 089/137] Prepare 6.2 release. --- LICENSE | 2 +- config.mk | 2 +- drw.c | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index 954cdc9..d221f09 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2017 Anselm R Garbe +© 2006-2019 Anselm R Garbe © 2006-2009 Jukka Salmi © 2006-2007 Sander van Dijk © 2007-2011 Peter Hartlich diff --git a/config.mk b/config.mk index 25e2685..6d36cb7 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.1 +VERSION = 6.2 # Customize below to fit your system diff --git a/drw.c b/drw.c index c638323..8fd1ca4 100644 --- a/drw.c +++ b/drw.c @@ -132,6 +132,19 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) die("no font specified."); } + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; @@ -200,7 +213,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) Clr *ret; /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr)))) + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) return NULL; for (i = 0; i < clrcount; i++) @@ -337,6 +350,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcDefaultSubstitute(fcpattern); From c82db690cc0c4624dad4dc6ae899020799ec84db Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 3 Apr 2020 15:36:32 +0200 Subject: [PATCH 090/137] config.mk: fix POSIX_C_SOURCE macro for feature test for snprintf() The feature test was incorrect: _POSIX_C_SOURCE=2 "The value 2 or greater additionally exposes definitions for POSIX.2-1992." http://man7.org/linux/man-pages/man7/feature_test_macros.7.html A higher value is needed (atleast 1995): https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html FreeBSD feature test macro: on https://github.com/freebsd/freebsd/blob/master/include/stdio.h line 297 This was already fixed in dmenu. This fixes a warning on FreeBSD, reported by Plasmoduck on IRC, thanks. --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 6d36cb7..7084c33 100644 --- a/config.mk +++ b/config.mk @@ -25,7 +25,7 @@ INCS = -I${X11INC} -I${FREETYPEINC} LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} # flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = ${LIBS} From a8e9513783f335b1ac7255e40a663adfffc4b475 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 20 Apr 2020 16:41:52 +0100 Subject: [PATCH 091/137] setmfact: Unify bounds for compile-time and runtime mfact There are two places that mfact can be set: - In the mfact global, which is defined at compile time and passed into m->mfact during monitor setup. No bounds checks are performed, but the comment alongside it says that valid values are [0.05..0.95]: static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ - By setmfact, which adjusts m->mfact at runtime. It also does some minimum and maximum bounds checks, allowing [0.1..0.9]. Values outside of that range are ignored, and mfact is not adjusted. These different thresholds mean that one cannot setmfact 0.95 or 0.05, despite the comment above that lists the legal range for mfact. Clarify this by enforcing the same bounds in setmfact at runtime as those listed for mfact at compile time. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 4465af1..41c6767 100644 --- a/dwm.c +++ b/dwm.c @@ -1520,7 +1520,7 @@ setmfact(const Arg *arg) if (!arg || !selmon->lt[selmon->sellt]->arrange) return; f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.1 || f > 0.9) + if (f < 0.05 || f > 0.95) return; selmon->mfact = f; arrange(selmon); From f087d20e6e60a49c756936b4312f5d194d8e63b4 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Wed, 22 Apr 2020 15:48:08 +0100 Subject: [PATCH 092/137] getatomprop: Add forward declaration No functional changes, but for every other function we have a forward declaration here. getatomprop should be no exception. --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 41c6767..972f261 100644 --- a/dwm.c +++ b/dwm.c @@ -169,6 +169,7 @@ static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); From ed3ab6b4fceded0e9f2d22372df49a2bbd58de66 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Wed, 22 Apr 2020 15:48:27 +0100 Subject: [PATCH 093/137] drawbar: Don't shadow sw global This jarred me a bit while reading the code, since "sw" usually refers to the global screen geometry, but in drawbar() only it refers to text-related geometry. Renaming it makes it more obvious that these are not related. --- dwm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index 972f261..fb1e326 100644 --- a/dwm.c +++ b/dwm.c @@ -696,7 +696,7 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, sw = 0; + int x, w, tw = 0; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; @@ -705,8 +705,8 @@ drawbar(Monitor *m) /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); } for (c = m->clients; c; c = c->next) { @@ -729,7 +729,7 @@ drawbar(Monitor *m) drw_setscheme(drw, scheme[SchemeNorm]); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - if ((w = m->ww - sw - x) > bh) { + if ((w = m->ww - tw - x) > bh) { if (m->sel) { drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); From f09418bbb6651ab4c299cfefbe1d18de401f630e Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 23 Apr 2020 09:50:54 +0200 Subject: [PATCH 094/137] dwm crashes when opening 50+ clients (tile layout) Many users new to dwm find themselves caught out by being kicked out to the login manager (dwm crashing) when they open 50+ clients for demonstration purposes. The number of clients reported varies depending on the resolution of the monitor. The cause of this is due to how the default tile layout calculates the height of the next client based on the position of the previous client. Because clients have a minimum size the (ty) position can exceed that of the window height, resulting in (m->wh - ty) becoming negative. The negative height stored as an unsigned int results in a very large height ultimately resulting in dwm crashing. This patch adds safeguards to prevent the ty and my positions from exceeding that of the window height. --- dwm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index fb1e326..9fd0286 100644 --- a/dwm.c +++ b/dwm.c @@ -1689,11 +1689,13 @@ tile(Monitor *m) if (i < m->nmaster) { h = (m->wh - my) / (MIN(n, m->nmaster) - i); resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); - my += HEIGHT(c); + if (my + HEIGHT(c) < m->wh) + my += HEIGHT(c); } else { h = (m->wh - ty) / (n - i); resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - ty += HEIGHT(c); + if (ty + HEIGHT(c) < m->wh) + ty += HEIGHT(c); } } From f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2 Mon Sep 17 00:00:00 2001 From: Alex Flierl Date: Thu, 11 Jun 2020 15:28:32 +0200 Subject: [PATCH 095/137] Fix memory leaks in drw The function drw_fontset_free in drw.c was never called. --- drw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drw.c b/drw.c index 8fd1ca4..4cdbcbe 100644 --- a/drw.c +++ b/drw.c @@ -95,6 +95,7 @@ drw_free(Drw *drw) { XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); free(drw); } From bb2e7222baeec7776930354d0e9f210cc2aaad5f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 8 Jul 2020 18:05:50 +0200 Subject: [PATCH 096/137] dwm.1: fix wrong text in man page --- dwm.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.1 b/dwm.1 index 13b3729..ddc8321 100644 --- a/dwm.1 +++ b/dwm.1 @@ -33,7 +33,7 @@ dwm draws a small border around windows to indicate the focus state. .SH OPTIONS .TP .B \-v -prints version information to standard output, then exits. +prints version information to stderr, then exits. .SH USAGE .SS Status bar .TP From 61bb8b2241d4db08bea4261c82e27cd9797099e7 Mon Sep 17 00:00:00 2001 From: Ian Remmler Date: Tue, 3 Mar 2020 16:23:53 -0600 Subject: [PATCH 097/137] Fix x coordinate calculation in buttonpress. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 9fd0286..664c527 100644 --- a/dwm.c +++ b/dwm.c @@ -440,7 +440,7 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + blw) click = ClkLtSymbol; - else if (ev->x > selmon->ww - TEXTW(stext)) + else if (ev->x > selmon->ww - (int)TEXTW(stext)) click = ClkStatusText; else click = ClkWinTitle; From 67d76bdc68102df976177de351f65329d8683064 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Thu, 2 Jul 2020 20:18:30 +0100 Subject: [PATCH 098/137] Do not allow focus to drift from fullscreen client via focusstack() It generally doesn't make much sense to allow focusstack() to navigate away from the selected fullscreen client, as you can't even see which client you're selecting behind it. I have had this up for a while on the wiki as a separate patch[0], but it seems reasonable to avoid this behaviour in dwm mainline, since I'm struggling to think of any reason to navigate away from a fullscreen client other than a mistake. 0: https://dwm.suckless.org/patches/alwaysfullscreen/ --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 664c527..b0b3466 100644 --- a/dwm.c +++ b/dwm.c @@ -835,7 +835,7 @@ focusstack(const Arg *arg) { Client *c = NULL, *i; - if (!selmon->sel) + if (!selmon->sel || selmon->sel->isfullscreen) return; if (arg->i > 0) { for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); From 138b405f0c8aa24d8a040cc1a1cf6e3eb5a0ebc7 Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 12 Jul 2021 23:44:16 +0200 Subject: [PATCH 099/137] Add a configuration option for fullscreen locking Some people are annoyed to have this new behaviour forced for some application which use fake fullscreen. --- config.def.h | 1 + dwm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 1c0b587..a2ac963 100644 --- a/config.def.h +++ b/config.def.h @@ -35,6 +35,7 @@ static const Rule rules[] = { static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ static const int nmaster = 1; /* number of clients in master area */ static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static const Layout layouts[] = { /* symbol arrange function */ diff --git a/dwm.c b/dwm.c index b0b3466..5e4d494 100644 --- a/dwm.c +++ b/dwm.c @@ -835,7 +835,7 @@ focusstack(const Arg *arg) { Client *c = NULL, *i; - if (!selmon->sel || selmon->sel->isfullscreen) + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) return; if (arg->i > 0) { for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); From 716233534b35f74dba5a46ade8f1a6f8cc72fea4 Mon Sep 17 00:00:00 2001 From: Miles Alan Date: Mon, 9 Aug 2021 18:24:14 +0200 Subject: [PATCH 100/137] Improve speed of drw_text when provided with large strings Calculates len & ew in drw_font_getexts loop by incrementing instead of decrementing; as such avoids proportional increase in time spent in loop based on provided strings size. --- drw.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drw.c b/drw.c index 4cdbcbe..9c39086 100644 --- a/drw.c +++ b/drw.c @@ -310,8 +310,11 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (utf8strlen) { drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + if (ew > w) + for (ew = 0, len = 0; ew < w - lpad * 2 && len < MIN(utf8strlen, sizeof(buf) - 1); len++) + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + else + len = MIN(utf8strlen, sizeof(buf) - 1); if (len) { memcpy(buf, utf8str, len); From a786211d6cb794fba0ea406d86002c7618998afc Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 20 Aug 2021 23:09:48 +0200 Subject: [PATCH 101/137] Revert "Improve speed of drw_text when provided with large strings" This reverts commit 716233534b35f74dba5a46ade8f1a6f8cc72fea4. It causes issues with truncation of characters when the text does not fit and so on. The patch should be reworked and properly tested. --- drw.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drw.c b/drw.c index 9c39086..4cdbcbe 100644 --- a/drw.c +++ b/drw.c @@ -310,11 +310,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (utf8strlen) { drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - if (ew > w) - for (ew = 0, len = 0; ew < w - lpad * 2 && len < MIN(utf8strlen, sizeof(buf) - 1); len++) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - else - len = MIN(utf8strlen, sizeof(buf) - 1); + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); if (len) { memcpy(buf, utf8str, len); From 8657affa2a61e85ca8df76b62e43cb02897d1d80 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Sat, 18 Dec 2021 16:58:23 +0000 Subject: [PATCH 102/137] drawbar: Don't expend effort drawing bar if it is occluded I noticed that a non-trivial amount of dwm's work on my machine was from drw_text, which seemed weird, because I have the bar disabled and we only use drw_text as part of bar drawing. Looking more closely, I realised that while we use m->showbar when updating the monitor bar margins, but don't skip actually drawing the bar if it is hidden. This patch skips drawing it entirely if that is the case. On my machine, this takes 10% of dwm's on-CPU time, primarily from restack() and focus(). When the bar is toggled on again, the X server will generate an Expose event, and we'll redraw the bar as normal as part of expose(). --- dwm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwm.c b/dwm.c index 5e4d494..a96f33c 100644 --- a/dwm.c +++ b/dwm.c @@ -702,6 +702,9 @@ drawbar(Monitor *m) unsigned int i, occ = 0, urg = 0; Client *c; + if (!m->showbar) + return; + /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ drw_setscheme(drw, scheme[SchemeNorm]); From d39e2f3441fe18aba8d1a62c08918a411ec6f237 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 7 Jan 2022 12:39:18 +0100 Subject: [PATCH 103/137] bump version to 6.3 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 7084c33..b6eb7e0 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.2 +VERSION = 6.3 # Customize below to fit your system From 60e9a14998bfe8666c641f7c27fec18e85ac7494 Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 11 Mar 2022 20:40:05 +0600 Subject: [PATCH 104/137] fix mem leak in cleanup() maybe leak isn't the best word, given that the object lives for the entire duration of the program's lifetime. however, all elements of scheme are free-ed, can't think of any reason why scheme itself should be an exception. --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index a96f33c..1ee4ea2 100644 --- a/dwm.c +++ b/dwm.c @@ -487,6 +487,7 @@ cleanup(void) drw_cur_free(drw, cursor[i]); for (i = 0; i < LENGTH(colors); i++) free(scheme[i]); + free(scheme); XDestroyWindow(dpy, wmcheckwin); drw_free(drw); XSync(dpy, False); From bece862a0fc4fc18ef9065b18cd28e2032d0d975 Mon Sep 17 00:00:00 2001 From: Miles Alan Date: Mon, 21 Feb 2022 01:10:56 -0500 Subject: [PATCH 105/137] manage: For isfloating/oldstate check/set, ensure trans client actually exists In certain instances trans may be set to a window that doesn't actually map to a client via wintoclient; in this case it doesn't make sense to set isfloating/oldstate since trans is essentially invalid in that case / correlates to the above condition check where trans is set / XGetTransientForHint is called. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 1ee4ea2..5f16260 100644 --- a/dwm.c +++ b/dwm.c @@ -1064,7 +1064,7 @@ manage(Window w, XWindowAttributes *wa) XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; + c->isfloating = c->oldstate = t || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); attach(c); From 8806b6e2379372900e3d9e0bf6604bc7f727350b Mon Sep 17 00:00:00 2001 From: Chris Down Date: Thu, 17 Mar 2022 15:56:13 +0000 Subject: [PATCH 106/137] manage: propertynotify: Reduce cost of unused size hints This patch defers all size hint calculations until they are actually needed, drastically reducing the number of calls to updatesizehints(), which can be expensive when called repeatedly (as it currently is during resizes). In my unscientific testing this reduces calls to updatesizehints() by over 90% during a typical work session. There are no functional changes for users other than an increase in responsiveness after resizes and a reduction in CPU time. In slower environments or X servers, this patch also offers an improvement in responsiveness that is often tangible after resizing a client that changes hints during resizes. There are two main motivations to defer this work to the time of hint application: 1. Some clients, especially terminals using incremental size hints, resend XA_WM_NORMAL_HINTS events on resize to avoid fighting with the WM or mouse resizing. For example, some terminals like urxvt clear PBaseSize and PResizeInc during XResizeWindow and restore them afterwards. For this reason, after the resize is concluded, we typically receive a backlogged XA_WM_NORMAL_HINTS message for each update period with movement, which is useless. In some cases one may get hundreds or thousands of XA_WM_NORMAL_HINTS messages on large resizes, and currently all of these result in a separate updatesizehints() call, of which all but the final one are immediately outdated. (We can't just blindly discard these messages during resizes like we do for EnterNotify, because some of them might actually be for other windows, and may not be XA_WM_NORMAL_HINTS events.) 2. For users which use resizehints=0 most of these updates are unused anyway -- in the normal case where the client is not floating these values won't be used, so there's no need to calculate them up front. A synthetic test using the mouse to resize a floating terminal window from roughly 256x256 to 1024x1024 and back again shows that the number of calls to updatesizehints() goes from over 500 before this patch (one for each update interval with movement) to 2 after this patch (one for each hint application), with no change in user visible behaviour. This also reduces the delay before dwm is ready to process new events again after a large resize on such a client, as it avoids the thundering herd of updatesizehints() calls when hundreds of backlogged XA_WM_NORMAL_HINTS messages appear at once after a resize is finished. --- dwm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 5f16260..d8075ad 100644 --- a/dwm.c +++ b/dwm.c @@ -89,7 +89,7 @@ struct Client { float mina, maxa; int x, y, w, h; int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; @@ -345,6 +345,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) if (*w < bh) *w = bh; if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); /* see last two sentences in ICCCM 4.1.2.3 */ baseismin = c->basew == c->minw && c->baseh == c->minh; if (!baseismin) { /* temporarily remove base dimensions */ @@ -1059,7 +1061,6 @@ manage(Window w, XWindowAttributes *wa) XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); - updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); @@ -1233,7 +1234,7 @@ propertynotify(XEvent *e) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: - updatesizehints(c); + c->hintsvalid = 0; break; case XA_WM_HINTS: updatewmhints(c); @@ -1989,6 +1990,7 @@ updatesizehints(Client *c) } else c->maxa = c->mina = 0.0; c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; } void From d93ff48803f04f1363bf303af1d7e6ccc5cb8d3f Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Mon, 21 Feb 2022 16:58:28 +0200 Subject: [PATCH 107/137] Update monitor positions also on removal When monitors are removed, the coordinates of existing monitors may change, if the removed monitors had smaller coordinates than the remaining ones. Remove special case handling so that the same update-if-necessary loop is run also in the case when monitors are removed. --- dwm.c | 68 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/dwm.c b/dwm.c index d8075ad..0fc328a 100644 --- a/dwm.c +++ b/dwm.c @@ -1876,42 +1876,42 @@ updategeom(void) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); nn = j; - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); + + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); } + if (m == selmon) + selmon = mons; + cleanupmon(m); } free(unique); } else From a4771de5ba54a38b062a7d748635f21c141b5c7e Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 26 Apr 2022 10:30:59 +0200 Subject: [PATCH 108/137] Revert "manage: For isfloating/oldstate check/set, ensure trans client actually exists" This reverts commit bece862a0fc4fc18ef9065b18cd28e2032d0d975. It caused a regression, for example: https://lists.suckless.org/hackers/2203/18220.html --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 0fc328a..823bf6b 100644 --- a/dwm.c +++ b/dwm.c @@ -1065,7 +1065,7 @@ manage(Window w, XWindowAttributes *wa) XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); if (!c->isfloating) - c->isfloating = c->oldstate = t || c->isfixed; + c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); attach(c); From a83dc2031050d786ddf5f329b57d658a931c94b7 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 26 Apr 2022 15:50:32 +0200 Subject: [PATCH 109/137] LICENSE: add Chris Down --- LICENSE | 1 + 1 file changed, 1 insertion(+) diff --git a/LICENSE b/LICENSE index d221f09..995172f 100644 --- a/LICENSE +++ b/LICENSE @@ -17,6 +17,7 @@ MIT/X Consortium License © 2015-2016 Quentin Rameau © 2015-2016 Eric Pruitt © 2016-2017 Markus Teich +© 2020-2022 Chris Down Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), From 8b48e309735f5fe49d35f86e967f4b5dea2a2f2d Mon Sep 17 00:00:00 2001 From: Chris Down Date: Tue, 26 Apr 2022 09:42:23 +0100 Subject: [PATCH 110/137] manage: Make sure c->isfixed is applied before floating checks Commit 8806b6e23793 ("manage: propertynotify: Reduce cost of unused size hints") mistakenly removed an early size hints update that's needed to populate c->isfixed for floating checks at manage() time. This resulted in fixed (size hint min dimensions == max dimensions) subset of windows not floating when they should. See https://lists.suckless.org/dev/2204/34730.html for discussion. --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 823bf6b..5646a5c 100644 --- a/dwm.c +++ b/dwm.c @@ -1061,6 +1061,7 @@ manage(Window w, XWindowAttributes *wa) XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); + updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); From cd0773cee9bad694dc9a6b1355a32bbe61abadff Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 1 May 2022 18:37:54 +0200 Subject: [PATCH 111/137] Makefile: add manual path for OpenBSD Reported by fossy , thanks --- config.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mk b/config.mk index b6eb7e0..81c493e 100644 --- a/config.mk +++ b/config.mk @@ -19,6 +19,7 @@ FREETYPELIBS = -lfontconfig -lXft FREETYPEINC = /usr/include/freetype2 # OpenBSD (uncomment) #FREETYPEINC = ${X11INC}/freetype2 +#MANPREFIX = ${PREFIX}/man # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} From d3f93c7c1a13a2a78f04fb41ad1935525df948db Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 10 May 2022 19:07:56 +0200 Subject: [PATCH 112/137] sync latest drw.{c,h} changes from dmenu --- drw.c | 88 +++++++++++++++++++++++++++++++++++++++-------------------- drw.h | 1 + 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/drw.c b/drw.c index 4cdbcbe..ced7d37 100644 --- a/drw.c +++ b/drw.c @@ -251,12 +251,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { - char buf[1024]; - int ty; - unsigned int ew; + int i, ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont; - size_t i, len; int utf8strlen, utf8charlen, render = x || y || w || h; long utf8codepoint = 0; const char *utf8str; @@ -264,13 +262,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcPattern *fcpattern; FcPattern *match; XftResult result; - int charexists = 0; + int charexists = 0, overflow = 0; + /* keep track of a couple codepoints for which we have no match. */ + enum { nomatches_len = 64 }; + static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; + static unsigned int ellipsis_width = 0; - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) return 0; if (!render) { - w = ~w; + w = invert ? invert : ~invert; } else { XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); @@ -282,8 +284,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } usedfont = drw->fonts; + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, "..."); while (1) { - utf8strlen = 0; + ew = ellipsis_len = utf8strlen = 0; utf8str = text; nextfont = NULL; while (*text) { @@ -291,9 +295,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp for (curfont = drw->fonts; curfont; curfont = curfont->next) { charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); if (charexists) { - if (curfont == usedfont) { + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (ew + ellipsis_width <= w) { + /* keep track where the ellipsis still fits */ + ellipsis_x = x + ew; + ellipsis_w = w - ew; + ellipsis_len = utf8strlen; + } + + if (ew + tmpw > w) { + overflow = 1; + /* called from drw_fontset_getwidth_clamp(): + * it wants the width AFTER the overflow + */ + if (!render) + x += tmpw; + else + utf8strlen = ellipsis_len; + } else if (curfont == usedfont) { utf8strlen += utf8charlen; text += utf8charlen; + ew += tmpw; } else { nextfont = curfont; } @@ -301,36 +323,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } } - if (!charexists || nextfont) + if (overflow || !charexists || nextfont) break; else charexists = 0; } if (utf8strlen) { - drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); - /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - - if (len) { - memcpy(buf, utf8str, len); - buf[len] = '\0'; - if (len < utf8strlen) - for (i = len; i && i > len - 3; buf[--i] = '.') - ; /* NOP */ - - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)buf, len); - } - x += ew; - w -= ew; + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); } + x += ew; + w -= ew; } + if (render && overflow) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - if (!*text) { + if (!*text || overflow) { break; } else if (nextfont) { charexists = 0; @@ -340,6 +351,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp * character must be drawn. */ charexists = 1; + for (i = 0; i < nomatches_len; ++i) { + /* avoid calling XftFontMatch if we know we won't find a match */ + if (utf8codepoint == nomatches.codepoint[i]) + goto no_match; + } + fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); @@ -368,6 +385,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp curfont->next = usedfont; } else { xfont_free(usedfont); + nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; +no_match: usedfont = drw->fonts; } } @@ -397,6 +416,15 @@ drw_fontset_getwidth(Drw *drw, const char *text) return drw_text(drw, 0, 0, 0, 0, 0, text, 0); } +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->fonts && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); + return MIN(n, tmp); +} + void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { diff --git a/drw.h b/drw.h index 4bcd5ad..6471431 100644 --- a/drw.h +++ b/drw.h @@ -35,6 +35,7 @@ void drw_free(Drw *drw); Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); void drw_fontset_free(Fnt* set); unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); /* Colorscheme abstraction */ From 9bffa845faa181fb3afe05f3dc86ad79c80736be Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 14 Jul 2022 07:27:34 +0600 Subject: [PATCH 113/137] use named parameter for func prototype all the other prototypes use names. --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 5646a5c..b3c43ee 100644 --- a/dwm.c +++ b/dwm.c @@ -185,7 +185,7 @@ static void monocle(Monitor *m); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); -static void pop(Client *); +static void pop(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); @@ -209,7 +209,7 @@ static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); -static void tile(Monitor *); +static void tile(Monitor *m); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); From 6613d9f9a1a5630bab30bc2b70bdc793977073ee Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 14 Jul 2022 07:26:40 +0600 Subject: [PATCH 114/137] do not call signal-unsafe function inside sighanlder die() calls vprintf, fputc and exit; none of these are async-signal-safe, see `man 7 signal-safety`. --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index b3c43ee..7c0f978 100644 --- a/dwm.c +++ b/dwm.c @@ -1541,6 +1541,8 @@ setup(void) Atom utf8string; /* clean up any zombies immediately */ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); sigchld(0); /* init screen */ @@ -1638,8 +1640,6 @@ showhide(Client *c) void sigchld(int unused) { - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); while (0 < waitpid(-1, NULL, WNOHANG)); } From e03248a4d5feaaacb130416be6e467a04de81f78 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 22 Jul 2022 09:18:52 +0200 Subject: [PATCH 115/137] Revert "do not call signal-unsafe function inside sighanlder" This reverts commit 6613d9f9a1a5630bab30bc2b70bdc793977073ee. Discussed on the mailinglist: https://lists.suckless.org/hackers/2207/18405.html --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 7c0f978..b3c43ee 100644 --- a/dwm.c +++ b/dwm.c @@ -1541,8 +1541,6 @@ setup(void) Atom utf8string; /* clean up any zombies immediately */ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); sigchld(0); /* init screen */ @@ -1640,6 +1638,8 @@ showhide(Client *c) void sigchld(int unused) { + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); while (0 < waitpid(-1, NULL, WNOHANG)); } From 786f6e2a6f8466ad94706781bc93bc6eb6e69512 Mon Sep 17 00:00:00 2001 From: Stein Date: Mon, 1 Aug 2022 11:42:44 +0200 Subject: [PATCH 116/137] unmanage: stop listening for events for unmanaged windows This is in particular to avoid flickering in dwm (and high CPU usage) when hovering the mouse over a tabbed window that was previously managed by dwm. Consider the following two scenarios: 1) We start tabbed (window 0xc000003), tabbed is managed by the window manager. We start st being embedded into tabbed. $ st -w 0xc000003 What happens here is that: - tabbed gets a MapRequest for the st window - tabbed reparents the st window - tabbed will receive X events for the window The window manager will have no awareness of the st window and the X server will not send X events to the window manager relating to the st window. There is no flickering or any other issues relating to focus. 2) We start tabbed (window 0xc000003), tabbed is managed by the window manager. We start st as normal (window 0xd400005). What happens here is that: - the window manager gets a MapRequest for the st window - dwm manages the st window as a normal client - dwm will receive X events for the window Now we use xdotool to trigger a reparenting of the st window into tabbed. $ xdotool windowreparent 0xd400005 0xc000003 What happens here is that: - tabbed gets a MapRequest for the st window - tabbed reparents the st window - the window manager gets an UnmapNotify - the window manager no longer manages the st window - both the window manager and tabbed will receive X events for the st window In dwm move the mouse cursor over the tabbed window. What happens now is that: - dwm will receive a FocusIn event for the tabbed window - dwm will set input focus for the tabbed window - tabbed will receive a FocusIn event for the main window - tabbed will give focus to the window on the currently selected tab - which again triggers a FocusIn event which dwm receives - dwm determines that the window that the FocusIn event is for (0xd400005) is not the currently selected client (tabbed) - dwm sets input focus for the tabbed window - this causes an infinite loop as long as the mouse cursor hovers the tabbed window, resulting in flickering and high CPU usage The fix here is to tell the X server that we are no longer interested in receiving events for this window when the window manager stops managing the window. --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index b3c43ee..c0c3b9b 100644 --- a/dwm.c +++ b/dwm.c @@ -1780,6 +1780,7 @@ unmanage(Client *c, int destroyed) wc.border_width = c->oldbw; XGrabServer(dpy); /* avoid race conditions */ XSetErrorHandler(xerrordummy); + XSelectInput(dpy, c->win, NoEventMask); XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ XUngrabButton(dpy, AnyButton, AnyModifier, c->win); setclientstate(c, WithdrawnState); From 5b2e5e7a4001479e4dc3e245f96e49f7ea0da658 Mon Sep 17 00:00:00 2001 From: explosion-mental Date: Fri, 29 Jul 2022 18:26:04 -0500 Subject: [PATCH 117/137] spawn: reduce 2 lines, change fprintf() + perror() + exit() to die("... :") when calling die and the last character of the string corresponds to ':', die() will call perror(). See util.c Also change EXIT_SUCCESS to EXIT_FAILURE --- dwm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index c0c3b9b..61713b7 100644 --- a/dwm.c +++ b/dwm.c @@ -1653,9 +1653,7 @@ spawn(const Arg *arg) close(ConnectionNumber(dpy)); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); - fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); - perror(" failed"); - exit(EXIT_SUCCESS); + die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); } } From 5e76e7e21da042c493c59235ca82d7275f20a7e4 Mon Sep 17 00:00:00 2001 From: NRK Date: Sat, 6 Aug 2022 04:27:13 +0600 Subject: [PATCH 118/137] code-style: simplify some checks main change here is making the `zoom()` logic saner. the rest of the changes are just small stuff which accumulated on my local branch. pop() must not be called with NULL. and `zoom()` achieves this, but in a very (unnecessarily) complicated way: if c == NULL then nexttiled() will return NULL as well, so we enter this branch: if (c == nexttiled(selmon->clients)) in here the !c check fails and the function returns before calling pop() if (!c || !(c = nexttiled(c->next))) return; however, none of this was needed. we can simply return early if c was NULL. Also `c` is set to `selmon->sel` so we can use `c` in the first check instead which makes things shorter. --- dwm.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/dwm.c b/dwm.c index 61713b7..967c9e8 100644 --- a/dwm.c +++ b/dwm.c @@ -918,13 +918,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) text[0] = '\0'; if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) return 0; - if (name.encoding == XA_STRING) + if (name.encoding == XA_STRING) { strncpy(text, (char *)name.value, size - 1); - else { - if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } + } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); } text[size - 1] = '\0'; XFree(name.value); @@ -1099,9 +1097,7 @@ maprequest(XEvent *e) static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; - if (!XGetWindowAttributes(dpy, ev->window, &wa)) - return; - if (wa.override_redirect) + if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) return; if (!wintoclient(ev->window)) manage(ev->window, &wa); @@ -1603,7 +1599,6 @@ setup(void) focus(NULL); } - void seturgent(Client *c, int urg) { @@ -2124,12 +2119,10 @@ zoom(const Arg *arg) { Client *c = selmon->sel; - if (!selmon->lt[selmon->sellt]->arrange - || (selmon->sel && selmon->sel->isfloating)) + if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) + return; + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) return; - if (c == nexttiled(selmon->clients)) - if (!c || !(c = nexttiled(c->next))) - return; pop(c); } From e0dee911455cee739a5b05a994828f4a37a2764d Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Mon, 8 Aug 2022 10:43:09 +0200 Subject: [PATCH 119/137] sync code-style patch from libsl --- util.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/util.c b/util.c index fe044fc..96b82c9 100644 --- a/util.c +++ b/util.c @@ -6,18 +6,9 @@ #include "util.h" -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - void -die(const char *fmt, ...) { +die(const char *fmt, ...) +{ va_list ap; va_start(ap, fmt); @@ -33,3 +24,13 @@ die(const char *fmt, ...) { exit(1); } + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} From a859676ead17017bbe81b4989b2f2e0b00a0b4ba Mon Sep 17 00:00:00 2001 From: Stein Date: Tue, 9 Aug 2022 10:38:08 +0200 Subject: [PATCH 120/137] Simplify client y-offset correction The reasoning behind the original line may be lost to time as it does not make much sense checking the position on the x-axis to determine how to position the client on the y-axis. In the context of multi-monitor setups the monitor y position (m->my) may be greater than 0 (say 500), in which case the window could be placed out of view if: - the window attributes have a 0 value for the y position and - we end up using the y position of bh (e.g. 22) If the aim is to avoid a new floating client covering the bar then restricting y position to be at least that of the window area (m->wy) should cover the two cases of using a top bar and using a bottom bar. --- dwm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 967c9e8..87d0ada 100644 --- a/dwm.c +++ b/dwm.c @@ -1049,9 +1049,7 @@ manage(Window w, XWindowAttributes *wa) if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) c->y = c->mon->my + c->mon->mh - HEIGHT(c); c->x = MAX(c->x, c->mon->mx); - /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->y = MAX(c->y, c->mon->wy); c->bw = borderpx; wc.border_width = c->bw; From 44adafe0069e73aa03a3829d7bb39591cd8b3f1d Mon Sep 17 00:00:00 2001 From: Stein Date: Thu, 11 Aug 2022 11:15:55 +0200 Subject: [PATCH 121/137] Make floating windows spawn within the monitor's window area This is a follow-up on this thread: https://lists.suckless.org/hackers/2208/18462.html The orginal code had constraints such that if a window's starting attributes (position and size) were to place the window outside of the edges of the monitor, then the window would be moved into view at the closest monitor edge. There was an exception to this where if a top bar is used then the window should not obscure the bar if present, which meant to place the window within the window area instead. The proposed change here makes it the general rule that floating windows should spawn within the window area rather than within the monitor area. This makes it simple and consistent with no exceptions and it makes the intention of the code clear. This has the benefit of making the behaviour consistent regardless of whether the user is using a top bar or a bottom bar. Additionally this will have an effect on patches that modify the size of the window area. For example if the insets patch is used to reserve space on the left hand side of the monitor for a dock or a vertical bar then new floating clients will not obscure that area. --- dwm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dwm.c b/dwm.c index 87d0ada..f2bc4ba 100644 --- a/dwm.c +++ b/dwm.c @@ -1044,11 +1044,11 @@ manage(Window w, XWindowAttributes *wa) applyrules(c); } - if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) - c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) - c->y = c->mon->my + c->mon->mh - HEIGHT(c); - c->x = MAX(c->x, c->mon->mx); + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) + c->x = c->mon->wx + c->mon->ww - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) + c->y = c->mon->wy + c->mon->wh - HEIGHT(c); + c->x = MAX(c->x, c->mon->wx); c->y = MAX(c->y, c->mon->wy); c->bw = borderpx; From 5799dd1fca6576b662d299e210cd5933b29d502d Mon Sep 17 00:00:00 2001 From: Stein Date: Mon, 15 Aug 2022 14:31:22 +0200 Subject: [PATCH 122/137] Remove blw variable in favour of calculating the value when needed The purpose and reasoning behind the bar layout width (blw) variable in dwm the way it is today may not be immediately obvious. The use of the variable makes more sense when looking at commit 2ce37bc from 2009 where blw was initialised in the setup function and it represented the maximum of all available layout symbols. for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { w = TEXTW(layouts[i].symbol); blw = MAX(blw, w); } As such the layout symbol back then was fixed in size and both drawbar and buttonpress depended on this variable. The the way the blw variable is set today in drawbar means that it merely caches the size of the layout symbol for the last bar drawn. While unlikely to happen in practice it is possible that the last bar drawn is not that of the currently selected monitor, which can result in misaligned button clicks if there is a difference in layout symbol width between monitors. --- dwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index f2bc4ba..253aba7 100644 --- a/dwm.c +++ b/dwm.c @@ -240,7 +240,7 @@ static const char broken[] = "broken"; static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ -static int bh, blw = 0; /* bar geometry */ +static int bh; /* bar height */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; @@ -440,7 +440,7 @@ buttonpress(XEvent *e) if (i < LENGTH(tags)) { click = ClkTagBar; arg.ui = 1 << i; - } else if (ev->x < x + blw) + } else if (ev->x < x + TEXTW(selmon->ltsymbol)) click = ClkLtSymbol; else if (ev->x > selmon->ww - (int)TEXTW(stext)) click = ClkStatusText; @@ -731,7 +731,7 @@ drawbar(Monitor *m) urg & 1 << i); x += w; } - w = blw = TEXTW(m->ltsymbol); + w = TEXTW(m->ltsymbol); drw_setscheme(drw, scheme[SchemeNorm]); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); From 84d7322113c2bf023f5eaa8537fb0e72d4105046 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 18 Aug 2022 22:13:08 +0600 Subject: [PATCH 123/137] config.def.h: make keys and buttons const pretty much all other variables are declared as const when they're not modified. --- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index a2ac963..9efa774 100644 --- a/config.def.h +++ b/config.def.h @@ -60,7 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; static const char *termcmd[] = { "st", NULL }; -static Key keys[] = { +static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, @@ -99,7 +99,7 @@ static Key keys[] = { /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { +static const Button buttons[] = { /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, From c2b748e7931e5f28984efc236f9b1a212dbc65e8 Mon Sep 17 00:00:00 2001 From: Stein Date: Fri, 26 Aug 2022 14:48:46 +0200 Subject: [PATCH 124/137] Remove dmenumon variable Reasoning: Since 2011 dmenu has been capable of working out which monitor currently has focus in a Xinerama setup, making the use of the -m flag more or less redundant. This is easily demonstrated by using dmenu in any other window manager. There used to be a nodmenu patch that provided these changes: https://git.suckless.org/sites/commit/ed68e3629de4ef2ca2d3f8893a79fb570b4c0cbc.html but this was removed on the basis that it was very easy to work out and apply manually if needed. The proposal here is to remove this dependency from dwm. The mechanism of the dmenumon variable could be provided via a patch if need be. The edge case scenario that dmenu does not handle on its own, and the effect of removing this mechanism, is that if the user trigger focusmon via keybindings to change focus to another monitor that has no clients, then dmenu will open on the monitor containing the window with input focus (or the monitor with the mouse cursor if no windows have input focus). If this edge case is important to cover then this can be addressed by setting input focus to selmon->barwin in the focus function if there is no client to give focus to (rather than giving focus back to the root window). --- config.def.h | 3 +-- dwm.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 9efa774..061ad66 100644 --- a/config.def.h +++ b/config.def.h @@ -56,8 +56,7 @@ static const Layout layouts[] = { #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; static const char *termcmd[] = { "st", NULL }; static const Key keys[] = { diff --git a/dwm.c b/dwm.c index 253aba7..e5efb6a 100644 --- a/dwm.c +++ b/dwm.c @@ -1639,8 +1639,6 @@ sigchld(int unused) void spawn(const Arg *arg) { - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); From 970f37697358574e127019eb0ee2f5725ec05ce0 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 16 Sep 2022 23:06:47 +0200 Subject: [PATCH 125/137] remove workaround for a crash with color emojis on some systems, now fixed in libXft 2.3.5 https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS --- drw.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drw.c b/drw.c index ced7d37..a58a2b4 100644 --- a/drw.c +++ b/drw.c @@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) die("no font specified."); } - /* Do not allow using color fonts. This is a workaround for a BadLength - * error from Xft with color glyphs. Modelled on the Xterm workaround. See - * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - * https://lists.suckless.org/dev/1701/30932.html - * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 - * and lots more all over the internet. - */ - FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { - XftFontClose(drw->dpy, xfont); - return NULL; - } - font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; @@ -368,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcDefaultSubstitute(fcpattern); From 50ad171eea9db5ccb36fce2592e047c3282975ff Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 4 Oct 2022 19:35:13 +0200 Subject: [PATCH 126/137] bump version to 6.4 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 81c493e..ef8acf7 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.3 +VERSION = 6.4 # Customize below to fit your system From ba56fe9fea0a28d8184a727a987836a0903e2682 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 28 Oct 2022 16:37:56 +0200 Subject: [PATCH 127/137] Revert "Remove dmenumon variable" This reverts commit c2b748e7931e5f28984efc236f9b1a212dbc65e8. Revert back this change. It seems to not be an edge-case anymore since multiple users have asked about this new behaviour now. --- config.def.h | 3 ++- dwm.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 061ad66..9efa774 100644 --- a/config.def.h +++ b/config.def.h @@ -56,7 +56,8 @@ static const Layout layouts[] = { #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ -static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; static const char *termcmd[] = { "st", NULL }; static const Key keys[] = { diff --git a/dwm.c b/dwm.c index e5efb6a..253aba7 100644 --- a/dwm.c +++ b/dwm.c @@ -1639,6 +1639,8 @@ sigchld(int unused) void spawn(const Arg *arg) { + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); From 89f9905714c1c1b2e8b09986dfbeca15b68d8af8 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Wed, 7 Dec 2022 14:55:08 +0000 Subject: [PATCH 128/137] grabkeys: Avoid missing events when a keysym maps to multiple keycodes It's not uncommon for one keysym to map to multiple keycodes. For example, the "play" button on my keyboard sends keycode 172, but my bluetooth headphones send keycode 208, both of which map back to XF86AudioPlay: % xmodmap -pke | grep XF86AudioPlay keycode 172 = XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause keycode 208 = XF86AudioPlay NoSymbol XF86AudioPlay keycode 215 = XF86AudioPlay NoSymbol XF86AudioPlay This is a problem because the current code only grabs a single one of these keycodes, which means that events for any other keycode also mapping to the bound keysym will not be handled by dwm. In my case, this means that binding XF86AudioPlay does the right thing and correctly handles my keyboard's keys, but does nothing on my headphones. I'm not the only person affected by this, there are other reports[0]. In order to fix this, we look at the mappings between keycodes and keysyms at grabkeys() time and pick out all matching keycodes rather than just the first one. The keypress() side of this doesn't need any changes because the keycode gets converted back to a canonical keysym before any action is taken. 0: https://github.com/cdown/dwm/issues/11 --- dwm.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/dwm.c b/dwm.c index 253aba7..03baf42 100644 --- a/dwm.c +++ b/dwm.c @@ -955,16 +955,26 @@ grabkeys(void) { updatenumlockmask(); { - unsigned int i, j; + unsigned int i, j, k; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; + int start, end, skip; + KeySym *syms; XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < LENGTH(keys); i++) - if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + XDisplayKeycodes(dpy, &start, &end); + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(keys); i++) + /* skip modifier codes, we do that ourselves */ + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + XFree(syms); } } From 712d6639ff8e863560328131bbb92b248dc9cde7 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Sat, 28 Jan 2023 12:53:48 +0100 Subject: [PATCH 129/137] Use sigaction(SA_NOCLDWAIT) for SIGCHLD handling signal() semantics are pretty unclearly specified. For example, depending on OS kernel and libc, the handler may be returned to SIG_DFL (hence the inner call to read the signal handler). Moving to sigaction() means the behaviour is consistently defined. Using SA_NOCLDWAIT also allows us to avoid calling the non-reentrant function die() in the handler. Some addditional notes for archival purposes: * NRK pointed out errno of waitpid could also theoretically get clobbered. * The original patch was iterated on and modified by NRK and Hiltjo: * SIG_DFL was changed to SIG_IGN, this is required, atleast on older systems such as tested on Slackware 11. * signals are not blocked using sigprocmask, because in theory it would briefly for example also ignore a SIGTERM signal. It is OK if waitpid() is (in theory interrupted). POSIX reference: "Consequences of Process Termination": https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html#tag_16_01_03_01 --- dwm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dwm.c b/dwm.c index 03baf42..c2bd871 100644 --- a/dwm.c +++ b/dwm.c @@ -205,7 +205,6 @@ static void setmfact(const Arg *arg); static void setup(void); static void seturgent(Client *c, int urg); static void showhide(Client *c); -static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -1543,9 +1542,16 @@ setup(void) int i; XSetWindowAttributes wa; Atom utf8string; + struct sigaction sa; - /* clean up any zombies immediately */ - sigchld(0); + /* do not transform children into zombies when they terminate */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + + /* clean up any zombies (inherited from .xinitrc etc) immediately */ + while (waitpid(-1, NULL, WNOHANG) > 0); /* init screen */ screen = DefaultScreen(dpy); @@ -1638,14 +1644,6 @@ showhide(Client *c) } } -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); - while (0 < waitpid(-1, NULL, WNOHANG)); -} - void spawn(const Arg *arg) { From 348f6559ab0d4793db196ffa56ba96ab95a594a6 Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 17 Feb 2023 11:05:09 +0600 Subject: [PATCH 130/137] config.mk: update to _XOPEN_SOURCE=700L SA_NOCLDWAIT is marked as XSI in the posix spec [0] and FreeBSD and NetBSD seems to more be strict about the feature test macro [1]. so update the macro to use _XOPEN_SOURCE=700L instead, which is equivalent to _POSIX_C_SOURCE=200809L except that it also unlocks the X/Open System Interfaces. [0]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html#tag_13_42 [1]: https://lists.suckless.org/dev/2302/35111.html Tested on: * NetBSD 9.3 (fixed). * FreeBSD 13 (fixed). * Void Linux musl. * Void Linux glibc. * OpenBSD 7.2 (stable). * Slackware 11. Reported-by: beastie --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index ef8acf7..ba64d3d 100644 --- a/config.mk +++ b/config.mk @@ -26,7 +26,7 @@ INCS = -I${X11INC} -I${FREETYPEINC} LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} # flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = ${LIBS} From e81f17d4c196aaed6893fd4beed49991caa3e2a4 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 9 Apr 2023 12:37:14 +0200 Subject: [PATCH 131/137] restore SIGCHLD sighandler to default before spawning a program From sigaction(2): A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged. This refused to start directly some programs from configuring in config.h: static Key keys[] = { MODKEY, XK_o, spawn, {.v = cmd } }, }; Some reported programs that didn't start were: mpv, anki, dmenu_extended. Reported by pfx. Initial patch suggestion by Storkman. --- dwm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dwm.c b/dwm.c index c2bd871..f1d86b2 100644 --- a/dwm.c +++ b/dwm.c @@ -1647,12 +1647,20 @@ showhide(Client *c) void spawn(const Arg *arg) { + struct sigaction sa; + if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); setsid(); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + execvp(((char **)arg->v)[0], (char **)arg->v); die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); } From 9f8855343c881bdc01b9fff5b956537ba1106b76 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 22 Sep 2023 15:13:29 +0200 Subject: [PATCH 132/137] Makefile: remove the options target The Makefile used to suppress output (by using @), so this target made sense at the time. But the Makefile should be simple and make debugging with less abstractions or fancy printing. The Makefile was made verbose and doesn't hide the build output, so remove this target. Prompted by a question on the mailing list about the options target. --- Makefile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 77bcbc0..ffa69b4 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,7 @@ include config.mk SRC = drw.c dwm.c util.c OBJ = ${SRC:.c=.o} -all: options dwm - -options: - @echo dwm build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" - @echo "CC = ${CC}" +all: dwm .c.o: ${CC} -c ${CFLAGS} $< @@ -48,4 +42,4 @@ uninstall: rm -f ${DESTDIR}${PREFIX}/bin/dwm\ ${DESTDIR}${MANPREFIX}/man1/dwm.1 -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall From 061e9fe9a7db396c0c4f3d996c3908fb43a6d50c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 19 Mar 2024 12:13:16 +0100 Subject: [PATCH 133/137] bump version to 6.5 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index ba64d3d..8efca9a 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.4 +VERSION = 6.5 # Customize below to fit your system From 5687f4696472ba6029bbba18e293e3e8b9e154ea Mon Sep 17 00:00:00 2001 From: Pontus Stenetorp Date: Sat, 8 Jun 2024 19:36:15 +0900 Subject: [PATCH 134/137] Add missing void to updateclientlist definition Caught by -pedantic implying -Wstrict-prototypes for OpenBSD's 16.0.6 Clang. --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index f1d86b2..67c6b2b 100644 --- a/dwm.c +++ b/dwm.c @@ -1851,7 +1851,7 @@ updatebarpos(Monitor *m) } void -updateclientlist() +updateclientlist(void) { Client *c; Monitor *m; From 8933ebcf50024f4378a78e556b1ac08091197206 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 5 Oct 2024 13:01:49 +0200 Subject: [PATCH 135/137] sync drw.{c,h} from dmenu - drw: minor improvement to the nomatches cache - overhaul utf8decoding and render invalid utf8 sequences as U+FFFD. Thanks NRK for these improvements! --- drw.c | 114 ++++++++++++++++++++++++++++----------------------------- dwm.c | 1 - util.h | 1 + 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/drw.c b/drw.c index a58a2b4..344de61 100644 --- a/drw.c +++ b/drw.c @@ -9,54 +9,40 @@ #include "util.h" #define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) +static int +utf8decode(const char *s_in, long *u, int *err) { - for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) - return (unsigned char)c & ~utfmask[*i]; - return 0; -} - -static size_t -utf8validate(long *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - return i; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) -{ - size_t i, j, len, type; - long udecoded; + static const unsigned char lens[] = { + /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ + /* 110XX */ 2, 2, 2, 2, + /* 1110X */ 3, 3, + /* 11110 */ 4, + /* 11111 */ 0, /* invalid */ + }; + static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; + static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; + const unsigned char *s = (const unsigned char *)s_in; + int len = lens[*s >> 3]; *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) + *err = 1; + if (len == 0) return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); + long cp = s[0] & leading_mask[len - 1]; + for (int i = 1; i < len; ++i) { + if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) + return i; + cp = (cp << 6) | (s[i] & 0x3F); + } + /* out of range, surrogate, overlong encoding */ + if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) + return len; + + *err = 0; + *u = cp; return len; } @@ -238,11 +224,11 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { - int i, ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; + int ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont; - int utf8strlen, utf8charlen, render = x || y || w || h; + int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; long utf8codepoint = 0; const char *utf8str; FcCharSet *fccharset; @@ -251,9 +237,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp XftResult result; int charexists = 0, overflow = 0; /* keep track of a couple codepoints for which we have no match. */ - enum { nomatches_len = 64 }; - static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; - static unsigned int ellipsis_width = 0; + static unsigned int nomatches[128], ellipsis_width, invalid_width; + static const char invalid[] = "�"; if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) return 0; @@ -273,12 +258,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp usedfont = drw->fonts; if (!ellipsis_width && render) ellipsis_width = drw_fontset_getwidth(drw, "..."); + if (!invalid_width && render) + invalid_width = drw_fontset_getwidth(drw, invalid); while (1) { - ew = ellipsis_len = utf8strlen = 0; + ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; utf8str = text; nextfont = NULL; while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); for (curfont = drw->fonts; curfont; curfont = curfont->next) { charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); if (charexists) { @@ -300,9 +287,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp else utf8strlen = ellipsis_len; } else if (curfont == usedfont) { - utf8strlen += utf8charlen; text += utf8charlen; - ew += tmpw; + utf8strlen += utf8err ? 0 : utf8charlen; + ew += utf8err ? 0 : tmpw; } else { nextfont = curfont; } @@ -310,7 +297,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } } - if (overflow || !charexists || nextfont) + if (overflow || !charexists || nextfont || utf8err) break; else charexists = 0; @@ -325,6 +312,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp x += ew; w -= ew; } + if (utf8err && (!render || invalid_width < w)) { + if (render) + drw_text(drw, x, y, w, h, 0, invalid, invert); + x += invalid_width; + w -= invalid_width; + } if (render && overflow) drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); @@ -338,11 +331,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp * character must be drawn. */ charexists = 1; - for (i = 0; i < nomatches_len; ++i) { - /* avoid calling XftFontMatch if we know we won't find a match */ - if (utf8codepoint == nomatches.codepoint[i]) - goto no_match; - } + hash = (unsigned int)utf8codepoint; + hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; + hash = ((hash >> 15) ^ hash) * 0xD35A2D97; + h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); + h1 = (hash >> 17) % LENGTH(nomatches); + /* avoid expensive XftFontMatch call when we know we won't find a match */ + if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) + goto no_match; fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); @@ -371,7 +367,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp curfont->next = usedfont; } else { xfont_free(usedfont); - nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; + nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; no_match: usedfont = drw->fonts; } diff --git a/dwm.c b/dwm.c index 67c6b2b..1443802 100644 --- a/dwm.c +++ b/dwm.c @@ -50,7 +50,6 @@ #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -#define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) diff --git a/util.h b/util.h index f633b51..c0a50d4 100644 --- a/util.h +++ b/util.h @@ -3,6 +3,7 @@ #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) void die(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); From fcb2476b693ca4c40ad32c7119e27bbeb856865c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 27 Oct 2024 20:10:07 +0100 Subject: [PATCH 136/137] util.c: output function might override errno and thus affect perror() Original patch by Raymond Cole with some modifications, thanks! --- util.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/util.c b/util.c index 96b82c9..8e26a51 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include @@ -10,17 +11,17 @@ void die(const char *fmt, ...) { va_list ap; + int saved_errno; + + saved_errno = errno; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } + if (fmt[0] && fmt[strlen(fmt)-1] == ':') + fprintf(stderr, " %s", strerror(saved_errno)); + fputc('\n', stderr); exit(1); } From cfb8627a80a334f200f68c2c8f3e384313ebbaf5 Mon Sep 17 00:00:00 2001 From: Raymond Cole Date: Mon, 28 Oct 2024 00:34:55 +0000 Subject: [PATCH 137/137] Avoid unsigned integer underflow in drw_text() --- drw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drw.c b/drw.c index 344de61..c41e6af 100644 --- a/drw.c +++ b/drw.c @@ -248,6 +248,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } else { XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + if (w < lpad) + return x + w; d = XftDrawCreate(drw->dpy, drw->drawable, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen));