sites

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

dwm-swallow-20201211-61bb8b2.diff (9942B)


      1 From f0cdf40e0a7126838d051eb84d84b91421b771d6 Mon Sep 17 00:00:00 2001
      2 From: 0x1bi <ben@0x1bi.net>
      3 Date: Fri, 11 Dec 2020 10:16:25 -0500
      4 Subject: [PATCH] fix swallow for openbsd
      5 
      6 ---
      7  config.def.h |   9 +-
      8  config.mk    |   3 +-
      9  dwm.c        | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
     10  3 files changed, 237 insertions(+), 10 deletions(-)
     11 
     12 diff --git a/config.def.h b/config.def.h
     13 index 1c0b587..fe51476 100644
     14 --- a/config.def.h
     15 +++ b/config.def.h
     16 @@ -3,6 +3,7 @@
     17  /* appearance */
     18  static const unsigned int borderpx  = 1;        /* border pixel of windows */
     19  static const unsigned int snap      = 32;       /* snap pixel */
     20 +static const int swallowfloating    = 0;        /* 1 means swallow floating windows by default */
     21  static const int showbar            = 1;        /* 0 means no bar */
     22  static const int topbar             = 1;        /* 0 means bottom bar */
     23  static const char *fonts[]          = { "monospace:size=10" };
     24 @@ -26,9 +27,11 @@ static const Rule rules[] = {
     25  	 *	WM_CLASS(STRING) = instance, class
     26  	 *	WM_NAME(STRING) = title
     27  	 */
     28 -	/* class      instance    title       tags mask     isfloating   monitor */
     29 -	{ "Gimp",     NULL,       NULL,       0,            1,           -1 },
     30 -	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
     31 +	/* class     instance  title           tags mask  isfloating  isterminal  noswallow  monitor */
     32 +	{ "Gimp",    NULL,     NULL,           0,         1,          0,           0,        -1 },
     33 +	{ "Firefox", NULL,     NULL,           1 << 8,    0,          0,          -1,        -1 },
     34 +	{ "St",      NULL,     NULL,           0,         0,          1,           0,        -1 },
     35 +	{ NULL,      NULL,     "Event Tester", 0,         0,          0,           1,        -1 }, /* xev */
     36  };
     37  
     38  /* layout(s) */
     39 diff --git a/config.mk b/config.mk
     40 index 7084c33..ff9e508 100644
     41 --- a/config.mk
     42 +++ b/config.mk
     43 @@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
     44  FREETYPEINC = /usr/include/freetype2
     45  # OpenBSD (uncomment)
     46  #FREETYPEINC = ${X11INC}/freetype2
     47 +#KVMLIB = -lkvm
     48  
     49  # includes and libs
     50  INCS = -I${X11INC} -I${FREETYPEINC}
     51 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
     52 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
     53  
     54  # flags
     55  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
     56 diff --git a/dwm.c b/dwm.c
     57 index 664c527..0b20086 100644
     58 --- a/dwm.c
     59 +++ b/dwm.c
     60 @@ -40,6 +40,12 @@
     61  #include <X11/extensions/Xinerama.h>
     62  #endif /* XINERAMA */
     63  #include <X11/Xft/Xft.h>
     64 +#include <X11/Xlib-xcb.h>
     65 +#include <xcb/res.h>
     66 +#ifdef __OpenBSD__
     67 +#include <sys/sysctl.h>
     68 +#include <kvm.h>
     69 +#endif /* __OpenBSD */
     70  
     71  #include "drw.h"
     72  #include "util.h"
     73 @@ -92,9 +98,11 @@ struct Client {
     74  	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
     75  	int bw, oldbw;
     76  	unsigned int tags;
     77 -	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     78 +	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
     79 +	pid_t pid;
     80  	Client *next;
     81  	Client *snext;
     82 +	Client *swallowing;
     83  	Monitor *mon;
     84  	Window win;
     85  };
     86 @@ -138,6 +146,8 @@ typedef struct {
     87  	const char *title;
     88  	unsigned int tags;
     89  	int isfloating;
     90 +	int isterminal;
     91 +	int noswallow;
     92  	int monitor;
     93  } Rule;
     94  
     95 @@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
     96  static int xerrorstart(Display *dpy, XErrorEvent *ee);
     97  static void zoom(const Arg *arg);
     98  
     99 +static pid_t getparentprocess(pid_t p);
    100 +static int isdescprocess(pid_t p, pid_t c);
    101 +static Client *swallowingclient(Window w);
    102 +static Client *termforwin(const Client *c);
    103 +static pid_t winpid(Window w);
    104 +
    105  /* variables */
    106  static const char broken[] = "broken";
    107  static char stext[256];
    108 @@ -269,6 +285,8 @@ static Drw *drw;
    109  static Monitor *mons, *selmon;
    110  static Window root, wmcheckwin;
    111  
    112 +static xcb_connection_t *xcon;
    113 +
    114  /* configuration, allows nested code to access above variables */
    115  #include "config.h"
    116  
    117 @@ -298,6 +316,8 @@ applyrules(Client *c)
    118  		&& (!r->class || strstr(class, r->class))
    119  		&& (!r->instance || strstr(instance, r->instance)))
    120  		{
    121 +			c->isterminal = r->isterminal;
    122 +			c->noswallow  = r->noswallow;
    123  			c->isfloating = r->isfloating;
    124  			c->tags |= r->tags;
    125  			for (m = mons; m && m->num != r->monitor; m = m->next);
    126 @@ -414,6 +434,53 @@ attachstack(Client *c)
    127  	c->mon->stack = c;
    128  }
    129  
    130 +void
    131 +swallow(Client *p, Client *c)
    132 +{
    133 +
    134 +	if (c->noswallow || c->isterminal)
    135 +		return;
    136 +	if (c->noswallow && !swallowfloating && c->isfloating)
    137 +		return;
    138 +
    139 +	detach(c);
    140 +	detachstack(c);
    141 +
    142 +	setclientstate(c, WithdrawnState);
    143 +	XUnmapWindow(dpy, p->win);
    144 +
    145 +	p->swallowing = c;
    146 +	c->mon = p->mon;
    147 +
    148 +	Window w = p->win;
    149 +	p->win = c->win;
    150 +	c->win = w;
    151 +	updatetitle(p);
    152 +	XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
    153 +	arrange(p->mon);
    154 +	configure(p);
    155 +	updateclientlist();
    156 +}
    157 +
    158 +void
    159 +unswallow(Client *c)
    160 +{
    161 +	c->win = c->swallowing->win;
    162 +
    163 +	free(c->swallowing);
    164 +	c->swallowing = NULL;
    165 +
    166 +	/* unfullscreen the client */
    167 +	setfullscreen(c, 0);
    168 +	updatetitle(c);
    169 +	arrange(c->mon);
    170 +	XMapWindow(dpy, c->win);
    171 +	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    172 +	setclientstate(c, NormalState);
    173 +	focus(NULL);
    174 +	arrange(c->mon);
    175 +}
    176 +
    177  void
    178  buttonpress(XEvent *e)
    179  {
    180 @@ -653,6 +720,9 @@ destroynotify(XEvent *e)
    181  
    182  	if ((c = wintoclient(ev->window)))
    183  		unmanage(c, 1);
    184 +
    185 +	else if ((c = swallowingclient(ev->window)))
    186 +		unmanage(c->swallowing, 1);
    187  }
    188  
    189  void
    190 @@ -1018,12 +1088,13 @@ killclient(const Arg *arg)
    191  void
    192  manage(Window w, XWindowAttributes *wa)
    193  {
    194 -	Client *c, *t = NULL;
    195 +	Client *c, *t = NULL, *term = NULL;
    196  	Window trans = None;
    197  	XWindowChanges wc;
    198  
    199  	c = ecalloc(1, sizeof(Client));
    200  	c->win = w;
    201 +	c->pid = winpid(w);
    202  	/* geometry */
    203  	c->x = c->oldx = wa->x;
    204  	c->y = c->oldy = wa->y;
    205 @@ -1038,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
    206  	} else {
    207  		c->mon = selmon;
    208  		applyrules(c);
    209 +		term = termforwin(c);
    210  	}
    211  
    212  	if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
    213 @@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa)
    214  	c->mon->sel = c;
    215  	arrange(c->mon);
    216  	XMapWindow(dpy, c->win);
    217 +	if (term)
    218 +		swallow(term, c);
    219  	focus(NULL);
    220  }
    221  
    222 @@ -1768,6 +1842,20 @@ unmanage(Client *c, int destroyed)
    223  	Monitor *m = c->mon;
    224  	XWindowChanges wc;
    225  
    226 +	if (c->swallowing) {
    227 +		unswallow(c);
    228 +		return;
    229 +	}
    230 +
    231 +	Client *s = swallowingclient(c->win);
    232 +	if (s) {
    233 +		free(s->swallowing);
    234 +		s->swallowing = NULL;
    235 +		arrange(m);
    236 +		focus(NULL);
    237 +		return;
    238 +	}
    239 +
    240  	detach(c);
    241  	detachstack(c);
    242  	if (!destroyed) {
    243 @@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed)
    244  		XUngrabServer(dpy);
    245  	}
    246  	free(c);
    247 -	focus(NULL);
    248 -	updateclientlist();
    249 -	arrange(m);
    250 +
    251 +	if (!s) {
    252 +		arrange(m);
    253 +		focus(NULL);
    254 +		updateclientlist();
    255 +	}
    256  }
    257  
    258  void
    259 @@ -2047,6 +2138,136 @@ view(const Arg *arg)
    260  	arrange(selmon);
    261  }
    262  
    263 +pid_t
    264 +winpid(Window w)
    265 +{
    266 +
    267 +	pid_t result = 0;
    268 +
    269 +#ifdef __linux__
    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 +
    296 +#endif /* __linux__ */
    297 +
    298 +#ifdef __OpenBSD__
    299 +        Atom type;
    300 +        int format;
    301 +        unsigned long len, bytes;
    302 +        unsigned char *prop;
    303 +        pid_t ret;
    304 +
    305 +        if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
    306 +               return 0;
    307 +
    308 +        ret = *(pid_t*)prop;
    309 +        XFree(prop);
    310 +        result = ret;
    311 +
    312 +#endif /* __OpenBSD__ */
    313 +	return result;
    314 +}
    315 +
    316 +pid_t
    317 +getparentprocess(pid_t p)
    318 +{
    319 +	unsigned int v = 0;
    320 +
    321 +#ifdef __linux__
    322 +	FILE *f;
    323 +	char buf[256];
    324 +	snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
    325 +
    326 +	if (!(f = fopen(buf, "r")))
    327 +		return 0;
    328 +
    329 +	fscanf(f, "%*u %*s %*c %u", &v);
    330 +	fclose(f);
    331 +#endif /* __linux__*/
    332 +
    333 +#ifdef __OpenBSD__
    334 +	int n;
    335 +	kvm_t *kd;
    336 +	struct kinfo_proc *kp;
    337 +
    338 +	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
    339 +	if (!kd)
    340 +		return 0;
    341 +
    342 +	kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
    343 +	v = kp->p_ppid;
    344 +#endif /* __OpenBSD__ */
    345 +
    346 +	return (pid_t)v;
    347 +}
    348 +
    349 +int
    350 +isdescprocess(pid_t p, pid_t c)
    351 +{
    352 +	while (p != c && c != 0)
    353 +		c = getparentprocess(c);
    354 +
    355 +	return (int)c;
    356 +}
    357 +
    358 +Client *
    359 +termforwin(const Client *w)
    360 +{
    361 +	Client *c;
    362 +	Monitor *m;
    363 +
    364 +	if (!w->pid || w->isterminal)
    365 +		return NULL;
    366 +
    367 +	for (m = mons; m; m = m->next) {
    368 +		for (c = m->clients; c; c = c->next) {
    369 +			if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
    370 +				return c;
    371 +		}
    372 +	}
    373 +
    374 +	return NULL;
    375 +}
    376 +
    377 +Client *
    378 +swallowingclient(Window w)
    379 +{
    380 +	Client *c;
    381 +	Monitor *m;
    382 +
    383 +	for (m = mons; m; m = m->next) {
    384 +		for (c = m->clients; c; c = c->next) {
    385 +			if (c->swallowing && c->swallowing->win == w)
    386 +				return c;
    387 +		}
    388 +	}
    389 +
    390 +	return NULL;
    391 +}
    392 +
    393  Client *
    394  wintoclient(Window w)
    395  {
    396 @@ -2138,10 +2359,12 @@ main(int argc, char *argv[])
    397  		fputs("warning: no locale support\n", stderr);
    398  	if (!(dpy = XOpenDisplay(NULL)))
    399  		die("dwm: cannot open display");
    400 +	if (!(xcon = XGetXCBConnection(dpy)))
    401 +		die("dwm: cannot get xcb connection\n");
    402  	checkotherwm();
    403  	setup();
    404  #ifdef __OpenBSD__
    405 -	if (pledge("stdio rpath proc exec", NULL) == -1)
    406 +	if (pledge("stdio rpath proc exec ps", NULL) == -1)
    407  		die("pledge");
    408  #endif /* __OpenBSD__ */
    409  	scan();
    410 -- 
    411 2.28.0
    412