dwm-swallow-6.1.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.1.diff (9337B)
       ---
            1 diff --git a/config.def.h b/config.def.h
            2 index 7054c06..2bfd607 100644
            3 --- a/config.def.h
            4 +++ b/config.def.h
            5 @@ -24,9 +24,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 4eefb71..34ea872 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_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
           32 diff --git a/dwm.c b/dwm.c
           33 index 0362114..1d38293 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 @@ -92,9 +94,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 @@ -138,6 +142,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 @@ -170,12 +176,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 @@ -206,8 +214,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 @@ -227,6 +237,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 @@ -267,6 +278,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 @@ -296,6 +309,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 @@ -412,6 +426,48 @@ attachstack(Client *c)
          119          c->mon->stack = c;
          120  }
          121  
          122 +void
          123 +swallow(Client *p, Client *c)
          124 +{
          125 +        if (c->noswallow || c->isterminal)
          126 +                return;
          127 +
          128 +        detach(c);
          129 +        detachstack(c);
          130 +
          131 +        setclientstate(c, WithdrawnState);
          132 +        XUnmapWindow(dpy, p->win);
          133 +
          134 +        p->swallowing = c;
          135 +        c->mon = p->mon;
          136 +
          137 +        Window w = p->win;
          138 +        p->win = c->win;
          139 +        c->win = w;
          140 +        updatetitle(p);
          141 +        arrange(p->mon);
          142 +        XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
          143 +        configure(p);
          144 +        updateclientlist();
          145 +}
          146 +
          147 +void
          148 +unswallow(Client *c)
          149 +{
          150 +        c->win = c->swallowing->win;
          151 +
          152 +        free(c->swallowing);
          153 +        c->swallowing = NULL;
          154 +
          155 +        updatetitle(c);
          156 +        arrange(c->mon);
          157 +        XMapWindow(dpy, c->win);
          158 +        XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
          159 +        configure(c);
          160 +        setclientstate(c, NormalState);
          161 +        focus(c);
          162 +}
          163 +
          164  void
          165  buttonpress(XEvent *e)
          166  {
          167 @@ -475,7 +531,7 @@ cleanup(void)
          168          selmon->lt[selmon->sellt] = &foo;
          169          for (m = mons; m; m = m->next)
          170                  while (m->stack)
          171 -                        unmanage(m->stack, 0);
          172 +                        unmanage(m->stack, 0); // XXX - unmanage swallowing windows too
          173          XUngrabKey(dpy, AnyKey, AnyModifier, root);
          174          while (mons)
          175                  cleanupmon(mons);
          176 @@ -661,6 +717,9 @@ destroynotify(XEvent *e)
          177  
          178          if ((c = wintoclient(ev->window)))
          179                  unmanage(c, 1);
          180 +
          181 +        else if ((c = swallowingclient(ev->window)))
          182 +                unmanage(c->swallowing, 1);
          183  }
          184  
          185  void
          186 @@ -1032,12 +1091,13 @@ killclient(const Arg *arg)
          187  void
          188  manage(Window w, XWindowAttributes *wa)
          189  {
          190 -        Client *c, *t = NULL;
          191 +        Client *c, *t, *term = NULL;
          192          Window trans = None;
          193          XWindowChanges wc;
          194  
          195          c = ecalloc(1, sizeof(Client));
          196          c->win = w;
          197 +        c->pid = winpid(w);
          198          updatetitle(c);
          199          if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
          200                  c->mon = t->mon;
          201 @@ -1045,7 +1105,9 @@ manage(Window w, XWindowAttributes *wa)
          202          } else {
          203                  c->mon = selmon;
          204                  applyrules(c);
          205 +                term = termforwin(c);
          206          }
          207 +
          208          /* geometry */
          209          c->x = c->oldx = wa->x;
          210          c->y = c->oldy = wa->y;
          211 @@ -1085,8 +1147,11 @@ manage(Window w, XWindowAttributes *wa)
          212          if (c->mon == selmon)
          213                  unfocus(selmon->sel, 0);
          214          c->mon->sel = c;
          215 -        arrange(c->mon);
          216 +        if (!term)
          217 +                arrange(c->mon);
          218          XMapWindow(dpy, c->win);
          219 +        if (term)
          220 +                swallow(term, c);
          221          focus(NULL);
          222  }
          223  
          224 @@ -1758,6 +1823,20 @@ unmanage(Client *c, int destroyed)
          225          Monitor *m = c->mon;
          226          XWindowChanges wc;
          227  
          228 +        if (c->swallowing) {
          229 +                unswallow(c);
          230 +                return;
          231 +        }
          232 +
          233 +        Client *s = swallowingclient(c->win);
          234 +        if (s) {
          235 +                free(s->swallowing);
          236 +                s->swallowing = NULL;
          237 +                arrange(m);
          238 +        focus(NULL);
          239 +                return;
          240 +        }
          241 +
          242          /* The server grab construct avoids race conditions. */
          243          detach(c);
          244          detachstack(c);
          245 @@ -1773,9 +1852,12 @@ unmanage(Client *c, int destroyed)
          246                  XUngrabServer(dpy);
          247          }
          248          free(c);
          249 -        focus(NULL);
          250 -        updateclientlist();
          251 -        arrange(m);
          252 +
          253 +        if (!s) {
          254 +                arrange(m);
          255 +                focus(NULL);
          256 +                updateclientlist();
          257 +        }
          258  }
          259  
          260  void
          261 @@ -2040,16 +2122,116 @@ view(const Arg *arg)
          262          arrange(selmon);
          263  }
          264  
          265 +pid_t
          266 +winpid(Window w)
          267 +{
          268 +        pid_t result = 0;
          269 +
          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 +        return result;
          296 +}
          297 +
          298 +pid_t
          299 +getparentprocess(pid_t p)
          300 +{
          301 +        unsigned int v = 0;
          302 +
          303 +#ifdef __linux__
          304 +        FILE *f;
          305 +        char buf[256];
          306 +        snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
          307 +
          308 +        if (!(f = fopen(buf, "r")))
          309 +                return 0;
          310 +
          311 +        fscanf(f, "%*u %*s %*c %u", &v);
          312 +        fclose(f);
          313 +#endif /* __linux__ */
          314 +
          315 +        return (pid_t)v;
          316 +}
          317 +
          318 +int
          319 +isdescprocess(pid_t p, pid_t c)
          320 +{
          321 +        while (p != c && c != 0)
          322 +                c = getparentprocess(c);
          323 +
          324 +        return (int)c;
          325 +}
          326 +
          327 +Client *
          328 +termforwin(const Client *w)
          329 +{
          330 +        Client *c;
          331 +        Monitor *m;
          332 +
          333 +        if (!w->pid || w->isterminal)
          334 +                return NULL;
          335 +
          336 +        for (m = mons; m; m = m->next) {
          337 +                for (c = m->clients; c; c = c->next) {
          338 +                        if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
          339 +                                return c;
          340 +                }
          341 +        }
          342 +
          343 +        return NULL;
          344 +}
          345 +
          346 +Client *
          347 +swallowingclient(Window w)
          348 +{
          349 +        Client *c;
          350 +        Monitor *m;
          351 +
          352 +        for (m = mons; m; m = m->next) {
          353 +                for (c = m->clients; c; c = c->next) {
          354 +                        if (c->swallowing && c->swallowing->win == w)
          355 +                                return c;
          356 +                }
          357 +        }
          358 +
          359 +        return NULL;
          360 +}
          361 +
          362  Client *
          363  wintoclient(Window w)
          364  {
          365          Client *c;
          366          Monitor *m;
          367  
          368 -        for (m = mons; m; m = m->next)
          369 -                for (c = m->clients; c; c = c->next)
          370 +        for (m = mons; m; m = m->next) {
          371 +                for (c = m->clients; c; c = c->next) {
          372                          if (c->win == w)
          373                                  return c;
          374 +                }
          375 +        }
          376 +
          377          return NULL;
          378  }
          379  
          380 @@ -2131,6 +2313,8 @@ main(int argc, char *argv[])
          381                  fputs("warning: no locale support\n", stderr);
          382          if (!(dpy = XOpenDisplay(NULL)))
          383                  die("dwm: cannot open display\n");
          384 +        if (!(xcon = XGetXCBConnection(dpy)))
          385 +                die("dwm: cannot get xcb connection\n");
          386          checkotherwm();
          387          setup();
          388          scan();