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 }