dwm-swallow-20200707-8d1e703.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-swallow-20200707-8d1e703.diff (8904B)
       ---
            1 From 8d1e7039c239619bee159e07e32b8d49837bf445 Mon Sep 17 00:00:00 2001
            2 From: jmanabc <jdwilkesx@gmail.com>
            3 Date: Tue, 7 Jul 2020 21:24:56 -0400
            4 Subject: [PATCH] Fixed swallowing by removing scanner variable from dwm.c and
            5  corrected capitalization in config.def.h
            6 
            7 ---
            8  config.def.h |   9 ++-
            9  config.mk    |   2 +-
           10  dwm.c        | 196 +++++++++++++++++++++++++++++++++++++++++++++++++--
           11  3 files changed, 198 insertions(+), 9 deletions(-)
           12 
           13 diff --git a/config.def.h b/config.def.h
           14 index 1c0b587..fe51476 100644
           15 --- a/config.def.h
           16 +++ b/config.def.h
           17 @@ -3,6 +3,7 @@
           18  /* appearance */
           19  static const unsigned int borderpx  = 1;        /* border pixel of windows */
           20  static const unsigned int snap      = 32;       /* snap pixel */
           21 +static const int swallowfloating    = 0;        /* 1 means swallow floating windows by default */
           22  static const int showbar            = 1;        /* 0 means no bar */
           23  static const int topbar             = 1;        /* 0 means bottom bar */
           24  static const char *fonts[]          = { "monospace:size=10" };
           25 @@ -26,9 +27,11 @@ static const Rule rules[] = {
           26           *        WM_CLASS(STRING) = instance, class
           27           *        WM_NAME(STRING) = title
           28           */
           29 -        /* class      instance    title       tags mask     isfloating   monitor */
           30 -        { "Gimp",     NULL,       NULL,       0,            1,           -1 },
           31 -        { "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
           32 +        /* class     instance  title           tags mask  isfloating  isterminal  noswallow  monitor */
           33 +        { "Gimp",    NULL,     NULL,           0,         1,          0,           0,        -1 },
           34 +        { "Firefox", NULL,     NULL,           1 << 8,    0,          0,          -1,        -1 },
           35 +        { "St",      NULL,     NULL,           0,         0,          1,           0,        -1 },
           36 +        { NULL,      NULL,     "Event Tester", 0,         0,          0,           1,        -1 }, /* xev */
           37  };
           38  
           39  /* layout(s) */
           40 diff --git a/config.mk b/config.mk
           41 index 7084c33..b77641d 100644
           42 --- a/config.mk
           43 +++ b/config.mk
           44 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
           45  
           46  # includes and libs
           47  INCS = -I${X11INC} -I${FREETYPEINC}
           48 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
           49 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res
           50  
           51  # flags
           52  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
           53 diff --git a/dwm.c b/dwm.c
           54 index 9fd0286..c58de28 100644
           55 --- a/dwm.c
           56 +++ b/dwm.c
           57 @@ -40,6 +40,8 @@
           58  #include <X11/extensions/Xinerama.h>
           59  #endif /* XINERAMA */
           60  #include <X11/Xft/Xft.h>
           61 +#include <X11/Xlib-xcb.h>
           62 +#include <xcb/res.h>
           63  
           64  #include "drw.h"
           65  #include "util.h"
           66 @@ -92,9 +94,11 @@ struct Client {
           67          int basew, baseh, incw, inch, maxw, maxh, minw, minh;
           68          int bw, oldbw;
           69          unsigned int tags;
           70 -        int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
           71 +        int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
           72 +        pid_t pid;
           73          Client *next;
           74          Client *snext;
           75 +        Client *swallowing;
           76          Monitor *mon;
           77          Window win;
           78  };
           79 @@ -138,6 +142,8 @@ typedef struct {
           80          const char *title;
           81          unsigned int tags;
           82          int isfloating;
           83 +        int isterminal;
           84 +        int noswallow;
           85          int monitor;
           86  } Rule;
           87  
           88 @@ -235,6 +241,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
           89  static int xerrorstart(Display *dpy, XErrorEvent *ee);
           90  static void zoom(const Arg *arg);
           91  
           92 +static pid_t getparentprocess(pid_t p);
           93 +static int isdescprocess(pid_t p, pid_t c);
           94 +static Client *swallowingclient(Window w);
           95 +static Client *termforwin(const Client *c);
           96 +static pid_t winpid(Window w);
           97 +
           98  /* variables */
           99  static const char broken[] = "broken";
          100  static char stext[256];
          101 @@ -269,6 +281,8 @@ static Drw *drw;
          102  static Monitor *mons, *selmon;
          103  static Window root, wmcheckwin;
          104  
          105 +static xcb_connection_t *xcon;
          106 +
          107  /* configuration, allows nested code to access above variables */
          108  #include "config.h"
          109  
          110 @@ -298,6 +312,8 @@ applyrules(Client *c)
          111                  && (!r->class || strstr(class, r->class))
          112                  && (!r->instance || strstr(instance, r->instance)))
          113                  {
          114 +                        c->isterminal = r->isterminal;
          115 +                        c->noswallow  = r->noswallow;
          116                          c->isfloating = r->isfloating;
          117                          c->tags |= r->tags;
          118                          for (m = mons; m && m->num != r->monitor; m = m->next);
          119 @@ -414,6 +430,53 @@ attachstack(Client *c)
          120          c->mon->stack = c;
          121  }
          122  
          123 +void
          124 +swallow(Client *p, Client *c)
          125 +{
          126 +
          127 +        if (c->noswallow || c->isterminal)
          128 +                return;
          129 +        if (c->noswallow && !swallowfloating && c->isfloating)
          130 +                return;
          131 +
          132 +        detach(c);
          133 +        detachstack(c);
          134 +
          135 +        setclientstate(c, WithdrawnState);
          136 +        XUnmapWindow(dpy, p->win);
          137 +
          138 +        p->swallowing = c;
          139 +        c->mon = p->mon;
          140 +
          141 +        Window w = p->win;
          142 +        p->win = c->win;
          143 +        c->win = w;
          144 +        updatetitle(p);
          145 +        XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
          146 +        arrange(p->mon);
          147 +        configure(p);
          148 +        updateclientlist();
          149 +}
          150 +
          151 +void
          152 +unswallow(Client *c)
          153 +{
          154 +        c->win = c->swallowing->win;
          155 +
          156 +        free(c->swallowing);
          157 +        c->swallowing = NULL;
          158 +
          159 +        /* unfullscreen the client */
          160 +        setfullscreen(c, 0);
          161 +        updatetitle(c);
          162 +        arrange(c->mon);
          163 +        XMapWindow(dpy, c->win);
          164 +        XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
          165 +        setclientstate(c, NormalState);
          166 +        focus(NULL);
          167 +        arrange(c->mon);
          168 +}
          169 +
          170  void
          171  buttonpress(XEvent *e)
          172  {
          173 @@ -653,6 +716,9 @@ destroynotify(XEvent *e)
          174  
          175          if ((c = wintoclient(ev->window)))
          176                  unmanage(c, 1);
          177 +
          178 +        else if ((c = swallowingclient(ev->window)))
          179 +                unmanage(c->swallowing, 1);
          180  }
          181  
          182  void
          183 @@ -1018,12 +1084,13 @@ killclient(const Arg *arg)
          184  void
          185  manage(Window w, XWindowAttributes *wa)
          186  {
          187 -        Client *c, *t = NULL;
          188 +        Client *c, *t = NULL, *term = NULL;
          189          Window trans = None;
          190          XWindowChanges wc;
          191  
          192          c = ecalloc(1, sizeof(Client));
          193          c->win = w;
          194 +        c->pid = winpid(w);
          195          /* geometry */
          196          c->x = c->oldx = wa->x;
          197          c->y = c->oldy = wa->y;
          198 @@ -1038,6 +1105,7 @@ manage(Window w, XWindowAttributes *wa)
          199          } else {
          200                  c->mon = selmon;
          201                  applyrules(c);
          202 +                term = termforwin(c);
          203          }
          204  
          205          if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
          206 @@ -1074,6 +1142,8 @@ manage(Window w, XWindowAttributes *wa)
          207          c->mon->sel = c;
          208          arrange(c->mon);
          209          XMapWindow(dpy, c->win);
          210 +        if (term)
          211 +                swallow(term, c);
          212          focus(NULL);
          213  }
          214  
          215 @@ -1768,6 +1838,20 @@ unmanage(Client *c, int destroyed)
          216          Monitor *m = c->mon;
          217          XWindowChanges wc;
          218  
          219 +        if (c->swallowing) {
          220 +                unswallow(c);
          221 +                return;
          222 +        }
          223 +
          224 +        Client *s = swallowingclient(c->win);
          225 +        if (s) {
          226 +                free(s->swallowing);
          227 +                s->swallowing = NULL;
          228 +                arrange(m);
          229 +                focus(NULL);
          230 +                return;
          231 +        }
          232 +
          233          detach(c);
          234          detachstack(c);
          235          if (!destroyed) {
          236 @@ -1782,9 +1866,12 @@ unmanage(Client *c, int destroyed)
          237                  XUngrabServer(dpy);
          238          }
          239          free(c);
          240 -        focus(NULL);
          241 -        updateclientlist();
          242 -        arrange(m);
          243 +
          244 +        if (!s) {
          245 +                arrange(m);
          246 +                focus(NULL);
          247 +                updateclientlist();
          248 +        }
          249  }
          250  
          251  void
          252 @@ -2047,6 +2134,103 @@ view(const Arg *arg)
          253          arrange(selmon);
          254  }
          255  
          256 +pid_t
          257 +winpid(Window w)
          258 +{
          259 +        pid_t result = 0;
          260 +
          261 +        xcb_res_client_id_spec_t spec = {0};
          262 +        spec.client = w;
          263 +        spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
          264 +
          265 +        xcb_generic_error_t *e = NULL;
          266 +        xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
          267 +        xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
          268 +
          269 +        if (!r)
          270 +                return (pid_t)0;
          271 +
          272 +        xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
          273 +        for (; i.rem; xcb_res_client_id_value_next(&i)) {
          274 +                spec = i.data->spec;
          275 +                if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
          276 +                        uint32_t *t = xcb_res_client_id_value_value(i.data);
          277 +                        result = *t;
          278 +                        break;
          279 +                }
          280 +        }
          281 +
          282 +        free(r);
          283 +
          284 +        if (result == (pid_t)-1)
          285 +                result = 0;
          286 +        return result;
          287 +}
          288 +
          289 +pid_t
          290 +getparentprocess(pid_t p)
          291 +{
          292 +        unsigned int v = 0;
          293 +
          294 +#ifdef __linux__
          295 +        FILE *f;
          296 +        char buf[256];
          297 +        snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
          298 +
          299 +        if (!(f = fopen(buf, "r")))
          300 +                return 0;
          301 +
          302 +        fscanf(f, "%*u %*s %*c %u", &v);
          303 +        fclose(f);
          304 +#endif /* __linux__*/
          305 +
          306 +        return (pid_t)v;
          307 +}
          308 +
          309 +int
          310 +isdescprocess(pid_t p, pid_t c)
          311 +{
          312 +        while (p != c && c != 0)
          313 +                c = getparentprocess(c);
          314 +
          315 +        return (int)c;
          316 +}
          317 +
          318 +Client *
          319 +termforwin(const Client *w)
          320 +{
          321 +        Client *c;
          322 +        Monitor *m;
          323 +
          324 +        if (!w->pid || w->isterminal)
          325 +                return NULL;
          326 +
          327 +        for (m = mons; m; m = m->next) {
          328 +                for (c = m->clients; c; c = c->next) {
          329 +                        if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
          330 +                                return c;
          331 +                }
          332 +        }
          333 +
          334 +        return NULL;
          335 +}
          336 +
          337 +Client *
          338 +swallowingclient(Window w)
          339 +{
          340 +        Client *c;
          341 +        Monitor *m;
          342 +
          343 +        for (m = mons; m; m = m->next) {
          344 +                for (c = m->clients; c; c = c->next) {
          345 +                        if (c->swallowing && c->swallowing->win == w)
          346 +                                return c;
          347 +                }
          348 +        }
          349 +
          350 +        return NULL;
          351 +}
          352 +
          353  Client *
          354  wintoclient(Window w)
          355  {
          356 @@ -2138,6 +2322,8 @@ main(int argc, char *argv[])
          357                  fputs("warning: no locale support\n", stderr);
          358          if (!(dpy = XOpenDisplay(NULL)))
          359                  die("dwm: cannot open display");
          360 +        if (!(xcon = XGetXCBConnection(dpy)))
          361 +                die("dwm: cannot get xcb connection\n");
          362          checkotherwm();
          363          setup();
          364  #ifdef __OpenBSD__
          365 -- 
          366 2.27.0
          367