From 67d76bdc68102df976177de351f65329d8683064 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Thu, 2 Jul 2020 20:18:30 +0100 Subject: [PATCH 01/16] 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); -- 2.20.1 From 138b405f0c8aa24d8a040cc1a1cf6e3eb5a0ebc7 Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Mon, 12 Jul 2021 23:44:16 +0200 Subject: [PATCH 02/16] 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); -- 2.20.1 From 716233534b35f74dba5a46ade8f1a6f8cc72fea4 Mon Sep 17 00:00:00 2001 From: Miles Alan Date: Mon, 9 Aug 2021 18:24:14 +0200 Subject: [PATCH 03/16] 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); -- 2.20.1 From a786211d6cb794fba0ea406d86002c7618998afc Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 20 Aug 2021 23:09:48 +0200 Subject: [PATCH 04/16] 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); -- 2.20.1 From 8657affa2a61e85ca8df76b62e43cb02897d1d80 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Sat, 18 Dec 2021 16:58:23 +0000 Subject: [PATCH 05/16] 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]); -- 2.20.1 From d39e2f3441fe18aba8d1a62c08918a411ec6f237 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 7 Jan 2022 12:39:18 +0100 Subject: [PATCH 06/16] 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 -- 2.20.1 From 60e9a14998bfe8666c641f7c27fec18e85ac7494 Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 11 Mar 2022 20:40:05 +0600 Subject: [PATCH 07/16] 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); -- 2.20.1 From a0d107ab2baf13c7c57efc5be5931cd9ebbad6a0 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:17:25 +0800 Subject: [PATCH 08/16] add .gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8b4e08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +tags + +dwm +config.h +drw.o +dwm.o +util.o -- 2.20.1 From 6b043f44229c59ba7a81df884605c5d297229d23 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:21:57 +0800 Subject: [PATCH 09/16] minor key update --- config.def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index a2ac963..3562099 100644 --- a/config.def.h +++ b/config.def.h @@ -5,8 +5,8 @@ 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 *fonts[] = { "monospace:size=12" }; +static const char dmenufont[] = "monospace:size=12"; static const char col_gray1[] = "#222222"; static const char col_gray2[] = "#444444"; static const char col_gray3[] = "#bbbbbb"; @@ -45,7 +45,7 @@ static const Layout layouts[] = { }; /* key definitions */ -#define MODKEY Mod1Mask +#define MODKEY Mod4Mask #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ -- 2.20.1 From 992956f2b7aaa5b7c632825d1582663b9781c036 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:22:28 +0800 Subject: [PATCH 10/16] patch: swallow --- .gitignore | 2 + config.def.h | 9 +- config.mk | 3 +- dwm.c | 235 +++++++++++- patches/dwm-swallow-20201211-61bb8b2.diff | 412 ++++++++++++++++++++++ 5 files changed, 651 insertions(+), 10 deletions(-) create mode 100644 patches/dwm-swallow-20201211-61bb8b2.diff diff --git a/.gitignore b/.gitignore index d8b4e08..d8c817f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ config.h drw.o dwm.o util.o + +dwm.c.orig \ No newline at end of file diff --git a/config.def.h b/config.def.h index 3562099..c434d36 100644 --- a/config.def.h +++ b/config.def.h @@ -3,6 +3,7 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ static const char *fonts[] = { "monospace:size=12" }; @@ -26,9 +27,11 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + /* class instance title tags mask isfloating isterminal noswallow monitor */ + { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, + { "St", NULL, NULL, 0, 0, 1, 0, -1 }, + { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ }; /* layout(s) */ diff --git a/config.mk b/config.mk index b6eb7e0..b574d96 100644 --- a/config.mk +++ b/config.mk @@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft FREETYPEINC = /usr/include/freetype2 # OpenBSD (uncomment) #FREETYPEINC = ${X11INC}/freetype2 +#KVMLIB = -lkvm # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/dwm.c b/dwm.c index 1ee4ea2..f266a37 100644 --- a/dwm.c +++ b/dwm.c @@ -40,6 +40,12 @@ #include #endif /* XINERAMA */ #include +#include +#include +#ifdef __OpenBSD__ +#include +#include +#endif /* __OpenBSD */ #include "drw.h" #include "util.h" @@ -92,9 +98,11 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; + pid_t pid; Client *next; Client *snext; + Client *swallowing; Monitor *mon; Window win; }; @@ -138,6 +146,8 @@ typedef struct { const char *title; unsigned int tags; int isfloating; + int isterminal; + int noswallow; int monitor; } Rule; @@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); +static pid_t getparentprocess(pid_t p); +static int isdescprocess(pid_t p, pid_t c); +static Client *swallowingclient(Window w); +static Client *termforwin(const Client *c); +static pid_t winpid(Window w); + /* variables */ static const char broken[] = "broken"; static char stext[256]; @@ -269,6 +285,8 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +static xcb_connection_t *xcon; + /* configuration, allows nested code to access above variables */ #include "config.h" @@ -298,6 +316,8 @@ applyrules(Client *c) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { + c->isterminal = r->isterminal; + c->noswallow = r->noswallow; c->isfloating = r->isfloating; c->tags |= r->tags; for (m = mons; m && m->num != r->monitor; m = m->next); @@ -414,6 +434,53 @@ attachstack(Client *c) c->mon->stack = c; } +void +swallow(Client *p, Client *c) +{ + + if (c->noswallow || c->isterminal) + return; + if (c->noswallow && !swallowfloating && c->isfloating) + return; + + detach(c); + detachstack(c); + + setclientstate(c, WithdrawnState); + XUnmapWindow(dpy, p->win); + + p->swallowing = c; + c->mon = p->mon; + + Window w = p->win; + p->win = c->win; + c->win = w; + updatetitle(p); + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); + arrange(p->mon); + configure(p); + updateclientlist(); +} + +void +unswallow(Client *c) +{ + c->win = c->swallowing->win; + + free(c->swallowing); + c->swallowing = NULL; + + /* unfullscreen the client */ + setfullscreen(c, 0); + updatetitle(c); + arrange(c->mon); + XMapWindow(dpy, c->win); + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + setclientstate(c, NormalState); + focus(NULL); + arrange(c->mon); +} + void buttonpress(XEvent *e) { @@ -654,6 +721,9 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); + + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); } void @@ -1022,12 +1092,13 @@ killclient(const Arg *arg) void manage(Window w, XWindowAttributes *wa) { - Client *c, *t = NULL; + Client *c, *t = NULL, *term = NULL; Window trans = None; XWindowChanges wc; c = ecalloc(1, sizeof(Client)); c->win = w; + c->pid = winpid(w); /* geometry */ c->x = c->oldx = wa->x; c->y = c->oldy = wa->y; @@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa) } else { c->mon = selmon; applyrules(c); + term = termforwin(c); } if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) @@ -1078,6 +1150,8 @@ manage(Window w, XWindowAttributes *wa) c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); + if (term) + swallow(term, c); focus(NULL); } @@ -1772,6 +1846,20 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; + if (c->swallowing) { + unswallow(c); + return; + } + + Client *s = swallowingclient(c->win); + if (s) { + free(s->swallowing); + s->swallowing = NULL; + arrange(m); + focus(NULL); + return; + } + detach(c); detachstack(c); if (!destroyed) { @@ -1786,9 +1874,12 @@ unmanage(Client *c, int destroyed) XUngrabServer(dpy); } free(c); - focus(NULL); - updateclientlist(); - arrange(m); + + if (!s) { + arrange(m); + focus(NULL); + updateclientlist(); + } } void @@ -2051,6 +2142,136 @@ view(const Arg *arg) arrange(selmon); } +pid_t +winpid(Window w) +{ + + pid_t result = 0; + +#ifdef __linux__ + xcb_res_client_id_spec_t spec = {0}; + spec.client = w; + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; + + xcb_generic_error_t *e = NULL; + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); + + if (!r) + return (pid_t)0; + + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); + for (; i.rem; xcb_res_client_id_value_next(&i)) { + spec = i.data->spec; + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { + uint32_t *t = xcb_res_client_id_value_value(i.data); + result = *t; + break; + } + } + + free(r); + + if (result == (pid_t)-1) + result = 0; + +#endif /* __linux__ */ + +#ifdef __OpenBSD__ + Atom type; + int format; + unsigned long len, bytes; + unsigned char *prop; + pid_t ret; + + if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) + return 0; + + ret = *(pid_t*)prop; + XFree(prop); + result = ret; + +#endif /* __OpenBSD__ */ + return result; +} + +pid_t +getparentprocess(pid_t p) +{ + unsigned int v = 0; + +#ifdef __linux__ + FILE *f; + char buf[256]; + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + + if (!(f = fopen(buf, "r"))) + return 0; + + fscanf(f, "%*u %*s %*c %u", &v); + fclose(f); +#endif /* __linux__*/ + +#ifdef __OpenBSD__ + int n; + kvm_t *kd; + struct kinfo_proc *kp; + + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); + if (!kd) + return 0; + + kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); + v = kp->p_ppid; +#endif /* __OpenBSD__ */ + + return (pid_t)v; +} + +int +isdescprocess(pid_t p, pid_t c) +{ + while (p != c && c != 0) + c = getparentprocess(c); + + return (int)c; +} + +Client * +termforwin(const Client *w) +{ + Client *c; + Monitor *m; + + if (!w->pid || w->isterminal) + return NULL; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + return c; + } + } + + return NULL; +} + +Client * +swallowingclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->swallowing && c->swallowing->win == w) + return c; + } + } + + return NULL; +} + Client * wintoclient(Window w) { @@ -2142,10 +2363,12 @@ main(int argc, char *argv[]) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) die("dwm: cannot open display"); + if (!(xcon = XGetXCBConnection(dpy))) + die("dwm: cannot get xcb connection\n"); checkotherwm(); setup(); #ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) + if (pledge("stdio rpath proc exec ps", NULL) == -1) die("pledge"); #endif /* __OpenBSD__ */ scan(); diff --git a/patches/dwm-swallow-20201211-61bb8b2.diff b/patches/dwm-swallow-20201211-61bb8b2.diff new file mode 100644 index 0000000..6bc0a1f --- /dev/null +++ b/patches/dwm-swallow-20201211-61bb8b2.diff @@ -0,0 +1,412 @@ +From f0cdf40e0a7126838d051eb84d84b91421b771d6 Mon Sep 17 00:00:00 2001 +From: 0x1bi +Date: Fri, 11 Dec 2020 10:16:25 -0500 +Subject: [PATCH] fix swallow for openbsd + +--- + config.def.h | 9 +- + config.mk | 3 +- + dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 237 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..fe51476 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,7 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ + 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" }; +@@ -26,9 +27,11 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating isterminal noswallow monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, ++ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, ++ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + }; + + /* layout(s) */ +diff --git a/config.mk b/config.mk +index 7084c33..ff9e508 100644 +--- a/config.mk ++++ b/config.mk +@@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft + FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 ++#KVMLIB = -lkvm + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index 664c527..0b20086 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,12 @@ + #include + #endif /* XINERAMA */ + #include ++#include ++#include ++#ifdef __OpenBSD__ ++#include ++#include ++#endif /* __OpenBSD */ + + #include "drw.h" + #include "util.h" +@@ -92,9 +98,11 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; ++ pid_t pid; + Client *next; + Client *snext; ++ Client *swallowing; + Monitor *mon; + Window win; + }; +@@ -138,6 +146,8 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ int isterminal; ++ int noswallow; + int monitor; + } Rule; + +@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++static pid_t getparentprocess(pid_t p); ++static int isdescprocess(pid_t p, pid_t c); ++static Client *swallowingclient(Window w); ++static Client *termforwin(const Client *c); ++static pid_t winpid(Window w); ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -269,6 +285,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static xcb_connection_t *xcon; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -298,6 +316,8 @@ applyrules(Client *c) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { ++ c->isterminal = r->isterminal; ++ c->noswallow = r->noswallow; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); +@@ -414,6 +434,53 @@ attachstack(Client *c) + c->mon->stack = c; + } + ++void ++swallow(Client *p, Client *c) ++{ ++ ++ if (c->noswallow || c->isterminal) ++ return; ++ if (c->noswallow && !swallowfloating && c->isfloating) ++ return; ++ ++ detach(c); ++ detachstack(c); ++ ++ setclientstate(c, WithdrawnState); ++ XUnmapWindow(dpy, p->win); ++ ++ p->swallowing = c; ++ c->mon = p->mon; ++ ++ Window w = p->win; ++ p->win = c->win; ++ c->win = w; ++ updatetitle(p); ++ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); ++ arrange(p->mon); ++ configure(p); ++ updateclientlist(); ++} ++ ++void ++unswallow(Client *c) ++{ ++ c->win = c->swallowing->win; ++ ++ free(c->swallowing); ++ c->swallowing = NULL; ++ ++ /* unfullscreen the client */ ++ setfullscreen(c, 0); ++ updatetitle(c); ++ arrange(c->mon); ++ XMapWindow(dpy, c->win); ++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); ++ setclientstate(c, NormalState); ++ focus(NULL); ++ arrange(c->mon); ++} ++ + void + buttonpress(XEvent *e) + { +@@ -653,6 +720,9 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ ++ else if ((c = swallowingclient(ev->window))) ++ unmanage(c->swallowing, 1); + } + + void +@@ -1018,12 +1088,13 @@ killclient(const Arg *arg) + void + manage(Window w, XWindowAttributes *wa) + { +- Client *c, *t = NULL; ++ Client *c, *t = NULL, *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; ++ c->pid = winpid(w); + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; +@@ -1038,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa) + } else { + c->mon = selmon; + applyrules(c); ++ term = termforwin(c); + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) +@@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa) + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); ++ if (term) ++ swallow(term, c); + focus(NULL); + } + +@@ -1768,6 +1842,20 @@ unmanage(Client *c, int destroyed) + Monitor *m = c->mon; + XWindowChanges wc; + ++ if (c->swallowing) { ++ unswallow(c); ++ return; ++ } ++ ++ Client *s = swallowingclient(c->win); ++ if (s) { ++ free(s->swallowing); ++ s->swallowing = NULL; ++ arrange(m); ++ focus(NULL); ++ return; ++ } ++ + detach(c); + detachstack(c); + if (!destroyed) { +@@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed) + XUngrabServer(dpy); + } + free(c); +- focus(NULL); +- updateclientlist(); +- arrange(m); ++ ++ if (!s) { ++ arrange(m); ++ focus(NULL); ++ updateclientlist(); ++ } + } + + void +@@ -2047,6 +2138,136 @@ view(const Arg *arg) + arrange(selmon); + } + ++pid_t ++winpid(Window w) ++{ ++ ++ pid_t result = 0; ++ ++#ifdef __linux__ ++ xcb_res_client_id_spec_t spec = {0}; ++ spec.client = w; ++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; ++ ++ xcb_generic_error_t *e = NULL; ++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); ++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); ++ ++ if (!r) ++ return (pid_t)0; ++ ++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); ++ for (; i.rem; xcb_res_client_id_value_next(&i)) { ++ spec = i.data->spec; ++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { ++ uint32_t *t = xcb_res_client_id_value_value(i.data); ++ result = *t; ++ break; ++ } ++ } ++ ++ free(r); ++ ++ if (result == (pid_t)-1) ++ result = 0; ++ ++#endif /* __linux__ */ ++ ++#ifdef __OpenBSD__ ++ Atom type; ++ int format; ++ unsigned long len, bytes; ++ unsigned char *prop; ++ pid_t ret; ++ ++ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) ++ return 0; ++ ++ ret = *(pid_t*)prop; ++ XFree(prop); ++ result = ret; ++ ++#endif /* __OpenBSD__ */ ++ return result; ++} ++ ++pid_t ++getparentprocess(pid_t p) ++{ ++ unsigned int v = 0; ++ ++#ifdef __linux__ ++ FILE *f; ++ char buf[256]; ++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); ++ ++ if (!(f = fopen(buf, "r"))) ++ return 0; ++ ++ fscanf(f, "%*u %*s %*c %u", &v); ++ fclose(f); ++#endif /* __linux__*/ ++ ++#ifdef __OpenBSD__ ++ int n; ++ kvm_t *kd; ++ struct kinfo_proc *kp; ++ ++ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); ++ if (!kd) ++ return 0; ++ ++ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); ++ v = kp->p_ppid; ++#endif /* __OpenBSD__ */ ++ ++ return (pid_t)v; ++} ++ ++int ++isdescprocess(pid_t p, pid_t c) ++{ ++ while (p != c && c != 0) ++ c = getparentprocess(c); ++ ++ return (int)c; ++} ++ ++Client * ++termforwin(const Client *w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ if (!w->pid || w->isterminal) ++ return NULL; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ ++Client * ++swallowingclient(Window w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->swallowing && c->swallowing->win == w) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ + Client * + wintoclient(Window w) + { +@@ -2138,10 +2359,12 @@ main(int argc, char *argv[]) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); ++ if (!(xcon = XGetXCBConnection(dpy))) ++ die("dwm: cannot get xcb connection\n"); + checkotherwm(); + setup(); + #ifdef __OpenBSD__ +- if (pledge("stdio rpath proc exec", NULL) == -1) ++ if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); + #endif /* __OpenBSD__ */ + scan(); +-- +2.28.0 + -- 2.20.1 From f8e2a655036a3f2e45d01b9121837270998b240b Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:25:52 +0800 Subject: [PATCH 11/16] patch: alpha --- .gitignore | 8 +- config.def.h | 7 + config.mk | 2 +- drw.c | 26 ++- drw.h | 9 +- dwm.c | 60 ++++- patches/dwm-alpha-20201019-61bb8b2.diff | 289 ++++++++++++++++++++++++ 7 files changed, 374 insertions(+), 27 deletions(-) create mode 100644 patches/dwm-alpha-20201019-61bb8b2.diff diff --git a/.gitignore b/.gitignore index d8c817f..d31d40e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ tags dwm config.h -drw.o -dwm.o -util.o - -dwm.c.orig \ No newline at end of file +*.o +*.orig +*.rej diff --git a/config.def.h b/config.def.h index c434d36..15f1e82 100644 --- a/config.def.h +++ b/config.def.h @@ -13,11 +13,18 @@ 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 unsigned int baralpha = 0xd0; +static const unsigned int borderalpha = OPAQUE; static const char *colors[][3] = { /* fg bg border */ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, [SchemeSel] = { col_gray4, col_cyan, col_cyan }, }; +static const unsigned int alphas[][3] = { + /* fg bg border */ + [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeSel] = { OPAQUE, baralpha, borderalpha }, +}; /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; diff --git a/config.mk b/config.mk index b574d96..5745461 100644 --- a/config.mk +++ b/config.mk @@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} -lXrender # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/drw.c b/drw.c index 4cdbcbe..fe3aadd 100644 --- a/drw.c +++ b/drw.c @@ -61,7 +61,7 @@ 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_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) { Drw *drw = ecalloc(1, sizeof(Drw)); @@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->root = root; drw->w = w; drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); + drw->visual = visual; + drw->depth = depth; + drw->cmap = cmap; + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; @@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) drw->h = h; if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); } void @@ -194,21 +197,22 @@ drw_fontset_free(Fnt *font) } void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) { if (!drw || !dest || !clrname) return; - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, clrname, dest)) die("error, cannot allocate color '%s'", clrname); + + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); } /* Wrapper to create color schemes. The caller has to call free(3) on the * returned color scheme when done using it. */ Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) { size_t i; Clr *ret; @@ -218,7 +222,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) return NULL; for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); return ret; } @@ -274,9 +278,7 @@ 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); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); x += lpad; w -= lpad; } diff --git a/drw.h b/drw.h index 4bcd5ad..a56f523 100644 --- a/drw.h +++ b/drw.h @@ -20,6 +20,9 @@ typedef struct { Display *dpy; int screen; Window root; + Visual *visual; + unsigned int depth; + Colormap cmap; Drawable drawable; GC gc; Clr *scheme; @@ -27,7 +30,7 @@ typedef struct { } Drw; /* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); @@ -38,8 +41,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, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); diff --git a/dwm.c b/dwm.c index f266a37..5b0c792 100644 --- a/dwm.c +++ b/dwm.c @@ -63,6 +63,8 @@ #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#define OPAQUE 0xffU + /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { SchemeNorm, SchemeSel }; /* color schemes */ @@ -243,6 +245,7 @@ static Monitor *wintomon(Window w); static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void xinitvisual(); static void zoom(const Arg *arg); static pid_t getparentprocess(pid_t p); @@ -287,6 +290,11 @@ static Window root, wmcheckwin; static xcb_connection_t *xcon; +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; + /* configuration, allows nested code to access above variables */ #include "config.h" @@ -1620,7 +1628,8 @@ setup(void) sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); + xinitvisual(); + drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); lrpad = drw->fonts->h; @@ -1648,7 +1657,7 @@ setup(void) /* init appearance */ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); + scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); /* init bars */ updatebars(); updatestatus(); @@ -1902,16 +1911,18 @@ updatebars(void) Monitor *m; XSetWindowAttributes wa = { .override_redirect = True, - .background_pixmap = ParentRelative, + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, .event_mask = ButtonPressMask|ExposureMask }; XClassHint ch = {"dwm", "dwm"}; 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); + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); XSetClassHint(dpy, m->barwin, &ch); @@ -2338,6 +2349,43 @@ xerrorstart(Display *dpy, XErrorEvent *ee) return -1; } +void +xinitvisual() +{ + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + for(i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + if (! visual) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +} + void zoom(const Arg *arg) { diff --git a/patches/dwm-alpha-20201019-61bb8b2.diff b/patches/dwm-alpha-20201019-61bb8b2.diff new file mode 100644 index 0000000..9a8e92a --- /dev/null +++ b/patches/dwm-alpha-20201019-61bb8b2.diff @@ -0,0 +1,289 @@ +From 51f9c34480b984e261a738e5295f518b42c2f29c Mon Sep 17 00:00:00 2001 +From: Petrus Karell +Date: Mon, 19 Oct 2020 19:15:24 +0300 +Subject: [PATCH] Allow dwm to have translucent bars, while keeping all + the text on it opaque, just like the alpha-patch for st. Updated for 61bb8b2 + +--- + config.def.h | 7 ++++++ + config.mk | 2 +- + drw.c | 26 ++++++++++++----------- + drw.h | 9 +++++--- + dwm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++------ + 5 files changed, 82 insertions(+), 22 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..4f68fe8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,11 +12,18 @@ 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 unsigned int baralpha = 0xd0; ++static const unsigned int borderalpha = OPAQUE; + static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; ++static const unsigned int alphas[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, ++ [SchemeSel] = { OPAQUE, baralpha, borderalpha }, ++}; + + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +diff --git a/config.mk b/config.mk +index 7084c33..21b5404 100644 +--- a/config.mk ++++ b/config.mk +@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/drw.c b/drw.c +index 4cdbcbe..fe3aadd 100644 +--- a/drw.c ++++ b/drw.c +@@ -61,7 +61,7 @@ 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_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) + { + Drw *drw = ecalloc(1, sizeof(Drw)); + +@@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h + drw->root = root; + drw->w = w; + drw->h = h; +- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); +- drw->gc = XCreateGC(dpy, root, 0, NULL); ++ drw->visual = visual; ++ drw->depth = depth; ++ drw->cmap = cmap; ++ drw->drawable = XCreatePixmap(dpy, root, w, h, depth); ++ drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +@@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); +- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); + } + + void +@@ -194,21 +197,22 @@ drw_fontset_free(Fnt *font) + } + + void +-drw_clr_create(Drw *drw, Clr *dest, const char *clrname) ++drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) + { + if (!drw || !dest || !clrname) + return; + +- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen), ++ if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); ++ ++ dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); + } + + /* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ + Clr * +-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) ++drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) + { + size_t i; + Clr *ret; +@@ -218,7 +222,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) + return NULL; + + for (i = 0; i < clrcount; i++) +- drw_clr_create(drw, &ret[i], clrnames[i]); ++ drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); + return ret; + } + +@@ -274,9 +278,7 @@ 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); +- d = XftDrawCreate(drw->dpy, drw->drawable, +- DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen)); ++ d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + x += lpad; + w -= lpad; + } +diff --git a/drw.h b/drw.h +index 4bcd5ad..a56f523 100644 +--- a/drw.h ++++ b/drw.h +@@ -20,6 +20,9 @@ typedef struct { + Display *dpy; + int screen; + Window root; ++ Visual *visual; ++ unsigned int depth; ++ Colormap cmap; + Drawable drawable; + GC gc; + Clr *scheme; +@@ -27,7 +30,7 @@ typedef struct { + } Drw; + + /* Drawable abstraction */ +-Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); ++Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); + void drw_resize(Drw *drw, unsigned int w, unsigned int h); + void drw_free(Drw *drw); + +@@ -38,8 +41,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, Clr *dest, const char *clrname); +-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); ++void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); ++Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); + + /* Cursor abstraction */ + Cur *drw_cur_create(Drw *drw, int shape); +diff --git a/dwm.c b/dwm.c +index 664c527..d8005c7 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -57,6 +57,8 @@ + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + ++#define OPAQUE 0xffU ++ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ +@@ -233,6 +235,7 @@ static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); ++static void xinitvisual(); + static void zoom(const Arg *arg); + + /* variables */ +@@ -269,6 +272,11 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static int useargb = 0; ++static Visual *visual; ++static int depth; ++static Colormap cmap; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -1542,7 +1550,8 @@ setup(void) + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); +- drw = drw_create(dpy, screen, root, sw, sh); ++ xinitvisual(); ++ drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +@@ -1570,7 +1579,7 @@ setup(void) + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) +- scheme[i] = drw_scm_create(drw, colors[i], 3); ++ scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1807,16 +1816,18 @@ updatebars(void) + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, +- .background_pixmap = ParentRelative, ++ .background_pixel = 0, ++ .border_pixel = 0, ++ .colormap = cmap, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + 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); ++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, ++ InputOutput, visual, ++ CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); +@@ -2113,6 +2124,43 @@ xerrorstart(Display *dpy, XErrorEvent *ee) + return -1; + } + ++void ++xinitvisual() ++{ ++ XVisualInfo *infos; ++ XRenderPictFormat *fmt; ++ int nitems; ++ int i; ++ ++ XVisualInfo tpl = { ++ .screen = screen, ++ .depth = 32, ++ .class = TrueColor ++ }; ++ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; ++ ++ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); ++ visual = NULL; ++ for(i = 0; i < nitems; i ++) { ++ fmt = XRenderFindVisualFormat(dpy, infos[i].visual); ++ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { ++ visual = infos[i].visual; ++ depth = infos[i].depth; ++ cmap = XCreateColormap(dpy, root, visual, AllocNone); ++ useargb = 1; ++ break; ++ } ++ } ++ ++ XFree(infos); ++ ++ if (! visual) { ++ visual = DefaultVisual(dpy, screen); ++ depth = DefaultDepth(dpy, screen); ++ cmap = DefaultColormap(dpy, screen); ++ } ++} ++ + void + zoom(const Arg *arg) + { +-- +2.28.0 + -- 2.20.1 From 35d1c1e9bb97f8721064444275c57cfb8b863e48 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:29:00 +0800 Subject: [PATCH 12/16] patch: fullscreen --- config.def.h | 1 + dwm.c | 14 +++++++++ patches/dwm-fullscreen-6.2.diff | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 patches/dwm-fullscreen-6.2.diff diff --git a/config.def.h b/config.def.h index 15f1e82..07da813 100644 --- a/config.def.h +++ b/config.def.h @@ -87,6 +87,7 @@ static Key keys[] = { { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, { MODKEY, XK_0, view, {.ui = ~0 } }, diff --git a/dwm.c b/dwm.c index 5b0c792..fb1c33f 100644 --- a/dwm.c +++ b/dwm.c @@ -212,6 +212,7 @@ static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); +static void fullscreen(const Arg *arg); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -1584,6 +1585,19 @@ setfullscreen(Client *c, int fullscreen) } } +Layout *last_layout; +void +fullscreen(const Arg *arg) +{ + if (selmon->showbar) { + for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); + setlayout(&((Arg) { .v = &layouts[2] })); + } else { + setlayout(&((Arg) { .v = last_layout })); + } + togglebar(arg); +} + void setlayout(const Arg *arg) { diff --git a/patches/dwm-fullscreen-6.2.diff b/patches/dwm-fullscreen-6.2.diff new file mode 100644 index 0000000..36e3140 --- /dev/null +++ b/patches/dwm-fullscreen-6.2.diff @@ -0,0 +1,56 @@ +From 54719285bd1a984e2efce6e8a8eab184fec11abf Mon Sep 17 00:00:00 2001 +From: Sermak +Date: Mon, 8 Jul 2019 01:06:44 +0200 +Subject: [PATCH] Simulate toggleable fullscreen mode + +--- + config.def.h | 1 + + dwm.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..f774cc5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -76,6 +76,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 4465af1..04b1e06 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -199,6 +199,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void fullscreen(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -1497,6 +1498,19 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++Layout *last_layout; ++void ++fullscreen(const Arg *arg) ++{ ++ if (selmon->showbar) { ++ for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); ++ setlayout(&((Arg) { .v = &layouts[2] })); ++ } else { ++ setlayout(&((Arg) { .v = last_layout })); ++ } ++ togglebar(arg); ++} ++ + void + setlayout(const Arg *arg) + { +-- +2.22.0 -- 2.20.1 From f3f4e621b3498301b0a628e006d8ed02bbb21b8a Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Sun, 13 Mar 2022 22:31:43 +0800 Subject: [PATCH 13/16] patch: restartsig --- config.def.h | 1 + dwm.1 | 10 ++ dwm.c | 22 ++++ patches/dwm-restartsig-20180523-6.2.diff | 139 +++++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 patches/dwm-restartsig-20180523-6.2.diff diff --git a/config.def.h b/config.def.h index 07da813..54c2b4d 100644 --- a/config.def.h +++ b/config.def.h @@ -106,6 +106,7 @@ static Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, }; /* button definitions */ diff --git a/dwm.1 b/dwm.1 index ddc8321..7b6cadb 100644 --- a/dwm.1 +++ b/dwm.1 @@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. .TP .B Mod1\-Shift\-q Quit dwm. +.TP +.B Mod1\-Control\-Shift\-q +Restart dwm. .SS Mouse commands .TP .B Mod1\-Button1 @@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float .SH CUSTOMIZATION dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. +.SH SIGNALS +.TP +.B SIGHUP - 1 +Restart the dwm process. +.TP +.B SIGTERM - 15 +Cleanly terminate the dwm process. .SH SEE ALSO .BR dmenu (1), .BR st (1) diff --git a/dwm.c b/dwm.c index fb1c33f..7665557 100644 --- a/dwm.c +++ b/dwm.c @@ -219,6 +219,8 @@ static void setup(void); static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); +static void sighup(int unused); +static void sigterm(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -281,6 +283,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; +static int restart = 0; static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; @@ -1336,6 +1339,7 @@ propertynotify(XEvent *e) void quit(const Arg *arg) { + if(arg->i) restart = 1; running = 0; } @@ -1637,6 +1641,9 @@ setup(void) /* clean up any zombies immediately */ sigchld(0); + signal(SIGHUP, sighup); + signal(SIGTERM, sigterm); + /* init screen */ screen = DefaultScreen(dpy); sw = DisplayWidth(dpy, screen); @@ -1738,6 +1745,20 @@ sigchld(int unused) while (0 < waitpid(-1, NULL, WNOHANG)); } +void +sighup(int unused) +{ + Arg a = {.i = 1}; + quit(&a); +} + +void +sigterm(int unused) +{ + Arg a = {.i = 0}; + quit(&a); +} + void spawn(const Arg *arg) { @@ -2435,6 +2456,7 @@ main(int argc, char *argv[]) #endif /* __OpenBSD__ */ scan(); run(); + if(restart) execvp(argv[0], argv); cleanup(); XCloseDisplay(dpy); return EXIT_SUCCESS; diff --git a/patches/dwm-restartsig-20180523-6.2.diff b/patches/dwm-restartsig-20180523-6.2.diff new file mode 100644 index 0000000..f1f8680 --- /dev/null +++ b/patches/dwm-restartsig-20180523-6.2.diff @@ -0,0 +1,139 @@ +From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 +From: Christopher Drelich +Date: Wed, 23 May 2018 22:50:38 -0400 +Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM + handlers. + +Modified quit() to restart if it receives arg .i = 1 +MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. + +Signal handlers were handled for SIGHUP and SIGTERM. +If dwm receives these signals it calls quit() with +arg .i = to 1 or 0, respectively. + +To restart dwm: +MOD+CTRL+SHIFT+Q +or +kill -HUP dwmpid + +To quit dwm cleanly: +MOD+SHIFT+Q +or +kill -TERM dwmpid +--- + config.def.h | 1 + + dwm.1 | 10 ++++++++++ + dwm.c | 22 ++++++++++++++++++++++ + 3 files changed, 33 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a9ac303..e559429 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -94,6 +94,7 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, + }; + + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index 13b3729..36a331c 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. + .TP + .B Mod1\-Shift\-q + Quit dwm. ++.TP ++.B Mod1\-Control\-Shift\-q ++Restart dwm. + .SS Mouse commands + .TP + .B Mod1\-Button1 +@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float + .SH CUSTOMIZATION + dwm is customized by creating a custom config.h and (re)compiling the source + code. This keeps it fast, secure and simple. ++.SH SIGNALS ++.TP ++.B SIGHUP - 1 ++Restart the dwm process. ++.TP ++.B SIGTERM - 15 ++Cleanly terminate the dwm process. + .SH SEE ALSO + .BR dmenu (1), + .BR st (1) +diff --git a/dwm.c b/dwm.c +index bb95e26..286eecd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -205,6 +205,8 @@ static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); ++static void sighup(int unused); ++static void sigterm(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [UnmapNotify] = unmapnotify + }; + static Atom wmatom[WMLast], netatom[NetLast]; ++static int restart = 0; + static int running = 1; + static Cur *cursor[CurLast]; + static Clr **scheme; +@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) + void + quit(const Arg *arg) + { ++ if(arg->i) restart = 1; + running = 0; + } + +@@ -1536,6 +1540,9 @@ setup(void) + /* clean up any zombies immediately */ + sigchld(0); + ++ signal(SIGHUP, sighup); ++ signal(SIGTERM, sigterm); ++ + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); +@@ -1637,6 +1644,20 @@ sigchld(int unused) + } + + void ++sighup(int unused) ++{ ++ Arg a = {.i = 1}; ++ quit(&a); ++} ++ ++void ++sigterm(int unused) ++{ ++ Arg a = {.i = 0}; ++ quit(&a); ++} ++ ++void + spawn(const Arg *arg) + { + if (arg->v == dmenucmd) +@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) + setup(); + scan(); + run(); ++ if(restart) execvp(argv[0], argv); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +-- +2.7.4 + -- 2.20.1 From 4a0af747c2f271592fa37474c993bd522a710e61 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Mon, 14 Mar 2022 14:58:20 +0800 Subject: [PATCH 14/16] patch: fullgaps --- config.def.h | 4 + dwm.1 | 10 ++ dwm.c | 33 +++-- patches/dwm-fullgaps-20200508-7b77734.diff | 138 +++++++++++++++++++++ 4 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 patches/dwm-fullgaps-20200508-7b77734.diff diff --git a/config.def.h b/config.def.h index 54c2b4d..1482968 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,7 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int gappx = 5; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ @@ -96,6 +97,9 @@ static Key keys[] = { { MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = +1 } }, + { MODKEY, XK_equal, setgaps, {.i = 0 } }, TAGKEYS( XK_1, 0) TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) diff --git a/dwm.1 b/dwm.1 index 7b6cadb..192b7bd 100644 --- a/dwm.1 +++ b/dwm.1 @@ -140,6 +140,16 @@ View all windows with any tag. .B Mod1\-Control\-[1..n] Add/remove all windows with nth tag to/from the view. .TP +.B Mod1\-- +Decrease the gaps around windows. +.TP +.B Mod1\-= +Increase the gaps around windows. +.TP +.B Mod1\-Shift-= +Reset the gaps around windows to +.BR 0 . +.TP .B Mod1\-Shift\-q Quit dwm. .TP diff --git a/dwm.c b/dwm.c index 7665557..781e060 100644 --- a/dwm.c +++ b/dwm.c @@ -129,6 +129,7 @@ struct Monitor { int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ + int gappx; /* gaps between windows */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; @@ -212,6 +213,7 @@ static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); +static void setgaps(const Arg *arg); static void fullscreen(const Arg *arg); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); @@ -719,6 +721,7 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->gappx = gappx; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -1602,6 +1605,16 @@ fullscreen(const Arg *arg) togglebar(arg); } +void +setgaps(const Arg *arg) +{ + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) + selmon->gappx = 0; + else + selmon->gappx += arg->i; + arrange(selmon); +} + void setlayout(const Arg *arg) { @@ -1806,18 +1819,18 @@ tile(Monitor *m) 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++) + mw = m->ww - m->gappx; + for (i = 0, my = ty = m->gappx, 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); - if (my + HEIGHT(c) < m->wh) - my += HEIGHT(c); + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); + if (my + HEIGHT(c) + m->gappx < m->wh) + my += HEIGHT(c) + m->gappx; } 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); - if (ty + HEIGHT(c) < m->wh) - ty += HEIGHT(c); + h = (m->wh - ty) / (n - i) - m->gappx; + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); + if (ty + HEIGHT(c) + m->gappx < m->wh) + ty += HEIGHT(c) + m->gappx; } } diff --git a/patches/dwm-fullgaps-20200508-7b77734.diff b/patches/dwm-fullgaps-20200508-7b77734.diff new file mode 100644 index 0000000..368c871 --- /dev/null +++ b/patches/dwm-fullgaps-20200508-7b77734.diff @@ -0,0 +1,138 @@ +From 7b7773458c072e4b24d6ea32d0364a8e402e4a43 Mon Sep 17 00:00:00 2001 +From: swy7ch +Date: Fri, 8 May 2020 19:07:24 +0200 +Subject: [PATCH] [PATCH] update dwm-fullgaps patch to be used with tile layout + update + +the recent tile layout changes in commit HEAD~1 (f09418b) broke the +patch + +this patch adapt the new `if` statements to take gaps into account + +this patch also provides manpage entries for the keybindings +--- + config.def.h | 4 ++++ + dwm.1 | 10 ++++++++++ + dwm.c | 33 +++++++++++++++++++++++---------- + 3 files changed, 37 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..38d2f6c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,7 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappx = 5; /* gaps between 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 */ +@@ -84,6 +85,9 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_minus, setgaps, {.i = -1 } }, ++ { MODKEY, XK_equal, setgaps, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +diff --git a/dwm.1 b/dwm.1 +index 13b3729..0202d96 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -140,6 +140,16 @@ View all windows with any tag. + .B Mod1\-Control\-[1..n] + Add/remove all windows with nth tag to/from the view. + .TP ++.B Mod1\-- ++Decrease the gaps around windows. ++.TP ++.B Mod1\-= ++Increase the gaps around windows. ++.TP ++.B Mod1\-Shift-= ++Reset the gaps around windows to ++.BR 0 . ++.TP + .B Mod1\-Shift\-q + Quit dwm. + .SS Mouse commands +diff --git a/dwm.c b/dwm.c +index 9fd0286..45a58f3 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -119,6 +119,7 @@ struct Monitor { + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ ++ int gappx; /* gaps between windows */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; +@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void setgaps(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -639,6 +641,7 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->gappx = gappx; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1498,6 +1501,16 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++void ++setgaps(const Arg *arg) ++{ ++ if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) ++ selmon->gappx = 0; ++ else ++ selmon->gappx += arg->i; ++ arrange(selmon); ++} ++ + void + setlayout(const Arg *arg) + { +@@ -1684,18 +1697,18 @@ tile(Monitor *m) + 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++) ++ mw = m->ww - m->gappx; ++ for (i = 0, my = ty = m->gappx, 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); +- if (my + HEIGHT(c) < m->wh) +- my += HEIGHT(c); ++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; ++ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); ++ if (my + HEIGHT(c) + m->gappx < m->wh) ++ my += HEIGHT(c) + m->gappx; + } 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); +- if (ty + HEIGHT(c) < m->wh) +- ty += HEIGHT(c); ++ h = (m->wh - ty) / (n - i) - m->gappx; ++ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); ++ if (ty + HEIGHT(c) + m->gappx < m->wh) ++ ty += HEIGHT(c) + m->gappx; + } + } + +-- +2.26.2 + -- 2.20.1 From 9188493674d74f8623b38224cf8d61842287ae88 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Mon, 14 Mar 2022 17:18:29 +0800 Subject: [PATCH 15/16] shortcut updated --- config.def.h | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/config.def.h b/config.def.h index 1482968..7f8851a 100644 --- a/config.def.h +++ b/config.def.h @@ -1,5 +1,7 @@ /* See LICENSE file for copyright and license details. */ +#define TERMINAL "st" + /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int gappx = 5; /* gaps between windows */ @@ -51,8 +53,9 @@ static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen win static const Layout layouts[] = { /* symbol arrange function */ { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, + + { "><>", NULL }, /* no layout function means floating behavior */ }; /* key definitions */ @@ -69,12 +72,10 @@ 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", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -static const char *termcmd[] = { "st", NULL }; +static const char *termcmd[] = { TERMINAL, NULL }; static Key keys[] = { /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, @@ -82,15 +83,7 @@ static Key keys[] = { { 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} }, { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, { MODKEY, XK_0, view, {.ui = ~0 } }, { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, { MODKEY, XK_comma, focusmon, {.i = -1 } }, @@ -110,7 +103,22 @@ static Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, + { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, + + /* layout */ + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_f, fullscreen, {0} }, + { MODKEY, XK_space, zoom, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + + /* launch applications */ + { MODKEY, XK_q, killclient, {0} }, + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_w, spawn, SHCMD("firefox") }, + { MODKEY, XK_n, spawn, SHCMD(TERMINAL " -e sudo nmtui") }, + { MODKEY, XK_h, spawn, SHCMD(TERMINAL " -e htop") }, }; /* button definitions */ -- 2.20.1 From 6a95d0428757af844c315e357d743e3d42ae72b5 Mon Sep 17 00:00:00 2001 From: Xinqi Bao Date: Mon, 14 Mar 2022 18:04:46 +0800 Subject: [PATCH 16/16] patch: remove fullscreen --- config.def.h | 1 - dwm.c | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/config.def.h b/config.def.h index 7f8851a..e3ad0a5 100644 --- a/config.def.h +++ b/config.def.h @@ -108,7 +108,6 @@ static Key keys[] = { /* layout */ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_f, fullscreen, {0} }, { MODKEY, XK_space, zoom, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, diff --git a/dwm.c b/dwm.c index 781e060..1348e47 100644 --- a/dwm.c +++ b/dwm.c @@ -214,7 +214,6 @@ static void setclientstate(Client *c, long state); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); static void setgaps(const Arg *arg); -static void fullscreen(const Arg *arg); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -1592,19 +1591,6 @@ setfullscreen(Client *c, int fullscreen) } } -Layout *last_layout; -void -fullscreen(const Arg *arg) -{ - if (selmon->showbar) { - for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); - setlayout(&((Arg) { .v = &layouts[2] })); - } else { - setlayout(&((Arg) { .v = last_layout })); - } - togglebar(arg); -} - void setgaps(const Arg *arg) { -- 2.20.1