dwm-swallow-6.2.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-swallow-6.2.diff (9943B)
       ---
            1 From 3904d7521ef64938b2a8b7fb06ef5a5223d3f62b Mon Sep 17 00:00:00 2001
            2 From: Jack Bird <jack.bird@durham.ac.uk>
            3 Date: Fri, 27 Aug 2021 00:04:45 +0100
            4 Subject: [PATCH] 6.2 swallow patch
            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 6d36cb7..5d136bc 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=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
           56 diff --git a/dwm.c b/dwm.c
           57 index 4465af1..66bd0ed 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 @@ -234,6 +244,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 @@ -268,6 +284,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 @@ -297,6 +315,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 @@ -413,6 +433,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 @@ -652,6 +719,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 @@ -1017,12 +1087,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 @@ -1037,6 +1108,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 @@ -1073,6 +1145,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 @@ -1765,6 +1839,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 @@ -1779,9 +1867,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 @@ -2044,6 +2135,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 @@ -2135,10 +2356,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.33.0
          412