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