#include #include static xcb_connection_t *xcon; void swallow(Client *p, Client *c) { if (c->noswallow || c->isterminal) return; 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; updatetitle(p); arrange(p->mon); XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); configure(p); updateclientlist(); } void unswallow(Client *c) { c->win = c->swallowing->win; free(c->swallowing); c->swallowing = NULL; updatetitle(c); arrange(c->mon); XMapWindow(dpy, c->win); XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); configure(c); setclientstate(c, NormalState); } pid_t winpid(Window w) { pid_t result = 0; 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; 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 0; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-result" fscanf(f, "%*u %*s %*c %u", &v); #pragma GCC diagnostic pop fclose(f); #endif /* __linux__ */ 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; }