sites

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

dwm-swallow-6.1.diff (9337B)


      1 diff --git a/config.def.h b/config.def.h
      2 index 7054c06..2bfd607 100644
      3 --- a/config.def.h
      4 +++ b/config.def.h
      5 @@ -24,9 +24,10 @@ static const Rule rules[] = {
      6  	 *	WM_CLASS(STRING) = instance, class
      7  	 *	WM_NAME(STRING) = title
      8  	 */
      9 -	/* class      instance    title       tags mask     isfloating   monitor */
     10 -	{ "Gimp",     NULL,       NULL,       0,            1,           -1 },
     11 -	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
     12 +	/* class      instance    title       tags mask     isfloating   isterminal noswallow monitor */
     13 +	{ "Gimp",     NULL,       NULL,       0,            1,           0,         0,        -1 },
     14 +	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           0,         0,        -1 },
     15 +	{ "st",       NULL,       NULL,       0,            0,           1,         1,        -1 },
     16  };
     17  
     18  /* layout(s) */
     19 diff --git a/config.mk b/config.mk
     20 index 4eefb71..34ea872 100644
     21 --- a/config.mk
     22 +++ b/config.mk
     23 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
     24  
     25  # includes and libs
     26  INCS = -I${X11INC} -I${FREETYPEINC}
     27 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
     28 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res
     29  
     30  # flags
     31  CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
     32 diff --git a/dwm.c b/dwm.c
     33 index 0362114..1d38293 100644
     34 --- a/dwm.c
     35 +++ b/dwm.c
     36 @@ -40,6 +40,8 @@
     37  #include <X11/extensions/Xinerama.h>
     38  #endif /* XINERAMA */
     39  #include <X11/Xft/Xft.h>
     40 +#include <X11/Xlib-xcb.h>
     41 +#include <xcb/res.h>
     42  
     43  #include "drw.h"
     44  #include "util.h"
     45 @@ -92,9 +94,11 @@ struct Client {
     46  	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
     47  	int bw, oldbw;
     48  	unsigned int tags;
     49 -	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     50 +	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
     51 +	pid_t pid;
     52  	Client *next;
     53  	Client *snext;
     54 +	Client *swallowing;
     55  	Monitor *mon;
     56  	Window win;
     57  };
     58 @@ -138,6 +142,8 @@ typedef struct {
     59  	const char *title;
     60  	unsigned int tags;
     61  	int isfloating;
     62 +	int isterminal;
     63 +	int noswallow;
     64  	int monitor;
     65  } Rule;
     66  
     67 @@ -170,12 +176,14 @@ static void focus(Client *c);
     68  static void focusin(XEvent *e);
     69  static void focusmon(const Arg *arg);
     70  static void focusstack(const Arg *arg);
     71 +static pid_t getparentprocess(pid_t p);
     72  static int getrootptr(int *x, int *y);
     73  static long getstate(Window w);
     74  static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
     75  static void grabbuttons(Client *c, int focused);
     76  static void grabkeys(void);
     77  static void incnmaster(const Arg *arg);
     78 +static int isdescprocess(pid_t p, pid_t c);
     79  static void keypress(XEvent *e);
     80  static void killclient(const Arg *arg);
     81  static void manage(Window w, XWindowAttributes *wa);
     82 @@ -206,8 +214,10 @@ static void setup(void);
     83  static void showhide(Client *c);
     84  static void sigchld(int unused);
     85  static void spawn(const Arg *arg);
     86 +static Client *swallowingclient(Window w);
     87  static void tag(const Arg *arg);
     88  static void tagmon(const Arg *arg);
     89 +static Client *termforwin(const Client *c);
     90  static void tile(Monitor *);
     91  static void togglebar(const Arg *arg);
     92  static void togglefloating(const Arg *arg);
     93 @@ -227,6 +237,7 @@ static void updatewindowtype(Client *c);
     94  static void updatetitle(Client *c);
     95  static void updatewmhints(Client *c);
     96  static void view(const Arg *arg);
     97 +static pid_t winpid(Window w);
     98  static Client *wintoclient(Window w);
     99  static Monitor *wintomon(Window w);
    100  static int xerror(Display *dpy, XErrorEvent *ee);
    101 @@ -267,6 +278,8 @@ static Drw *drw;
    102  static Monitor *mons, *selmon;
    103  static Window root;
    104  
    105 +static xcb_connection_t *xcon;
    106 +
    107  /* configuration, allows nested code to access above variables */
    108  #include "config.h"
    109  
    110 @@ -296,6 +309,7 @@ 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->isfloating = r->isfloating;
    116  			c->tags |= r->tags;
    117  			for (m = mons; m && m->num != r->monitor; m = m->next);
    118 @@ -412,6 +426,48 @@ attachstack(Client *c)
    119  	c->mon->stack = c;
    120  }
    121  
    122 +void
    123 +swallow(Client *p, Client *c)
    124 +{
    125 +	if (c->noswallow || c->isterminal)
    126 +		return;
    127 +
    128 +	detach(c);
    129 +	detachstack(c);
    130 +
    131 +	setclientstate(c, WithdrawnState);
    132 +	XUnmapWindow(dpy, p->win);
    133 +
    134 +	p->swallowing = c;
    135 +	c->mon = p->mon;
    136 +
    137 +	Window w = p->win;
    138 +	p->win = c->win;
    139 +	c->win = w;
    140 +	updatetitle(p);
    141 +	arrange(p->mon);
    142 +	XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
    143 +	configure(p);
    144 +	updateclientlist();
    145 +}
    146 +
    147 +void
    148 +unswallow(Client *c)
    149 +{
    150 +	c->win = c->swallowing->win;
    151 +
    152 +	free(c->swallowing);
    153 +	c->swallowing = NULL;
    154 +
    155 +	updatetitle(c);
    156 +	arrange(c->mon);
    157 +	XMapWindow(dpy, c->win);
    158 +	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    159 +	configure(c);
    160 +	setclientstate(c, NormalState);
    161 +	focus(c);
    162 +}
    163 +
    164  void
    165  buttonpress(XEvent *e)
    166  {
    167 @@ -475,7 +531,7 @@ cleanup(void)
    168  	selmon->lt[selmon->sellt] = &foo;
    169  	for (m = mons; m; m = m->next)
    170  		while (m->stack)
    171 -			unmanage(m->stack, 0);
    172 +			unmanage(m->stack, 0); // XXX - unmanage swallowing windows too
    173  	XUngrabKey(dpy, AnyKey, AnyModifier, root);
    174  	while (mons)
    175  		cleanupmon(mons);
    176 @@ -661,6 +717,9 @@ destroynotify(XEvent *e)
    177  
    178  	if ((c = wintoclient(ev->window)))
    179  		unmanage(c, 1);
    180 +
    181 +	else if ((c = swallowingclient(ev->window)))
    182 +		unmanage(c->swallowing, 1);
    183  }
    184  
    185  void
    186 @@ -1032,12 +1091,13 @@ killclient(const Arg *arg)
    187  void
    188  manage(Window w, XWindowAttributes *wa)
    189  {
    190 -	Client *c, *t = NULL;
    191 +	Client *c, *t, *term = NULL;
    192  	Window trans = None;
    193  	XWindowChanges wc;
    194  
    195  	c = ecalloc(1, sizeof(Client));
    196  	c->win = w;
    197 +	c->pid = winpid(w);
    198  	updatetitle(c);
    199  	if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
    200  		c->mon = t->mon;
    201 @@ -1045,7 +1105,9 @@ manage(Window w, XWindowAttributes *wa)
    202  	} else {
    203  		c->mon = selmon;
    204  		applyrules(c);
    205 +		term = termforwin(c);
    206  	}
    207 +
    208  	/* geometry */
    209  	c->x = c->oldx = wa->x;
    210  	c->y = c->oldy = wa->y;
    211 @@ -1085,8 +1147,11 @@ manage(Window w, XWindowAttributes *wa)
    212  	if (c->mon == selmon)
    213  		unfocus(selmon->sel, 0);
    214  	c->mon->sel = c;
    215 -	arrange(c->mon);
    216 +	if (!term)
    217 +		arrange(c->mon);
    218  	XMapWindow(dpy, c->win);
    219 +	if (term)
    220 +		swallow(term, c);
    221  	focus(NULL);
    222  }
    223  
    224 @@ -1758,6 +1823,20 @@ unmanage(Client *c, int destroyed)
    225  	Monitor *m = c->mon;
    226  	XWindowChanges wc;
    227  
    228 +	if (c->swallowing) {
    229 +		unswallow(c);
    230 +		return;
    231 +	}
    232 +
    233 +	Client *s = swallowingclient(c->win);
    234 +	if (s) {
    235 +		free(s->swallowing);
    236 +		s->swallowing = NULL;
    237 +		arrange(m);
    238 +        focus(NULL);
    239 +		return;
    240 +	}
    241 +
    242  	/* The server grab construct avoids race conditions. */
    243  	detach(c);
    244  	detachstack(c);
    245 @@ -1773,9 +1852,12 @@ unmanage(Client *c, int destroyed)
    246  		XUngrabServer(dpy);
    247  	}
    248  	free(c);
    249 -	focus(NULL);
    250 -	updateclientlist();
    251 -	arrange(m);
    252 +
    253 +	if (!s) {
    254 +		arrange(m);
    255 +		focus(NULL);
    256 +		updateclientlist();
    257 +	}
    258  }
    259  
    260  void
    261 @@ -2040,16 +2122,116 @@ view(const Arg *arg)
    262  	arrange(selmon);
    263  }
    264  
    265 +pid_t
    266 +winpid(Window w)
    267 +{
    268 +	pid_t result = 0;
    269 +
    270 +	xcb_res_client_id_spec_t spec = {0};
    271 +	spec.client = w;
    272 +	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
    273 +
    274 +	xcb_generic_error_t *e = NULL;
    275 +	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
    276 +	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
    277 +
    278 +	if (!r)
    279 +		return (pid_t)0;
    280 +
    281 +	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
    282 +	for (; i.rem; xcb_res_client_id_value_next(&i)) {
    283 +		spec = i.data->spec;
    284 +		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
    285 +			uint32_t *t = xcb_res_client_id_value_value(i.data);
    286 +			result = *t;
    287 +			break;
    288 +		}
    289 +	}
    290 +
    291 +	free(r);
    292 +
    293 +	if (result == (pid_t)-1)
    294 +		result = 0;
    295 +	return result;
    296 +}
    297 +
    298 +pid_t
    299 +getparentprocess(pid_t p)
    300 +{
    301 +	unsigned int v = 0;
    302 +
    303 +#ifdef __linux__
    304 +	FILE *f;
    305 +	char buf[256];
    306 +	snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
    307 +
    308 +	if (!(f = fopen(buf, "r")))
    309 +		return 0;
    310 +
    311 +	fscanf(f, "%*u %*s %*c %u", &v);
    312 +	fclose(f);
    313 +#endif /* __linux__ */
    314 +
    315 +	return (pid_t)v;
    316 +}
    317 +
    318 +int
    319 +isdescprocess(pid_t p, pid_t c)
    320 +{
    321 +	while (p != c && c != 0)
    322 +		c = getparentprocess(c);
    323 +
    324 +	return (int)c;
    325 +}
    326 +
    327 +Client *
    328 +termforwin(const Client *w)
    329 +{
    330 +	Client *c;
    331 +	Monitor *m;
    332 +
    333 +	if (!w->pid || w->isterminal)
    334 +		return NULL;
    335 +
    336 +	for (m = mons; m; m = m->next) {
    337 +		for (c = m->clients; c; c = c->next) {
    338 +			if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
    339 +				return c;
    340 +		}
    341 +	}
    342 +
    343 +	return NULL;
    344 +}
    345 +
    346 +Client *
    347 +swallowingclient(Window w)
    348 +{
    349 +	Client *c;
    350 +	Monitor *m;
    351 +
    352 +	for (m = mons; m; m = m->next) {
    353 +		for (c = m->clients; c; c = c->next) {
    354 +			if (c->swallowing && c->swallowing->win == w)
    355 +				return c;
    356 +		}
    357 +	}
    358 +
    359 +	return NULL;
    360 +}
    361 +
    362  Client *
    363  wintoclient(Window w)
    364  {
    365  	Client *c;
    366  	Monitor *m;
    367  
    368 -	for (m = mons; m; m = m->next)
    369 -		for (c = m->clients; c; c = c->next)
    370 +	for (m = mons; m; m = m->next) {
    371 +		for (c = m->clients; c; c = c->next) {
    372  			if (c->win == w)
    373  				return c;
    374 +		}
    375 +	}
    376 +
    377  	return NULL;
    378  }
    379  
    380 @@ -2131,6 +2313,8 @@ main(int argc, char *argv[])
    381  		fputs("warning: no locale support\n", stderr);
    382  	if (!(dpy = XOpenDisplay(NULL)))
    383  		die("dwm: cannot open display\n");
    384 +	if (!(xcon = XGetXCBConnection(dpy)))
    385 +		die("dwm: cannot get xcb connection\n");
    386  	checkotherwm();
    387  	setup();
    388  	scan();