dwm-swallow-20200707-8d1e703.diff (8904B)
1 From 8d1e7039c239619bee159e07e32b8d49837bf445 Mon Sep 17 00:00:00 2001 2 From: jmanabc <jdwilkesx@gmail.com> 3 Date: Tue, 7 Jul 2020 21:24:56 -0400 4 Subject: [PATCH] Fixed swallowing by removing scanner variable from dwm.c and 5 corrected capitalization in config.def.h 6 7 --- 8 config.def.h | 9 ++- 9 config.mk | 2 +- 10 dwm.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++-- 11 3 files changed, 198 insertions(+), 9 deletions(-) 12 13 diff --git a/config.def.h b/config.def.h 14 index 1c0b587..fe51476 100644 15 --- a/config.def.h 16 +++ b/config.def.h 17 @@ -3,6 +3,7 @@ 18 /* appearance */ 19 static const unsigned int borderpx = 1; /* border pixel of windows */ 20 static const unsigned int snap = 32; /* snap pixel */ 21 +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ 22 static const int showbar = 1; /* 0 means no bar */ 23 static const int topbar = 1; /* 0 means bottom bar */ 24 static const char *fonts[] = { "monospace:size=10" }; 25 @@ -26,9 +27,11 @@ static const Rule rules[] = { 26 * WM_CLASS(STRING) = instance, class 27 * WM_NAME(STRING) = title 28 */ 29 - /* class instance title tags mask isfloating monitor */ 30 - { "Gimp", NULL, NULL, 0, 1, -1 }, 31 - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, 32 + /* class instance title tags mask isfloating isterminal noswallow monitor */ 33 + { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, 34 + { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, 35 + { "St", NULL, NULL, 0, 0, 1, 0, -1 }, 36 + { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ 37 }; 38 39 /* layout(s) */ 40 diff --git a/config.mk b/config.mk 41 index 7084c33..b77641d 100644 42 --- a/config.mk 43 +++ b/config.mk 44 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 45 46 # includes and libs 47 INCS = -I${X11INC} -I${FREETYPEINC} 48 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 49 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res 50 51 # flags 52 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 53 diff --git a/dwm.c b/dwm.c 54 index 9fd0286..c58de28 100644 55 --- a/dwm.c 56 +++ b/dwm.c 57 @@ -40,6 +40,8 @@ 58 #include <X11/extensions/Xinerama.h> 59 #endif /* XINERAMA */ 60 #include <X11/Xft/Xft.h> 61 +#include <X11/Xlib-xcb.h> 62 +#include <xcb/res.h> 63 64 #include "drw.h" 65 #include "util.h" 66 @@ -92,9 +94,11 @@ struct Client { 67 int basew, baseh, incw, inch, maxw, maxh, minw, minh; 68 int bw, oldbw; 69 unsigned int tags; 70 - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 71 + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; 72 + pid_t pid; 73 Client *next; 74 Client *snext; 75 + Client *swallowing; 76 Monitor *mon; 77 Window win; 78 }; 79 @@ -138,6 +142,8 @@ typedef struct { 80 const char *title; 81 unsigned int tags; 82 int isfloating; 83 + int isterminal; 84 + int noswallow; 85 int monitor; 86 } Rule; 87 88 @@ -235,6 +241,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); 89 static int xerrorstart(Display *dpy, XErrorEvent *ee); 90 static void zoom(const Arg *arg); 91 92 +static pid_t getparentprocess(pid_t p); 93 +static int isdescprocess(pid_t p, pid_t c); 94 +static Client *swallowingclient(Window w); 95 +static Client *termforwin(const Client *c); 96 +static pid_t winpid(Window w); 97 + 98 /* variables */ 99 static const char broken[] = "broken"; 100 static char stext[256]; 101 @@ -269,6 +281,8 @@ static Drw *drw; 102 static Monitor *mons, *selmon; 103 static Window root, wmcheckwin; 104 105 +static xcb_connection_t *xcon; 106 + 107 /* configuration, allows nested code to access above variables */ 108 #include "config.h" 109 110 @@ -298,6 +312,8 @@ applyrules(Client *c) 111 && (!r->class || strstr(class, r->class)) 112 && (!r->instance || strstr(instance, r->instance))) 113 { 114 + c->isterminal = r->isterminal; 115 + c->noswallow = r->noswallow; 116 c->isfloating = r->isfloating; 117 c->tags |= r->tags; 118 for (m = mons; m && m->num != r->monitor; m = m->next); 119 @@ -414,6 +430,53 @@ attachstack(Client *c) 120 c->mon->stack = c; 121 } 122 123 +void 124 +swallow(Client *p, Client *c) 125 +{ 126 + 127 + if (c->noswallow || c->isterminal) 128 + return; 129 + if (c->noswallow && !swallowfloating && c->isfloating) 130 + return; 131 + 132 + detach(c); 133 + detachstack(c); 134 + 135 + setclientstate(c, WithdrawnState); 136 + XUnmapWindow(dpy, p->win); 137 + 138 + p->swallowing = c; 139 + c->mon = p->mon; 140 + 141 + Window w = p->win; 142 + p->win = c->win; 143 + c->win = w; 144 + updatetitle(p); 145 + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); 146 + arrange(p->mon); 147 + configure(p); 148 + updateclientlist(); 149 +} 150 + 151 +void 152 +unswallow(Client *c) 153 +{ 154 + c->win = c->swallowing->win; 155 + 156 + free(c->swallowing); 157 + c->swallowing = NULL; 158 + 159 + /* unfullscreen the client */ 160 + setfullscreen(c, 0); 161 + updatetitle(c); 162 + arrange(c->mon); 163 + XMapWindow(dpy, c->win); 164 + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); 165 + setclientstate(c, NormalState); 166 + focus(NULL); 167 + arrange(c->mon); 168 +} 169 + 170 void 171 buttonpress(XEvent *e) 172 { 173 @@ -653,6 +716,9 @@ destroynotify(XEvent *e) 174 175 if ((c = wintoclient(ev->window))) 176 unmanage(c, 1); 177 + 178 + else if ((c = swallowingclient(ev->window))) 179 + unmanage(c->swallowing, 1); 180 } 181 182 void 183 @@ -1018,12 +1084,13 @@ killclient(const Arg *arg) 184 void 185 manage(Window w, XWindowAttributes *wa) 186 { 187 - Client *c, *t = NULL; 188 + Client *c, *t = NULL, *term = NULL; 189 Window trans = None; 190 XWindowChanges wc; 191 192 c = ecalloc(1, sizeof(Client)); 193 c->win = w; 194 + c->pid = winpid(w); 195 /* geometry */ 196 c->x = c->oldx = wa->x; 197 c->y = c->oldy = wa->y; 198 @@ -1038,6 +1105,7 @@ manage(Window w, XWindowAttributes *wa) 199 } else { 200 c->mon = selmon; 201 applyrules(c); 202 + term = termforwin(c); 203 } 204 205 if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) 206 @@ -1074,6 +1142,8 @@ manage(Window w, XWindowAttributes *wa) 207 c->mon->sel = c; 208 arrange(c->mon); 209 XMapWindow(dpy, c->win); 210 + if (term) 211 + swallow(term, c); 212 focus(NULL); 213 } 214 215 @@ -1768,6 +1838,20 @@ unmanage(Client *c, int destroyed) 216 Monitor *m = c->mon; 217 XWindowChanges wc; 218 219 + if (c->swallowing) { 220 + unswallow(c); 221 + return; 222 + } 223 + 224 + Client *s = swallowingclient(c->win); 225 + if (s) { 226 + free(s->swallowing); 227 + s->swallowing = NULL; 228 + arrange(m); 229 + focus(NULL); 230 + return; 231 + } 232 + 233 detach(c); 234 detachstack(c); 235 if (!destroyed) { 236 @@ -1782,9 +1866,12 @@ unmanage(Client *c, int destroyed) 237 XUngrabServer(dpy); 238 } 239 free(c); 240 - focus(NULL); 241 - updateclientlist(); 242 - arrange(m); 243 + 244 + if (!s) { 245 + arrange(m); 246 + focus(NULL); 247 + updateclientlist(); 248 + } 249 } 250 251 void 252 @@ -2047,6 +2134,103 @@ view(const Arg *arg) 253 arrange(selmon); 254 } 255 256 +pid_t 257 +winpid(Window w) 258 +{ 259 + pid_t result = 0; 260 + 261 + xcb_res_client_id_spec_t spec = {0}; 262 + spec.client = w; 263 + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; 264 + 265 + xcb_generic_error_t *e = NULL; 266 + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); 267 + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); 268 + 269 + if (!r) 270 + return (pid_t)0; 271 + 272 + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); 273 + for (; i.rem; xcb_res_client_id_value_next(&i)) { 274 + spec = i.data->spec; 275 + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { 276 + uint32_t *t = xcb_res_client_id_value_value(i.data); 277 + result = *t; 278 + break; 279 + } 280 + } 281 + 282 + free(r); 283 + 284 + if (result == (pid_t)-1) 285 + result = 0; 286 + return result; 287 +} 288 + 289 +pid_t 290 +getparentprocess(pid_t p) 291 +{ 292 + unsigned int v = 0; 293 + 294 +#ifdef __linux__ 295 + FILE *f; 296 + char buf[256]; 297 + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); 298 + 299 + if (!(f = fopen(buf, "r"))) 300 + return 0; 301 + 302 + fscanf(f, "%*u %*s %*c %u", &v); 303 + fclose(f); 304 +#endif /* __linux__*/ 305 + 306 + return (pid_t)v; 307 +} 308 + 309 +int 310 +isdescprocess(pid_t p, pid_t c) 311 +{ 312 + while (p != c && c != 0) 313 + c = getparentprocess(c); 314 + 315 + return (int)c; 316 +} 317 + 318 +Client * 319 +termforwin(const Client *w) 320 +{ 321 + Client *c; 322 + Monitor *m; 323 + 324 + if (!w->pid || w->isterminal) 325 + return NULL; 326 + 327 + for (m = mons; m; m = m->next) { 328 + for (c = m->clients; c; c = c->next) { 329 + if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) 330 + return c; 331 + } 332 + } 333 + 334 + return NULL; 335 +} 336 + 337 +Client * 338 +swallowingclient(Window w) 339 +{ 340 + Client *c; 341 + Monitor *m; 342 + 343 + for (m = mons; m; m = m->next) { 344 + for (c = m->clients; c; c = c->next) { 345 + if (c->swallowing && c->swallowing->win == w) 346 + return c; 347 + } 348 + } 349 + 350 + return NULL; 351 +} 352 + 353 Client * 354 wintoclient(Window w) 355 { 356 @@ -2138,6 +2322,8 @@ main(int argc, char *argv[]) 357 fputs("warning: no locale support\n", stderr); 358 if (!(dpy = XOpenDisplay(NULL))) 359 die("dwm: cannot open display"); 360 + if (!(xcon = XGetXCBConnection(dpy))) 361 + die("dwm: cannot get xcb connection\n"); 362 checkotherwm(); 363 setup(); 364 #ifdef __OpenBSD__ 365 -- 366 2.27.0 367