dwm-swallow-20200807-b2de9b0.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-swallow-20200807-b2de9b0.diff (9956B) | |
--- | |
1 From b2de9b0fd7988241db516a8f032f26cb9cf32be1 Mon Sep 17 00:00:00 2001 | |
2 From: Ben <[email protected]> | |
3 Date: Fri, 7 Aug 2020 20:14:29 -0400 | |
4 Subject: [PATCH] added openbsd support for swallowing | |
5 | |
6 --- | |
7 config.def.h | 9 +- | |
8 config.mk | 3 +- | |
9 dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- | |
10 3 files changed, 237 insertions(+), 10 deletions(-) | |
11 | |
12 diff --git a/config.def.h b/config.def.h | |
13 index 1c0b587..fe51476 100644 | |
14 --- a/config.def.h | |
15 +++ b/config.def.h | |
16 @@ -3,6 +3,7 @@ | |
17 /* appearance */ | |
18 static const unsigned int borderpx = 1; /* border pixel of wind… | |
19 static const unsigned int snap = 32; /* snap pixel */ | |
20 +static const int swallowfloating = 0; /* 1 means swallow floa… | |
21 static const int showbar = 1; /* 0 means no bar */ | |
22 static const int topbar = 1; /* 0 means bottom bar */ | |
23 static const char *fonts[] = { "monospace:size=10" }; | |
24 @@ -26,9 +27,11 @@ static const Rule rules[] = { | |
25 * WM_CLASS(STRING) = instance, class | |
26 * WM_NAME(STRING) = title | |
27 */ | |
28 - /* class instance title tags mask isfloating … | |
29 - { "Gimp", NULL, NULL, 0, 1, … | |
30 - { "Firefox", NULL, NULL, 1 << 8, 0, … | |
31 + /* class instance title tags mask isfloating i… | |
32 + { "Gimp", NULL, NULL, 0, 1, 0… | |
33 + { "Firefox", NULL, NULL, 1 << 8, 0, 0… | |
34 + { "St", NULL, NULL, 0, 0, 1… | |
35 + { NULL, NULL, "Event Tester", 0, 0, 0… | |
36 }; | |
37 | |
38 /* layout(s) */ | |
39 diff --git a/config.mk b/config.mk | |
40 index 7084c33..ff9e508 100644 | |
41 --- a/config.mk | |
42 +++ b/config.mk | |
43 @@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft | |
44 FREETYPEINC = /usr/include/freetype2 | |
45 # OpenBSD (uncomment) | |
46 #FREETYPEINC = ${X11INC}/freetype2 | |
47 +#KVMLIB = -lkvm | |
48 | |
49 # includes and libs | |
50 INCS = -I${X11INC} -I${FREETYPEINC} | |
51 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} | |
52 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxc… | |
53 | |
54 # flags | |
55 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -D… | |
56 diff --git a/dwm.c b/dwm.c | |
57 index 9fd0286..e9f08f7 100644 | |
58 --- a/dwm.c | |
59 +++ b/dwm.c | |
60 @@ -40,6 +40,12 @@ | |
61 #include <X11/extensions/Xinerama.h> | |
62 #endif /* XINERAMA */ | |
63 #include <X11/Xft/Xft.h> | |
64 +#include <X11/Xlib-xcb.h> | |
65 +#include <xcb/res.h> | |
66 +#ifdef __OpenBSD__ | |
67 +#include <sys/sysctl.h> | |
68 +#include <kvm.h> | |
69 +#endif /* __OpenBSD */ | |
70 | |
71 #include "drw.h" | |
72 #include "util.h" | |
73 @@ -92,9 +98,11 @@ struct Client { | |
74 int basew, baseh, incw, inch, maxw, maxh, minw, minh; | |
75 int bw, oldbw; | |
76 unsigned int tags; | |
77 - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull… | |
78 + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull… | |
79 + pid_t pid; | |
80 Client *next; | |
81 Client *snext; | |
82 + Client *swallowing; | |
83 Monitor *mon; | |
84 Window win; | |
85 }; | |
86 @@ -138,6 +146,8 @@ typedef struct { | |
87 const char *title; | |
88 unsigned int tags; | |
89 int isfloating; | |
90 + int isterminal; | |
91 + int noswallow; | |
92 int monitor; | |
93 } Rule; | |
94 | |
95 @@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *e… | |
96 static int xerrorstart(Display *dpy, XErrorEvent *ee); | |
97 static void zoom(const Arg *arg); | |
98 | |
99 +static pid_t getparentprocess(pid_t p); | |
100 +static int isdescprocess(pid_t p, pid_t c); | |
101 +static Client *swallowingclient(Window w); | |
102 +static Client *termforwin(const Client *c); | |
103 +static pid_t winpid(Window w); | |
104 + | |
105 /* variables */ | |
106 static const char broken[] = "broken"; | |
107 static char stext[256]; | |
108 @@ -269,6 +285,8 @@ static Drw *drw; | |
109 static Monitor *mons, *selmon; | |
110 static Window root, wmcheckwin; | |
111 | |
112 +static xcb_connection_t *xcon; | |
113 + | |
114 /* configuration, allows nested code to access above variables */ | |
115 #include "config.h" | |
116 | |
117 @@ -298,6 +316,8 @@ applyrules(Client *c) | |
118 && (!r->class || strstr(class, r->class)) | |
119 && (!r->instance || strstr(instance, r->instance))) | |
120 { | |
121 + c->isterminal = r->isterminal; | |
122 + c->noswallow = r->noswallow; | |
123 c->isfloating = r->isfloating; | |
124 c->tags |= r->tags; | |
125 for (m = mons; m && m->num != r->monitor; m = m… | |
126 @@ -414,6 +434,53 @@ attachstack(Client *c) | |
127 c->mon->stack = c; | |
128 } | |
129 | |
130 +void | |
131 +swallow(Client *p, Client *c) | |
132 +{ | |
133 + | |
134 + if (c->noswallow || c->isterminal) | |
135 + return; | |
136 + if (c->noswallow && !swallowfloating && c->isfloating) | |
137 + return; | |
138 + | |
139 + detach(c); | |
140 + detachstack(c); | |
141 + | |
142 + setclientstate(c, WithdrawnState); | |
143 + XUnmapWindow(dpy, p->win); | |
144 + | |
145 + p->swallowing = c; | |
146 + c->mon = p->mon; | |
147 + | |
148 + Window w = p->win; | |
149 + p->win = c->win; | |
150 + c->win = w; | |
151 + updatetitle(p); | |
152 + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); | |
153 + arrange(p->mon); | |
154 + configure(p); | |
155 + updateclientlist(); | |
156 +} | |
157 + | |
158 +void | |
159 +unswallow(Client *c) | |
160 +{ | |
161 + c->win = c->swallowing->win; | |
162 + | |
163 + free(c->swallowing); | |
164 + c->swallowing = NULL; | |
165 + | |
166 + /* unfullscreen the client */ | |
167 + setfullscreen(c, 0); | |
168 + updatetitle(c); | |
169 + arrange(c->mon); | |
170 + XMapWindow(dpy, c->win); | |
171 + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); | |
172 + setclientstate(c, NormalState); | |
173 + focus(NULL); | |
174 + arrange(c->mon); | |
175 +} | |
176 + | |
177 void | |
178 buttonpress(XEvent *e) | |
179 { | |
180 @@ -653,6 +720,9 @@ destroynotify(XEvent *e) | |
181 | |
182 if ((c = wintoclient(ev->window))) | |
183 unmanage(c, 1); | |
184 + | |
185 + else if ((c = swallowingclient(ev->window))) | |
186 + unmanage(c->swallowing, 1); | |
187 } | |
188 | |
189 void | |
190 @@ -1018,12 +1088,13 @@ killclient(const Arg *arg) | |
191 void | |
192 manage(Window w, XWindowAttributes *wa) | |
193 { | |
194 - Client *c, *t = NULL; | |
195 + Client *c, *t = NULL, *term = NULL; | |
196 Window trans = None; | |
197 XWindowChanges wc; | |
198 | |
199 c = ecalloc(1, sizeof(Client)); | |
200 c->win = w; | |
201 + c->pid = winpid(w); | |
202 /* geometry */ | |
203 c->x = c->oldx = wa->x; | |
204 c->y = c->oldy = wa->y; | |
205 @@ -1038,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa) | |
206 } else { | |
207 c->mon = selmon; | |
208 applyrules(c); | |
209 + term = termforwin(c); | |
210 } | |
211 | |
212 if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) | |
213 @@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa) | |
214 c->mon->sel = c; | |
215 arrange(c->mon); | |
216 XMapWindow(dpy, c->win); | |
217 + if (term) | |
218 + swallow(term, c); | |
219 focus(NULL); | |
220 } | |
221 | |
222 @@ -1768,6 +1842,20 @@ unmanage(Client *c, int destroyed) | |
223 Monitor *m = c->mon; | |
224 XWindowChanges wc; | |
225 | |
226 + if (c->swallowing) { | |
227 + unswallow(c); | |
228 + return; | |
229 + } | |
230 + | |
231 + Client *s = swallowingclient(c->win); | |
232 + if (s) { | |
233 + free(s->swallowing); | |
234 + s->swallowing = NULL; | |
235 + arrange(m); | |
236 + focus(NULL); | |
237 + return; | |
238 + } | |
239 + | |
240 detach(c); | |
241 detachstack(c); | |
242 if (!destroyed) { | |
243 @@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed) | |
244 XUngrabServer(dpy); | |
245 } | |
246 free(c); | |
247 - focus(NULL); | |
248 - updateclientlist(); | |
249 - arrange(m); | |
250 + | |
251 + if (!s) { | |
252 + arrange(m); | |
253 + focus(NULL); | |
254 + updateclientlist(); | |
255 + } | |
256 } | |
257 | |
258 void | |
259 @@ -2047,6 +2138,136 @@ view(const Arg *arg) | |
260 arrange(selmon); | |
261 } | |
262 | |
263 +pid_t | |
264 +winpid(Window w) | |
265 +{ | |
266 + | |
267 + pid_t result = 0; | |
268 + | |
269 + #ifdef __linux__ | |
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 + | |
296 + #endif /* __linux__ */ | |
297 + | |
298 + #ifdef __OpenBSD__ | |
299 + Atom type; | |
300 + int format; | |
301 + unsigned long len, bytes; | |
302 + unsigned char *prop; | |
303 + pid_t ret; | |
304 + | |
305 + if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", … | |
306 + return 0; | |
307 + | |
308 + ret = *(pid_t*)prop; | |
309 + XFree(prop); | |
310 + result = ret; | |
311 + | |
312 + #endif /* __OpenBSD__ */ | |
313 + return result; | |
314 +} | |
315 + | |
316 +pid_t | |
317 +getparentprocess(pid_t p) | |
318 +{ | |
319 + unsigned int v = 0; | |
320 + | |
321 +#ifdef __linux__ | |
322 + FILE *f; | |
323 + char buf[256]; | |
324 + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); | |
325 + | |
326 + if (!(f = fopen(buf, "r"))) | |
327 + return 0; | |
328 + | |
329 + fscanf(f, "%*u %*s %*c %u", &v); | |
330 + fclose(f); | |
331 +#endif /* __linux__*/ | |
332 + | |
333 +#ifdef __OpenBSD__ | |
334 + int n; | |
335 + kvm_t *kd; | |
336 + struct kinfo_proc *kp; | |
337 + | |
338 + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); | |
339 + if (!kd) | |
340 + return 0; | |
341 + | |
342 + kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); | |
343 + v = kp->p_ppid; | |
344 +#endif /* __OpenBSD__ */ | |
345 + | |
346 + return (pid_t)v; | |
347 +} | |
348 + | |
349 +int | |
350 +isdescprocess(pid_t p, pid_t c) | |
351 +{ | |
352 + while (p != c && c != 0) | |
353 + c = getparentprocess(c); | |
354 + | |
355 + return (int)c; | |
356 +} | |
357 + | |
358 +Client * | |
359 +termforwin(const Client *w) | |
360 +{ | |
361 + Client *c; | |
362 + Monitor *m; | |
363 + | |
364 + if (!w->pid || w->isterminal) | |
365 + return NULL; | |
366 + | |
367 + for (m = mons; m; m = m->next) { | |
368 + for (c = m->clients; c; c = c->next) { | |
369 + if (c->isterminal && !c->swallowing && c->pid &… | |
370 + return c; | |
371 + } | |
372 + } | |
373 + | |
374 + return NULL; | |
375 +} | |
376 + | |
377 +Client * | |
378 +swallowingclient(Window w) | |
379 +{ | |
380 + Client *c; | |
381 + Monitor *m; | |
382 + | |
383 + for (m = mons; m; m = m->next) { | |
384 + for (c = m->clients; c; c = c->next) { | |
385 + if (c->swallowing && c->swallowing->win == w) | |
386 + return c; | |
387 + } | |
388 + } | |
389 + | |
390 + return NULL; | |
391 +} | |
392 + | |
393 Client * | |
394 wintoclient(Window w) | |
395 { | |
396 @@ -2138,10 +2359,12 @@ main(int argc, char *argv[]) | |
397 fputs("warning: no locale support\n", stderr); | |
398 if (!(dpy = XOpenDisplay(NULL))) | |
399 die("dwm: cannot open display"); | |
400 + if (!(xcon = XGetXCBConnection(dpy))) | |
401 + die("dwm: cannot get xcb connection\n"); | |
402 checkotherwm(); | |
403 setup(); | |
404 #ifdef __OpenBSD__ | |
405 - if (pledge("stdio rpath proc exec", NULL) == -1) | |
406 + if (pledge("stdio rpath proc exec ps", NULL) == -1) | |
407 die("pledge"); | |
408 #endif /* __OpenBSD__ */ | |
409 scan(); | |
410 -- | |
411 2.26.2 | |
412 |