#include #include #ifdef __OpenBSD__ #include #include #endif /* __OpenBSD__ */ static int scanner; static xcb_connection_t *xcon; int swallow(Client *p, Client *c) { Client *s; XWindowChanges wc; if (c->noswallow > 0 || c->isterminal) return 0; if (c->noswallow < 0 && !swallowfloating && c->isfloating) return 0; XMapWindow(dpy, c->win); detach(c); detachstack(c); setclientstate(c, WithdrawnState); XUnmapWindow(dpy, p->win); p->swallowing = c; c->mon = p->mon; Window w = p->win; p->win = c->win; c->win = w; XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, (unsigned char *) &(p->win), 1); updatetitle(p); s = scanner ? c : p; setfloatinghint(s); wc.border_width = p->bw; XConfigureWindow(dpy, p->win, CWBorderWidth, &wc); XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel); arrange(p->mon); configure(p); updateclientlist(); return 1; } void unswallow(Client *c) { XWindowChanges wc; c->win = c->swallowing->win; free(c->swallowing); c->swallowing = NULL; XDeleteProperty(dpy, c->win, netatom[NetClientList]); /* unfullscreen the client */ setfullscreen(c, 0); updatetitle(c); arrange(c->mon); XMapWindow(dpy, c->win); wc.border_width = c->bw; XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); setfloatinghint(c); setclientstate(c, NormalState); focus(NULL); arrange(c->mon); } pid_t winpid(Window w) { pid_t result = 0; #ifdef __linux__ xcb_res_client_id_spec_t spec = {0}; spec.client = w; spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; xcb_generic_error_t *e = NULL; xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); if (!r) return (pid_t)0; xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); for (; i.rem; xcb_res_client_id_value_next(&i)) { spec = i.data->spec; if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { uint32_t *t = xcb_res_client_id_value_value(i.data); result = *t; break; } } free(r); if (result == (pid_t)-1) result = 0; #endif /* __linux__ */ #ifdef __OpenBSD__ Atom type; int format; unsigned long len, bytes; unsigned char *prop; pid_t ret; if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) return 0; ret = *(pid_t*)prop; XFree(prop); result = ret; #endif /* __OpenBSD__ */ return result; } pid_t getparentprocess(pid_t p) { unsigned int v = 0; #ifdef __linux__ FILE *f; char buf[256]; snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); if (!(f = fopen(buf, "r"))) return (pid_t)0; if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) v = (pid_t)0; fclose(f); #endif /* __linux__ */ #ifdef __OpenBSD__ int n; kvm_t *kd; struct kinfo_proc *kp; kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); if (!kd) return 0; kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); v = kp->p_ppid; #endif /* __OpenBSD__ */ return (pid_t)v; } int isdescprocess(pid_t p, pid_t c) { while (p != c && c != 0) c = getparentprocess(c); return (int)c; } Client * termforwin(const Client *w) { Client *c; Monitor *m; if (!w->pid || w->isterminal) return NULL; c = selmon->sel; if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) return c; for (m = mons; m; m = m->next) { for (c = m->clients; c; c = c->next) { if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) return c; } } return NULL; } Client * swallowingclient(Window w) { Client *c; Monitor *m; for (m = mons; m; m = m->next) { for (c = m->clients; c; c = c->next) { if (c->swallowing && c->swallowing->win == w) return c; } } return NULL; }