sites

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

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