sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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