dwm-cropwindows-20170709-ceac8c9.diff - sites - public wiki contents of suckles… | |
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, … | |
7 { ClkStatusText, 0, Button2, spawn, … | |
8 { ClkClientWin, MODKEY, Button1, movemou… | |
9 + { ClkClientWin, MODKEY|ShiftMask, Button1, movemou… | |
10 { ClkClientWin, MODKEY, Button2, togglef… | |
11 { ClkClientWin, MODKEY, Button3, resizem… | |
12 + { ClkClientWin, MODKEY|ShiftMask, Button3, resizem… | |
13 { ClkTagBar, 0, Button1, view, … | |
14 { ClkTagBar, 0, Button3, togglev… | |
15 { ClkTagBar, MODKEY, Button1, tag, … | |
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 = SubstructureRedirectM… | |
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, … | |
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 … | |
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… | |
107 + BETWEEN(c->crop->y, -(c->crop->h), 0) ? c->crop->y… | |
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]->a… | |
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-… | |
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->w… | |
163 unmanage(c, 1); | |
164 } | |
165 | |
166 @@ -762,6 +850,8 @@ enternotify(XEvent *e) | |
167 if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) … | |
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, Gr… | |
193 None, cursor[CurMove]->cursor, CurrentTime) != GrabSucc… | |
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 + … | |
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 … | |
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, Gr… | |
229 None, cursor[CurResize]->cursor, CurrentTime) != GrabSu… | |
230 return; | |
231 - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c… | |
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|SubstructureRedi… | |
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… | |
247 && c->mon->wy + nh >= selmon->wy && c->mon->wy … | |
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], … | |
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, Curren… | |
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_AT… | |
275 PropModeReplace, (unsigned char*)&netatom[NetWM… | |
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 } |