From 4e0318919dd726f485ea3a495ff0989f69f35630 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 6 Jun 2020 19:56:41 -0700 Subject: hand added swallow patch --- sys/cmd/dwm/client.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++- sys/cmd/dwm/config.h | 10 ++--- sys/cmd/dwm/dwm.c | 75 +++++++++++++++++++++++++++++++++++- sys/cmd/dwm/dwm.h | 39 ++++++++++++------- sys/cmd/dwm/rules.mk | 2 +- sys/cmd/dwm/util.c | 41 ++++++++++++++++++-- 6 files changed, 246 insertions(+), 27 deletions(-) (limited to 'sys/cmd') diff --git a/sys/cmd/dwm/client.c b/sys/cmd/dwm/client.c index d2ea972..1401677 100644 --- a/sys/cmd/dwm/client.c +++ b/sys/cmd/dwm/client.c @@ -11,7 +11,8 @@ applyrules(Client *c) /* rule matching */ c->isfloating = 0; - c->tags = 0; + c->tags = 0; + c->noswallow = -1; XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; @@ -22,8 +23,10 @@ applyrules(Client *c) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { + c->isterm = r->isterm; + c->noswallow = r->noswallow; c->isfloating = r->isfloating; - c->tags |= r->tags; + c->tags |= r->tags; for (m = mons; m && m->num != r->monitor; m = m->next) ; if (m) @@ -414,6 +417,60 @@ showhide(Client *c) } } +void +swallow(Client *p, Client *c) +{ + Client *s; + + + if (c->noswallow > 0 || c->isterm) + return; + if (c->noswallow < 0 && !swallowfloating && c->isfloating) + 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; + + XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(p->win), 1); + + updatetitle(p); + s = scanner ? c : p; + XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); + arrange(p->mon); + configure(p); + updateclientlist(); +} + +Client * +termof(Client *w) +{ + Client *c; + Monitor *m; + + if (!w->pid || w->isterm) + return NULL; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->isterm && !c->swallowing && c->pid && isdescendent(c->pid, w->pid)) + return c; + } + } + + return NULL; +} + void unfocus(Client *c, int setfocus) { @@ -430,11 +487,28 @@ unfocus(Client *c, int setfocus) void unmanage(Client *c, int destroyed) { + Client *s; Monitor *m = c->mon; XWindowChanges wc; + if (c->swallowing) { + unswallow(c); + return; + } + + s = swallowing(c->win); + if (s) { + free(s->swallowing); + s->swallowing = nil; + arrange(m); + focus(nil); + return; + } + + detach(c); detachstack(c); + if (!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); /* avoid race conditions */ @@ -450,8 +524,36 @@ unmanage(Client *c, int destroyed) focus(nil); updateclientlist(); arrange(m); + + if (!s) { + // arrange(m); + focus(nil); + updateclientlist(); + } +} + +void +unswallow(Client *c) +{ + c->win = c->swallowing->win; + + free(c->swallowing); + c->swallowing = nil; + + XDeleteProperty(dpy, c->win, netatom[NetClientList]); + + /* unfullscreen the client */ + setfullscreen(c, 0); + updatetitle(c); + arrange(c->mon); + XMapWindow(dpy, c->win); + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + setclientstate(c, NormalState); + focus(nil); + arrange(c->mon); } + void updatesizehints(Client *c) { diff --git a/sys/cmd/dwm/config.h b/sys/cmd/dwm/config.h index 3e950ba..47ee371 100644 --- a/sys/cmd/dwm/config.h +++ b/sys/cmd/dwm/config.h @@ -5,7 +5,7 @@ static uint borderpx = 1; /* border pixel of windows */ static uint gapx = 4; /* gaps between windows */ static uint snap = 32; /* snap pixel */ -static int swallowfloating = 1; /* will swallow floating by default */ +static int swallowfloating = 0; /* 1 will swallow floating by default */ static int showbar = 1; /* 0 means no bar */ static int topbar = 1; /* 0 means bottom bar */ static char *fonts[] = { "consolas:size=14" }; @@ -30,10 +30,10 @@ static Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask isfloating isterminal noswallow monitor */ - { "Gimp", nil, nil, 0, 1, 0, 0, -1 }, - { "Firefox", nil, nil, 1 << 8, 0, 0, 01, -1 }, - { "term", nil, nil, 0, 0, 0, 1, -1 }, + /* class instance title tags mask isfloating isterminal noswallow monitor */ + { "Gimp", nil, nil, 0, 1, 0, 0, -1 }, + { "qutebrowser", nil, nil, 1 << 8, 0, 0, -1, -1 }, + { "term", nil, nil, 0, 0, 0, -1, -1 }, }; /* layout(s) */ diff --git a/sys/cmd/dwm/dwm.c b/sys/cmd/dwm/dwm.c index 22ccc91..8e8d44c 100644 --- a/sys/cmd/dwm/dwm.c +++ b/sys/cmd/dwm/dwm.c @@ -3,6 +3,7 @@ /* global variables */ char broken[] = ""; char stext[256]; +int scanner; int screen; int sw, sh; /* X display screen geometry width, height */ int bh, blw = 0; /* bar geometry */ @@ -26,6 +27,8 @@ void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; +xcb_connection_t *xcon; + Atom wmatom[WMLast] = {0}, netatom[NetLast] = {0}; int running = 1; Cur *cursor[MouseLast] = {0}; @@ -282,6 +285,8 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); + else if ((c = swallowing(ev->window))) + unmanage(c->swallowing, 1); } Monitor * @@ -498,12 +503,13 @@ keypress(XEvent *e) void manage(Window w, XWindowAttributes *wa) { - Client *c, *t = nil; + Client *c, *t = nil, *term = nil; Window trans = None; XWindowChanges wc; c = ecalloc(1, sizeof(Client)); c->win = w; + c->pid = winpid(w); /* geometry */ c->x = c->oldx = wa->x; c->y = c->oldy = wa->y; @@ -518,6 +524,7 @@ manage(Window w, XWindowAttributes *wa) } else { c->mon = selmon; applyrules(c); + term = termof(c); } if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) @@ -539,12 +546,15 @@ manage(Window w, XWindowAttributes *wa) updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); + if (!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); + attach(c); attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ @@ -554,6 +564,8 @@ manage(Window w, XWindowAttributes *wa) c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); + if (term) + swallow(term, c); focus(nil); } @@ -706,6 +718,9 @@ scan(void) uint i, num; Window d1, d2, *wins = nil; XWindowAttributes wa; + char swin[256]; + + scanner = 1; if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { for (i = 0; i < num; i++) { @@ -714,6 +729,8 @@ scan(void) continue; if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); + else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) + manage(wins[i], &wa); } for (i = 0; i < num; i++) { /* now the transients */ if (!XGetWindowAttributes(dpy, wins[i], &wa)) @@ -725,6 +742,8 @@ scan(void) if (wins) XFree(wins); } + + scanner = 0; } void @@ -806,6 +825,22 @@ sigchld(int unused) while (0 < waitpid(-1, nil, WNOHANG)); } +Client * +swallowing(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 nil; +} + void tile(Monitor *m) { @@ -830,7 +865,7 @@ tile(Monitor *m) h = (m->wh - ty) / (n - i) - m->gapx; resize(c, m->wx + mw + m->gapx, m->wy + ty, m->ww - mw - (2*c->bw) - (2*m->gapx), h - (2*c->bw), 0); if (ty + HEIGHT(c) < m->wh) - ty += HEIGHT(c) + m->gapx; + ty += HEIGHT(c); } } @@ -997,6 +1032,40 @@ updatestatus(void) drawbar(selmon); } +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; +} + Client * wintoclient(Window w) { @@ -1074,6 +1143,8 @@ main(int argc, char *argv[]) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(nil))) fatal("dwm: cannot open display"); + if (!(xcon = XGetXCBConnection(dpy))) + fatal("dwm: cannot get xcb connection"); checkotherwm(); setup(); diff --git a/sys/cmd/dwm/dwm.h b/sys/cmd/dwm/dwm.h index d8bfbb3..070717e 100644 --- a/sys/cmd/dwm/dwm.h +++ b/sys/cmd/dwm/dwm.h @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -125,9 +127,11 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; uint tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterm, noswallow; + pid_t pid; Client *next; Client *snext; + Client *swallowing; Monitor *mon; Window win; }; @@ -172,15 +176,14 @@ struct Rule { char *title; uint tags; int isfloating; + int isterm; + int noswallow; int monitor; }; /* draw.c */ typedef struct { - union { - Cursor; - Cursor cursor; - }; + Cursor cursor; } Cur; typedef struct Fnt { @@ -191,7 +194,7 @@ typedef struct Fnt { struct Fnt *next; } Fnt; -typedef XftColor Color; +typedef XftColor Clr; typedef struct { uint w, h; @@ -200,14 +203,15 @@ typedef struct { Window root; Drawable drawable; GC gc; - Color *scheme; - Font *fonts; + Clr *scheme; + Fnt *fonts; } Drw; /* global state */ extern char broken[]; extern char stext[256]; +extern int scanner; extern int screen; extern int sw, sh; extern int bh, blw; @@ -216,10 +220,12 @@ extern int (*xerrorxlib)(Display *, XErrorEvent *); extern uint numlockmask; extern void (*handler[LASTEvent]) (XEvent *); +extern xcb_connection_t *xcon; + extern Atom wmatom[WMLast], netatom[NetLast]; extern int running; -extern Cur *cursor[MouseLast]; -extern Color **scheme; +extern Cur *cursor[MouseLast]; +extern Clr **scheme; extern Display *dpy; extern Drw *drw; extern Monitor *mons, *selmon; @@ -296,9 +302,12 @@ void setup(void); void seturgent(Client *c, int urg); void showhide(Client *c); void sigchld(int unused); +void swallow(Client *p, Client *c); +Client *swallowing(Window w); void spawn(Arg *arg); void tag(Arg *arg); void tagmon(Arg *arg); +Client *termof(Client *c); void tile(Monitor *); void togglebar(Arg *arg); void togglefocus(Arg *arg); @@ -308,6 +317,7 @@ void toggleview(Arg *arg); void unfocus(Client *c, int setfocus); void unmanage(Client *c, int destroyed); void unmapnotify(XEvent *e); +void unswallow(Client *c); void updatebarpos(Monitor *m); void updatebars(void); void updateclientlist(void); @@ -319,6 +329,7 @@ void updatetitle(Client *c); void updatewindowtype(Client *c); void updatewmhints(Client *c); void view(Arg *arg); +pid_t winpid(Window w); Client *wintoclient(Window w); Monitor *wintomon(Window w); int xerror(Display *dpy, XErrorEvent *ee); @@ -342,8 +353,8 @@ uint drw_fontset_getwidth(Drw *drw, char *text); void drw_font_getexts(Fnt *font, char *text, uint len, uint *w, uint *h); /* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Color *dest, char *clrname); -Color *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); +void drw_clr_create(Drw *drw, Clr *dest, char *clrname); +Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); @@ -351,7 +362,7 @@ void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Color *scm); +void drw_setscheme(Drw *drw, Clr *scm); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, uint w, uint h, int filled, int invert); @@ -363,3 +374,5 @@ void drw_map(Drw *drw, Window win, int x, int y, uint w, uint h); /* util.c */ void fatal(char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); +pid_t getparentproc(pid_t p); +pid_t isdescendent(pid_t p, pid_t c); diff --git a/sys/cmd/dwm/rules.mk b/sys/cmd/dwm/rules.mk index bc4d574..680d741 100644 --- a/sys/cmd/dwm/rules.mk +++ b/sys/cmd/dwm/rules.mk @@ -20,7 +20,7 @@ $(BINS_$(d)): TCFLAGS = \ $(BINS_$(d)): TCLIBS = \ `$(PKG) --libs fontconfig` \ `$(PKG) --libs freetype2` \ - -lX11 -lXinerama -lXft \ + -lX11 -lXinerama -lXft -lX11-xcb -lxcb -lxcb-res \ $(OBJ_DIR)/libn/libn.a $(BINS_$(d)): $(OBJS_$(d)) $(COMPLINK) diff --git a/sys/cmd/dwm/util.c b/sys/cmd/dwm/util.c index 1306c9c..445d479 100644 --- a/sys/cmd/dwm/util.c +++ b/sys/cmd/dwm/util.c @@ -1,8 +1,5 @@ /* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include +#include "dwm.h" void fatal(char *fmt, ...) { @@ -31,3 +28,39 @@ ecalloc(size_t nmemb, size_t size) fatal("calloc:"); return p; } + +pid_t +getparentprocess(pid_t p) +{ + uint v = 0; + +#if defined(__linux__) + Stream *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); +#elif defined(__FreeBSD__) + struct kinfo_proc *proc = kinfo_getproc(p); + if (!proc) + return (pid_t)0; + + v = proc->ki_ppid; + free(proc); +#endif + return (pid_t)v; +} + +int +isdescendent(pid_t p, pid_t c) +{ + while (p != c && c != 0) + c = getparentprocess(c); + + return (int)c; +} -- cgit v1.2.1