dwm-swallow-20160717-56a31dc.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-swallow-20160717-56a31dc.diff (9208B)
       ---
            1 diff --git a/config.def.h b/config.def.h
            2 index fd77a07..69976b3 100644
            3 --- a/config.def.h
            4 +++ b/config.def.h
            5 @@ -26,9 +26,10 @@ static const Rule rules[] = {
            6           *        WM_CLASS(STRING) = instance, class
            7           *        WM_NAME(STRING) = title
            8           */
            9 -        /* class      instance    title       tags mask     isfloating   monitor */
           10 -        { "Gimp",     NULL,       NULL,       0,            1,           -1 },
           11 -        { "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
           12 +        /* class      instance    title       tags mask     isfloating   isterminal noswallow monitor */
           13 +        { "Gimp",     NULL,       NULL,       0,            1,           0,         0,        -1 },
           14 +        { "Firefox",  NULL,       NULL,       1 << 8,       0,           0,         0,        -1 },
           15 +        { "st",       NULL,       NULL,       0,            0,           1,         1,        -1 },
           16  };
           17  
           18  /* layout(s) */
           19 diff --git a/config.mk b/config.mk
           20 index 80dc936..5ed14e3 100644
           21 --- a/config.mk
           22 +++ b/config.mk
           23 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
           24  
           25  # includes and libs
           26  INCS = -I${X11INC} -I${FREETYPEINC}
           27 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
           28 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res
           29  
           30  # flags
           31  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
           32 diff --git a/dwm.c b/dwm.c
           33 index b2bc9bd..528df2f 100644
           34 --- a/dwm.c
           35 +++ b/dwm.c
           36 @@ -40,6 +40,8 @@
           37  #include <X11/extensions/Xinerama.h>
           38  #endif /* XINERAMA */
           39  #include <X11/Xft/Xft.h>
           40 +#include <X11/Xlib-xcb.h>
           41 +#include <xcb/res.h>
           42  
           43  #include "drw.h"
           44  #include "util.h"
           45 @@ -93,9 +95,11 @@ struct Client {
           46          int basew, baseh, incw, inch, maxw, maxh, minw, minh;
           47          int bw, oldbw;
           48          unsigned int tags;
           49 -        int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
           50 +        int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
           51 +        pid_t pid;
           52          Client *next;
           53          Client *snext;
           54 +        Client *swallowing;
           55          Monitor *mon;
           56          Window win;
           57  };
           58 @@ -139,6 +143,8 @@ typedef struct {
           59          const char *title;
           60          unsigned int tags;
           61          int isfloating;
           62 +        int isterminal;
           63 +        int noswallow;
           64          int monitor;
           65  } Rule;
           66  
           67 @@ -171,12 +177,14 @@ static void focus(Client *c);
           68  static void focusin(XEvent *e);
           69  static void focusmon(const Arg *arg);
           70  static void focusstack(const Arg *arg);
           71 +static pid_t getparentprocess(pid_t p);
           72  static int getrootptr(int *x, int *y);
           73  static long getstate(Window w);
           74  static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
           75  static void grabbuttons(Client *c, int focused);
           76  static void grabkeys(void);
           77  static void incnmaster(const Arg *arg);
           78 +static int isdescprocess(pid_t p, pid_t c);
           79  static void keypress(XEvent *e);
           80  static void killclient(const Arg *arg);
           81  static void manage(Window w, XWindowAttributes *wa);
           82 @@ -207,8 +215,10 @@ static void setup(void);
           83  static void showhide(Client *c);
           84  static void sigchld(int unused);
           85  static void spawn(const Arg *arg);
           86 +static Client *swallowingclient(Window w);
           87  static void tag(const Arg *arg);
           88  static void tagmon(const Arg *arg);
           89 +static Client *termforwin(const Client *c);
           90  static void tile(Monitor *);
           91  static void togglebar(const Arg *arg);
           92  static void togglefloating(const Arg *arg);
           93 @@ -228,6 +238,7 @@ static void updatewindowtype(Client *c);
           94  static void updatetitle(Client *c);
           95  static void updatewmhints(Client *c);
           96  static void view(const Arg *arg);
           97 +static pid_t winpid(Window w);
           98  static Client *wintoclient(Window w);
           99  static Monitor *wintomon(Window w);
          100  static int xerror(Display *dpy, XErrorEvent *ee);
          101 @@ -269,6 +280,8 @@ static Drw *drw;
          102  static Monitor *mons, *selmon;
          103  static Window root;
          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 +311,7 @@ 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->isfloating = r->isfloating;
          116                          c->tags |= r->tags;
          117                          for (m = mons; m && m->num != r->monitor; m = m->next);
          118 @@ -415,6 +429,47 @@ attachstack(Client *c)
          119  }
          120  
          121  void
          122 +swallow(Client *p, Client *c)
          123 +{
          124 +        if (c->noswallow || c->isterminal)
          125 +                return;
          126 +
          127 +        detach(c);
          128 +        detachstack(c);
          129 +
          130 +        setclientstate(c, WithdrawnState);
          131 +        XUnmapWindow(dpy, p->win);
          132 +
          133 +        p->swallowing = c;
          134 +        c->mon = p->mon;
          135 +
          136 +        Window w = p->win;
          137 +        p->win = c->win;
          138 +        c->win = w;
          139 +        updatetitle(p);
          140 +        arrange(p->mon);
          141 +        XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
          142 +        configure(p);
          143 +        updateclientlist();
          144 +}
          145 +
          146 +void
          147 +unswallow(Client *c)
          148 +{
          149 +        c->win = c->swallowing->win;
          150 +
          151 +        free(c->swallowing);
          152 +        c->swallowing = NULL;
          153 +
          154 +        updatetitle(c);
          155 +        arrange(c->mon);
          156 +        XMapWindow(dpy, c->win);
          157 +        XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
          158 +        configure(c);
          159 +        setclientstate(c, NormalState);
          160 +}
          161 +
          162 +void
          163  buttonpress(XEvent *e)
          164  {
          165          unsigned int i, x, click;
          166 @@ -477,7 +531,7 @@ cleanup(void)
          167          selmon->lt[selmon->sellt] = &foo;
          168          for (m = mons; m; m = m->next)
          169                  while (m->stack)
          170 -                        unmanage(m->stack, 0);
          171 +                        unmanage(m->stack, 0); // XXX - unmanage swallowing windows too
          172          XUngrabKey(dpy, AnyKey, AnyModifier, root);
          173          while (mons)
          174                  cleanupmon(mons);
          175 @@ -665,6 +719,9 @@ destroynotify(XEvent *e)
          176  
          177          if ((c = wintoclient(ev->window)))
          178                  unmanage(c, 1);
          179 +
          180 +        else if ((c = swallowingclient(ev->window)))
          181 +                unmanage(c->swallowing, 1);
          182  }
          183  
          184  void
          185 @@ -1034,12 +1091,13 @@ killclient(const Arg *arg)
          186  void
          187  manage(Window w, XWindowAttributes *wa)
          188  {
          189 -        Client *c, *t = NULL;
          190 +        Client *c, *t = NULL, *term = NULL;
          191          Window trans = None;
          192          XWindowChanges wc;
          193  
          194          c = ecalloc(1, sizeof(Client));
          195          c->win = w;
          196 +        c->pid = winpid(w);
          197          /* geometry */
          198          c->x = c->oldx = wa->x;
          199          c->y = c->oldy = wa->y;
          200 @@ -1054,6 +1112,7 @@ manage(Window w, XWindowAttributes *wa)
          201          } else {
          202                  c->mon = selmon;
          203                  applyrules(c);
          204 +                term = termforwin(c);
          205          }
          206  
          207          if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
          208 @@ -1090,6 +1149,8 @@ manage(Window w, XWindowAttributes *wa)
          209          c->mon->sel = c;
          210          arrange(c->mon);
          211          XMapWindow(dpy, c->win);
          212 +        if (term)
          213 +                swallow(term, c);
          214          focus(NULL);
          215  }
          216  
          217 @@ -1757,6 +1818,20 @@ unmanage(Client *c, int destroyed)
          218          Monitor *m = c->mon;
          219          XWindowChanges wc;
          220  
          221 +        if (c->swallowing) {
          222 +                unswallow(c);
          223 +                return;
          224 +        }
          225 +
          226 +        Client *s = swallowingclient(c->win);
          227 +        if (s) {
          228 +                free(s->swallowing);
          229 +                s->swallowing = NULL;
          230 +                arrange(m);
          231 +        focus(NULL);
          232 +                return;
          233 +        }
          234 +
          235          /* The server grab construct avoids race conditions. */
          236          detach(c);
          237          detachstack(c);
          238 @@ -1772,9 +1847,12 @@ unmanage(Client *c, int destroyed)
          239                  XUngrabServer(dpy);
          240          }
          241          free(c);
          242 -        focus(NULL);
          243 -        updateclientlist();
          244 -        arrange(m);
          245 +
          246 +        if (!s) {
          247 +                arrange(m);
          248 +                focus(NULL);
          249 +                updateclientlist();
          250 +        }
          251  }
          252  
          253  void
          254 @@ -2039,16 +2117,116 @@ view(const Arg *arg)
          255          arrange(selmon);
          256  }
          257  
          258 +pid_t
          259 +winpid(Window w)
          260 +{
          261 +        pid_t result = 0;
          262 +
          263 +        xcb_res_client_id_spec_t spec = {0};
          264 +        spec.client = w;
          265 +        spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
          266 +
          267 +        xcb_generic_error_t *e = NULL;
          268 +        xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
          269 +        xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
          270 +
          271 +        if (!r)
          272 +                return (pid_t)0;
          273 +
          274 +        xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
          275 +        for (; i.rem; xcb_res_client_id_value_next(&i)) {
          276 +                spec = i.data->spec;
          277 +                if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
          278 +                        uint32_t *t = xcb_res_client_id_value_value(i.data);
          279 +                        result = *t;
          280 +                        break;
          281 +                }
          282 +        }
          283 +
          284 +        free(r);
          285 +
          286 +        if (result == (pid_t)-1)
          287 +                result = 0;
          288 +        return result;
          289 +}
          290 +
          291 +pid_t
          292 +getparentprocess(pid_t p)
          293 +{
          294 +        unsigned int v = 0;
          295 +
          296 +#ifdef __linux__
          297 +        FILE *f;
          298 +        char buf[256];
          299 +        snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
          300 +
          301 +        if (!(f = fopen(buf, "r")))
          302 +                return 0;
          303 +
          304 +        fscanf(f, "%*u %*s %*c %u", &v);
          305 +        fclose(f);
          306 +#endif /* __linux__ */
          307 +
          308 +        return (pid_t)v;
          309 +}
          310 +
          311 +int
          312 +isdescprocess(pid_t p, pid_t c)
          313 +{
          314 +        while (p != c && c != 0)
          315 +                c = getparentprocess(c);
          316 +
          317 +        return (int)c;
          318 +}
          319 +
          320 +Client *
          321 +termforwin(const Client *w)
          322 +{
          323 +        Client *c;
          324 +        Monitor *m;
          325 +
          326 +        if (!w->pid || w->isterminal)
          327 +                return NULL;
          328 +
          329 +        for (m = mons; m; m = m->next) {
          330 +                for (c = m->clients; c; c = c->next) {
          331 +                        if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
          332 +                                return c;
          333 +                }
          334 +        }
          335 +
          336 +        return NULL;
          337 +}
          338 +
          339 +Client *
          340 +swallowingclient(Window w)
          341 +{
          342 +        Client *c;
          343 +        Monitor *m;
          344 +
          345 +        for (m = mons; m; m = m->next) {
          346 +                for (c = m->clients; c; c = c->next) {
          347 +                        if (c->swallowing && c->swallowing->win == w)
          348 +                                return c;
          349 +                }
          350 +        }
          351 +
          352 +        return NULL;
          353 +}
          354 +
          355  Client *
          356  wintoclient(Window w)
          357  {
          358          Client *c;
          359          Monitor *m;
          360  
          361 -        for (m = mons; m; m = m->next)
          362 -                for (c = m->clients; c; c = c->next)
          363 +        for (m = mons; m; m = m->next) {
          364 +                for (c = m->clients; c; c = c->next) {
          365                          if (c->win == w)
          366                                  return c;
          367 +                }
          368 +        }
          369 +
          370          return NULL;
          371  }
          372  
          373 @@ -2130,6 +2308,8 @@ main(int argc, char *argv[])
          374                  fputs("warning: no locale support\n", stderr);
          375          if (!(dpy = XOpenDisplay(NULL)))
          376                  die("dwm: cannot open display\n");
          377 +        if (!(xcon = XGetXCBConnection(dpy)))
          378 +                die("dwm: cannot get xcb connection\n");
          379          checkotherwm();
          380          setup();
          381          scan();