dwm-swallow-6.1.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-swallow-6.1.diff (9337B) | |
--- | |
1 diff --git a/config.def.h b/config.def.h | |
2 index 7054c06..2bfd607 100644 | |
3 --- a/config.def.h | |
4 +++ b/config.def.h | |
5 @@ -24,9 +24,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 4eefb71..34ea872 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_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" $… | |
32 diff --git a/dwm.c b/dwm.c | |
33 index 0362114..1d38293 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 @@ -92,9 +94,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 @@ -138,6 +142,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 @@ -170,12 +176,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 @@ -206,8 +214,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 @@ -227,6 +237,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 @@ -267,6 +278,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 @@ -296,6 +309,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 @@ -412,6 +426,48 @@ attachstack(Client *c) | |
119 c->mon->stack = c; | |
120 } | |
121 | |
122 +void | |
123 +swallow(Client *p, Client *c) | |
124 +{ | |
125 + if (c->noswallow || c->isterminal) | |
126 + return; | |
127 + | |
128 + detach(c); | |
129 + detachstack(c); | |
130 + | |
131 + setclientstate(c, WithdrawnState); | |
132 + XUnmapWindow(dpy, p->win); | |
133 + | |
134 + p->swallowing = c; | |
135 + c->mon = p->mon; | |
136 + | |
137 + Window w = p->win; | |
138 + p->win = c->win; | |
139 + c->win = w; | |
140 + updatetitle(p); | |
141 + arrange(p->mon); | |
142 + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); | |
143 + configure(p); | |
144 + updateclientlist(); | |
145 +} | |
146 + | |
147 +void | |
148 +unswallow(Client *c) | |
149 +{ | |
150 + c->win = c->swallowing->win; | |
151 + | |
152 + free(c->swallowing); | |
153 + c->swallowing = NULL; | |
154 + | |
155 + updatetitle(c); | |
156 + arrange(c->mon); | |
157 + XMapWindow(dpy, c->win); | |
158 + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); | |
159 + configure(c); | |
160 + setclientstate(c, NormalState); | |
161 + focus(c); | |
162 +} | |
163 + | |
164 void | |
165 buttonpress(XEvent *e) | |
166 { | |
167 @@ -475,7 +531,7 @@ cleanup(void) | |
168 selmon->lt[selmon->sellt] = &foo; | |
169 for (m = mons; m; m = m->next) | |
170 while (m->stack) | |
171 - unmanage(m->stack, 0); | |
172 + unmanage(m->stack, 0); // XXX - unmanage swallo… | |
173 XUngrabKey(dpy, AnyKey, AnyModifier, root); | |
174 while (mons) | |
175 cleanupmon(mons); | |
176 @@ -661,6 +717,9 @@ destroynotify(XEvent *e) | |
177 | |
178 if ((c = wintoclient(ev->window))) | |
179 unmanage(c, 1); | |
180 + | |
181 + else if ((c = swallowingclient(ev->window))) | |
182 + unmanage(c->swallowing, 1); | |
183 } | |
184 | |
185 void | |
186 @@ -1032,12 +1091,13 @@ killclient(const Arg *arg) | |
187 void | |
188 manage(Window w, XWindowAttributes *wa) | |
189 { | |
190 - Client *c, *t = NULL; | |
191 + Client *c, *t, *term = NULL; | |
192 Window trans = None; | |
193 XWindowChanges wc; | |
194 | |
195 c = ecalloc(1, sizeof(Client)); | |
196 c->win = w; | |
197 + c->pid = winpid(w); | |
198 updatetitle(c); | |
199 if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(tr… | |
200 c->mon = t->mon; | |
201 @@ -1045,7 +1105,9 @@ manage(Window w, XWindowAttributes *wa) | |
202 } else { | |
203 c->mon = selmon; | |
204 applyrules(c); | |
205 + term = termforwin(c); | |
206 } | |
207 + | |
208 /* geometry */ | |
209 c->x = c->oldx = wa->x; | |
210 c->y = c->oldy = wa->y; | |
211 @@ -1085,8 +1147,11 @@ manage(Window w, XWindowAttributes *wa) | |
212 if (c->mon == selmon) | |
213 unfocus(selmon->sel, 0); | |
214 c->mon->sel = c; | |
215 - arrange(c->mon); | |
216 + if (!term) | |
217 + arrange(c->mon); | |
218 XMapWindow(dpy, c->win); | |
219 + if (term) | |
220 + swallow(term, c); | |
221 focus(NULL); | |
222 } | |
223 | |
224 @@ -1758,6 +1823,20 @@ unmanage(Client *c, int destroyed) | |
225 Monitor *m = c->mon; | |
226 XWindowChanges wc; | |
227 | |
228 + if (c->swallowing) { | |
229 + unswallow(c); | |
230 + return; | |
231 + } | |
232 + | |
233 + Client *s = swallowingclient(c->win); | |
234 + if (s) { | |
235 + free(s->swallowing); | |
236 + s->swallowing = NULL; | |
237 + arrange(m); | |
238 + focus(NULL); | |
239 + return; | |
240 + } | |
241 + | |
242 /* The server grab construct avoids race conditions. */ | |
243 detach(c); | |
244 detachstack(c); | |
245 @@ -1773,9 +1852,12 @@ unmanage(Client *c, int destroyed) | |
246 XUngrabServer(dpy); | |
247 } | |
248 free(c); | |
249 - focus(NULL); | |
250 - updateclientlist(); | |
251 - arrange(m); | |
252 + | |
253 + if (!s) { | |
254 + arrange(m); | |
255 + focus(NULL); | |
256 + updateclientlist(); | |
257 + } | |
258 } | |
259 | |
260 void | |
261 @@ -2040,16 +2122,116 @@ view(const Arg *arg) | |
262 arrange(selmon); | |
263 } | |
264 | |
265 +pid_t | |
266 +winpid(Window w) | |
267 +{ | |
268 + pid_t result = 0; | |
269 + | |
270 + xcb_res_client_id_spec_t spec = {0}; | |
271 + spec.client = w; | |
272 + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; | |
273 + | |
274 + xcb_generic_error_t *e = NULL; | |
275 + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(… | |
276 + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_… | |
277 + | |
278 + if (!r) | |
279 + return (pid_t)0; | |
280 + | |
281 + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids… | |
282 + for (; i.rem; xcb_res_client_id_value_next(&i)) { | |
283 + spec = i.data->spec; | |
284 + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID… | |
285 + uint32_t *t = xcb_res_client_id_value_value(i.d… | |
286 + result = *t; | |
287 + break; | |
288 + } | |
289 + } | |
290 + | |
291 + free(r); | |
292 + | |
293 + if (result == (pid_t)-1) | |
294 + result = 0; | |
295 + return result; | |
296 +} | |
297 + | |
298 +pid_t | |
299 +getparentprocess(pid_t p) | |
300 +{ | |
301 + unsigned int v = 0; | |
302 + | |
303 +#ifdef __linux__ | |
304 + FILE *f; | |
305 + char buf[256]; | |
306 + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); | |
307 + | |
308 + if (!(f = fopen(buf, "r"))) | |
309 + return 0; | |
310 + | |
311 + fscanf(f, "%*u %*s %*c %u", &v); | |
312 + fclose(f); | |
313 +#endif /* __linux__ */ | |
314 + | |
315 + return (pid_t)v; | |
316 +} | |
317 + | |
318 +int | |
319 +isdescprocess(pid_t p, pid_t c) | |
320 +{ | |
321 + while (p != c && c != 0) | |
322 + c = getparentprocess(c); | |
323 + | |
324 + return (int)c; | |
325 +} | |
326 + | |
327 +Client * | |
328 +termforwin(const Client *w) | |
329 +{ | |
330 + Client *c; | |
331 + Monitor *m; | |
332 + | |
333 + if (!w->pid || w->isterminal) | |
334 + return NULL; | |
335 + | |
336 + for (m = mons; m; m = m->next) { | |
337 + for (c = m->clients; c; c = c->next) { | |
338 + if (c->isterminal && !c->swallowing && c->pid &… | |
339 + return c; | |
340 + } | |
341 + } | |
342 + | |
343 + return NULL; | |
344 +} | |
345 + | |
346 +Client * | |
347 +swallowingclient(Window w) | |
348 +{ | |
349 + Client *c; | |
350 + Monitor *m; | |
351 + | |
352 + for (m = mons; m; m = m->next) { | |
353 + for (c = m->clients; c; c = c->next) { | |
354 + if (c->swallowing && c->swallowing->win == w) | |
355 + return c; | |
356 + } | |
357 + } | |
358 + | |
359 + return NULL; | |
360 +} | |
361 + | |
362 Client * | |
363 wintoclient(Window w) | |
364 { | |
365 Client *c; | |
366 Monitor *m; | |
367 | |
368 - for (m = mons; m; m = m->next) | |
369 - for (c = m->clients; c; c = c->next) | |
370 + for (m = mons; m; m = m->next) { | |
371 + for (c = m->clients; c; c = c->next) { | |
372 if (c->win == w) | |
373 return c; | |
374 + } | |
375 + } | |
376 + | |
377 return NULL; | |
378 } | |
379 | |
380 @@ -2131,6 +2313,8 @@ main(int argc, char *argv[]) | |
381 fputs("warning: no locale support\n", stderr); | |
382 if (!(dpy = XOpenDisplay(NULL))) | |
383 die("dwm: cannot open display\n"); | |
384 + if (!(xcon = XGetXCBConnection(dpy))) | |
385 + die("dwm: cannot get xcb connection\n"); | |
386 checkotherwm(); | |
387 setup(); | |
388 scan(); |