dwm-cropwindows-20170709-ceac8c9.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-cropwindows-20170709-ceac8c9.diff (9365B)
       ---
            1 diff --git a/config.def.h b/config.def.h
            2 index a9ac303..a9797ac 100644
            3 --- a/config.def.h
            4 +++ b/config.def.h
            5 @@ -105,8 +105,10 @@ static Button buttons[] = {
            6          { ClkWinTitle,          0,              Button2,        zoom,           {0} },
            7          { ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
            8          { ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
            9 +        { ClkClientWin,         MODKEY|ShiftMask, Button1,      movemouse,      {.i = 1} },
           10          { ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} },
           11          { ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} },
           12 +        { ClkClientWin,         MODKEY|ShiftMask, Button3,      resizemouse,    {.i = 1} },
           13          { ClkTagBar,            0,              Button1,        view,           {0} },
           14          { ClkTagBar,            0,              Button3,        toggleview,     {0} },
           15          { ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
           16 diff --git a/dwm.c b/dwm.c
           17 index a5ce993..e922ef6 100644
           18 --- a/dwm.c
           19 +++ b/dwm.c
           20 @@ -98,6 +98,7 @@ struct Client {
           21          Client *snext;
           22          Monitor *mon;
           23          Window win;
           24 +        Client *crop;
           25  };
           26  
           27  typedef struct {
           28 @@ -276,6 +277,88 @@ static Window root, wmcheckwin;
           29  struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
           30  
           31  /* function implementations */
           32 +Client *
           33 +cropwintoclient(Window w)
           34 +{
           35 +        Client *c;
           36 +        Monitor *m;
           37 +
           38 +        for (m = mons; m; m = m->next)
           39 +                for (c = m->clients; c; c = c->next)
           40 +                        if (c->crop && c->crop->win == w)
           41 +                                return c;
           42 +        return NULL;
           43 +}
           44 +
           45 +void
           46 +cropwindow(Client *c)
           47 +{
           48 +        int x, y;
           49 +        XEvent ev;
           50 +        XSetWindowAttributes wa = { .event_mask = SubstructureRedirectMask };
           51 +
           52 +        if (!getrootptr(&x, &y))
           53 +                return;
           54 +        if (!c->crop) {
           55 +                c->crop = ecalloc(1, sizeof(Client));
           56 +                memcpy(c->crop, c, sizeof(Client));
           57 +                c->crop->crop = NULL;
           58 +                c->crop->x = c->crop->y = c->crop->bw = 0;
           59 +                c->basew = c->baseh = c->mina = c->maxa = 0;
           60 +                c->maxw = c->maxh = c->incw = c->inch = 0;
           61 +                c->minw = c->minh = 1;
           62 +                if (!c->isfloating)
           63 +                        togglefloating(NULL);
           64 +                c->win = XCreateWindow(dpy, root, x, y, 1, 1, c->bw,
           65 +                        0, 0, 0, CWEventMask, &wa);
           66 +                XReparentWindow(dpy, c->crop->win, c->win, 0, 0);
           67 +                XMapWindow(dpy, c->win);
           68 +                focus(c);
           69 +                XCheckTypedWindowEvent(dpy, c->crop->win, UnmapNotify, &ev);
           70 +                if (XCheckTypedWindowEvent(dpy, root, UnmapNotify, &ev)
           71 +                && ev.xunmap.window != c->crop->win)
           72 +                        XPutBackEvent(dpy, &ev);
           73 +        }
           74 +        resizeclient(c->crop, c->crop->x + c->x - x, c->crop->y + c->y - y,
           75 +                     c->crop->w, c->crop->h);
           76 +        resizeclient(c, x, y, 1, 1);
           77 +}
           78 +
           79 +void
           80 +cropdelete(Client *c)
           81 +{
           82 +        Client *crop;
           83 +        XEvent ev;
           84 +
           85 +        c->crop->x += c->x;
           86 +        c->crop->y += c->y;
           87 +        c->crop->bw = c->bw;
           88 +        c->crop->next = c->next;
           89 +        c->crop->snext = c->snext;
           90 +        c->crop->tags = c->tags;
           91 +        c->crop->mon = c->mon;
           92 +        XReparentWindow(dpy, c->crop->win, root, c->crop->x, c->crop->y);
           93 +        XDestroyWindow(dpy, c->win);
           94 +        crop = c->crop;
           95 +        memcpy(c, c->crop, sizeof(Client));
           96 +        free(crop);
           97 +        resize(c, c->x, c->y, c->w, c->h, 0);
           98 +        focus(c);
           99 +        XCheckTypedWindowEvent(dpy, c->win, UnmapNotify, &ev);
          100 +}
          101 +
          102 +void
          103 +cropresize(Client* c)
          104 +{
          105 +        resizeclient(c->crop,
          106 +                     BETWEEN(c->crop->x, -(c->crop->w), 0) ? c->crop->x : 0,
          107 +                     BETWEEN(c->crop->y, -(c->crop->h), 0) ? c->crop->y : 0,
          108 +                     c->crop->w, c->crop->h);
          109 +        resize(c, c->x, c->y,
          110 +               MIN(c->w, c->crop->x + c->crop->w),
          111 +               MIN(c->h, c->crop->y + c->crop->h), 0);
          112 +}
          113 +
          114  void
          115  applyrules(Client *c)
          116  {
          117 @@ -516,7 +599,7 @@ clientmessage(XEvent *e)
          118          XClientMessageEvent *cme = &e->xclient;
          119          Client *c = wintoclient(cme->window);
          120  
          121 -        if (!c)
          122 +        if (!c && !(c = cropwintoclient(cme->window)))
          123                  return;
          124          if (cme->message_type == netatom[NetWMState]) {
          125                  if (cme->data.l[1] == netatom[NetWMFullscreen]
          126 @@ -579,16 +662,19 @@ configurenotify(XEvent *e)
          127  void
          128  configurerequest(XEvent *e)
          129  {
          130 -        Client *c;
          131 +        Client *c, *cc = NULL;
          132          Monitor *m;
          133          XConfigureRequestEvent *ev = &e->xconfigurerequest;
          134          XWindowChanges wc;
          135  
          136 -        if ((c = wintoclient(ev->window))) {
          137 +        if ((c = wintoclient(ev->window))
          138 +        || (c = cc = cropwintoclient(ev->window))) {
          139                  if (ev->value_mask & CWBorderWidth)
          140                          c->bw = ev->border_width;
          141                  else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
          142                          m = c->mon;
          143 +                        if (c->crop)
          144 +                                c = c->crop;
          145                          if (ev->value_mask & CWX) {
          146                                  c->oldx = c->x;
          147                                  c->x = m->mx + ev->x;
          148 @@ -613,6 +699,8 @@ configurerequest(XEvent *e)
          149                                  configure(c);
          150                          if (ISVISIBLE(c))
          151                                  XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
          152 +                        if (cc)
          153 +                                cropresize(cc);
          154                  } else
          155                          configure(c);
          156          } else {
          157 @@ -651,7 +739,7 @@ destroynotify(XEvent *e)
          158          Client *c;
          159          XDestroyWindowEvent *ev = &e->xdestroywindow;
          160  
          161 -        if ((c = wintoclient(ev->window)))
          162 +        if ((c = wintoclient(ev->window)) || (c = cropwintoclient(ev->window)))
          163                  unmanage(c, 1);
          164  }
          165  
          166 @@ -762,6 +850,8 @@ enternotify(XEvent *e)
          167          if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
          168                  return;
          169          c = wintoclient(ev->window);
          170 +        if (!c)
          171 +                c = cropwintoclient(ev->window);
          172          m = c ? c->mon : wintomon(ev->window);
          173          if (m != selmon) {
          174                  unfocus(selmon->sel, 1);
          175 @@ -1005,6 +1095,8 @@ killclient(const Arg *arg)
          176  {
          177          if (!selmon->sel)
          178                  return;
          179 +        if (selmon->sel->crop)
          180 +                cropdelete(selmon->sel);
          181          if (!sendevent(selmon->sel, wmatom[WMDelete])) {
          182                  XGrabServer(dpy);
          183                  XSetErrorHandler(xerrordummy);
          184 @@ -1150,6 +1242,10 @@ movemouse(const Arg *arg)
          185          restack(selmon);
          186          ocx = c->x;
          187          ocy = c->y;
          188 +        if (arg->i == 1 && c->crop) {
          189 +                ocx = c->crop->x;
          190 +                ocy = c->crop->y;
          191 +        }
          192          if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
          193                  None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
          194                  return;
          195 @@ -1170,6 +1266,12 @@ movemouse(const Arg *arg)
          196  
          197                          nx = ocx + (ev.xmotion.x - x);
          198                          ny = ocy + (ev.xmotion.y - y);
          199 +                        if (arg->i == 1 && c->crop) {
          200 +                                c->crop->x = nx;
          201 +                                c->crop->y = ny;
          202 +                                cropresize(c);
          203 +                                continue;
          204 +                        }
          205                          if (abs(selmon->wx - nx) < snap)
          206                                  nx = selmon->wx;
          207                          else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
          208 @@ -1221,7 +1323,10 @@ propertynotify(XEvent *e)
          209                  updatestatus();
          210          else if (ev->state == PropertyDelete)
          211                  return; /* ignore */
          212 -        else if ((c = wintoclient(ev->window))) {
          213 +        else if ((c = wintoclient(ev->window))
          214 +        || (c = cropwintoclient(ev->window))) {
          215 +                if (c->crop)
          216 +                        c = c->crop;
          217                  switch(ev->atom) {
          218                  default: break;
          219                  case XA_WM_TRANSIENT_FOR:
          220 @@ -1303,12 +1408,16 @@ resizemouse(const Arg *arg)
          221          if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
          222                  return;
          223          restack(selmon);
          224 +        if (arg->i == 1)
          225 +                cropwindow(c);
          226          ocx = c->x;
          227          ocy = c->y;
          228          if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
          229                  None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
          230                  return;
          231 -        XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
          232 +        if (arg->i != 1)
          233 +                XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
          234 +                        c->w + c->bw - 1, c->h + c->bw - 1);
          235          do {
          236                  XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
          237                  switch(ev.type) {
          238 @@ -1324,6 +1433,10 @@ resizemouse(const Arg *arg)
          239  
          240                          nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
          241                          nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
          242 +                        if (c->crop) {
          243 +                                nw = MIN(nw, c->crop->w + c->crop->x);
          244 +                                nh = MIN(nh, c->crop->h + c->crop->y);
          245 +                        }
          246                          if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
          247                          && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
          248                          {
          249 @@ -1430,6 +1543,8 @@ setclientstate(Client *c, long state)
          250  {
          251          long data[] = { state, None };
          252  
          253 +        if (c->crop)
          254 +                c = c->crop;
          255          XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
          256                  PropModeReplace, (unsigned char *)data, 2);
          257  }
          258 @@ -1462,6 +1577,8 @@ sendevent(Client *c, Atom proto)
          259  void
          260  setfocus(Client *c)
          261  {
          262 +        if (c->crop)
          263 +                c = c->crop;
          264          if (!c->neverfocus) {
          265                  XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
          266                  XChangeProperty(dpy, root, netatom[NetActiveWindow],
          267 @@ -1474,6 +1591,8 @@ setfocus(Client *c)
          268  void
          269  setfullscreen(Client *c, int fullscreen)
          270  {
          271 +        if (c->crop)
          272 +                c = c->crop;
          273          if (fullscreen && !c->isfullscreen) {
          274                  XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
          275                          PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
          276 @@ -1718,6 +1837,8 @@ togglefloating(const Arg *arg)
          277          if (selmon->sel->isfloating)
          278                  resize(selmon->sel, selmon->sel->x, selmon->sel->y,
          279                          selmon->sel->w, selmon->sel->h, 0);
          280 +        if (!selmon->sel->isfloating && selmon->sel->crop)
          281 +                cropdelete(selmon->sel);
          282          arrange(selmon);
          283  }
          284  
          285 @@ -1767,6 +1888,8 @@ unmanage(Client *c, int destroyed)
          286          Monitor *m = c->mon;
          287          XWindowChanges wc;
          288  
          289 +        if (c->crop)
          290 +                cropdelete(c);
          291          detach(c);
          292          detachstack(c);
          293          if (!destroyed) {
          294 @@ -1792,7 +1915,8 @@ unmapnotify(XEvent *e)
          295          Client *c;
          296          XUnmapEvent *ev = &e->xunmap;
          297  
          298 -        if ((c = wintoclient(ev->window))) {
          299 +        if ((c = wintoclient(ev->window))
          300 +        || (c = cropwintoclient(ev->window))) {
          301                  if (ev->send_event)
          302                          setclientstate(c, WithdrawnState);
          303                  else
          304 @@ -2070,7 +2194,7 @@ wintomon(Window w)
          305          for (m = mons; m; m = m->next)
          306                  if (w == m->barwin)
          307                          return m;
          308 -        if ((c = wintoclient(w)))
          309 +        if ((c = wintoclient(w)) || (c = cropwintoclient(w)))
          310                  return c->mon;
          311          return selmon;
          312  }