dwm-swallow-20160717-56a31dc.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-swallow-20160717-56a31dc.diff (9208B) | |
--- | |
1 diff --git a/config.def.h b/config.def.h | |
2 index fd77a07..69976b3 100644 | |
3 --- a/config.def.h | |
4 +++ b/config.def.h | |
5 @@ -26,9 +26,10 @@ static const Rule rules[] = { | |
6 * WM_CLASS(STRING) = instance, class | |
7 * WM_NAME(STRING) = title | |
8 */ | |
9 - /* class instance title tags mask isfloating … | |
10 - { "Gimp", NULL, NULL, 0, 1, … | |
11 - { "Firefox", NULL, NULL, 1 << 8, 0, … | |
12 + /* class instance title tags mask isfloating … | |
13 + { "Gimp", NULL, NULL, 0, 1, … | |
14 + { "Firefox", NULL, NULL, 1 << 8, 0, … | |
15 + { "st", NULL, NULL, 0, 0, … | |
16 }; | |
17 | |
18 /* layout(s) */ | |
19 diff --git a/config.mk b/config.mk | |
20 index 80dc936..5ed14e3 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 -lxc… | |
29 | |
30 # flags | |
31 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSIO… | |
32 diff --git a/dwm.c b/dwm.c | |
33 index b2bc9bd..528df2f 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 @@ -93,9 +95,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, isfull… | |
50 + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull… | |
51 + pid_t pid; | |
52 Client *next; | |
53 Client *snext; | |
54 + Client *swallowing; | |
55 Monitor *mon; | |
56 Window win; | |
57 }; | |
58 @@ -139,6 +143,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 @@ -171,12 +177,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 si… | |
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 @@ -207,8 +215,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 @@ -228,6 +238,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 @@ -269,6 +280,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 @@ -298,6 +311,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… | |
118 @@ -415,6 +429,47 @@ attachstack(Client *c) | |
119 } | |
120 | |
121 void | |
122 +swallow(Client *p, Client *c) | |
123 +{ | |
124 + if (c->noswallow || c->isterminal) | |
125 + return; | |
126 + | |
127 + detach(c); | |
128 + detachstack(c); | |
129 + | |
130 + setclientstate(c, WithdrawnState); | |
131 + XUnmapWindow(dpy, p->win); | |
132 + | |
133 + p->swallowing = c; | |
134 + c->mon = p->mon; | |
135 + | |
136 + Window w = p->win; | |
137 + p->win = c->win; | |
138 + c->win = w; | |
139 + updatetitle(p); | |
140 + arrange(p->mon); | |
141 + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); | |
142 + configure(p); | |
143 + updateclientlist(); | |
144 +} | |
145 + | |
146 +void | |
147 +unswallow(Client *c) | |
148 +{ | |
149 + c->win = c->swallowing->win; | |
150 + | |
151 + free(c->swallowing); | |
152 + c->swallowing = NULL; | |
153 + | |
154 + updatetitle(c); | |
155 + arrange(c->mon); | |
156 + XMapWindow(dpy, c->win); | |
157 + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); | |
158 + configure(c); | |
159 + setclientstate(c, NormalState); | |
160 +} | |
161 + | |
162 +void | |
163 buttonpress(XEvent *e) | |
164 { | |
165 unsigned int i, x, click; | |
166 @@ -477,7 +531,7 @@ cleanup(void) | |
167 selmon->lt[selmon->sellt] = &foo; | |
168 for (m = mons; m; m = m->next) | |
169 while (m->stack) | |
170 - unmanage(m->stack, 0); | |
171 + unmanage(m->stack, 0); // XXX - unmanage swallo… | |
172 XUngrabKey(dpy, AnyKey, AnyModifier, root); | |
173 while (mons) | |
174 cleanupmon(mons); | |
175 @@ -665,6 +719,9 @@ destroynotify(XEvent *e) | |
176 | |
177 if ((c = wintoclient(ev->window))) | |
178 unmanage(c, 1); | |
179 + | |
180 + else if ((c = swallowingclient(ev->window))) | |
181 + unmanage(c->swallowing, 1); | |
182 } | |
183 | |
184 void | |
185 @@ -1034,12 +1091,13 @@ killclient(const Arg *arg) | |
186 void | |
187 manage(Window w, XWindowAttributes *wa) | |
188 { | |
189 - Client *c, *t = NULL; | |
190 + Client *c, *t = NULL, *term = NULL; | |
191 Window trans = None; | |
192 XWindowChanges wc; | |
193 | |
194 c = ecalloc(1, sizeof(Client)); | |
195 c->win = w; | |
196 + c->pid = winpid(w); | |
197 /* geometry */ | |
198 c->x = c->oldx = wa->x; | |
199 c->y = c->oldy = wa->y; | |
200 @@ -1054,6 +1112,7 @@ manage(Window w, XWindowAttributes *wa) | |
201 } else { | |
202 c->mon = selmon; | |
203 applyrules(c); | |
204 + term = termforwin(c); | |
205 } | |
206 | |
207 if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) | |
208 @@ -1090,6 +1149,8 @@ manage(Window w, XWindowAttributes *wa) | |
209 c->mon->sel = c; | |
210 arrange(c->mon); | |
211 XMapWindow(dpy, c->win); | |
212 + if (term) | |
213 + swallow(term, c); | |
214 focus(NULL); | |
215 } | |
216 | |
217 @@ -1757,6 +1818,20 @@ unmanage(Client *c, int destroyed) | |
218 Monitor *m = c->mon; | |
219 XWindowChanges wc; | |
220 | |
221 + if (c->swallowing) { | |
222 + unswallow(c); | |
223 + return; | |
224 + } | |
225 + | |
226 + Client *s = swallowingclient(c->win); | |
227 + if (s) { | |
228 + free(s->swallowing); | |
229 + s->swallowing = NULL; | |
230 + arrange(m); | |
231 + focus(NULL); | |
232 + return; | |
233 + } | |
234 + | |
235 /* The server grab construct avoids race conditions. */ | |
236 detach(c); | |
237 detachstack(c); | |
238 @@ -1772,9 +1847,12 @@ unmanage(Client *c, int destroyed) | |
239 XUngrabServer(dpy); | |
240 } | |
241 free(c); | |
242 - focus(NULL); | |
243 - updateclientlist(); | |
244 - arrange(m); | |
245 + | |
246 + if (!s) { | |
247 + arrange(m); | |
248 + focus(NULL); | |
249 + updateclientlist(); | |
250 + } | |
251 } | |
252 | |
253 void | |
254 @@ -2039,16 +2117,116 @@ view(const Arg *arg) | |
255 arrange(selmon); | |
256 } | |
257 | |
258 +pid_t | |
259 +winpid(Window w) | |
260 +{ | |
261 + pid_t result = 0; | |
262 + | |
263 + xcb_res_client_id_spec_t spec = {0}; | |
264 + spec.client = w; | |
265 + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; | |
266 + | |
267 + xcb_generic_error_t *e = NULL; | |
268 + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(… | |
269 + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_… | |
270 + | |
271 + if (!r) | |
272 + return (pid_t)0; | |
273 + | |
274 + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids… | |
275 + for (; i.rem; xcb_res_client_id_value_next(&i)) { | |
276 + spec = i.data->spec; | |
277 + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID… | |
278 + uint32_t *t = xcb_res_client_id_value_value(i.d… | |
279 + result = *t; | |
280 + break; | |
281 + } | |
282 + } | |
283 + | |
284 + free(r); | |
285 + | |
286 + if (result == (pid_t)-1) | |
287 + result = 0; | |
288 + return result; | |
289 +} | |
290 + | |
291 +pid_t | |
292 +getparentprocess(pid_t p) | |
293 +{ | |
294 + unsigned int v = 0; | |
295 + | |
296 +#ifdef __linux__ | |
297 + FILE *f; | |
298 + char buf[256]; | |
299 + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); | |
300 + | |
301 + if (!(f = fopen(buf, "r"))) | |
302 + return 0; | |
303 + | |
304 + fscanf(f, "%*u %*s %*c %u", &v); | |
305 + fclose(f); | |
306 +#endif /* __linux__ */ | |
307 + | |
308 + return (pid_t)v; | |
309 +} | |
310 + | |
311 +int | |
312 +isdescprocess(pid_t p, pid_t c) | |
313 +{ | |
314 + while (p != c && c != 0) | |
315 + c = getparentprocess(c); | |
316 + | |
317 + return (int)c; | |
318 +} | |
319 + | |
320 +Client * | |
321 +termforwin(const Client *w) | |
322 +{ | |
323 + Client *c; | |
324 + Monitor *m; | |
325 + | |
326 + if (!w->pid || w->isterminal) | |
327 + return NULL; | |
328 + | |
329 + for (m = mons; m; m = m->next) { | |
330 + for (c = m->clients; c; c = c->next) { | |
331 + if (c->isterminal && !c->swallowing && c->pid &… | |
332 + return c; | |
333 + } | |
334 + } | |
335 + | |
336 + return NULL; | |
337 +} | |
338 + | |
339 +Client * | |
340 +swallowingclient(Window w) | |
341 +{ | |
342 + Client *c; | |
343 + Monitor *m; | |
344 + | |
345 + for (m = mons; m; m = m->next) { | |
346 + for (c = m->clients; c; c = c->next) { | |
347 + if (c->swallowing && c->swallowing->win == w) | |
348 + return c; | |
349 + } | |
350 + } | |
351 + | |
352 + return NULL; | |
353 +} | |
354 + | |
355 Client * | |
356 wintoclient(Window w) | |
357 { | |
358 Client *c; | |
359 Monitor *m; | |
360 | |
361 - for (m = mons; m; m = m->next) | |
362 - for (c = m->clients; c; c = c->next) | |
363 + for (m = mons; m; m = m->next) { | |
364 + for (c = m->clients; c; c = c->next) { | |
365 if (c->win == w) | |
366 return c; | |
367 + } | |
368 + } | |
369 + | |
370 return NULL; | |
371 } | |
372 | |
373 @@ -2130,6 +2308,8 @@ main(int argc, char *argv[]) | |
374 fputs("warning: no locale support\n", stderr); | |
375 if (!(dpy = XOpenDisplay(NULL))) | |
376 die("dwm: cannot open display\n"); | |
377 + if (!(xcon = XGetXCBConnection(dpy))) | |
378 + die("dwm: cannot get xcb connection\n"); | |
379 checkotherwm(); | |
380 setup(); | |
381 scan(); |