dwm

Kris's build of dwm
git clone git clone https://git.krisyotam.com/krisyotam/dwm.git
Log | Files | Refs | README | LICENSE

swallow.c (5215B)


      1 #include <X11/Xlib-xcb.h>
      2 #include <xcb/res.h>
      3 #ifdef __OpenBSD__
      4 #include <sys/sysctl.h>
      5 #include <kvm.h>
      6 #endif /* __OpenBSD__ */
      7 
      8 static int scanner;
      9 static xcb_connection_t *xcon;
     10 
     11 int
     12 swallow(Client *p, Client *c)
     13 {
     14 	Client *s;
     15 	XWindowChanges wc;
     16 	#if NOBORDER_PATCH
     17 	int border_padding = 0;
     18 	#endif // NOBORDER_PATCH
     19 
     20 	if (c->noswallow > 0 || c->isterminal)
     21 		return 0;
     22 	if (c->noswallow < 0 && !swallowfloating && c->isfloating)
     23 		return 0;
     24 
     25 	XMapWindow(dpy, c->win);
     26 
     27 	detach(c);
     28 	detachstack(c);
     29 
     30 	setclientstate(c, WithdrawnState);
     31 	XUnmapWindow(dpy, p->win);
     32 
     33 	p->swallowing = c;
     34 	c->mon = p->mon;
     35 
     36 	Window w = p->win;
     37 	p->win = c->win;
     38 	c->win = w;
     39 
     40 	XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace,
     41 		(unsigned char *) &(p->win), 1);
     42 
     43 	#if BAR_WINICON_PATCH
     44 	updateicon(p);
     45 	#endif
     46 	updatetitle(p);
     47 	s = scanner ? c : p;
     48 	#if BAR_EWMHTAGS_PATCH
     49 	setfloatinghint(s);
     50 	#endif // BAR_EWMHTAGS_PATCH
     51 
     52 	#if NOBORDER_PATCH
     53 	wc.border_width = p->bw;
     54 	if (noborder(p)) {
     55 		wc.border_width = 0;
     56 		border_padding = p->bw * 2;
     57 	}
     58 
     59 	XConfigureWindow(dpy, p->win, CWBorderWidth, &wc);
     60 	XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w + border_padding, s->h + border_padding);
     61 	#else
     62 	wc.border_width = p->bw;
     63 	XConfigureWindow(dpy, p->win, CWBorderWidth, &wc);
     64 	XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h);
     65 	#endif // NOBORDER_PATCH
     66 
     67 	#if !BAR_FLEXWINTITLE_PATCH
     68 	XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel);
     69 	#endif // BAR_FLEXWINTITLE_PATCH
     70 
     71 	arrange(p->mon);
     72 	configure(p);
     73 	updateclientlist();
     74 
     75 	return 1;
     76 }
     77 
     78 void
     79 unswallow(Client *c)
     80 {
     81 	XWindowChanges wc;
     82 	c->win = c->swallowing->win;
     83 	#if NOBORDER_PATCH
     84 	int border_padding = 0;
     85 	#endif // NOBORDER_PATCH
     86 
     87 	free(c->swallowing);
     88 	c->swallowing = NULL;
     89 
     90 	XDeleteProperty(dpy, c->win, netatom[NetClientList]);
     91 
     92 	/* unfullscreen the client */
     93 	setfullscreen(c, 0);
     94 	#if BAR_WINICON_PATCH
     95 	updateicon(c);
     96 	#endif
     97 	updatetitle(c);
     98 	arrange(c->mon);
     99 	XMapWindow(dpy, c->win);
    100 
    101 	#if NOBORDER_PATCH
    102 	wc.border_width = c->bw;
    103 	if (noborder(c)) {
    104 		wc.border_width = 0;
    105 		border_padding = c->bw * 2;
    106 	}
    107 
    108 	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
    109 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w + border_padding, c->h + border_padding);
    110 	#else
    111 	wc.border_width = c->bw;
    112 	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
    113 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
    114 	#endif // NOBORDER_PATCH
    115 	#if !BAR_FLEXWINTITLE_PATCH
    116 	XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
    117 	#endif // BAR_FLEXWINTITLE_PATCH
    118 
    119 	#if BAR_EWMHTAGS_PATCH
    120 	setfloatinghint(c);
    121 	#endif // BAR_EWMHTAGS_PATCH
    122 	setclientstate(c, NormalState);
    123 	arrange(c->mon);
    124 	focus(NULL);
    125 }
    126 
    127 pid_t
    128 winpid(Window w)
    129 {
    130 	pid_t result = 0;
    131 
    132 	#ifdef __linux__
    133 	xcb_res_client_id_spec_t spec = {0};
    134 	spec.client = w;
    135 	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
    136 
    137 	xcb_generic_error_t *e = NULL;
    138 	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
    139 	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
    140 
    141 	if (!r)
    142 		return (pid_t)0;
    143 
    144 	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
    145 	for (; i.rem; xcb_res_client_id_value_next(&i)) {
    146 		spec = i.data->spec;
    147 		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
    148 			uint32_t *t = xcb_res_client_id_value_value(i.data);
    149 			result = *t;
    150 			break;
    151 		}
    152 	}
    153 
    154 	free(r);
    155 
    156 	if (result == (pid_t)-1)
    157 		result = 0;
    158 
    159 	#endif /* __linux__ */
    160 	#ifdef __OpenBSD__
    161 	Atom type;
    162 	int format;
    163 	unsigned long len, bytes;
    164 	unsigned char *prop;
    165 	pid_t ret;
    166 
    167 	if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
    168 		return 0;
    169 
    170 	ret = *(pid_t*)prop;
    171 	XFree(prop);
    172 	result = ret;
    173 	#endif /* __OpenBSD__ */
    174 
    175 	return result;
    176 }
    177 
    178 pid_t
    179 getparentprocess(pid_t p)
    180 {
    181 	unsigned int v = 0;
    182 
    183 #ifdef __linux__
    184 	FILE *f;
    185 	char buf[256];
    186 	snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
    187 
    188 	if (!(f = fopen(buf, "r")))
    189 		return (pid_t)0;
    190 
    191 	if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1)
    192 		v = (pid_t)0;
    193 	fclose(f);
    194 #endif /* __linux__ */
    195 #ifdef __OpenBSD__
    196 	int n;
    197 	kvm_t *kd;
    198 	struct kinfo_proc *kp;
    199 
    200 	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
    201 	if (!kd)
    202 		return 0;
    203 
    204 	kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
    205 	v = kp->p_ppid;
    206 #endif /* __OpenBSD__ */
    207 	return (pid_t)v;
    208 }
    209 
    210 int
    211 isdescprocess(pid_t p, pid_t c)
    212 {
    213 	while (p != c && c != 0)
    214 		c = getparentprocess(c);
    215 
    216 	return (int)c;
    217 }
    218 
    219 Client *
    220 termforwin(const Client *w)
    221 {
    222 	Client *c;
    223 	Monitor *m;
    224 
    225 	if (!w->pid || w->isterminal)
    226 		return NULL;
    227 
    228 	c = selmon->sel;
    229 	if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
    230 		return c;
    231 
    232 	for (m = mons; m; m = m->next) {
    233 		for (c = m->clients; c; c = c->next) {
    234 			if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
    235 				return c;
    236 		}
    237 	}
    238 
    239 	return NULL;
    240 }
    241 
    242 Client *
    243 swallowingclient(Window w)
    244 {
    245 	Client *c;
    246 	Monitor *m;
    247 
    248 	for (m = mons; m; m = m->next) {
    249 		for (c = m->clients; c; c = c->next) {
    250 			if (c->swallowing && c->swallowing->win == w)
    251 				return c;
    252 		}
    253 	}
    254 
    255 	return NULL;
    256 }
    257