From 0927d635bc3b8683f7754bce5fcdfe483ecff3a7 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 14 Jul 2009 19:07:53 +0100 Subject: [PATCH 001/257] Added tag 5.6 for changeset 555070221577 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6ea1fa7..76178e2 100644 --- a/.hgtags +++ b/.hgtags @@ -61,3 +61,4 @@ e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2 8b7836a471f8f9ee61bec980df00971888d76343 5.4 85a78d8afa0fe8b106a8223b5327e5bddb5dd5e3 5.4.1 deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 +5550702215773aad462f22a774dced9b87437c51 5.6 From 6877a00033f4785049928bfe7e98d754e1c757a9 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 17 Jul 2009 13:35:17 +0100 Subject: [PATCH 002/257] it's all nsz's hard investigation effort, hail nsz! ;) --- config.mk | 2 +- dwm.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config.mk b/config.mk index 3fcfd2f..086424d 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.6 +VERSION = 5.7 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 71d7e63..289b508 100644 --- a/dwm.c +++ b/dwm.c @@ -350,9 +350,9 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { /* adjust for aspect limits */ if(c->mina > 0 && c->maxa > 0) { if(c->maxa < (float)*w / *h) - *w = *h * c->maxa; + *w = *h * c->maxa + 0.5; /* -Os double upcast workaround */ else if(c->mina < (float)*h / *w) - *h = *w * c->mina; + *h = *w * c->mina + 0.5; /* -Os double upcast workaround */ } if(baseismin) { /* increment calculation requires this */ *w -= c->basew; @@ -1807,8 +1807,8 @@ updatesizehints(Client *c) { else c->minw = c->minh = 0; if(size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / (float)size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / (float)size.max_aspect.y; + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; } else c->maxa = c->mina = 0.0; From 999d6e795f26f85e4b4b59adb7637ec067a9deee Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 17 Jul 2009 15:28:07 +0100 Subject: [PATCH 003/257] removed misleading comment --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 289b508..e22ea7a 100644 --- a/dwm.c +++ b/dwm.c @@ -350,9 +350,9 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { /* adjust for aspect limits */ if(c->mina > 0 && c->maxa > 0) { if(c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; /* -Os double upcast workaround */ + *w = *h * c->maxa + 0.5; else if(c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; /* -Os double upcast workaround */ + *h = *w * c->mina + 0.5; } if(baseismin) { /* increment calculation requires this */ *w -= c->basew; From 5bc4db0f7606f098a9d7309fef080f4e95ebf2f1 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 18 Jul 2009 11:28:03 +0100 Subject: [PATCH 004/257] applied nsz' dwm.1 fixes, thanks Szabolcs! --- dwm.1 | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/dwm.1 b/dwm.1 index 7eb231f..bc3de7d 100644 --- a/dwm.1 +++ b/dwm.1 @@ -56,7 +56,7 @@ click on a tag label adds/removes that tag to/from the focused window. .TP .B Mod1\-Shift\-Return Start -.BR xterm. +.BR uxterm . .TP .B Mod1\-, Focus previous screen, if any. @@ -67,7 +67,7 @@ Focus next screen, if any. .B Mod1\-Shift\-, Send focused window to previous screen, if any. .TP -.B Mod1\-Shift\-, +.B Mod1\-Shift\-. Send focused window to next screen, if any. .TP .B Mod1\-b @@ -110,30 +110,22 @@ Toggle focused window between tiled and floating state. Toggles to the previously selected tags. .TP .B Mod1\-Shift\-[1..n] -Apply -.RB nth -tag to focused window. +Apply nth tag to focused window. .TP .B Mod1\-Shift\-0 Apply all tags to focused window. .TP .B Mod1\-Control\-Shift\-[1..n] -Add/remove -.B nth -tag to/from focused window. +Add/remove nth tag to/from focused window. .TP .B Mod1\-[1..n] -View all windows with -.BR nth -tag. +View all windows with nth tag. .TP .B Mod1\-0 View all windows with any tag. .TP .B Mod1\-Control\-[1..n] -Add/remove all windows with -.BR nth -tag to/from the view. +Add/remove all windows with nth tag to/from the view. .TP .B Mod1\-Shift\-q Quit dwm. From 7151bf8329fbac690361ef2bd064b30cd6266b29 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 20 Jul 2009 16:39:42 +0100 Subject: [PATCH 005/257] removed Standard input hint --- dwm.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.1 b/dwm.1 index 7eb231f..6963872 100644 --- a/dwm.1 +++ b/dwm.1 @@ -37,7 +37,7 @@ prints version information to standard output, then exits. .SH USAGE .SS Status bar .TP -.B Standard input +.B X root window name is read and displayed in the status text area. .TP .B Button1 From dc39ae85681db71c6cfcaac442c1317c8b313566 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 20 Jul 2009 17:08:34 +0100 Subject: [PATCH 006/257] applied nsz' man page comment, thanks! --- dwm.1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dwm.1 b/dwm.1 index 8e7eff6..ec4c179 100644 --- a/dwm.1 +++ b/dwm.1 @@ -38,7 +38,9 @@ prints version information to standard output, then exits. .SS Status bar .TP .B X root window name -is read and displayed in the status text area. +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. .TP .B Button1 click on a tag label to display all windows with that tag, click on the layout @@ -56,7 +58,7 @@ click on a tag label adds/removes that tag to/from the focused window. .TP .B Mod1\-Shift\-Return Start -.BR uxterm . +.BR uxterm (1). .TP .B Mod1\-, Focus previous screen, if any. From c13be8d620372a55f5867cafd6ad4277ad77790c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 21 Jul 2009 08:57:04 +0100 Subject: [PATCH 007/257] updategeom fix for same geom screens --- config.mk | 2 +- dwm.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config.mk b/config.mk index 086424d..11a16f7 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.7 +VERSION = 5.6.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index e22ea7a..43f0fd5 100644 --- a/dwm.c +++ b/dwm.c @@ -1683,7 +1683,7 @@ updatebarpos(Monitor *m) { void updategeom(void) { - int i, n = 1; + int i, n = 1, nn; Client *c; Monitor *newmons = NULL, *m = NULL, *tm; @@ -1692,6 +1692,11 @@ updategeom(void) { if(XineramaIsActive(dpy)) info = XineramaQueryScreens(dpy, &n); + for(i = 1, nn = n; i < n; i++) + if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org + && info[i - 1].width == info[i].width && info[i - 1].height == info[i].height) + --nn; + n = nn; /* we only consider unique geometrys as separate screens */ #endif /* XINERAMA */ /* allocate monitor(s) for the new geometry setup */ for(i = 0; i < n; i++) { From 244addb3f4253e1cd35dc9af504b3172aaccd576 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 21 Jul 2009 10:57:54 +0100 Subject: [PATCH 008/257] applied nsz patch --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 43f0fd5..314d150 100644 --- a/dwm.c +++ b/dwm.c @@ -1696,7 +1696,7 @@ updategeom(void) { if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org && info[i - 1].width == info[i].width && info[i - 1].height == info[i].height) --nn; - n = nn; /* we only consider unique geometrys as separate screens */ + n = nn; /* we only consider unique geometries as separate screens */ #endif /* XINERAMA */ /* allocate monitor(s) for the new geometry setup */ for(i = 0; i < n; i++) { From 1fa31efebf74f699ce91add53bc08a8e3ec2dccc Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 26 Jul 2009 14:02:28 +0100 Subject: [PATCH 009/257] Added tag 5.6.1 for changeset e47a47bd3ed4 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 76178e2..6ef9274 100644 --- a/.hgtags +++ b/.hgtags @@ -62,3 +62,4 @@ e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2 85a78d8afa0fe8b106a8223b5327e5bddb5dd5e3 5.4.1 deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 5550702215773aad462f22a774dced9b87437c51 5.6 +e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 From 91fffb3f7d0cd731aa2a2126c411590d30231c19 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 27 Jul 2009 12:01:58 +0100 Subject: [PATCH 010/257] fixed nn declaration --- config.mk | 2 +- dwm.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config.mk b/config.mk index 11a16f7..086424d 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.6.1 +VERSION = 5.7 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 314d150..873b794 100644 --- a/dwm.c +++ b/dwm.c @@ -1683,11 +1683,12 @@ updatebarpos(Monitor *m) { void updategeom(void) { - int i, n = 1, nn; + int i, n = 1; Client *c; Monitor *newmons = NULL, *m = NULL, *tm; #ifdef XINERAMA + int nn; XineramaScreenInfo *info = NULL; if(XineramaIsActive(dpy)) From 33fe200b521b19a089d39aca247bb78432e02e6d Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 13 Aug 2009 10:45:59 +0100 Subject: [PATCH 011/257] added merged patch of anydot and Neale --- dwm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 873b794..1b30cae 100644 --- a/dwm.c +++ b/dwm.c @@ -207,7 +207,7 @@ static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); static void showhide(Client *c); -static void sigchld(int signal); +static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -1428,6 +1428,10 @@ setup(void) { int w; XSetWindowAttributes wa; + /* clean up any zombies immediately */ + signal(SIGCHLD, sigchld); + sigchld(0); + /* init screen */ screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); @@ -1496,13 +1500,13 @@ showhide(Client *c) { void -sigchld(int signal) { +sigchld(int unused) { while(0 < waitpid(-1, NULL, WNOHANG)); + signal(SIGCHLD, sigchld); } void spawn(const Arg *arg) { - signal(SIGCHLD, sigchld); if(fork() == 0) { if(dpy) close(ConnectionNumber(dpy)); From 8ef465d592fada11dab075bb7569239c03e3afa4 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 16 Aug 2009 08:18:25 +0100 Subject: [PATCH 012/257] applied Jukka's sigchld patch --- LICENSE | 2 +- dwm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index a84241a..86b2c94 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ MIT/X Consortium License © 2006-2009 Anselm R Garbe © 2006-2007 Sander van Dijk -© 2006-2007 Jukka Salmi +© 2006-2009 Jukka Salmi © 2007-2009 Premysl Hruby © 2007-2009 Szabolcs Nagy © 2007-2009 Christof Musik diff --git a/dwm.c b/dwm.c index 1b30cae..e2f306c 100644 --- a/dwm.c +++ b/dwm.c @@ -1429,7 +1429,6 @@ setup(void) { XSetWindowAttributes wa; /* clean up any zombies immediately */ - signal(SIGCHLD, sigchld); sigchld(0); /* init screen */ @@ -1501,8 +1500,9 @@ 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)); - signal(SIGCHLD, sigchld); } void From 42750a621b3f0786e7fa3d7c9533c03c2a3d189d Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 16 Aug 2009 08:18:54 +0100 Subject: [PATCH 013/257] applied Jukka's cosmetic patch --- dwm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index e2f306c..74b7795 100644 --- a/dwm.c +++ b/dwm.c @@ -564,9 +564,9 @@ configurerequest(XEvent *e) { c->w = ev->width; if(ev->value_mask & CWHeight) c->h = ev->height; - if((c->x - m->mx + c->w) > m->mw && c->isfloating) + if((c->x + c->w) > m->mx + m->mw && c->isfloating) c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */ - if((c->y - m->my + c->h) > m->mh && c->isfloating) + if((c->y + c->h) > m->my + m->mh && c->isfloating) c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */ if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) configure(c); @@ -1595,23 +1595,23 @@ togglefloating(const Arg *arg) { void toggletag(const Arg *arg) { - unsigned int mask; + unsigned int newtags; if(!selmon->sel) return; - mask = selmon->sel->tags ^ (arg->ui & TAGMASK); - if(mask) { - selmon->sel->tags = mask; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if(newtags) { + selmon->sel->tags = newtags; arrange(); } } void toggleview(const Arg *arg) { - unsigned int mask = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - if(mask) { - selmon->tagset[selmon->seltags] = mask; + if(newtagset) { + selmon->tagset[selmon->seltags] = newtagset; arrange(); } } From cba6b211c2ab1564d818fa7dac85b71ba5663e0d Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 16 Aug 2009 21:39:24 +0100 Subject: [PATCH 014/257] applied nsz's dwm.1 patch, also added wmname --- dwm.1 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dwm.1 b/dwm.1 index ec4c179..5f3cc2c 100644 --- a/dwm.1 +++ b/dwm.1 @@ -149,11 +149,17 @@ code. This keeps it fast, secure and simple. .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 -JDK 1.6 versions, because it assumes a reparenting window manager. As a workaround -you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you -can set the following environment variable (to use the older Motif -backend instead): -.BR AWT_TOOLKIT=MToolkit . +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(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 From 57629642321b9850edddf068ac9ddf8737979390 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 18 Aug 2009 15:42:55 +0100 Subject: [PATCH 015/257] also update title if the client is on an unfocused monitor --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 74b7795..f63a1c0 100644 --- a/dwm.c +++ b/dwm.c @@ -1235,7 +1235,7 @@ propertynotify(XEvent *e) { } if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); - if(c == selmon->sel) + if(c == c->mon->sel) drawbars(); } } From 0a668922a4de625d128a362d102844e33e36ae1c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 18 Aug 2009 15:59:38 +0100 Subject: [PATCH 016/257] another small optimisation --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index f63a1c0..f7e9e84 100644 --- a/dwm.c +++ b/dwm.c @@ -1236,7 +1236,7 @@ propertynotify(XEvent *e) { if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); if(c == c->mon->sel) - drawbars(); + drawbar(c->mon); } } } From 9c066c24b3d0b7767651f0f403db2e4007a847c8 Mon Sep 17 00:00:00 2001 From: "nsz@tpx" Date: Mon, 7 Sep 2009 11:46:02 +0200 Subject: [PATCH 017/257] always updategeom when root is configured --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index f7e9e84..7a4600f 100644 --- a/dwm.c +++ b/dwm.c @@ -530,7 +530,7 @@ configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - if(ev->window == root && (ev->width != sw || ev->height != sh)) { + if(ev->window == root) { sw = ev->width; sh = ev->height; updategeom(); From a3a859b4e93d65fd22619449d18e0437d5c2774b Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:13:03 +0100 Subject: [PATCH 018/257] added isdestroyed flag to unmanage --- dwm.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/dwm.c b/dwm.c index 7a4600f..a2c1e00 100644 --- a/dwm.c +++ b/dwm.c @@ -218,7 +218,7 @@ static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c); -static void unmanage(Client *c); +static void unmanage(Client *c, Bool isdestroyed); static void unmapnotify(XEvent *e); static void updategeom(void); static void updatebarpos(Monitor *m); @@ -466,7 +466,7 @@ cleanup(void) { selmon->lt[selmon->sellt] = &foo; for(m = mons; m; m = m->next) while(m->stack) - unmanage(m->stack); + unmanage(m->stack, False); if(dc.font.set) XFreeFontSet(dpy, dc.font.set); else @@ -595,7 +595,7 @@ destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; if((c = wintoclient(ev->window))) - unmanage(c); + unmanage(c, True); } void @@ -1626,24 +1626,25 @@ unfocus(Client *c) { } void -unmanage(Client *c) { +unmanage(Client *c, Bool isdestroyed) { XWindowChanges wc; - wc.border_width = c->oldbw; /* The server grab construct avoids race conditions. */ - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ detach(c); detachstack(c); - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); + if(!isdestroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } free(c); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); focus(NULL); - arrange(); } void @@ -1652,7 +1653,7 @@ unmapnotify(XEvent *e) { XUnmapEvent *ev = &e->xunmap; if((c = wintoclient(ev->window))) - unmanage(c); + unmanage(c, False); } void From 7fe81359d46df4b3173c233a7787d81ce322c827 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:16:54 +0100 Subject: [PATCH 019/257] sync when a client is being killed --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index a2c1e00..5ea74cb 100644 --- a/dwm.c +++ b/dwm.c @@ -1041,6 +1041,7 @@ killclient(const Arg *arg) { } else XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); } void From eb260b1a414fb82fc01d3638e3e77495297c45d5 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:18:05 +0100 Subject: [PATCH 020/257] renaming isdestroyed into destroyed --- dwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 5ea74cb..413e795 100644 --- a/dwm.c +++ b/dwm.c @@ -218,7 +218,7 @@ static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c); -static void unmanage(Client *c, Bool isdestroyed); +static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); static void updategeom(void); static void updatebarpos(Monitor *m); @@ -1627,13 +1627,13 @@ unfocus(Client *c) { } void -unmanage(Client *c, Bool isdestroyed) { +unmanage(Client *c, Bool destroyed) { XWindowChanges wc; /* The server grab construct avoids race conditions. */ detach(c); detachstack(c); - if(!isdestroyed) { + if(!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); XSetErrorHandler(xerrordummy); From 01056b66369f650d02145f27d1399141f93015df Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:30:18 +0100 Subject: [PATCH 021/257] hard-core destruction --- dwm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 413e795..cb296b5 100644 --- a/dwm.c +++ b/dwm.c @@ -1039,9 +1039,15 @@ killclient(const Arg *arg) { ev.xclient.data.l[1] = CurrentTime; XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev); } - else + else { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } } void From 956a430054d5bb1869289475f4f7989552489f77 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:33:58 +0100 Subject: [PATCH 022/257] update --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index cb296b5..7d19b07 100644 --- a/dwm.c +++ b/dwm.c @@ -1652,6 +1652,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); + arrange(); } void From c3feffa1e25da4c39a31d7ae76637bacb0444042 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 15 Sep 2009 13:50:41 +0100 Subject: [PATCH 023/257] applied Tony Lainson's config.def.h patch --- config.def.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index cca37df..cca63f7 100644 --- a/config.def.h +++ b/config.def.h @@ -24,7 +24,7 @@ static const Rule rules[] = { /* layout(s) */ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const Bool resizehints = True; /* False 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 */ @@ -84,8 +84,7 @@ static Key keys[] = { }; /* button definitions */ -/* click can be a tag number (starting at 0), - * ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static Button buttons[] = { /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, From e7300e0f6f10900b50d15ea3ae8949049431e38b Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 16 Sep 2009 15:59:54 +0100 Subject: [PATCH 024/257] implemented dynamic layout symbol stuff --- dwm.1 | 15 +++++++-------- dwm.c | 37 ++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/dwm.1 b/dwm.1 index 5f3cc2c..7ed8ead 100644 --- a/dwm.1 +++ b/dwm.1 @@ -20,14 +20,13 @@ Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P Each screen contains a small status bar which displays all available tags, the -layout, the number of visible windows, the title of the focused window, and the -text read from the root window name property, if the screen is focused. A -floating window is indicated with an empty square and a maximised floating -window is indicated with a filled square before the windows title. The -selected tags are indicated with a different color. The tags of the focused -window are indicated with a filled square in the top left corner. The tags -which are applied to one or more windows are indicated with an empty square in -the top left corner. +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS diff --git a/dwm.c b/dwm.c index 7d19b07..1cb07d3 100644 --- a/dwm.c +++ b/dwm.c @@ -121,6 +121,7 @@ typedef struct { } Layout; struct Monitor { + const char *ltsymbol; float mfact; int num; int by; /* bar geometry */ @@ -238,7 +239,7 @@ static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; -static char stext[256], ntext[8]; +static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ @@ -384,6 +385,7 @@ arrange(void) { showhide(m->stack); focus(NULL); for(m = mons; m; m = m->next) { + m->ltsymbol = m->lt[m->sellt]->symbol; if(m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); restack(m); @@ -649,13 +651,11 @@ dirtomon(int dir) { void drawbar(Monitor *m) { int x; - unsigned int i, n = 0, occ = 0, urg = 0; + unsigned int i, occ = 0, urg = 0; unsigned long *col; Client *c; for(c = m->clients; c; c = c->next) { - if(ISVISIBLE(c)) - n++; occ |= c->tags; if(c->isurgent) urg |= c->tags; @@ -669,15 +669,10 @@ drawbar(Monitor *m) { occ & 1 << i, urg & 1 << i, col); dc.x += dc.w; } - if(blw > 0) { - dc.w = blw; - drawtext(m->lt[m->sellt]->symbol, dc.norm, False); - dc.x += dc.w; - } - snprintf(ntext, sizeof ntext, "%u", n); - dc.w = TEXTW(ntext); - drawtext(ntext, dc.norm, False); - x = (dc.x += dc.w); + dc.w = blw = TEXTW(m->ltsymbol); + drawtext(m->ltsymbol, dc.norm, False); + dc.x += dc.w; + x = dc.x; if(m == selmon) { /* status is only drawn on selected monitor */ dc.w = TEXTW(stext); dc.x = m->ww - dc.w; @@ -1137,8 +1132,17 @@ maprequest(XEvent *e) { void monocle(Monitor *m) { + static char ntext[8]; + unsigned int n = 0; Client *c; + for(c = m->clients; c; c = c->next) + if(ISVISIBLE(c)) + n++; + if(n > 0) { /* override layout symbol */ + snprintf(ntext, sizeof ntext, "[%d]", n); + m->ltsymbol = ntext; + } 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); } @@ -1431,8 +1435,6 @@ setmfact(const Arg *arg) { void setup(void) { - unsigned int i; - int w; XSetWindowAttributes wa; /* clean up any zombies immediately */ @@ -1469,10 +1471,6 @@ setup(void) { if(!dc.font.set) XSetFont(dpy, dc.gc, dc.font.xfont->fid); /* init bars */ - for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { - w = TEXTW(layouts[i].symbol); - blw = MAX(blw, w); - } updatebars(); updatestatus(); /* EWMH support per view */ @@ -1752,6 +1750,7 @@ updategeom(void) { m->topbar = topbar; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; + m->ltsymbol = layouts[0].symbol; updatebarpos(m); } /* reassign left over clients of disappeared monitors */ From 82ec7a7ed4f3ba376faadfc2aca783b24618575f Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 18 Sep 2009 21:18:00 +0100 Subject: [PATCH 025/257] new experimental updategeom() additions that should avoid several problems with Xinerama, this is EXPERIMENTAL and might break something, the algorithms in use are quite complex and cumbersome, patches and comments welcome --- dwm.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/dwm.c b/dwm.c index 1cb07d3..2b4d6b0 100644 --- a/dwm.c +++ b/dwm.c @@ -221,7 +221,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c); 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 updatenumlockmask(void); @@ -535,14 +535,15 @@ configurenotify(XEvent *e) { if(ev->window == root) { sw = ev->width; sh = ev->height; - updategeom(); - 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); - arrange(); + if(updategeom()) { + 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); + arrange(); + } } } @@ -1692,26 +1693,73 @@ updatebarpos(Monitor *m) { m->by = -bh; } -void +Bool updategeom(void) { - int i, n = 1; + int i, j, nn = 1, n = 1; Client *c; Monitor *newmons = NULL, *m = NULL, *tm; #ifdef XINERAMA - int nn; XineramaScreenInfo *info = NULL; + Bool *flags = NULL; if(XineramaIsActive(dpy)) info = XineramaQueryScreens(dpy, &n); - for(i = 1, nn = n; i < n; i++) - if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org - && info[i - 1].width == info[i].width && info[i - 1].height == info[i].height) - --nn; - n = nn; /* we only consider unique geometries as separate screens */ + flags = (Bool *)malloc(sizeof(Bool) * n); + for(i = 0; i < n; i++) + flags[i] = False; + /* next double-loop seeks any combination of retrieved Xinerama info + * with existing monitors, this is used to avoid unnecessary + * re-allocations of monitor structs */ + for(i = 0, nn = n; i < n; i++) + for(j = 0, m = mons; m; m = m->next, j++) + if(!flags[j]) { + if((flags[j] = ( + info[i].x_org == m->mx + && info[i].y_org == m->my + && info[i].width == m->mw + && info[i].height == m->mh) + )) + --nn; + } + if(nn == 0) { /* no need to re-allocate monitors */ + j = 0; + for(i = 0, m = mons; m; m = m->next, i++) { + m->num = info[i].screen_number; + if(info[i].x_org != m->mx + || info[i].y_org != m->my + || info[i].width != m->mw + || info[i].height != m->mh) + { + m->mx = m->wx = info[i].x_org; + m->my = m->wy = info[i].y_org; + m->mw = m->ww = info[i].width; + m->mh = m->wh = info[i].height; + updatebarpos(m); + j++; + } + } + XFree(info); + free(flags); + return j > 0; + } + /* next algorithm only considers unique geometries as separate screens */ + for(i = 0; i < n; i++) + flags[i] = False; /* used for ignoring certain monitors */ + for(i = 0, nn = n; i < n; i++) + for(j = 0; j < n; j++) + if(i != j && !flags[i]) { + if((flags[i] = ( + info[i].x_org == info[j].x_org + && info[i].y_org == info[j].y_org + && info[i].width == info[j].width + && info[i].height == info[j].height) + )) + --nn; + } #endif /* XINERAMA */ /* allocate monitor(s) for the new geometry setup */ - for(i = 0; i < n; i++) { + for(i = 0; i < nn; i++) { if(!(m = (Monitor *)malloc(sizeof(Monitor)))) die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); m->next = newmons; @@ -1720,14 +1768,18 @@ updategeom(void) { /* initialise monitor(s) */ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - for(i = 0, m = newmons; m; m = m->next, i++) { - m->num = info[i].screen_number; - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; + for(i = 0, m = newmons; m && i < n; i++) { + if(!flags[i]) { /* only use screens that aren't dublettes */ + m->num = info[i].screen_number; + m->mx = m->wx = info[i].x_org; + m->my = m->wy = info[i].y_org; + m->mw = m->ww = info[i].width; + m->mh = m->wh = info[i].height; + m = m->next; + } } XFree(info); + free(flags); } else #endif /* XINERAMA */ @@ -1767,6 +1819,7 @@ updategeom(void) { cleanupmons(); selmon = mons = newmons; selmon = wintomon(root); + return True; } void From f0a4845e7dec3a4c7316311fcf1108148bb29730 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 19 Sep 2009 11:52:16 +0100 Subject: [PATCH 026/257] added TODO to updategeom in order to implement a decent version of it soon --- dwm.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dwm.c b/dwm.c index 2b4d6b0..7363396 100644 --- a/dwm.c +++ b/dwm.c @@ -1699,6 +1699,40 @@ updategeom(void) { Client *c; Monitor *newmons = NULL, *m = NULL, *tm; + /* TODO: + * This function needs to be seriously re-designed: + * + * #ifdef XINERAMA + * 1. Determine number of already existing monitors n + * 2. Determine number of monitors Xinerama reports nn + * 3. if(n <= nn) { + * if(n < nn) { + * append nn-n monitors to current struct + * flag dirty + * } + * for(i = 0; i < nn; i++) { + * if(oldgeom != newgeom) { + * apply newgeom; + * flag dirty; + * } + * } + * } + * else { + * detach all clients + * destroy current monitor struct + * create new monitor struct + * attach all clients to first monitor + * flag dirty; + * } + * return dirty flag to caller + * if dirty is seen by caller: + * re-arrange bars/pixmaps + * arrange() + * #else + * don't share between XINERAMA and non-XINERAMA handling if it gets + * too ugly + * #endif + */ #ifdef XINERAMA XineramaScreenInfo *info = NULL; Bool *flags = NULL; From 07ad2981337c9154fe84078454e646771b5a3425 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 21 Sep 2009 19:51:17 +0100 Subject: [PATCH 027/257] implemented different version of updategeom --- config.mk | 8 +- dwm.c | 234 ++++++++++++++++++++---------------------------------- 2 files changed, 89 insertions(+), 153 deletions(-) diff --git a/config.mk b/config.mk index 086424d..2b93435 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -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} +CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -g ${LIBS} +#LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" diff --git a/dwm.c b/dwm.c index 7363396..8ddc072 100644 --- a/dwm.c +++ b/dwm.c @@ -163,6 +163,7 @@ static void clearurgent(Client *c); static void configure(Client *c); static void configurenotify(XEvent *e); static void configurerequest(XEvent *e); +static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); @@ -592,6 +593,22 @@ configurerequest(XEvent *e) { XSync(dpy, False); } +Monitor * +createmon(void) { + Monitor *m; + + if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + m->ltsymbol = layouts[0].symbol; + return m; +} + void destroynotify(XEvent *e) { Client *c; @@ -1005,6 +1022,19 @@ isprotodel(Client *c) { return ret; } +#ifdef XINERAMA +static Bool +isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) { + unsigned int i; + + for(i = 0; i < len; i++) + if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org + && unique[i].width == info->width && unique[i].height == info->height) + return False; + return True; +} +#endif /* XINERAMA */ + void keypress(XEvent *e) { unsigned int i; @@ -1695,165 +1725,71 @@ updatebarpos(Monitor *m) { Bool updategeom(void) { - int i, j, nn = 1, n = 1; - Client *c; - Monitor *newmons = NULL, *m = NULL, *tm; + Bool dirty = False; - /* TODO: - * This function needs to be seriously re-designed: - * - * #ifdef XINERAMA - * 1. Determine number of already existing monitors n - * 2. Determine number of monitors Xinerama reports nn - * 3. if(n <= nn) { - * if(n < nn) { - * append nn-n monitors to current struct - * flag dirty - * } - * for(i = 0; i < nn; i++) { - * if(oldgeom != newgeom) { - * apply newgeom; - * flag dirty; - * } - * } - * } - * else { - * detach all clients - * destroy current monitor struct - * create new monitor struct - * attach all clients to first monitor - * flag dirty; - * } - * return dirty flag to caller - * if dirty is seen by caller: - * re-arrange bars/pixmaps - * arrange() - * #else - * don't share between XINERAMA and non-XINERAMA handling if it gets - * too ugly - * #endif - */ -#ifdef XINERAMA - XineramaScreenInfo *info = NULL; - Bool *flags = NULL; - - if(XineramaIsActive(dpy)) - info = XineramaQueryScreens(dpy, &n); - flags = (Bool *)malloc(sizeof(Bool) * n); - for(i = 0; i < n; i++) - flags[i] = False; - /* next double-loop seeks any combination of retrieved Xinerama info - * with existing monitors, this is used to avoid unnecessary - * re-allocations of monitor structs */ - for(i = 0, nn = n; i < n; i++) - for(j = 0, m = mons; m; m = m->next, j++) - if(!flags[j]) { - if((flags[j] = ( - info[i].x_org == m->mx - && info[i].y_org == m->my - && info[i].width == m->mw - && info[i].height == m->mh) - )) - --nn; - } - if(nn == 0) { /* no need to re-allocate monitors */ - j = 0; - for(i = 0, m = mons; m; m = m->next, i++) { - m->num = info[i].screen_number; - if(info[i].x_org != m->mx - || info[i].y_org != m->my - || info[i].width != m->mw - || info[i].height != m->mh) - { - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; - updatebarpos(m); - j++; - } - } - XFree(info); - free(flags); - return j > 0; - } - /* next algorithm only considers unique geometries as separate screens */ - for(i = 0; i < n; i++) - flags[i] = False; /* used for ignoring certain monitors */ - for(i = 0, nn = n; i < n; i++) - for(j = 0; j < n; j++) - if(i != j && !flags[i]) { - if((flags[i] = ( - info[i].x_org == info[j].x_org - && info[i].y_org == info[j].y_org - && info[i].width == info[j].width - && info[i].height == info[j].height) - )) - --nn; - } -#endif /* XINERAMA */ - /* allocate monitor(s) for the new geometry setup */ - for(i = 0; i < nn; i++) { - if(!(m = (Monitor *)malloc(sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); - m->next = newmons; - newmons = m; - } - /* initialise monitor(s) */ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - for(i = 0, m = newmons; m && i < n; i++) { - if(!flags[i]) { /* only use screens that aren't dublettes */ - m->num = info[i].screen_number; - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; - m = m->next; - } - } + int i, j, n, nn; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + info = XineramaQueryScreens(dpy, &nn); + 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(isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); - free(flags); + 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 = unique[i].screen_number; + 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 */ + cleanup(); + setup(); + } + free(unique); } else #endif /* XINERAMA */ /* default monitor setup */ { - m->num = 0; - m->mx = m->wx = 0; - m->my = m->wy = 0; - m->mw = m->ww = sw; - m->mh = m->wh = sh; - } - /* bar geometry setup */ - for(m = newmons; m; m = m->next) { - m->sel = m->stack = m->clients = NULL; - m->seltags = 0; - m->sellt = 0; - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->showbar = showbar; - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - m->ltsymbol = layouts[0].symbol; - updatebarpos(m); - } - /* reassign left over clients of disappeared monitors */ - for(tm = mons; tm; tm = tm->next) - while(tm->clients) { - c = tm->clients; - tm->clients = c->next; - detachstack(c); - c->mon = newmons; - attach(c); - attachstack(c); + 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); } - /* select focused monitor */ - cleanupmons(); - selmon = mons = newmons; - selmon = wintomon(root); - return True; + } + if(dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; } void From 6f55de83100547e6f78ebc276dfdbca5ee2581d9 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 09:16:48 +0100 Subject: [PATCH 028/257] added missing scan --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 8ddc072..0d2f670 100644 --- a/dwm.c +++ b/dwm.c @@ -1769,6 +1769,7 @@ updategeom(void) { else { /* less monitors available */ cleanup(); setup(); + scan(); } free(unique); } From c45d46ad9a44b9897c8c12eacb60b5cbdd31be7c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 09:53:11 +0100 Subject: [PATCH 029/257] use buffer instead of pointer for mon->ltsymbol --- dwm.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dwm.c b/dwm.c index 0d2f670..48f50da 100644 --- a/dwm.c +++ b/dwm.c @@ -121,7 +121,7 @@ typedef struct { } Layout; struct Monitor { - const char *ltsymbol; + char ltsymbol[16]; float mfact; int num; int by; /* bar geometry */ @@ -386,7 +386,7 @@ arrange(void) { showhide(m->stack); focus(NULL); for(m = mons; m; m = m->next) { - m->ltsymbol = m->lt[m->sellt]->symbol; + 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); @@ -605,7 +605,7 @@ createmon(void) { m->topbar = topbar; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; - m->ltsymbol = layouts[0].symbol; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); return m; } @@ -1163,17 +1163,14 @@ maprequest(XEvent *e) { void monocle(Monitor *m) { - static char ntext[8]; unsigned int n = 0; Client *c; for(c = m->clients; c; c = c->next) if(ISVISIBLE(c)) n++; - if(n > 0) { /* override layout symbol */ - snprintf(ntext, sizeof ntext, "[%d]", n); - m->ltsymbol = ntext; - } + 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); } From 30fed9a211e524f2b1d7387fc62468c2225ab93d Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 20:33:42 +0100 Subject: [PATCH 030/257] implemented nn < n case, k-zed please recheck --- dwm.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/dwm.c b/dwm.c index 48f50da..5199e71 100644 --- a/dwm.c +++ b/dwm.c @@ -158,7 +158,7 @@ static void attachstack(Client *c); static void buttonpress(XEvent *e); static void checkotherwm(void); static void cleanup(void); -static void cleanupmons(void); +static void cleanupmon(Monitor *mon); static void clearurgent(Client *c); static void configure(Client *c); static void configurenotify(XEvent *e); @@ -480,22 +480,25 @@ cleanup(void) { XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurResize]); XFreeCursor(dpy, cursor[CurMove]); - cleanupmons(); + while(mons) + cleanupmon(mons); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); } void -cleanupmons(void) { +cleanupmon(Monitor *mon) { Monitor *m; - while(mons) { - m = mons->next; - XUnmapWindow(dpy, mons->barwin); - XDestroyWindow(dpy, mons->barwin); - free(mons); - mons = m; + if(mon == mons) + mons = mons->next; + else { + for(m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); } void @@ -1727,6 +1730,7 @@ updategeom(void) { #ifdef XINERAMA if(XineramaIsActive(dpy)) { int i, j, n, nn; + Client *c; Monitor *m; XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; @@ -1755,7 +1759,7 @@ updategeom(void) { || unique[i].width != m->mw || unique[i].height != m->mh)) { dirty = True; - m->num = unique[i].screen_number; + 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; @@ -1763,10 +1767,22 @@ updategeom(void) { updatebarpos(m); } } - else { /* less monitors available */ - cleanup(); - setup(); - scan(); + 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); } From 91e902f7fe0c88933b1f8b85f1b8748b832a4d3c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 20:34:03 +0100 Subject: [PATCH 031/257] switching to release flags --- config.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.mk b/config.mk index 2b93435..086424d 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -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} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +#LDFLAGS = -g ${LIBS} +LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" From 0b72be924d3f0daa63e45a09951d6cb6cc9b335e Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 26 Sep 2009 19:52:04 +0100 Subject: [PATCH 032/257] Added tag 5.7 for changeset 257403d4cd96 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6ef9274..5b96aa2 100644 --- a/.hgtags +++ b/.hgtags @@ -63,3 +63,4 @@ e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2 deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 5550702215773aad462f22a774dced9b87437c51 5.6 e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 +257403d4cd962cac03344a871ea56cc742bae38e 5.7 From 9e8dd3479da9f484c9aa37adcd327989149e89ef Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 27 Sep 2009 10:31:14 +0100 Subject: [PATCH 033/257] fixed the layout symbol bug reported by Nibble (but using a different approach as he suggested) - optimised drawbar() and arrange() handling for multiple monitors, arrange only arranges the relevant monitors when applicable, same with drawbar - need to release 5.7.1 --- config.mk | 2 +- dwm.c | 66 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/config.mk b/config.mk index 086424d..bb55cfa 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.7 +VERSION = 5.7.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 5199e71..b3a389d 100644 --- a/dwm.c +++ b/dwm.c @@ -152,7 +152,8 @@ typedef struct { /* function declarations */ static void applyrules(Client *c); static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); -static void arrange(void); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); static void attach(Client *c); static void attachstack(Client *c); static void buttonpress(XEvent *e); @@ -379,18 +380,24 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { } void -arrange(void) { - Monitor *m; - - for(m = mons; m; m = m->next) +arrange(Monitor *m) { + if(m) + showhide(m->stack); + else for(m = mons; m; m = m->next) showhide(m->stack); focus(NULL); - for(m = mons; m; m = m->next) { - 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); - } + if(m) + arrangemon(m); + else for(m = mons; m; m = m->next) + arrangemon(m); +} + +void +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 @@ -546,7 +553,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - arrange(); + arrange(NULL); } } } @@ -1139,7 +1146,7 @@ manage(Window w, XWindowAttributes *wa) { XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ XMapWindow(dpy, c->win); setclientstate(c, NormalState); - arrange(); + arrange(c->mon); } void @@ -1265,7 +1272,7 @@ propertynotify(XEvent *e) { case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL))) - arrange(); + arrange(c->mon); break; case XA_WM_NORMAL_HINTS: updatesizehints(c); @@ -1360,7 +1367,7 @@ restack(Monitor *m) { XEvent ev; XWindowChanges wc; - drawbars(); + drawbar(m); if(!m->sel) return; if(m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1427,7 +1434,7 @@ sendmon(Client *c, Monitor *m) { attach(c); attachstack(c); focus(NULL); - arrange(); + arrange(NULL); } void @@ -1442,12 +1449,14 @@ void 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) - arrange(); + arrange(selmon); else - drawbars(); + drawbar(selmon); } /* arg > 1.0 will set mfact absolutly */ @@ -1461,7 +1470,7 @@ setmfact(const Arg *arg) { if(f < 0.1 || f > 0.9) return; selmon->mfact = f; - arrange(); + arrange(selmon); } void @@ -1558,7 +1567,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; - arrange(); + arrange(selmon); } } @@ -1615,7 +1624,7 @@ togglebar(const Arg *arg) { selmon->showbar = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(); + arrange(selmon); } void @@ -1626,7 +1635,7 @@ togglefloating(const Arg *arg) { if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, selmon->sel->w, selmon->sel->h, False); - arrange(); + arrange(selmon); } void @@ -1638,7 +1647,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; - arrange(); + arrange(selmon); } } @@ -1648,7 +1657,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; - arrange(); + arrange(selmon); } } @@ -1663,6 +1672,7 @@ unfocus(Client *c) { void unmanage(Client *c, Bool destroyed) { + Monitor *m = c->mon; XWindowChanges wc; /* The server grab construct avoids race conditions. */ @@ -1681,7 +1691,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); - arrange(); + arrange(m); } void @@ -1908,7 +1918,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - arrange(); + arrange(selmon); } Client * @@ -1986,7 +1996,7 @@ zoom(const Arg *arg) { detach(c); attach(c); focus(c); - arrange(); + arrange(c->mon); } int From 7879616a75948f7b713e56e51ca6461925be23b4 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 27 Sep 2009 10:31:20 +0100 Subject: [PATCH 034/257] Added tag 5.7.1 for changeset 48c3f87c335d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 5b96aa2..a1464db 100644 --- a/.hgtags +++ b/.hgtags @@ -64,3 +64,4 @@ deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 5550702215773aad462f22a774dced9b87437c51 5.6 e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 257403d4cd962cac03344a871ea56cc742bae38e 5.7 +48c3f87c335d6606e55fbae97267fa6b39ca56e0 5.7.1 From 210378f19833c739f3d2e4acaca55fccb29c57f7 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 27 Sep 2009 20:20:10 +0100 Subject: [PATCH 035/257] applied Ryan Zheng's patch and re-releasing 5.7.2 --- config.mk | 2 +- dwm.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/config.mk b/config.mk index bb55cfa..492f0f3 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.7.1 +VERSION = 5.7.2 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index b3a389d..32755cb 100644 --- a/dwm.c +++ b/dwm.c @@ -1449,10 +1449,9 @@ void 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); - } + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if(selmon->sel) arrange(selmon); else From 161f2d921bc47671a9e824389bae625e5c2c5938 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 27 Sep 2009 20:20:14 +0100 Subject: [PATCH 036/257] Added tag 5.7.2 for changeset 15761ac5e2f1 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index a1464db..8cfc85d 100644 --- a/.hgtags +++ b/.hgtags @@ -65,3 +65,4 @@ deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 257403d4cd962cac03344a871ea56cc742bae38e 5.7 48c3f87c335d6606e55fbae97267fa6b39ca56e0 5.7.1 +15761ac5e2f1e9010900f891616a24a22d82f128 5.7.2 From ac4caea92131a3fa46ea3f8b0c296ef175cc713a Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 31 Oct 2009 11:45:56 +0000 Subject: [PATCH 037/257] added BUGS, next version is 5.8 --- BUGS | 31 +++++++++++++++++++++++++++++++ config.mk | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 BUGS diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..d833acf --- /dev/null +++ b/BUGS @@ -0,0 +1,31 @@ +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 + + +> enternotify is handled even when the entered window is already focused +> (eg moving the mouse to the bar and back, scrolling on the border..) + > + > focusing might be expensive for some clients (eg dim/light up) + > + > a possible solution is to modify enternotify: + > + > + c = wintoclient(ev->window); + > if((m = wintomon(ev->window)) && m != selmon) { + > unfocus(selmon->sel); + > selmon = m; + > } + > + else if (c == selmon->sel || c == NULL) + > + return; + + + +> another corner case: + +a tiled client can be resized with mod+right click, but it only works +on the main monitor + +dmenu appears on the monitor where the pointer is and not on selmon + diff --git a/config.mk b/config.mk index 492f0f3..7583d37 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.7.2 +VERSION = 5.8 # Customize below to fit your system From bc554d45d8712533862984550a8ba8169a3ba278 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 23 Nov 2009 08:13:18 +0000 Subject: [PATCH 038/257] added nsz's last bug corner case --- BUGS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/BUGS b/BUGS index d833acf..370173f 100644 --- a/BUGS +++ b/BUGS @@ -29,3 +29,9 @@ on the main monitor dmenu appears on the monitor where the pointer is and not on selmon + +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 From 7671d03a90e83c13cd33111b25249c18c814c3d3 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 24 Nov 2009 09:31:17 +0000 Subject: [PATCH 039/257] removed misleading comment, thanks Romain Bertrand --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 7583d37..f17664f 100644 --- a/config.mk +++ b/config.mk @@ -10,7 +10,7 @@ MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib -# Xinerama, un-comment if you want it +# Xinerama XINERAMALIBS = -L${X11LIB} -lXinerama XINERAMAFLAGS = -DXINERAMA From 1144e983949878ea75e5d40e93b063ff7d1e1150 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 25 Nov 2009 13:56:17 +0000 Subject: [PATCH 040/257] another bug report --- BUGS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/BUGS b/BUGS index 370173f..181ae15 100644 --- a/BUGS +++ b/BUGS @@ -35,3 +35,12 @@ 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 + +Starting emacs from xterm doesnt show this problem, he uses tag 8 for emacs From d6bdd03d915ecb800444986503b43aa488a82e36 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 31 Mar 2010 23:24:22 +0100 Subject: [PATCH 041/257] it's debug season for upcoming dwm 5.8, so only use this if you really want to run experimental code or debug code --- BUGS | 13 +++++++++++++ config.mk | 8 ++++---- dwm.c | 24 ++++++++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/BUGS b/BUGS index 181ae15..de83186 100644 --- a/BUGS +++ b/BUGS @@ -44,3 +44,16 @@ 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. diff --git a/config.mk b/config.mk index f17664f..303984d 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -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} +CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -g ${LIBS} +#LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" diff --git a/dwm.c b/dwm.c index 32755cb..88d80b2 100644 --- a/dwm.c +++ b/dwm.c @@ -41,6 +41,7 @@ #endif /* XINERAMA */ /* macros */ +#define D if(1) #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) @@ -814,8 +815,8 @@ void focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if(selmon->sel) - unfocus(selmon->sel); +// if(selmon->sel) +// unfocus(selmon->sel); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -1388,12 +1389,27 @@ restack(Monitor *m) { void run(void) { XEvent ev; - + static const char *evname[LASTEvent] = { + [ButtonPress] = "buttonpress", + [ConfigureRequest] = "configurerequest", + [ConfigureNotify] = "configurenotify", + [DestroyNotify] = "destroynotify", + [EnterNotify] = "enternotify", + [Expose] = "expose", + [FocusIn] = "focusin", + [KeyPress] = "keypress", + [MappingNotify] = "mappingnotify", + [MapRequest] = "maprequest", + [PropertyNotify] = "propertynotify", + [UnmapNotify] = "unmapnotify" + }; /* main event loop */ XSync(dpy, False); - while(running && !XNextEvent(dpy, &ev)) + while(running && !XNextEvent(dpy, &ev)) { + D fprintf(stderr, "run event %s\n", evname[ev.type]); if(handler[ev.type]) handler[ev.type](&ev); /* call handler */ + } } void From c53b29e60b1fcc0f7f095eaabccf38b3630e28fa Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 31 Mar 2010 23:27:30 +0100 Subject: [PATCH 042/257] quick typo fix --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 88d80b2..b989e8a 100644 --- a/dwm.c +++ b/dwm.c @@ -815,8 +815,8 @@ void focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); -// if(selmon->sel) -// unfocus(selmon->sel); +/* if(selmon->sel) + unfocus(selmon->sel);*/ if(c) { if(c->mon != selmon) selmon = c->mon; From aa9f2be24ea9ea6d9419cad1975bf34c5b64b6e5 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 1 Apr 2010 00:14:15 +0100 Subject: [PATCH 043/257] more debug output, experimental focus optimisation --- dwm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index b989e8a..b1f77cc 100644 --- a/dwm.c +++ b/dwm.c @@ -815,8 +815,12 @@ void focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); -/* if(selmon->sel) - unfocus(selmon->sel);*/ + if(c && c == selmon->sel) { + D fprintf(stderr, "focus, optimising focus away\n"); + return; + } + if(selmon->sel) + unfocus(selmon->sel); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -848,7 +852,8 @@ focusmon(const Arg *arg) { if(!mons->next) return; - m = dirtomon(arg->i); + if((m = dirtomon(arg->i)) == selmon) + return; unfocus(selmon->sel); selmon = m; focus(NULL); @@ -1406,7 +1411,7 @@ run(void) { /* main event loop */ XSync(dpy, False); while(running && !XNextEvent(dpy, &ev)) { - D fprintf(stderr, "run event %s\n", evname[ev.type]); + D fprintf(stderr, "run event %s %ld\n", evname[ev.type], ev.xany.window); if(handler[ev.type]) handler[ev.type](&ev); /* call handler */ } From a88e0373efe5f6800a99fca2c228be98b522aaa9 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 1 Apr 2010 19:39:24 +0100 Subject: [PATCH 044/257] selmon optimisation is needed --- dwm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dwm.c b/dwm.c index b1f77cc..ac534a8 100644 --- a/dwm.c +++ b/dwm.c @@ -815,10 +815,6 @@ void focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if(c && c == selmon->sel) { - D fprintf(stderr, "focus, optimising focus away\n"); - return; - } if(selmon->sel) unfocus(selmon->sel); if(c) { From 427053f8d1cf8e8174d7ab4861a6ec19a79d1032 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 1 Apr 2010 22:34:46 +0100 Subject: [PATCH 045/257] pretty printing bugs a bit --- BUGS | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/BUGS b/BUGS index de83186..17f196e 100644 --- a/BUGS +++ b/BUGS @@ -1,34 +1,40 @@ +--- + 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 +--- > enternotify is handled even when the entered window is already focused > (eg moving the mouse to the bar and back, scrolling on the border..) - > - > focusing might be expensive for some clients (eg dim/light up) - > - > a possible solution is to modify enternotify: - > - > + c = wintoclient(ev->window); - > if((m = wintomon(ev->window)) && m != selmon) { - > unfocus(selmon->sel); - > selmon = m; - > } - > + else if (c == selmon->sel || c == NULL) - > + return; - +> +> focusing might be expensive for some clients (eg dim/light up) +> +> a possible solution is to modify enternotify: +> +> + c = wintoclient(ev->window); +> if((m = wintomon(ev->window)) && m != selmon) { +> unfocus(selmon->sel); +> selmon = m; +> } +> + else if (c == selmon->sel || c == NULL) +> + return; +--- > another corner case: a tiled client can be resized with mod+right click, but it only works on the main monitor +--- + dmenu appears on the monitor where the pointer is and not on selmon +--- yet another corner case: open a terminal, focus another monitor, but without moving the mouse @@ -36,7 +42,6 @@ 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: @@ -57,3 +62,15 @@ 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? + +--- From 1973ab0643707f708a7d6dbede749d5fa6ac1256 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 11 Apr 2010 18:42:32 +0100 Subject: [PATCH 046/257] added the related bug reported by voltaic --- BUGS | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/BUGS b/BUGS index 17f196e..5ee05ab 100644 --- a/BUGS +++ b/BUGS @@ -74,3 +74,24 @@ SDL seems to not like non-reparenting WMs: Patching SDL, bugging them? --- + +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. + +--- From c6180949a759e936e57d7ec9d4cfee3379a39cef Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Thu, 27 May 2010 08:19:08 +0100 Subject: [PATCH 047/257] applied Sylvain Laurent's EWMH fullscreen state patch, simplified his patch a bit --- config.def.h | 2 +- dwm.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index cca63f7..91cf439 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[] = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"; +static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; static const char normbordercolor[] = "#cccccc"; static const char normbgcolor[] = "#cccccc"; static const char normfgcolor[] = "#000000"; diff --git a/dwm.c b/dwm.c index ac534a8..3b18b2b 100644 --- a/dwm.c +++ b/dwm.c @@ -41,7 +41,6 @@ #endif /* XINERAMA */ /* macros */ -#define D if(1) #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) @@ -58,7 +57,8 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ -enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ +enum { NetSupported, NetWMName, NetWMState, + NetWMFullscreen, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -162,6 +162,7 @@ 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); static void configurerequest(XEvent *e); @@ -250,6 +251,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, [ConfigureRequest] = configurerequest, [ConfigureNotify] = configurenotify, [DestroyNotify] = destroynotify, @@ -1292,6 +1294,20 @@ propertynotify(XEvent *e) { } } +void +clientmessage(XEvent *e) { + XClientMessageEvent *cme = &e->xclient; + + if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { + if(cme->data.l[0]) + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + else + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + } +} + void quit(const Arg *arg) { running = False; @@ -1392,6 +1408,7 @@ run(void) { XEvent ev; static const char *evname[LASTEvent] = { [ButtonPress] = "buttonpress", + [ClientMessage] = "clientmessage", [ConfigureRequest] = "configurerequest", [ConfigureNotify] = "configurenotify", [DestroyNotify] = "destroynotify", @@ -1407,7 +1424,6 @@ run(void) { /* main event loop */ XSync(dpy, False); while(running && !XNextEvent(dpy, &ev)) { - D fprintf(stderr, "run event %s %ld\n", evname[ev.type], ev.xany.window); if(handler[ev.type]) handler[ev.type](&ev); /* call handler */ } @@ -1510,6 +1526,8 @@ setup(void) { wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); From f83d61dfe8f24c9a50ccf7e4b903b8844367ccb7 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Thu, 27 May 2010 08:20:42 +0100 Subject: [PATCH 048/257] removed DEBUG code and added 2010 to the copyright list --- LICENSE | 2 +- dwm.c | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/LICENSE b/LICENSE index 86b2c94..059cf28 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2009 Anselm R Garbe +© 2006-2010 Anselm R Garbe © 2006-2007 Sander van Dijk © 2006-2009 Jukka Salmi © 2007-2009 Premysl Hruby diff --git a/dwm.c b/dwm.c index 3b18b2b..fedf069 100644 --- a/dwm.c +++ b/dwm.c @@ -1406,21 +1406,6 @@ restack(Monitor *m) { void run(void) { XEvent ev; - static const char *evname[LASTEvent] = { - [ButtonPress] = "buttonpress", - [ClientMessage] = "clientmessage", - [ConfigureRequest] = "configurerequest", - [ConfigureNotify] = "configurenotify", - [DestroyNotify] = "destroynotify", - [EnterNotify] = "enternotify", - [Expose] = "expose", - [FocusIn] = "focusin", - [KeyPress] = "keypress", - [MappingNotify] = "mappingnotify", - [MapRequest] = "maprequest", - [PropertyNotify] = "propertynotify", - [UnmapNotify] = "unmapnotify" - }; /* main event loop */ XSync(dpy, False); while(running && !XNextEvent(dpy, &ev)) { @@ -2036,7 +2021,7 @@ zoom(const Arg *arg) { int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2010 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) From a704b1ee34dd84fa5ba65ed1981eb3a69bf8633f Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 28 May 2010 11:43:44 +0100 Subject: [PATCH 049/257] Added tag 5.8 for changeset 60ea8fed13ab --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8cfc85d..c78e6c2 100644 --- a/.hgtags +++ b/.hgtags @@ -66,3 +66,4 @@ e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 257403d4cd962cac03344a871ea56cc742bae38e 5.7 48c3f87c335d6606e55fbae97267fa6b39ca56e0 5.7.1 15761ac5e2f1e9010900f891616a24a22d82f128 5.7.2 +60ea8fed13ab750c6717f2764cbf9c13bb6f0d0a 5.8 From 5c6545adf5e2fc7011bd53735910f66998cade64 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 29 May 2010 12:48:11 +0100 Subject: [PATCH 050/257] removing Sylvain's patch because it breaks more than it fixes unfortunately, re-issuing a bugfix release 5.8.1 --- config.mk | 2 +- dwm.c | 20 +------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/config.mk b/config.mk index 303984d..df7194b 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.8 +VERSION = 5.8.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index fedf069..5df4919 100644 --- a/dwm.c +++ b/dwm.c @@ -57,8 +57,7 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ -enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetLast }; /* EWMH atoms */ +enum { NetSupported, NetWMName, NetWMState, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -162,7 +161,6 @@ 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); static void configurerequest(XEvent *e); @@ -251,7 +249,6 @@ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, [ConfigureRequest] = configurerequest, [ConfigureNotify] = configurenotify, [DestroyNotify] = destroynotify, @@ -1294,20 +1291,6 @@ propertynotify(XEvent *e) { } } -void -clientmessage(XEvent *e) { - XClientMessageEvent *cme = &e->xclient; - - if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { - if(cme->data.l[0]) - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - else - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - } -} - void quit(const Arg *arg) { running = False; @@ -1512,7 +1495,6 @@ 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[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); From 4c9b397ff9653277b6e0e35d7c79dca76756b7ba Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 29 May 2010 12:48:18 +0100 Subject: [PATCH 051/257] Added tag 5.8.1 for changeset 1ed1e75c9c2e --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c78e6c2..2995cd3 100644 --- a/.hgtags +++ b/.hgtags @@ -67,3 +67,4 @@ e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 48c3f87c335d6606e55fbae97267fa6b39ca56e0 5.7.1 15761ac5e2f1e9010900f891616a24a22d82f128 5.7.2 60ea8fed13ab750c6717f2764cbf9c13bb6f0d0a 5.8 +1ed1e75c9c2e395a2c475b52657a430bd95070c7 5.8.1 From 62d3caa9990e4fd936850341095da4dd1bf4c846 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 30 May 2010 10:02:56 +0100 Subject: [PATCH 052/257] implemented better fullscreen handling, please test --- dwm.c | 105 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/dwm.c b/dwm.c index 5df4919..670afbe 100644 --- a/dwm.c +++ b/dwm.c @@ -57,7 +57,8 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ -enum { NetSupported, NetWMName, NetWMState, NetLast }; /* EWMH atoms */ +enum { NetSupported, NetWMName, NetWMState, + NetWMFullscreen, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -83,10 +84,11 @@ struct Client { char name[256]; float mina, maxa; int x, y, w, h; + int oldx, oldy, oldw, oldh; int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent; + Bool isfixed, isfloating, isurgent, oldstate; Client *next; Client *snext; Monitor *mon; @@ -161,6 +163,7 @@ 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); static void configurerequest(XEvent *e); @@ -200,6 +203,7 @@ static Monitor *ptrtomon(int x, int y); static void propertynotify(XEvent *e); static void quit(const Arg *arg); 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); @@ -220,7 +224,7 @@ 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); +static void unfocus(Client *c, Bool setfocus); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); static Bool updategeom(void); @@ -249,6 +253,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, [ConfigureRequest] = configurerequest, [ConfigureNotify] = configurenotify, [DestroyNotify] = destroynotify, @@ -423,7 +428,7 @@ buttonpress(XEvent *e) { click = ClkRootWin; /* focus monitor if necessary */ if((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel); + unfocus(selmon->sel, True); selmon = m; focus(NULL); } @@ -792,7 +797,7 @@ enternotify(XEvent *e) { if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; if((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel); + unfocus(selmon->sel, True); selmon = m; } if((c = wintoclient(ev->window))) @@ -814,8 +819,9 @@ void focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if(selmon->sel) - unfocus(selmon->sel); + /* was if(selmon->sel) */ + if(selmon->sel && selmon->sel != c) + unfocus(selmon->sel, False); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -849,7 +855,7 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel); + unfocus(selmon->sel, True); selmon = m; focus(NULL); } @@ -901,15 +907,14 @@ getrootptr(int *x, int *y) { long getstate(Window w) { - int format, status; + int format; long result = -1; unsigned char *p = NULL; unsigned long n, extra; Atom real; - status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p); - if(status != Success) + if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) return -1; if(n != 0) result = *p; @@ -1110,12 +1115,13 @@ manage(Window w, XWindowAttributes *wa) { applyrules(c); } /* geometry */ - c->x = wa->x + c->mon->wx; - c->y = wa->y + c->mon->wy; - c->w = wa->width; - c->h = wa->height; + c->x = c->oldx = wa->x + c->mon->wx; + c->y = c->oldy = wa->y + c->mon->wy; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; c->oldbw = wa->border_width; if(c->w == c->mon->mw && c->h == c->mon->mh) { + c->isfloating = 1; c->x = c->mon->mx; c->y = c->mon->my; c->bw = 0; @@ -1139,7 +1145,7 @@ manage(Window w, XWindowAttributes *wa) { XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, False); if(!c->isfloating) - c->isfloating = trans != None || c->isfixed; + c->isfloating = c->oldstate = trans != None || c->isfixed; if(c->isfloating) XRaiseWindow(dpy, c->win); attach(c); @@ -1291,6 +1297,39 @@ propertynotify(XEvent *e) { } } +void +clientmessage(XEvent *e) { + XClientMessageEvent *cme = &e->xclient; + Client *c; + + if((c = wintoclient(cme->window)) + && (cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen])) + { + if(cme->data.l[0]) { + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + else { + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } + } +} + void quit(const Arg *arg) { running = False; @@ -1298,18 +1337,22 @@ quit(const Arg *arg) { void 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); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; - if(applysizehints(c, &x, &y, &w, &h, interact)) { - c->x = wc.x = x; - c->y = wc.y = y; - c->w = wc.width = w; - c->h = wc.height = h; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); - } + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); } void @@ -1427,7 +1470,7 @@ void sendmon(Client *c, Monitor *m) { if(c->mon == m) return; - unfocus(c); + unfocus(c, True); detach(c); detachstack(c); c->mon = m; @@ -1495,6 +1538,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[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); @@ -1663,12 +1707,13 @@ toggleview(const Arg *arg) { } void -unfocus(Client *c) { +unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + if(setfocus) + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); } void From ee734fae6b35cfbeeb810e637c4f458b55c29fce Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 30 May 2010 10:03:09 +0100 Subject: [PATCH 053/257] increased version --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index df7194b..9747462 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.8.1 +VERSION = 5.8.2 # Customize below to fit your system From f1a2a3c8501ed2acb4fdeb86f6aa2ce2c19bbc7d Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Fri, 4 Jun 2010 11:41:16 +0100 Subject: [PATCH 054/257] Added tag 5.8.2 for changeset a043f0800805 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 2995cd3..b0b566b 100644 --- a/.hgtags +++ b/.hgtags @@ -68,3 +68,4 @@ e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 15761ac5e2f1e9010900f891616a24a22d82f128 5.7.2 60ea8fed13ab750c6717f2764cbf9c13bb6f0d0a 5.8 1ed1e75c9c2e395a2c475b52657a430bd95070c7 5.8.1 +a043f08008051ca02ae87eb170cd066d8c8315a0 5.8.2 From 36311d88afc07b61131a165cdc383020b7201d95 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 25 Jul 2010 09:58:25 +0100 Subject: [PATCH 055/257] applied Hiltjo Posthuma's double-XineramaQueryScreens() patch, thanks Hiltjo! --- dwm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwm.c b/dwm.c index 670afbe..438b9e7 100644 --- a/dwm.c +++ b/dwm.c @@ -1791,7 +1791,6 @@ updategeom(void) { XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; - info = XineramaQueryScreens(dpy, &nn); for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) From 1529058f27821d50d7a1ea085b6362b6b353b399 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Mon, 23 Aug 2010 17:25:53 +0100 Subject: [PATCH 056/257] applied Hiltjo Posthuma's line saver patch --- dwm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dwm.c b/dwm.c index 438b9e7..4b43a18 100644 --- a/dwm.c +++ b/dwm.c @@ -790,7 +790,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { void enternotify(XEvent *e) { - Client *c; Monitor *m; XCrossingEvent *ev = &e->xcrossing; @@ -800,10 +799,7 @@ enternotify(XEvent *e) { unfocus(selmon->sel, True); selmon = m; } - if((c = wintoclient(ev->window))) - focus(c); - else - focus(NULL); + focus(wintoclient(ev->window)); } void From 83d10be1c1ffb301eaac3a775971f8e018c14cc4 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Tue, 24 Aug 2010 13:13:20 +0100 Subject: [PATCH 057/257] added TODO and bumped version to 5.9 --- TODO | 1 + config.mk | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..222cdac --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +- add updategeom() hook for external tools like dzen diff --git a/config.mk b/config.mk index 9747462..7c993ff 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.8.2 +VERSION = 5.9 # Customize below to fit your system From bea4dd24901235691b5f7ab7b2edd4561de5af27 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 11 Sep 2010 19:00:18 +0000 Subject: [PATCH 058/257] does this make a difference? --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 4b43a18..85762e2 100644 --- a/dwm.c +++ b/dwm.c @@ -799,7 +799,7 @@ enternotify(XEvent *e) { unfocus(selmon->sel, True); selmon = m; } - focus(wintoclient(ev->window)); + focus((wintoclient(ev->window))); } void From c1f8688bfa56e388dac0e0a9abc90fdb0324b6db Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 25 Sep 2010 13:39:08 +0000 Subject: [PATCH 059/257] applied Hiltjo's tiny cleanup patch, thanks! --- dwm.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/dwm.c b/dwm.c index 85762e2..cbe2752 100644 --- a/dwm.c +++ b/dwm.c @@ -372,10 +372,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { if(c->inch) *h -= *h % c->inch; /* restore base dimensions */ - *w += c->basew; - *h += c->baseh; - *w = MAX(*w, c->minw); - *h = MAX(*h, c->minh); + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); if(c->maxw) *w = MIN(*w, c->maxw); if(c->maxh) @@ -845,7 +843,7 @@ focusin(XEvent *e) { /* there are some broken focus acquiring clients */ void focusmon(const Arg *arg) { - Monitor *m = NULL; + Monitor *m; if(!mons->next) return; @@ -1100,9 +1098,7 @@ manage(Window w, XWindowAttributes *wa) { *c = cz; c->win = w; updatetitle(c); - if(XGetTransientForHint(dpy, w, &trans)) - t = wintoclient(trans); - if(t) { + if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; c->tags = t->tags; } @@ -1117,7 +1113,7 @@ manage(Window w, XWindowAttributes *wa) { c->h = c->oldh = wa->height; c->oldbw = wa->border_width; if(c->w == c->mon->mw && c->h == c->mon->mh) { - c->isfloating = 1; + c->isfloating = True; c->x = c->mon->mx; c->y = c->mon->my; c->bw = 0; @@ -1273,8 +1269,8 @@ propertynotify(XEvent *e) { switch (ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: - XGetTransientForHint(dpy, c->win, &trans); - if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL))) + if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)))) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: @@ -1307,7 +1303,7 @@ clientmessage(XEvent *e) { c->oldstate = c->isfloating; c->oldbw = c->bw; c->bw = 0; - c->isfloating = 1; + c->isfloating = True; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); } From a644baf674e80bebfe92ac4bde8f187d1cf949a8 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 27 Sep 2010 07:53:44 +0000 Subject: [PATCH 060/257] applied Hiltjo's tiny cleanup fix --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index cbe2752..0a23e5a 100644 --- a/dwm.c +++ b/dwm.c @@ -1270,7 +1270,7 @@ propertynotify(XEvent *e) { default: break; case XA_WM_TRANSIENT_FOR: if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)))) + (c->isfloating = (wintoclient(trans)) != NULL)) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: From b68528d85df68e681233609b38a137e3b6060775 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 19 Nov 2010 11:53:59 +0000 Subject: [PATCH 061/257] applied Hiltjo's cleanup patch --- dwm.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/dwm.c b/dwm.c index 0a23e5a..d171fe2 100644 --- a/dwm.c +++ b/dwm.c @@ -267,7 +267,6 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool otherwm; static Bool running = True; static Cursor cursor[CurLast]; static Display *dpy; @@ -458,13 +457,10 @@ buttonpress(XEvent *e) { void checkotherwm(void) { - otherwm = False; xerrorxlib = XSetErrorHandler(xerrorstart); /* this causes an error if some other window manager is running */ XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); XSync(dpy, False); - if(otherwm) - die("dwm: another window manager is already running\n"); XSetErrorHandler(xerror); XSync(dpy, False); } @@ -994,12 +990,11 @@ initfont(const char *fontstr) { XFreeStringList(missing); } if(dc.font.set) { - XFontSetExtents *font_extents; XFontStruct **xfonts; char **font_names; dc.font.ascent = dc.font.descent = 0; - font_extents = XExtentsOfFontSet(dc.font.set); + XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); @@ -1088,14 +1083,12 @@ killclient(const Arg *arg) { void manage(Window w, XWindowAttributes *wa) { - static Client cz; Client *c, *t = NULL; Window trans = None; XWindowChanges wc; - if(!(c = malloc(sizeof(Client)))) + if(!(c = calloc(1, sizeof(Client)))) die("fatal: could not malloc() %u bytes\n", sizeof(Client)); - *c = cz; c->win = w; updatetitle(c); if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { @@ -1579,7 +1572,6 @@ showhide(Client *c) { } } - void sigchld(int unused) { if(signal(SIGCHLD, sigchld) == SIG_ERR) @@ -2015,7 +2007,7 @@ xerrordummy(Display *dpy, XErrorEvent *ee) { * is already running. */ int xerrorstart(Display *dpy, XErrorEvent *ee) { - otherwm = True; + die("dwm: another window manager is already running\n"); return -1; } From 703c4dd2530bf7d4876e388757e62d04f40dc643 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 2 Dec 2010 10:16:47 +0000 Subject: [PATCH 062/257] added a todo --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 222cdac..8d4f19c 100644 --- a/TODO +++ b/TODO @@ -1 +1,2 @@ - add updategeom() hook for external tools like dzen +- consider onscreenkeyboard hooks for tablet deployment From 0bc4e41ebdf4dfbdb4e865ab5297f5df4f0d9e16 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 7 Jan 2011 16:05:22 +0000 Subject: [PATCH 063/257] applied anonymous patch, I don't think the reversed array access has semantic side-effects --- dwm.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/dwm.c b/dwm.c index d171fe2..be11381 100644 --- a/dwm.c +++ b/dwm.c @@ -980,7 +980,7 @@ grabkeys(void) { void initfont(const char *fontstr) { char *def, **missing; - int i, n; + int n; missing = NULL; dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); @@ -996,7 +996,7 @@ initfont(const char *fontstr) { dc.font.ascent = dc.font.descent = 0; XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); - for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { + while(n--) { dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); xfonts++; @@ -1014,14 +1014,13 @@ initfont(const char *fontstr) { Bool isprotodel(Client *c) { - int i, n; + int n; Atom *protocols; Bool ret = False; if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { - for(i = 0; !ret && i < n; i++) - if(protocols[i] == wmatom[WMDelete]) - ret = True; + while(!ret && n--) + ret = protocols[n] == wmatom[WMDelete]; XFree(protocols); } return ret; @@ -1029,12 +1028,10 @@ isprotodel(Client *c) { #ifdef XINERAMA static Bool -isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) { - unsigned int i; - - for(i = 0; i < len; i++) - if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org - && unique[i].width == info->width && unique[i].height == info->height) +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; } From dd46d5b588dc5d33940bde87817f3e8d608788d4 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 23 Mar 2011 08:58:57 +0000 Subject: [PATCH 064/257] applied Hiltjo's multimon mouse-based resize fix --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index be11381..4a8ee32 100644 --- a/dwm.c +++ b/dwm.c @@ -1365,8 +1365,8 @@ resizemouse(const Arg *arg) { case MotionNotify: nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if(snap && nw >= selmon->wx && nw <= selmon->wx + selmon->ww - && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) + if(snap && 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 && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) From 3c48858ffada0825b62e52ac14b1feba4b7654a4 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 25 Mar 2011 13:57:54 +0000 Subject: [PATCH 065/257] applied Hiltjos' BUGS patch from 23 Mar, sorry took a while :) --- BUGS | 7 ------- dwm.c | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/BUGS b/BUGS index 5ee05ab..267527d 100644 --- a/BUGS +++ b/BUGS @@ -25,13 +25,6 @@ reproducible with xrandr -s but not with --output and --mode, strange --- -> another corner case: - -a tiled client can be resized with mod+right click, but it only works -on the main monitor - ---- - dmenu appears on the monitor where the pointer is and not on selmon --- diff --git a/dwm.c b/dwm.c index 4a8ee32..7b5fa4e 100644 --- a/dwm.c +++ b/dwm.c @@ -1202,7 +1202,7 @@ movemouse(const Arg *arg) { case MotionNotify: nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); - if(snap && 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) nx = selmon->wx; From 96f9855248545d6e6da1aeece04e44a1f7246ccb Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 25 Mar 2011 14:06:46 +0000 Subject: [PATCH 066/257] applied another patch of Hiltjo, thanks --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 7b5fa4e..1297b2b 100644 --- a/dwm.c +++ b/dwm.c @@ -1365,7 +1365,7 @@ resizemouse(const Arg *arg) { case MotionNotify: nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if(snap && 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 From 1e20a0f78a580ebf4ad521d0e074125bb0a7d4b8 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 12 Apr 2011 20:19:32 +0000 Subject: [PATCH 067/257] applied Brendan MacDonell's WM_TAKE_FOCUS patch, thanks Brendan! --- dwm.c | 73 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/dwm.c b/dwm.c index 1297b2b..0a1b30e 100644 --- a/dwm.c +++ b/dwm.c @@ -59,7 +59,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -88,7 +88,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent, oldstate; + Bool isfixed, isfloating, isurgent, neverfocus, oldstate; Client *next; Client *snext; Monitor *mon; @@ -190,7 +190,6 @@ 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 initfont(const char *fontstr); -static Bool isprotodel(Client *c); static void keypress(XEvent *e); static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); @@ -208,8 +207,10 @@ 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 void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); +static void setfocus(Client *c); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -821,7 +822,7 @@ focus(Client *c) { attachstack(c); grabbuttons(c, True); XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + setfocus(c); } else XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -834,7 +835,7 @@ focusin(XEvent *e) { /* there are some broken focus acquiring clients */ XFocusChangeEvent *ev = &e->xfocus; if(selmon->sel && ev->window != selmon->sel->win) - XSetInputFocus(dpy, selmon->sel->win, RevertToPointerRoot, CurrentTime); + setfocus(selmon->sel); } void @@ -1012,20 +1013,6 @@ initfont(const char *fontstr) { dc.font.height = dc.font.ascent + dc.font.descent; } -Bool -isprotodel(Client *c) { - int n; - Atom *protocols; - Bool ret = False; - - if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while(!ret && n--) - ret = protocols[n] == wmatom[WMDelete]; - XFree(protocols); - } - return ret; -} - #ifdef XINERAMA static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { @@ -1054,20 +1041,9 @@ keypress(XEvent *e) { void killclient(const Arg *arg) { - XEvent ev; - if(!selmon->sel) return; - if(isprotodel(selmon->sel)) { - ev.type = ClientMessage; - ev.xclient.window = selmon->sel->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = wmatom[WMDelete]; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev); - } - else { + if(!sendevent(selmon->sel, wmatom[WMDelete])) { XGrabServer(dpy); XSetErrorHandler(xerrordummy); XSetCloseDownMode(dpy, DestroyAll); @@ -1124,6 +1100,7 @@ manage(Window w, XWindowAttributes *wa) { XSetWindowBorder(dpy, w, dc.norm[ColBorder]); configure(c); /* propagates border_width, if size doesn't change */ updatesizehints(c); + updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, False); if(!c->isfloating) @@ -1471,6 +1448,37 @@ setclientstate(Client *c, long state) { PropModeReplace, (unsigned char *)data, 2); } +Bool +sendevent(Client *c, Atom proto) { + int n; + Atom *protocols; + Bool exists = False; + XEvent ev; + + if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while(!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) { + if (!c->neverfocus) + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + sendevent(c, wmatom[WMTakeFocus]); +} + void setlayout(const Arg *arg) { if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) @@ -1517,6 +1525,7 @@ setup(void) { wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); @@ -1933,6 +1942,8 @@ updatewmhints(Client *c) { } else c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; + if (wmh->flags & InputHint) c->neverfocus = !wmh->input; + else c->neverfocus = False; XFree(wmh); } } From 3c2d303c0e8efc9a08f2e70867794b003b886810 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 14 Apr 2011 13:46:25 +0000 Subject: [PATCH 068/257] applied Peter/Andreas NetActiveWindow patch in a slightly modified version --- dwm.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index 0a1b30e..a3d83fb 100644 --- a/dwm.c +++ b/dwm.c @@ -58,7 +58,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetLast }; /* EWMH atoms */ + NetWMFullscreen, NetActiveWindow, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -1259,11 +1259,11 @@ propertynotify(XEvent *e) { void clientmessage(XEvent *e) { XClientMessageEvent *cme = &e->xclient; - Client *c; + Client *c = wintoclient(cme->window); - if((c = wintoclient(cme->window)) - && (cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen])) - { + if(!c) + return; + if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { if(cme->data.l[0]) { XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); @@ -1287,6 +1287,16 @@ clientmessage(XEvent *e) { arrange(c->mon); } } + else if(cme->message_type == netatom[NetActiveWindow]) { + if(!ISVISIBLE(c)) { + Arg a = { .ui = c->tags }; + view(&a); + } + detach(c); + attach(c); + focus(c); + arrange(c->mon); + } } void @@ -1460,7 +1470,7 @@ sendevent(Client *c, Atom proto) { exists = protocols[n] == proto; XFree(protocols); } - if (exists) { + if(exists) { ev.type = ClientMessage; ev.xclient.window = c->win; ev.xclient.message_type = wmatom[WMProtocols]; @@ -1474,7 +1484,7 @@ sendevent(Client *c, Atom proto) { void setfocus(Client *c) { - if (!c->neverfocus) + if(!c->neverfocus) XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); sendevent(c, wmatom[WMTakeFocus]); } @@ -1525,6 +1535,7 @@ setup(void) { wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); @@ -1942,8 +1953,10 @@ updatewmhints(Client *c) { } else c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; - if (wmh->flags & InputHint) c->neverfocus = !wmh->input; - else c->neverfocus = False; + if(wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = False; XFree(wmh); } } From d24837f1adb40b3ecdb6d20e0a5102b1bf3774a3 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 15 Apr 2011 08:12:20 +0000 Subject: [PATCH 069/257] minor fix of the NetActiveWindow multi-monitor flaw, slight rearrangement --- dwm.c | 107 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/dwm.c b/dwm.c index a3d83fb..5cafe12 100644 --- a/dwm.c +++ b/dwm.c @@ -520,6 +520,46 @@ clearurgent(Client *c) { XFree(wmh); } +void +clientmessage(XEvent *e) { + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if(!c) + return; + if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { + if(cme->data.l[0]) { + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = True; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + else { + XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } + } + else if(cme->message_type == netatom[NetActiveWindow]) { + if(!ISVISIBLE(c)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; + } + pop(c); + } +} + void configure(Client *c) { XConfigureEvent ce; @@ -1212,14 +1252,12 @@ nexttiled(Client *c) { return c; } -Monitor * -ptrtomon(int x, int y) { - Monitor *m; - - for(m = mons; m; m = m->next) - if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) - return m; - return selmon; +void +pop(Client *c) { + detach(c); + attach(c); + focus(c); + arrange(c->mon); } void @@ -1256,49 +1294,15 @@ propertynotify(XEvent *e) { } } -void -clientmessage(XEvent *e) { - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); +Monitor * +ptrtomon(int x, int y) { + Monitor *m; - if(!c) - return; - if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { - if(cme->data.l[0]) { - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = True; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } - else { - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } - } - else if(cme->message_type == netatom[NetActiveWindow]) { - if(!ISVISIBLE(c)) { - Arg a = { .ui = c->tags }; - view(&a); - } - detach(c); - attach(c); - focus(c); - arrange(c->mon); - } + for(m = mons; m; m = m->next) + if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) + return m; + return selmon; } - void quit(const Arg *arg) { running = False; @@ -2043,10 +2047,7 @@ zoom(const Arg *arg) { if(c == nexttiled(selmon->clients)) if(!c || !(c = nexttiled(c->next))) return; - detach(c); - attach(c); - focus(c); - arrange(c->mon); + pop(c); } int From 79b1657a1903447b69083515cfa81bb457a57554 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 15 Apr 2011 08:13:06 +0000 Subject: [PATCH 070/257] missed declaration --- dwm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 5cafe12..59b4498 100644 --- a/dwm.c +++ b/dwm.c @@ -198,8 +198,9 @@ static void maprequest(XEvent *e); static void monocle(Monitor *m); static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); -static Monitor *ptrtomon(int x, int y); +static void pop(Client *); static void propertynotify(XEvent *e); +static Monitor *ptrtomon(int x, int y); static void quit(const Arg *arg); 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); From c14d293e516fa9aebffb63f9775c3be38178ccb3 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 26 Apr 2011 08:13:39 +0000 Subject: [PATCH 071/257] applied Jack's mplayer fullscreen patch --- dwm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 59b4498..d088327 100644 --- a/dwm.c +++ b/dwm.c @@ -88,7 +88,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent, neverfocus, oldstate; + Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; @@ -532,6 +532,7 @@ clientmessage(XEvent *e) { if(cme->data.l[0]) { XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = True; c->oldstate = c->isfloating; c->oldbw = c->bw; c->bw = 0; @@ -542,6 +543,7 @@ clientmessage(XEvent *e) { else { XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = False; c->isfloating = c->oldstate; c->bw = c->oldbw; c->x = c->oldx; @@ -1584,7 +1586,7 @@ showhide(Client *c) { return; 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) + if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) resize(c, c->x, c->y, c->w, c->h, False); showhide(c->snext); } From 37fea84de800e70c8ca6db295ebfefe0b61dd6cb Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 27 Apr 2011 12:38:59 +0000 Subject: [PATCH 072/257] applied Thomas' README patch --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index 135c066..a97a8b1 100644 --- a/README +++ b/README @@ -43,7 +43,8 @@ like this in your .xinitrc: xsetroot -name "`date` `uptime | sed 's/.*,//'`" sleep 1 done & - exec dwm + dwm + kill $! Configuration From 6784429c3cd4eefbc3299ab0adfc9f3b1c7bf13e Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 27 Apr 2011 15:55:18 +0000 Subject: [PATCH 073/257] applied another minor change to the README --- README | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README b/README index a97a8b1..31fc835 100644 --- a/README +++ b/README @@ -38,13 +38,11 @@ the DISPLAY environment variable is set correctly, e.g.: In order to display status info in the bar, you can do something like this in your .xinitrc: - while true + while xsetroot -name "`date` `uptime | sed 's/.*,//'`" do - xsetroot -name "`date` `uptime | sed 's/.*,//'`" - sleep 1 + sleep 20 done & - dwm - kill $! + exec dwm Configuration From 22d88188505b2f08296c32ca82a81cce2b59c909 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Thu, 12 May 2011 14:16:33 +0000 Subject: [PATCH 074/257] applied Evil_Bobs cleanup patch --- dwm.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/dwm.c b/dwm.c index d088327..2feb22e 100644 --- a/dwm.c +++ b/dwm.c @@ -556,8 +556,8 @@ clientmessage(XEvent *e) { } else if(cme->message_type == netatom[NetActiveWindow]) { if(!ISVISIBLE(c)) { - c->mon->seltags ^= 1; - c->mon->tagset[c->mon->seltags] = c->tags; + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; } pop(c); } @@ -1213,7 +1213,7 @@ movemouse(const Arg *arg) { return; do { XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch (ev.type) { + switch(ev.type) { case ConfigureRequest: case Expose: case MapRequest: @@ -1274,7 +1274,7 @@ propertynotify(XEvent *e) { else if(ev->state == PropertyDelete) return; /* ignore */ else if((c = wintoclient(ev->window))) { - switch (ev->atom) { + switch(ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && @@ -1542,8 +1542,8 @@ setup(void) { wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); @@ -1612,7 +1612,7 @@ spawn(const Arg *arg) { execvp(((char **)arg->v)[0], (char **)arg->v); fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); perror(" failed"); - exit(0); + exit(EXIT_SUCCESS); } } @@ -1760,11 +1760,11 @@ unmapnotify(XEvent *e) { void updatebars(void) { Monitor *m; - XSetWindowAttributes wa; - - wa.override_redirect = True; - wa.background_pixmap = ParentRelative; - wa.event_mask = ButtonPressMask|ExposureMask; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; for(m = mons; m; m = m->next) { m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), @@ -2069,5 +2069,5 @@ main(int argc, char *argv[]) { run(); cleanup(); XCloseDisplay(dpy); - return 0; + return EXIT_SUCCESS; } From e7d41cc18824114300a09d3bdb26c536f30b466e Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Fri, 20 May 2011 19:10:26 +0100 Subject: [PATCH 075/257] added draw.h, draw.c --- draw.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ draw.h | 35 ++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 draw.c create mode 100644 draw.h diff --git a/draw.c b/draw.c new file mode 100644 index 0000000..341a26f --- /dev/null +++ b/draw.c @@ -0,0 +1,176 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include "draw.h" + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define DEFAULTFN "fixed" + +static Bool loadfont(DC *dc, const char *fontstr); + +void +drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color) { + XSetForeground(dc->dpy, dc->gc, color); + if(fill) + XFillRectangle(dc->dpy, dc->canvas, dc->gc, dc->x + x, dc->y + y, w, h); + else + XDrawRectangle(dc->dpy, dc->canvas, dc->gc, dc->x + x, dc->y + y, w-1, h-1); +} + +void +drawtext(DC *dc, const char *text, unsigned long col[ColLast]) { + char buf[BUFSIZ]; + size_t mn, n = strlen(text); + + /* shorten text if necessary */ + for(mn = MIN(n, sizeof buf); textnw(dc, text, mn) + dc->font.height/2 > dc->w; mn--) + if(mn == 0) + return; + memcpy(buf, text, mn); + if(mn < n) + for(n = MAX(mn-3, 0); n < mn; buf[n++] = '.'); + + drawrect(dc, 0, 0, dc->w, dc->h, True, BG(dc, col)); + drawtextn(dc, buf, mn, col); +} + +void +drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]) { + int x = dc->x + dc->font.height/2; + int y = dc->y + dc->font.ascent+1; + + XSetForeground(dc->dpy, dc->gc, FG(dc, col)); + if(dc->font.set) + XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, x, y, text, n); + else { + XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid); + XDrawString(dc->dpy, dc->canvas, dc->gc, x, y, text, n); + } +} + +void +eprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if(fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } + exit(EXIT_FAILURE); +} + +void +freedc(DC *dc) { + if(dc->font.set) + XFreeFontSet(dc->dpy, dc->font.set); + if(dc->font.xfont) + XFreeFont(dc->dpy, dc->font.xfont); + if(dc->canvas) + XFreePixmap(dc->dpy, dc->canvas); + XFreeGC(dc->dpy, dc->gc); + XCloseDisplay(dc->dpy); + free(dc); +} + +unsigned long +getcolor(DC *dc, const char *colstr) { + Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy)); + XColor color; + + if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color)) + eprintf("cannot allocate color '%s'\n", colstr); + return color.pixel; +} + +DC * +initdc(void) { + DC *dc; + + if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fprintf(stderr, "no locale support\n"); + if(!(dc = calloc(1, sizeof *dc))) + eprintf("cannot malloc %u bytes:", sizeof *dc); + if(!(dc->dpy = XOpenDisplay(NULL))) + eprintf("cannot open display\n"); + + dc->gc = XCreateGC(dc->dpy, DefaultRootWindow(dc->dpy), 0, NULL); + XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter); + return dc; +} + +void +initfont(DC *dc, const char *fontstr) { + if(!loadfont(dc, fontstr ? fontstr : DEFAULTFN)) { + if(fontstr != NULL) + fprintf(stderr, "cannot load font '%s'\n", fontstr); + if(fontstr == NULL || !loadfont(dc, DEFAULTFN)) + eprintf("cannot load font '%s'\n", DEFAULTFN); + } + dc->font.height = dc->font.ascent + dc->font.descent; +} + +Bool +loadfont(DC *dc, const char *fontstr) { + char *def, **missing, **names; + int i, n = 1; + XFontStruct **xfonts; + + if(!*fontstr) + return False; + if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) { + n = XFontsOfFontSet(dc->font.set, &xfonts, &names); + } + else { + dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr); + xfonts = &dc->font.xfont; + } + for(i = 0; i < n; i++) { + dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent); + dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent); + dc->font.width = MAX(dc->font.width, xfonts[i]->max_bounds.width); + } + if(missing) + XFreeStringList(missing); + return (dc->font.set || dc->font.xfont); +} + +void +mapdc(DC *dc, Window win, unsigned int w, unsigned int h) { + XCopyArea(dc->dpy, dc->canvas, win, dc->gc, 0, 0, w, h, 0, 0); +} + +void +resizedc(DC *dc, unsigned int w, unsigned int h) { + if(dc->canvas) + XFreePixmap(dc->dpy, dc->canvas); + + dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h, + DefaultDepth(dc->dpy, DefaultScreen(dc->dpy))); + dc->w = w; + dc->h = h; +} + +int +textnw(DC *dc, const char *text, size_t len) { + if(dc->font.set) { + XRectangle r; + + XmbTextExtents(dc->font.set, text, len, NULL, &r); + return r.width; + } + return XTextWidth(dc->font.xfont, text, len); +} + +int +textw(DC *dc, const char *text) { + return textnw(dc, text, strlen(text)) + dc->font.height; +} diff --git a/draw.h b/draw.h new file mode 100644 index 0000000..43a57bf --- /dev/null +++ b/draw.h @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ + +#define FG(dc, col) ((col)[(dc)->invert ? ColBG : ColFG]) +#define BG(dc, col) ((col)[(dc)->invert ? ColFG : ColBG]) + +enum { ColBG, ColFG, ColBorder, ColLast }; + +typedef struct { + int x, y, w, h; + Bool invert; + Display *dpy; + GC gc; + Pixmap canvas; + struct { + int ascent; + int descent; + int height; + int width; + XFontSet set; + XFontStruct *xfont; + } font; +} DC; /* draw context */ + +void drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color); +void drawtext(DC *dc, const char *text, unsigned long col[ColLast]); +void drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]); +void eprintf(const char *fmt, ...); +void freedc(DC *dc); +unsigned long getcolor(DC *dc, const char *colstr); +DC *initdc(void); +void initfont(DC *dc, const char *fontstr); +void mapdc(DC *dc, Window win, unsigned int w, unsigned int h); +void resizedc(DC *dc, unsigned int w, unsigned int h); +int textnw(DC *dc, const char *text, size_t len); +int textw(DC *dc, const char *text); From 04797343db457578906355cf1118548be90a183e Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sat, 21 May 2011 20:26:26 +0100 Subject: [PATCH 076/257] update draw.c --- draw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/draw.c b/draw.c index 341a26f..2028fd9 100644 --- a/draw.c +++ b/draw.c @@ -126,13 +126,13 @@ loadfont(DC *dc, const char *fontstr) { if(!*fontstr) return False; - if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) { + if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) n = XFontsOfFontSet(dc->font.set, &xfonts, &names); - } - else { - dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr); + else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) xfonts = &dc->font.xfont; - } + else + n = 0; + for(i = 0; i < n; i++) { dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent); dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent); From 2255bf46a0af475e70fb4cc90d912b435f21eb5e Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sat, 4 Jun 2011 10:17:25 +0100 Subject: [PATCH 077/257] cleaner drawing --- dwm.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/dwm.c b/dwm.c index 2feb22e..05ab119 100644 --- a/dwm.c +++ b/dwm.c @@ -780,32 +780,22 @@ drawbars(void) { void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; - XGCValues gcv; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - gcv.foreground = col[invert ? ColBG : ColFG]; - XChangeGC(dpy, dc.gc, GCForeground, &gcv); + XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); x = (dc.font.ascent + dc.font.descent + 2) / 4; - r.x = dc.x + 1; - r.y = dc.y + 1; - if(filled) { - r.width = r.height = x + 1; - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - } - else if(empty) { - r.width = r.height = x; - XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); - } + 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; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); + XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); if(!text) return; olen = strlen(text); From 8a111c181ea7c14fa3903bebccd3e1cc00e1fe31 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sat, 4 Jun 2011 10:18:54 +0100 Subject: [PATCH 078/257] fix typo --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 05ab119..780f1fb 100644 --- a/dwm.c +++ b/dwm.c @@ -781,7 +781,7 @@ void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); + 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); From 5c710cf89c93f9d87b94abeca25e8eb8e812d21d Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sat, 4 Jun 2011 23:02:00 +0100 Subject: [PATCH 079/257] rm draw.c from 5.9 branch --- draw.c | 176 --------------------------------------------------------- draw.h | 35 ------------ 2 files changed, 211 deletions(-) delete mode 100644 draw.c delete mode 100644 draw.h diff --git a/draw.c b/draw.c deleted file mode 100644 index 2028fd9..0000000 --- a/draw.c +++ /dev/null @@ -1,176 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include -#include "draw.h" - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define DEFAULTFN "fixed" - -static Bool loadfont(DC *dc, const char *fontstr); - -void -drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color) { - XSetForeground(dc->dpy, dc->gc, color); - if(fill) - XFillRectangle(dc->dpy, dc->canvas, dc->gc, dc->x + x, dc->y + y, w, h); - else - XDrawRectangle(dc->dpy, dc->canvas, dc->gc, dc->x + x, dc->y + y, w-1, h-1); -} - -void -drawtext(DC *dc, const char *text, unsigned long col[ColLast]) { - char buf[BUFSIZ]; - size_t mn, n = strlen(text); - - /* shorten text if necessary */ - for(mn = MIN(n, sizeof buf); textnw(dc, text, mn) + dc->font.height/2 > dc->w; mn--) - if(mn == 0) - return; - memcpy(buf, text, mn); - if(mn < n) - for(n = MAX(mn-3, 0); n < mn; buf[n++] = '.'); - - drawrect(dc, 0, 0, dc->w, dc->h, True, BG(dc, col)); - drawtextn(dc, buf, mn, col); -} - -void -drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]) { - int x = dc->x + dc->font.height/2; - int y = dc->y + dc->font.ascent+1; - - XSetForeground(dc->dpy, dc->gc, FG(dc, col)); - if(dc->font.set) - XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, x, y, text, n); - else { - XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid); - XDrawString(dc->dpy, dc->canvas, dc->gc, x, y, text, n); - } -} - -void -eprintf(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if(fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } - exit(EXIT_FAILURE); -} - -void -freedc(DC *dc) { - if(dc->font.set) - XFreeFontSet(dc->dpy, dc->font.set); - if(dc->font.xfont) - XFreeFont(dc->dpy, dc->font.xfont); - if(dc->canvas) - XFreePixmap(dc->dpy, dc->canvas); - XFreeGC(dc->dpy, dc->gc); - XCloseDisplay(dc->dpy); - free(dc); -} - -unsigned long -getcolor(DC *dc, const char *colstr) { - Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy)); - XColor color; - - if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color)) - eprintf("cannot allocate color '%s'\n", colstr); - return color.pixel; -} - -DC * -initdc(void) { - DC *dc; - - if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fprintf(stderr, "no locale support\n"); - if(!(dc = calloc(1, sizeof *dc))) - eprintf("cannot malloc %u bytes:", sizeof *dc); - if(!(dc->dpy = XOpenDisplay(NULL))) - eprintf("cannot open display\n"); - - dc->gc = XCreateGC(dc->dpy, DefaultRootWindow(dc->dpy), 0, NULL); - XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter); - return dc; -} - -void -initfont(DC *dc, const char *fontstr) { - if(!loadfont(dc, fontstr ? fontstr : DEFAULTFN)) { - if(fontstr != NULL) - fprintf(stderr, "cannot load font '%s'\n", fontstr); - if(fontstr == NULL || !loadfont(dc, DEFAULTFN)) - eprintf("cannot load font '%s'\n", DEFAULTFN); - } - dc->font.height = dc->font.ascent + dc->font.descent; -} - -Bool -loadfont(DC *dc, const char *fontstr) { - char *def, **missing, **names; - int i, n = 1; - XFontStruct **xfonts; - - if(!*fontstr) - return False; - if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) - n = XFontsOfFontSet(dc->font.set, &xfonts, &names); - else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) - xfonts = &dc->font.xfont; - else - n = 0; - - for(i = 0; i < n; i++) { - dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent); - dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent); - dc->font.width = MAX(dc->font.width, xfonts[i]->max_bounds.width); - } - if(missing) - XFreeStringList(missing); - return (dc->font.set || dc->font.xfont); -} - -void -mapdc(DC *dc, Window win, unsigned int w, unsigned int h) { - XCopyArea(dc->dpy, dc->canvas, win, dc->gc, 0, 0, w, h, 0, 0); -} - -void -resizedc(DC *dc, unsigned int w, unsigned int h) { - if(dc->canvas) - XFreePixmap(dc->dpy, dc->canvas); - - dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h, - DefaultDepth(dc->dpy, DefaultScreen(dc->dpy))); - dc->w = w; - dc->h = h; -} - -int -textnw(DC *dc, const char *text, size_t len) { - if(dc->font.set) { - XRectangle r; - - XmbTextExtents(dc->font.set, text, len, NULL, &r); - return r.width; - } - return XTextWidth(dc->font.xfont, text, len); -} - -int -textw(DC *dc, const char *text) { - return textnw(dc, text, strlen(text)) + dc->font.height; -} diff --git a/draw.h b/draw.h deleted file mode 100644 index 43a57bf..0000000 --- a/draw.h +++ /dev/null @@ -1,35 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define FG(dc, col) ((col)[(dc)->invert ? ColBG : ColFG]) -#define BG(dc, col) ((col)[(dc)->invert ? ColFG : ColBG]) - -enum { ColBG, ColFG, ColBorder, ColLast }; - -typedef struct { - int x, y, w, h; - Bool invert; - Display *dpy; - GC gc; - Pixmap canvas; - struct { - int ascent; - int descent; - int height; - int width; - XFontSet set; - XFontStruct *xfont; - } font; -} DC; /* draw context */ - -void drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color); -void drawtext(DC *dc, const char *text, unsigned long col[ColLast]); -void drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]); -void eprintf(const char *fmt, ...); -void freedc(DC *dc); -unsigned long getcolor(DC *dc, const char *colstr); -DC *initdc(void); -void initfont(DC *dc, const char *fontstr); -void mapdc(DC *dc, Window win, unsigned int w, unsigned int h); -void resizedc(DC *dc, unsigned int w, unsigned int h); -int textnw(DC *dc, const char *text, size_t len); -int textw(DC *dc, const char *text); From d384cee751a2d23220df45c3c34dab5567c0594f Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sat, 11 Jun 2011 08:33:20 +0100 Subject: [PATCH 080/257] fixing some minor issues, next week is dwm-5.9 release time --- LICENSE | 4 ++-- README | 2 +- dwm.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index 059cf28..ed4e415 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2006-2010 Anselm R Garbe +© 2006-2011 Anselm R Garbe © 2006-2007 Sander van Dijk © 2006-2009 Jukka Salmi © 2007-2009 Premysl Hruby @@ -10,7 +10,7 @@ MIT/X Consortium License © 2007-2008 Peter Hartlich © 2008 Martin Hurton © 2008 Neale Pickett -© 2009 Mate Nagy +© 2009 Mate Nagy 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/README b/README index 31fc835..b997623 100644 --- a/README +++ b/README @@ -38,7 +38,7 @@ the DISPLAY environment variable is set correctly, e.g.: In order to display status info in the bar, you can do something like this in your .xinitrc: - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" + while xsetroot -name "`date` `uptime | sed 's/.*,//'` do sleep 20 done & diff --git a/dwm.c b/dwm.c index 780f1fb..f6cec0b 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-2010 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2011 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) From 114754612228c51fb95fa4d7ad80b0ac0e99322e Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Tue, 14 Jun 2011 05:51:21 +0100 Subject: [PATCH 081/257] Thanks for the pedantic review :) --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index b997623..31fc835 100644 --- a/README +++ b/README @@ -38,7 +38,7 @@ the DISPLAY environment variable is set correctly, e.g.: In order to display status info in the bar, you can do something like this in your .xinitrc: - while xsetroot -name "`date` `uptime | sed 's/.*,//'` + while xsetroot -name "`date` `uptime | sed 's/.*,//'`" do sleep 20 done & From 60c06a7cb42219953edf1fa752750eb98384a14b Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Tue, 14 Jun 2011 22:28:16 +0100 Subject: [PATCH 082/257] don't check for monocle layout in zoom() exit condition --- dwm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwm.c b/dwm.c index f6cec0b..7846be0 100644 --- a/dwm.c +++ b/dwm.c @@ -2034,7 +2034,6 @@ zoom(const Arg *arg) { Client *c = selmon->sel; if(!selmon->lt[selmon->sellt]->arrange - || selmon->lt[selmon->sellt]->arrange == monocle || (selmon->sel && selmon->sel->isfloating)) return; if(c == nexttiled(selmon->clients)) From 6cf29bff33003a8ab00530115af14f8c270fa0da Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Fri, 17 Jun 2011 20:22:54 +0100 Subject: [PATCH 083/257] applied Rudys barwidth patch, thanks Rudy --- dwm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 7846be0..eba48ed 100644 --- a/dwm.c +++ b/dwm.c @@ -585,11 +585,13 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; + Bool dirty; if(ev->window == root) { + dirty = (sw != ev->width); sw = ev->width; sh = ev->height; - if(updategeom()) { + if(updategeom() || dirty) { if(dc.drawable != 0) XFreePixmap(dpy, dc.drawable); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); From 92fe06b501a5458a6aecdcc53f8d35c2a1f55c1c Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Fri, 24 Jun 2011 21:02:32 +0100 Subject: [PATCH 084/257] applied Andreas Amann's patch from Oct 2010, thanks --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index eba48ed..84c0ae6 100644 --- a/dwm.c +++ b/dwm.c @@ -42,7 +42,7 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) +#define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) From 3a392b855882786d1aa9c842d1c36b5c1cbc576a Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sat, 25 Jun 2011 09:07:28 +0100 Subject: [PATCH 085/257] making enternotify less focus hungry --- BUGS | 21 --------------------- dwm.c | 4 ++++ 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/BUGS b/BUGS index 267527d..fd1837f 100644 --- a/BUGS +++ b/BUGS @@ -8,27 +8,6 @@ reproducible with xrandr -s but not with --output and --mode, strange --- -> enternotify is handled even when the entered window is already focused -> (eg moving the mouse to the bar and back, scrolling on the border..) -> -> focusing might be expensive for some clients (eg dim/light up) -> -> a possible solution is to modify enternotify: -> -> + c = wintoclient(ev->window); -> if((m = wintomon(ev->window)) && m != selmon) { -> unfocus(selmon->sel); -> selmon = m; -> } -> + else if (c == selmon->sel || c == NULL) -> + return; - ---- - -dmenu appears on the monitor where the pointer is and not on selmon - ---- - yet another corner case: open a terminal, focus another monitor, but without moving the mouse pointer there diff --git a/dwm.c b/dwm.c index 84c0ae6..8c1adeb 100644 --- a/dwm.c +++ b/dwm.c @@ -820,15 +820,19 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { void enternotify(XEvent *e) { + Client *c; Monitor *m; XCrossingEvent *ev = &e->xcrossing; if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; + c = wintoclient(ev->window); if((m = wintomon(ev->window)) && m != selmon) { unfocus(selmon->sel, True); selmon = m; } + else if(c == selmon->sel || c == NULL) + return; focus((wintoclient(ev->window))); } From 212f417e44f631d406d65156b0d244f60598b8cc Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Mon, 27 Jun 2011 19:35:11 +0100 Subject: [PATCH 086/257] fix numlock (thanks mikhail) --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 8c1adeb..bb017f5 100644 --- a/dwm.c +++ b/dwm.c @@ -42,7 +42,7 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define CLEANMASK(mask) (mask & ~numlockmask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) From e83f36db101c125fe17034125e63f86fbd6f0568 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Mon, 27 Jun 2011 20:12:42 +0100 Subject: [PATCH 087/257] fixed scroll lock (thanks bogdan) --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index bb017f5..a2582f1 100644 --- a/dwm.c +++ b/dwm.c @@ -42,7 +42,7 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~numlockmask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) From 867ba360300682859ab963222ec0a3f42586ff54 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Fri, 1 Jul 2011 17:56:53 +0100 Subject: [PATCH 088/257] applied Nicolas Capit's patch as interim solution until the multiscreen support is reworked in 6.0 --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index a2582f1..f842b41 100644 --- a/dwm.c +++ b/dwm.c @@ -442,7 +442,7 @@ buttonpress(XEvent *e) { } else if(ev->x < x + blw) click = ClkLtSymbol; - else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext)) + else if(ev->x > selmon->ww - TEXTW(stext)) click = ClkStatusText; else click = ClkWinTitle; From 27b0142203e06bdbb1ff3c2179ac88e08aa4295e Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sat, 2 Jul 2011 11:02:22 +0200 Subject: [PATCH 089/257] applied Garys patch in a slightly modified way --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index f842b41..ba00afe 100644 --- a/dwm.c +++ b/dwm.c @@ -529,7 +529,7 @@ clientmessage(XEvent *e) { if(!c) return; if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { - if(cme->data.l[0]) { + if(cme->data.l[0] && !c->isfullscreen) { XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); c->isfullscreen = True; From d83454f6b7bcc982ab52b61aac564369ac8994e6 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sat, 9 Jul 2011 07:57:10 +0100 Subject: [PATCH 090/257] applied Peters two patches, please test hg tip, if nothing breaks this is 5.9 --- dwm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index ba00afe..5df912b 100644 --- a/dwm.c +++ b/dwm.c @@ -389,7 +389,6 @@ arrange(Monitor *m) { showhide(m->stack); else for(m = mons; m; m = m->next) showhide(m->stack); - focus(NULL); if(m) arrangemon(m); else for(m = mons; m; m = m->next) @@ -598,6 +597,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); arrange(NULL); } } @@ -1149,9 +1149,10 @@ manage(Window w, XWindowAttributes *wa) { attach(c); attachstack(c); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - XMapWindow(dpy, c->win); setclientstate(c, NormalState); arrange(c->mon); + XMapWindow(dpy, c->win); + focus(c); } void @@ -1616,6 +1617,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } } @@ -1696,6 +1698,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; + focus(NULL); arrange(selmon); } } @@ -1706,6 +1709,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); arrange(selmon); } } @@ -1971,6 +1975,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } From a692bdcf2b71dd0f776402be7b99df511a8333e7 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 10 Jul 2011 21:12:05 +0100 Subject: [PATCH 091/257] undo the focus optimisation patch for 5.9 --- dwm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/dwm.c b/dwm.c index 5df912b..ba00afe 100644 --- a/dwm.c +++ b/dwm.c @@ -389,6 +389,7 @@ arrange(Monitor *m) { showhide(m->stack); else for(m = mons; m; m = m->next) showhide(m->stack); + focus(NULL); if(m) arrangemon(m); else for(m = mons; m; m = m->next) @@ -597,7 +598,6 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - focus(NULL); arrange(NULL); } } @@ -1149,10 +1149,9 @@ manage(Window w, XWindowAttributes *wa) { attach(c); attachstack(c); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + XMapWindow(dpy, c->win); setclientstate(c, NormalState); arrange(c->mon); - XMapWindow(dpy, c->win); - focus(c); } void @@ -1617,7 +1616,6 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); arrange(selmon); } } @@ -1698,7 +1696,6 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; - focus(NULL); arrange(selmon); } } @@ -1709,7 +1706,6 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); arrange(selmon); } } @@ -1975,7 +1971,6 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); arrange(selmon); } From b3c5f5435ad8bdf69cd5b0cc23c8b3217c39ba5c Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 10 Jul 2011 21:18:50 +0100 Subject: [PATCH 092/257] removed unneeded offset recalculation, thanks Jukka, let's see if this breaks some other client --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index ba00afe..a0ab126 100644 --- a/dwm.c +++ b/dwm.c @@ -1112,8 +1112,8 @@ manage(Window w, XWindowAttributes *wa) { applyrules(c); } /* geometry */ - c->x = c->oldx = wa->x + c->mon->wx; - c->y = c->oldy = wa->y + c->mon->wy; + 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; From 3150a8a1beef1884365210e0e4d18b2599269a78 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 10 Jul 2011 21:22:22 +0100 Subject: [PATCH 093/257] applied Peters wintoclient/wintomon optimisation in enternotify() --- dwm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index a0ab126..01e8d1f 100644 --- a/dwm.c +++ b/dwm.c @@ -827,13 +827,14 @@ enternotify(XEvent *e) { if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; c = wintoclient(ev->window); - if((m = wintomon(ev->window)) && m != selmon) { + m = c ? c->mon : wintomon(ev->window); + if(m != selmon) { unfocus(selmon->sel, True); selmon = m; } - else if(c == selmon->sel || c == NULL) + else if(!c || c == selmon->sel) return; - focus((wintoclient(ev->window))); + focus(c); } void From cd8bb06af514ed9a30c0786b70c1d6ee6afb68c8 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 10 Jul 2011 21:24:17 +0100 Subject: [PATCH 094/257] enabled release flags --- config.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.mk b/config.mk index 7c993ff..16ffac3 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -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} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +#LDFLAGS = -g ${LIBS} +LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" From 03518ce49e68c74559a3c0f98cbecb31b5bcc0c1 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 10 Jul 2011 21:25:23 +0100 Subject: [PATCH 095/257] Added tag 5.9 for changeset dd74622a4785 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b0b566b..0034435 100644 --- a/.hgtags +++ b/.hgtags @@ -69,3 +69,4 @@ e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 60ea8fed13ab750c6717f2764cbf9c13bb6f0d0a 5.8 1ed1e75c9c2e395a2c475b52657a430bd95070c7 5.8.1 a043f08008051ca02ae87eb170cd066d8c8315a0 5.8.2 +dd74622a4785e55658b05b36834fa0c41084a8c1 5.9 From d0b4575bf47bb848b09edbd5c5a0f27e889a976a Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 20 Jul 2011 18:30:51 +0000 Subject: [PATCH 096/257] thanks to recursions on IRC for his remark --- dwm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index 01e8d1f..f955d44 100644 --- a/dwm.c +++ b/dwm.c @@ -615,14 +615,22 @@ configurerequest(XEvent *e) { c->bw = ev->border_width; 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) c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */ if((c->y + c->h) > m->my + m->mh && c->isfloating) From d5c5c52b306be5509422d7074d7416df0d425d08 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 20 Jul 2011 18:33:19 +0000 Subject: [PATCH 097/257] applied lolilolicon's floating center patch, further investigation wrt his second issue reported needed --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index f955d44..76bca38 100644 --- a/dwm.c +++ b/dwm.c @@ -632,9 +632,9 @@ configurerequest(XEvent *e) { c->h = ev->height; } if((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */ + 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) - c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */ + 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))) configure(c); if(ISVISIBLE(c)) From 6288c446974020c396923c9a4f1bf29c6f6c9645 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 20 Jul 2011 18:36:15 +0000 Subject: [PATCH 098/257] applied Peters magic float mode bugfix --- dwm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwm.c b/dwm.c index 76bca38..5e67084 100644 --- a/dwm.c +++ b/dwm.c @@ -1127,7 +1127,6 @@ manage(Window w, XWindowAttributes *wa) { c->h = c->oldh = wa->height; c->oldbw = wa->border_width; if(c->w == c->mon->mw && c->h == c->mon->mh) { - c->isfloating = True; c->x = c->mon->mx; c->y = c->mon->my; c->bw = 0; From d6670a800d33639cdf64de170650b64c1921a300 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 20 Jul 2011 18:45:40 +0000 Subject: [PATCH 099/257] applied Connors aesthitic buf fix in tile(), thanks --- dwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 5e67084..f176f4c 100644 --- a/dwm.c +++ b/dwm.c @@ -1662,9 +1662,9 @@ tile(Monitor *m) { if(--n == 0) return; /* tile stack */ - x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; + x = (m->wx > c->x) ? c->x + mw + 2 * c->bw : m->wx + mw; y = m->wy; - w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; + w = (m->wx > c->x) ? m->wx + m->ww - x : m->ww - mw; h = m->wh / n; if(h < bh) h = m->wh; From c99fe7dd7d0dfe00625ae3bcd037ff305661f56d Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 20 Jul 2011 18:56:10 +0000 Subject: [PATCH 100/257] changed sleep 20 into sleep 1 in example script as suggested by Snader_LB --- README | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 31fc835..7abf1cf 100644 --- a/README +++ b/README @@ -40,7 +40,7 @@ like this in your .xinitrc: while xsetroot -name "`date` `uptime | sed 's/.*,//'`" do - sleep 20 + sleep 1 done & exec dwm diff --git a/config.mk b/config.mk index 16ffac3..99085e1 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.9 +VERSION = 5.9.1 # Customize below to fit your system From 69e7d7dfd3b07431bf5e5c6e4814665529554031 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sun, 24 Jul 2011 10:41:43 +0100 Subject: [PATCH 101/257] added a marker for the flash fullscreen issue --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index f176f4c..7cc4ea7 100644 --- a/dwm.c +++ b/dwm.c @@ -1127,6 +1127,7 @@ manage(Window w, XWindowAttributes *wa) { c->h = c->oldh = wa->height; c->oldbw = wa->border_width; if(c->w == c->mon->mw && c->h == c->mon->mh) { + c->isfloating = True; // regression with flash, XXXX c->x = c->mon->mx; c->y = c->mon->my; c->bw = 0; From a372248b803e92e6e781d26703a7fee96550ef3a Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Wed, 27 Jul 2011 19:59:10 +0200 Subject: [PATCH 102/257] applied anonymous code cleanup patch --- dwm.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/dwm.c b/dwm.c index 7cc4ea7..402b2b9 100644 --- a/dwm.c +++ b/dwm.c @@ -433,9 +433,9 @@ buttonpress(XEvent *e) { } if(ev->window == selmon->barwin) { i = x = 0; - do { + do x += TEXTW(tags[i]); - } while(ev->x >= x && ++i < LENGTH(tags)); + while(ev->x >= x && ++i < LENGTH(tags)); if(i < LENGTH(tags)) { click = ClkTagBar; arg.ui = 1 << i; @@ -720,12 +720,10 @@ dirtomon(int dir) { if(!(m = selmon->next)) m = mons; } - else { - if(selmon == mons) - for(m = mons; m->next; m = m->next); - else - for(m = mons; m->next != selmon; 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); return m; } @@ -1017,12 +1015,11 @@ grabkeys(void) { KeyCode code; XUngrabKey(dpy, AnyKey, AnyModifier, root); - for(i = 0; i < LENGTH(keys); i++) { + 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); - } } } @@ -1031,7 +1028,6 @@ initfont(const char *fontstr) { char *def, **missing; int n; - missing = NULL; dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); if(missing) { while(n--) @@ -1311,6 +1307,7 @@ ptrtomon(int x, int y) { return m; return selmon; } + void quit(const Arg *arg) { running = False; @@ -1415,10 +1412,9 @@ run(void) { XEvent ev; /* main event loop */ XSync(dpy, False); - while(running && !XNextEvent(dpy, &ev)) { + while(running && !XNextEvent(dpy, &ev)) if(handler[ev.type]) handler[ev.type](&ev); /* call handler */ - } } void From 0de4197cc5e8e81d94d0faffbaf46abab4d44d1a Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Fri, 29 Jul 2011 20:01:22 +0200 Subject: [PATCH 103/257] applied Peter Hartlichs nice interim Xinerama and map fix patches, for debugging purposes I also added his transient test driver --- LICENSE | 7 ++++--- dwm.c | 12 ++++++++++-- transient.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 transient.c diff --git a/LICENSE b/LICENSE index ed4e415..e8e793a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,16 +1,17 @@ MIT/X Consortium License © 2006-2011 Anselm R Garbe -© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2010-2011 Connor Lane Smith © 2006-2009 Jukka Salmi © 2007-2009 Premysl Hruby © 2007-2009 Szabolcs Nagy © 2007-2009 Christof Musik +© 2009 Mate Nagy © 2007-2008 Enno Gottox Boland -© 2007-2008 Peter Hartlich © 2008 Martin Hurton © 2008 Neale Pickett -© 2009 Mate Nagy +© 2006-2007 Sander van Dijk 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/dwm.c b/dwm.c index 402b2b9..db0fdfb 100644 --- a/dwm.c +++ b/dwm.c @@ -389,7 +389,6 @@ arrange(Monitor *m) { showhide(m->stack); else for(m = mons; m; m = m->next) showhide(m->stack); - focus(NULL); if(m) arrangemon(m); else for(m = mons; m; m = m->next) @@ -598,6 +597,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); arrange(NULL); } } @@ -1154,9 +1154,13 @@ manage(Window w, XWindowAttributes *wa) { attach(c); attachstack(c); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - XMapWindow(dpy, c->win); setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, False); + c->mon->sel = c; arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); } void @@ -1621,6 +1625,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } } @@ -1701,6 +1706,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; + focus(NULL); arrange(selmon); } } @@ -1711,6 +1717,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); arrange(selmon); } } @@ -1976,6 +1983,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } diff --git a/transient.c b/transient.c new file mode 100644 index 0000000..040adb5 --- /dev/null +++ b/transient.c @@ -0,0 +1,42 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +int main(void) { + Display *d; + Window r, f, t = None; + XSizeHints h; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) + exit(1); + r = DefaultRootWindow(d); + + f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); + h.min_width = h.max_width = h.min_height = h.max_height = 400; + h.flags = PMinSize | PMaxSize; + XSetWMNormalHints(d, f, &h); + XStoreName(d, f, "floating"); + XMapWindow(d, f); + + XSelectInput(d, f, ExposureMask); + while (1) { + XNextEvent(d, &e); + + if (t == None) { + sleep(5); + t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); + XSetTransientForHint(d, t, f); + XStoreName(d, t, "transient"); + XMapWindow(d, t); + XSelectInput(d, t, ExposureMask); + } + } + + XCloseDisplay(d); + exit(0); +} From dec4850d0586f34f0dc69ed5285afefeefef90ae Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Mon, 8 Aug 2011 16:55:06 +0000 Subject: [PATCH 104/257] applied Connors and Valentins patch to improve the unmapnotify handling of broken clients --- dwm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index db0fdfb..6909969 100644 --- a/dwm.c +++ b/dwm.c @@ -1761,8 +1761,12 @@ unmapnotify(XEvent *e) { Client *c; XUnmapEvent *ev = &e->xunmap; - if((c = wintoclient(ev->window))) - unmanage(c, False); + if((c = wintoclient(ev->window))) { + if(ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, False); + } } void From 0f1f30daca0eaf0a400fd3f8d274594c07b32a51 Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Mon, 15 Aug 2011 18:44:12 +0200 Subject: [PATCH 105/257] applied Connors cleanup patch of Eckehards proposed fix of applyrules(), thanks everyone involved --- dwm.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dwm.c b/dwm.c index 6909969..39b0a51 100644 --- a/dwm.c +++ b/dwm.c @@ -289,31 +289,31 @@ applyrules(Client *c) { unsigned int i; const Rule *r; Monitor *m; - XClassHint ch = { 0 }; + XClassHint ch = { NULL, NULL }; /* rule matching */ c->isfloating = c->tags = 0; - if(XGetClassHint(dpy, c->win, &ch)) { - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - for(i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - 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) - c->mon = m; - } + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for(i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + 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) + c->mon = m; } - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); } + if(ch.res_class) + XFree(ch.res_class); + if(ch.res_name) + XFree(ch.res_name); c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } From 2b625eb73ed48ce671e497c60b61f4411c50c817 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Tue, 25 Oct 2011 20:01:18 +0100 Subject: [PATCH 106/257] hide clients to the left, not the right --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 39b0a51..d108e12 100644 --- a/dwm.c +++ b/dwm.c @@ -1597,7 +1597,7 @@ showhide(Client *c) { } else { /* hide clients bottom up */ showhide(c->snext); - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); + XMoveWindow(dpy, c->win, c->w * -2, c->y); } } From f68a01cd767659190bf690e29986184348672647 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Tue, 25 Oct 2011 20:08:08 +0100 Subject: [PATCH 107/257] apply resize hints in floating layout --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index d108e12..d274b50 100644 --- a/dwm.c +++ b/dwm.c @@ -349,7 +349,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { *h = bh; if(*w < bh) *w = bh; - if(resizehints || c->isfloating) { + 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 */ From b1a28ae1dab34a159e7cf17a82ecda0635e72f97 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Tue, 25 Oct 2011 20:40:46 +0100 Subject: [PATCH 108/257] apply nmaster patch --- config.def.h | 3 +++ dwm.c | 42 +++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/config.def.h b/config.def.h index 91cf439..973ab4c 100644 --- a/config.def.h +++ b/config.def.h @@ -24,6 +24,7 @@ static const Rule rules[] = { /* 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 Layout layouts[] = { @@ -55,6 +56,8 @@ static Key keys[] = { { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, { MODKEY, XK_h, setmfact, {.f = -0.05} }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, { MODKEY, XK_Return, zoom, {0} }, diff --git a/dwm.c b/dwm.c index d274b50..a58eb2a 100644 --- a/dwm.c +++ b/dwm.c @@ -125,6 +125,7 @@ typedef struct { struct Monitor { char ltsymbol[16]; float mfact; + int nmaster; int num; int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ @@ -189,6 +190,7 @@ 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); @@ -664,6 +666,7 @@ createmon(void) { die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; + m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; m->lt[0] = &layouts[0]; @@ -1023,6 +1026,12 @@ grabkeys(void) { } } +void +incnmaster(const Arg *arg) { + selmon->nmaster = MAX(selmon->nmaster + arg->i, 1); + arrange(selmon); +} + void initfont(const char *fontstr) { char *def, **missing; @@ -1650,32 +1659,23 @@ textnw(const char *text, unsigned int len) { void tile(Monitor *m) { - int x, y, h, w, mw; - unsigned int i, n; + unsigned int i, n, mw, mh, tw, th; Client *c; for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); if(n == 0) return; - /* master */ - c = nexttiled(m->clients); - mw = m->mfact * m->ww; - resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); - if(--n == 0) - return; - /* tile stack */ - x = (m->wx > c->x) ? c->x + mw + 2 * c->bw : m->wx + mw; - y = m->wy; - w = (m->wx > c->x) ? m->wx + m->ww - x : m->ww - mw; - h = m->wh / n; - if(h < bh) - h = m->wh; - for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { - resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) - ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); - if(h != m->wh) - y = c->y + HEIGHT(c); - } + + mh = (n > m->nmaster) ? m->wh / m->nmaster : m->wh / n; + mw = (n > m->nmaster) ? m->ww * m->mfact : m->ww; + th = (n > m->nmaster) ? m->wh / (n - m->nmaster) : 0; + tw = m->ww - mw; + + for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if(i < m->nmaster) + resize(c, m->wx, m->wy + (i*mh), mw - (2*c->bw), mh - (2*c->bw), False); + else + resize(c, m->wx + mw, m->wy + ((i - m->nmaster)*th), tw - (2*c->bw), th - (2*c->bw), False); } void From 04c26574b8567048ceec60142878318aa9081cb1 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Wed, 26 Oct 2011 12:16:25 +0100 Subject: [PATCH 109/257] add nmaster binds to manpage --- dwm.1 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.1 b/dwm.1 index 7ed8ead..5268a06 100644 --- a/dwm.1 +++ b/dwm.1 @@ -92,12 +92,18 @@ Focus next window. .B Mod1\-k Focus previous window. .TP -.B Mod1\-h -Decrease master area size. +.B Mod1\-i +Increase clients in master area. +.TP +.B Mod1\-d +Decrease clients in master area. .TP .B Mod1\-l Increase master area size. .TP +.B Mod1\-h +Decrease master area size. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP From 2420071f4c595438f3be9b476fcc23142624c50c Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Fri, 28 Oct 2011 23:45:12 +0100 Subject: [PATCH 110/257] improve tile spacing --- dwm.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index a58eb2a..cce215a 100644 --- a/dwm.c +++ b/dwm.c @@ -1659,23 +1659,26 @@ textnw(const char *text, unsigned int len) { void tile(Monitor *m) { - unsigned int i, n, mw, mh, tw, th; + 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) return; - mh = (n > m->nmaster) ? m->wh / m->nmaster : m->wh / n; mw = (n > m->nmaster) ? m->ww * m->mfact : m->ww; - th = (n > m->nmaster) ? m->wh / (n - m->nmaster) : 0; - tw = m->ww - mw; - for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if(i < m->nmaster) - resize(c, m->wx, m->wy + (i*mh), mw - (2*c->bw), mh - (2*c->bw), False); - else - resize(c, m->wx + mw, m->wy + ((i - m->nmaster)*th), tw - (2*c->bw), th - (2*c->bw), False); + 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); + 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); + ty += HEIGHT(c); + } } void From 1586b7a02d15df7648552ded5b370b80996dd94a Mon Sep 17 00:00:00 2001 From: "garbeam@gmail.com" Date: Sat, 29 Oct 2011 10:57:27 +0200 Subject: [PATCH 111/257] added keyrelease remark to TODO --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index 8d4f19c..b33a08d 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,4 @@ +- 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 From 5ccd42f80752be8f5152e09ecd250ba42739bf6d Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sun, 30 Oct 2011 12:14:34 +0100 Subject: [PATCH 112/257] fix big-border corner case --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index cce215a..8dbe83b 100644 --- a/dwm.c +++ b/dwm.c @@ -1606,7 +1606,7 @@ showhide(Client *c) { } else { /* hide clients bottom up */ showhide(c->snext); - XMoveWindow(dpy, c->win, c->w * -2, c->y); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); } } From 90af1ced3c634683ec4c0e51c5f1e69461a9192a Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Mon, 31 Oct 2011 20:09:27 +0100 Subject: [PATCH 113/257] allow 0 nmaster --- dwm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 8dbe83b..344966b 100644 --- a/dwm.c +++ b/dwm.c @@ -1028,7 +1028,7 @@ grabkeys(void) { void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 1); + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1666,8 +1666,10 @@ tile(Monitor *m) { if(n == 0) return; - mw = (n > m->nmaster) ? m->ww * m->mfact : m->ww; - + 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) { h = (m->wh - my) / (MIN(n, m->nmaster) - i); From 8262d9e663a98ab74b938bb5cdf0ddfd733bc5df Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Wed, 2 Nov 2011 12:01:28 +0000 Subject: [PATCH 114/257] make ewmh dialog windows float --- dwm.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 344966b..f753bfe 100644 --- a/dwm.c +++ b/dwm.c @@ -58,7 +58,8 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetLast }; /* EWMH atoms */ + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -237,6 +238,7 @@ static void updatebars(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 updatewmhints(Client *c); static void view(const Arg *arg); @@ -1152,6 +1154,7 @@ manage(Window w, XWindowAttributes *wa) { XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, dc.norm[ColBorder]); configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); @@ -1308,6 +1311,8 @@ propertynotify(XEvent *e) { if(c == c->mon->sel) drawbar(c->mon); } + if(ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); } } @@ -1562,6 +1567,8 @@ setup(void) { netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", 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); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); @@ -1966,6 +1973,25 @@ updatestatus(void) { drawbar(selmon); } +void +updatewindowtype(Client *c) +{ + Atom wtype, real; + int format; + unsigned long n, extra; + unsigned char *p = NULL; + + if(XGetWindowProperty(dpy, c->win, netatom[NetWMWindowType], 0L, + sizeof(Atom), False, XA_ATOM, &real, &format, + &n, &extra, (unsigned char **)&p) == Success && p) { + wtype = *(Atom *)p; + XFree(p); + + if(wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = True; + } +} + void updatewmhints(Client *c) { XWMHints *wmh; From e5a1e77351bb4538a1a475739a00dcb41aa35701 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Fri, 4 Nov 2011 20:02:35 +0100 Subject: [PATCH 115/257] testing Brians multiscreen issue fix --- dwm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dwm.c b/dwm.c index f753bfe..58a5746 100644 --- a/dwm.c +++ b/dwm.c @@ -340,14 +340,14 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { *y = 0; } else { - if(*x > m->mx + m->mw) - *x = m->mx + m->mw - WIDTH(c); - if(*y > m->my + m->mh) - *y = m->my + m->mh - HEIGHT(c); - if(*x + *w + 2 * c->bw < m->mx) - *x = m->mx; - if(*y + *h + 2 * c->bw < m->my) - *y = m->my; + if(*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if(*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if(*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if(*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; } if(*h < bh) *h = bh; @@ -1146,7 +1146,7 @@ manage(Window w, XWindowAttributes *wa) { 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 == 0) && (c->x + (c->w / 2) >= c->mon->wx) + 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->bw = borderpx; } From d21026f0a169841a70187b806cab8abd30e552ed Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sun, 6 Nov 2011 20:30:06 +0100 Subject: [PATCH 116/257] honour fullscreen hint on map --- dwm.c | 122 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/dwm.c b/dwm.c index 58a5746..4c6af64 100644 --- a/dwm.c +++ b/dwm.c @@ -215,6 +215,7 @@ 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 setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -531,31 +532,10 @@ clientmessage(XEvent *e) { if(!c) return; - if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) { - if(cme->data.l[0] && !c->isfullscreen) { - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = True; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } - else { - XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } + 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)) { @@ -928,6 +908,21 @@ focusstack(const Arg *arg) { } } +Atom +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, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + unsigned long getcolor(const char *colstr) { Colormap cmap = DefaultColormap(dpy, screen); @@ -1133,23 +1128,17 @@ manage(Window w, XWindowAttributes *wa) { c->w = c->oldw = wa->width; c->h = c->oldh = wa->height; c->oldbw = wa->border_width; - if(c->w == c->mon->mw && c->h == c->mon->mh) { - c->isfloating = True; // regression with flash, XXXX - c->x = c->mon->mx; - c->y = c->mon->my; - c->bw = 0; - } - else { - 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); - /* 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->bw = borderpx; - } + + 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); + /* 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->bw = borderpx; + wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, dc.norm[ColBorder]); @@ -1515,6 +1504,34 @@ setfocus(Client *c) { sendevent(c, wmatom[WMTakeFocus]); } +void +setfullscreen(Client *c, Bool fullscreen) { + if(fullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = True; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = True; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + else { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = False; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + void setlayout(const Arg *arg) { if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) @@ -1974,22 +1991,15 @@ updatestatus(void) { } void -updatewindowtype(Client *c) -{ - Atom wtype, real; - int format; - unsigned long n, extra; - unsigned char *p = NULL; +updatewindowtype(Client *c) { + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - if(XGetWindowProperty(dpy, c->win, netatom[NetWMWindowType], 0L, - sizeof(Atom), False, XA_ATOM, &real, &format, - &n, &extra, (unsigned char **)&p) == Success && p) { - wtype = *(Atom *)p; - XFree(p); + if(state == netatom[NetWMFullscreen]) + setfullscreen(c, True); - if(wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = True; - } + if(wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = True; } void From 80a9da555e81a69ab2e2e8fa9b779fa087d6863c Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sun, 6 Nov 2011 20:31:29 +0100 Subject: [PATCH 117/257] calculate window/monitor intersection --- dwm.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/dwm.c b/dwm.c index 4c6af64..fd6f04d 100644 --- a/dwm.c +++ b/dwm.c @@ -43,7 +43,8 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) +#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 MAX(A, B) ((A) > (B) ? (A) : (B)) @@ -203,8 +204,8 @@ static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); static void pop(Client *); static void propertynotify(XEvent *e); -static Monitor *ptrtomon(int x, int y); 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 resizeclient(Client *c, int x, int y, int w, int h); static void resizemouse(const Arg *arg); @@ -1248,7 +1249,7 @@ movemouse(const Arg *arg) { } } while(ev.type != ButtonRelease); XUngrabPointer(dpy, CurrentTime); - if((m = ptrtomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) { + if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { sendmon(c, m); selmon = m; focus(NULL); @@ -1305,21 +1306,24 @@ propertynotify(XEvent *e) { } } -Monitor * -ptrtomon(int x, int y) { - Monitor *m; - - for(m = mons; m; m = m->next) - if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) - return m; - return selmon; -} - void quit(const Arg *arg) { running = False; } +Monitor * +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) { + area = a; + r = m; + } + return r; +} + void resize(Client *c, int x, int y, int w, int h, Bool interact) { if(applysizehints(c, &x, &y, &w, &h, interact)) @@ -1383,7 +1387,7 @@ resizemouse(const Arg *arg) { 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 = ptrtomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) { + if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { sendmon(c, m); selmon = m; focus(NULL); @@ -2051,7 +2055,7 @@ wintomon(Window w) { Monitor *m; if(w == root && getrootptr(&x, &y)) - return ptrtomon(x, y); + return recttomon(x, y, 1, 1); for(m = mons; m; m = m->next) if(w == m->barwin) return m; From f099d2d5b50e8a0a21ef59142babcd87801e6abd Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Sun, 6 Nov 2011 20:36:23 +0100 Subject: [PATCH 118/257] new default colour scheme --- config.def.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config.def.h b/config.def.h index 973ab4c..77ff358 100644 --- a/config.def.h +++ b/config.def.h @@ -2,12 +2,12 @@ /* appearance */ static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; -static const char normbordercolor[] = "#cccccc"; -static const char normbgcolor[] = "#cccccc"; -static const char normfgcolor[] = "#000000"; -static const char selbordercolor[] = "#0066ff"; -static const char selbgcolor[] = "#0066ff"; -static const char selfgcolor[] = "#ffffff"; +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 Bool showbar = True; /* False means no bar */ From b5068e32e9428ea2fe2c7b1e7b6b0f769ab119cb Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Tue, 15 Nov 2011 20:16:58 +0100 Subject: [PATCH 119/257] add sloppy monitor focus --- dwm.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index fd6f04d..1d78655 100644 --- a/dwm.c +++ b/dwm.c @@ -200,6 +200,7 @@ static void manage(Window w, XWindowAttributes *wa); static void mappingnotify(XEvent *e); static void maprequest(XEvent *e); 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 *); @@ -271,6 +272,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [KeyPress] = keypress, [MappingNotify] = mappingnotify, [MapRequest] = maprequest, + [MotionNotify] = motionnotify, [PropertyNotify] = propertynotify, [UnmapNotify] = unmapnotify }; @@ -1201,6 +1203,21 @@ monocle(Monitor *m) { resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); } +void +motionnotify(XEvent *e) { + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if(ev->window != root) + return; + if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + selmon = m; + focus(NULL); + } + mon = m; +} + void movemouse(const Arg *arg) { int x, y, ocx, ocy, nx, ny; @@ -1614,9 +1631,8 @@ setup(void) { PropModeReplace, (unsigned char *) netatom, NetLast); /* select for events */ wa.cursor = cursor[CurNormal]; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask - |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(); From 26445a0dc95cd5efe3dce247e49d40b851561a84 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Mon, 19 Dec 2011 15:38:30 +0100 Subject: [PATCH 120/257] bump version to 6.0 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index 99085e1..484554a 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.9.1 +VERSION = 6.0 # Customize below to fit your system From 4e7c469862648420dcca95d7e88dc6cf24eb9ac1 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Mon, 19 Dec 2011 16:09:07 +0100 Subject: [PATCH 121/257] 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 122/257] 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 123/257] 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 124/257] 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 125/257] 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 126/257] 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 127/257] 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 128/257] 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 129/257] 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 130/257] =?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 131/257] 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 132/257] 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 133/257] 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 134/257] 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 135/257] 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 136/257] 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 137/257] 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 138/257] 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 139/257] 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 140/257] 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 141/257] 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 142/257] 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 143/257] 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 144/257] 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 145/257] 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 146/257] 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 147/257] 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 148/257] 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 149/257] 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 150/257] 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 151/257] 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 152/257] 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 153/257] 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 154/257] 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 155/257] 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 156/257] 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 157/257] =?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 158/257] 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 159/257] 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 160/257] 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 161/257] 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 162/257] 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 163/257] 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 164/257] 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 165/257] 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 166/257] 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 167/257] 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 168/257] 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 169/257] 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 170/257] 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 171/257] 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 172/257] 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 173/257] 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 174/257] 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 175/257] 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 176/257] 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 177/257] 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 178/257] 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 179/257] 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 180/257] 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 181/257] 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 182/257] 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 183/257] 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 184/257] 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 185/257] 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 186/257] 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 187/257] 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 188/257] 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 189/257] 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 190/257] 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 191/257] 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 192/257] 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 193/257] 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 194/257] 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 195/257] 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 196/257] 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 197/257] 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 198/257] 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 199/257] 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 200/257] 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 201/257] 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 202/257] 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 203/257] 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 204/257] 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 205/257] 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 206/257] 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 207/257] 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 208/257] 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 209/257] 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 210/257] 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 211/257] 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 212/257] 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 213/257] 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 214/257] 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 215/257] 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 216/257] 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 217/257] 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 218/257] 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 219/257] 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 220/257] 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 221/257] 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 222/257] 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 223/257] 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 224/257] 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 225/257] 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 226/257] 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 227/257] 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 228/257] 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 229/257] 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 230/257] 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 231/257] 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 232/257] 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 233/257] 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 234/257] 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 235/257] 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 236/257] 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 237/257] 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 238/257] 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 239/257] 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 240/257] 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 241/257] 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 242/257] 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 243/257] 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 244/257] 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 245/257] 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 246/257] 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 247/257] 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 248/257] 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 249/257] 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 250/257] 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 251/257] 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 252/257] 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 253/257] 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 254/257] 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 255/257] 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 256/257] 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 257/257] 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));