sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | 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  }