Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-swallow-20200522-7accbcf.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-swallow-20200522-7accbcf.diff (10221B)
---
1 From 7accbcf7db35995d4c26c5cd69338aafa6feb89a Mon Sep 17 00:00:00 2001
2 From: wtl <[email protected]>
3 Date: Fri, 22 May 2020 22:38:38 +0300
4 Subject: [PATCH] swallow X windows from the terminal
5
6 ---
7 config.def.h | 9 ++-
8 config.mk | 2 +-
9 dwm.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++--
10 3 files changed, 220 insertions(+), 9 deletions(-)
11
12 diff --git a/config.def.h b/config.def.h
13 index 1c0b587..4c0b25c 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, 1, 0…
36 };
37
38 /* layout(s) */
39 diff --git a/config.mk b/config.mk
40 index 7084c33..b77641d 100644
41 --- a/config.mk
42 +++ b/config.mk
43 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
44
45 # includes and libs
46 INCS = -I${X11INC} -I${FREETYPEINC}
47 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
48 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxc…
49
50 # flags
51 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -D…
52 diff --git a/dwm.c b/dwm.c
53 index 9fd0286..1befee4 100644
54 --- a/dwm.c
55 +++ b/dwm.c
56 @@ -40,6 +40,8 @@
57 #include <X11/extensions/Xinerama.h>
58 #endif /* XINERAMA */
59 #include <X11/Xft/Xft.h>
60 +#include <X11/Xlib-xcb.h>
61 +#include <xcb/res.h>
62
63 #include "drw.h"
64 #include "util.h"
65 @@ -92,9 +94,11 @@ struct Client {
66 int basew, baseh, incw, inch, maxw, maxh, minw, minh;
67 int bw, oldbw;
68 unsigned int tags;
69 - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull…
70 + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull…
71 + pid_t pid;
72 Client *next;
73 Client *snext;
74 + Client *swallowing;
75 Monitor *mon;
76 Window win;
77 };
78 @@ -138,6 +142,8 @@ typedef struct {
79 const char *title;
80 unsigned int tags;
81 int isfloating;
82 + int isterminal;
83 + int noswallow;
84 int monitor;
85 } Rule;
86
87 @@ -235,9 +241,16 @@ static int xerrordummy(Display *dpy, XErrorEvent *e…
88 static int xerrorstart(Display *dpy, XErrorEvent *ee);
89 static void zoom(const Arg *arg);
90
91 +static pid_t getparentprocess(pid_t p);
92 +static int isdescprocess(pid_t p, pid_t c);
93 +static Client *swallowingclient(Window w);
94 +static Client *termforwin(const Client *c);
95 +static pid_t winpid(Window w);
96 +
97 /* variables */
98 static const char broken[] = "broken";
99 static char stext[256];
100 +static int scanner;
101 static int screen;
102 static int sw, sh; /* X display screen geometry width, height…
103 static int bh, blw = 0; /* bar geometry */
104 @@ -269,6 +282,8 @@ static Drw *drw;
105 static Monitor *mons, *selmon;
106 static Window root, wmcheckwin;
107
108 +static xcb_connection_t *xcon;
109 +
110 /* configuration, allows nested code to access above variables */
111 #include "config.h"
112
113 @@ -286,6 +301,7 @@ applyrules(Client *c)
114 XClassHint ch = { NULL, NULL };
115
116 /* rule matching */
117 + c->noswallow = -1;
118 c->isfloating = 0;
119 c->tags = 0;
120 XGetClassHint(dpy, c->win, &ch);
121 @@ -298,6 +314,8 @@ applyrules(Client *c)
122 && (!r->class || strstr(class, r->class))
123 && (!r->instance || strstr(instance, r->instance)))
124 {
125 + c->isterminal = r->isterminal;
126 + c->noswallow = r->noswallow;
127 c->isfloating = r->isfloating;
128 c->tags |= r->tags;
129 for (m = mons; m && m->num != r->monitor; m = m…
130 @@ -414,6 +432,61 @@ attachstack(Client *c)
131 c->mon->stack = c;
132 }
133
134 +void
135 +swallow(Client *p, Client *c)
136 +{
137 + Client *s;
138 +
139 + if (c->noswallow > 0 || c->isterminal)
140 + return;
141 + if (c->noswallow < 0 && !swallowfloating && c->isfloating)
142 + return;
143 +
144 + detach(c);
145 + detachstack(c);
146 +
147 + setclientstate(c, WithdrawnState);
148 + XUnmapWindow(dpy, p->win);
149 +
150 + p->swallowing = c;
151 + c->mon = p->mon;
152 +
153 + Window w = p->win;
154 + p->win = c->win;
155 + c->win = w;
156 +
157 + XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW,…
158 + (unsigned char *) &(p->win), 1);
159 +
160 + updatetitle(p);
161 + s = scanner ? c : p;
162 + XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h);
163 + arrange(p->mon);
164 + configure(p);
165 + updateclientlist();
166 +}
167 +
168 +void
169 +unswallow(Client *c)
170 +{
171 + c->win = c->swallowing->win;
172 +
173 + free(c->swallowing);
174 + c->swallowing = NULL;
175 +
176 + XDeleteProperty(dpy, c->win, netatom[NetClientList]);
177 +
178 + /* unfullscreen the client */
179 + setfullscreen(c, 0);
180 + updatetitle(c);
181 + arrange(c->mon);
182 + XMapWindow(dpy, c->win);
183 + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
184 + setclientstate(c, NormalState);
185 + focus(NULL);
186 + arrange(c->mon);
187 +}
188 +
189 void
190 buttonpress(XEvent *e)
191 {
192 @@ -653,6 +726,9 @@ destroynotify(XEvent *e)
193
194 if ((c = wintoclient(ev->window)))
195 unmanage(c, 1);
196 +
197 + else if ((c = swallowingclient(ev->window)))
198 + unmanage(c->swallowing, 1);
199 }
200
201 void
202 @@ -1018,12 +1094,13 @@ killclient(const Arg *arg)
203 void
204 manage(Window w, XWindowAttributes *wa)
205 {
206 - Client *c, *t = NULL;
207 + Client *c, *t = NULL, *term = NULL;
208 Window trans = None;
209 XWindowChanges wc;
210
211 c = ecalloc(1, sizeof(Client));
212 c->win = w;
213 + c->pid = winpid(w);
214 /* geometry */
215 c->x = c->oldx = wa->x;
216 c->y = c->oldy = wa->y;
217 @@ -1038,6 +1115,7 @@ manage(Window w, XWindowAttributes *wa)
218 } else {
219 c->mon = selmon;
220 applyrules(c);
221 + term = termforwin(c);
222 }
223
224 if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
225 @@ -1074,6 +1152,8 @@ manage(Window w, XWindowAttributes *wa)
226 c->mon->sel = c;
227 arrange(c->mon);
228 XMapWindow(dpy, c->win);
229 + if (term)
230 + swallow(term, c);
231 focus(NULL);
232 }
233
234 @@ -1384,7 +1464,9 @@ run(void)
235 void
236 scan(void)
237 {
238 + scanner = 1;
239 unsigned int i, num;
240 + char swin[256];
241 Window d1, d2, *wins = NULL;
242 XWindowAttributes wa;
243
244 @@ -1395,6 +1477,8 @@ scan(void)
245 continue;
246 if (wa.map_state == IsViewable || getstate(wins…
247 manage(wins[i], &wa);
248 + else if (gettextprop(wins[i], netatom[NetClient…
249 + manage(wins[i], &wa);
250 }
251 for (i = 0; i < num; i++) { /* now the transients */
252 if (!XGetWindowAttributes(dpy, wins[i], &wa))
253 @@ -1406,6 +1490,7 @@ scan(void)
254 if (wins)
255 XFree(wins);
256 }
257 + scanner = 0;
258 }
259
260 void
261 @@ -1768,6 +1853,20 @@ unmanage(Client *c, int destroyed)
262 Monitor *m = c->mon;
263 XWindowChanges wc;
264
265 + if (c->swallowing) {
266 + unswallow(c);
267 + return;
268 + }
269 +
270 + Client *s = swallowingclient(c->win);
271 + if (s) {
272 + free(s->swallowing);
273 + s->swallowing = NULL;
274 + arrange(m);
275 + focus(NULL);
276 + return;
277 + }
278 +
279 detach(c);
280 detachstack(c);
281 if (!destroyed) {
282 @@ -1782,9 +1881,12 @@ unmanage(Client *c, int destroyed)
283 XUngrabServer(dpy);
284 }
285 free(c);
286 - focus(NULL);
287 - updateclientlist();
288 - arrange(m);
289 +
290 + if (!s) {
291 + arrange(m);
292 + focus(NULL);
293 + updateclientlist();
294 + }
295 }
296
297 void
298 @@ -2047,6 +2149,110 @@ view(const Arg *arg)
299 arrange(selmon);
300 }
301
302 +pid_t
303 +winpid(Window w)
304 +{
305 + pid_t result = 0;
306 +
307 + xcb_res_client_id_spec_t spec = {0};
308 + spec.client = w;
309 + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
310 +
311 + xcb_generic_error_t *e = NULL;
312 + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(…
313 + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_…
314 +
315 + if (!r)
316 + return (pid_t)0;
317 +
318 + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids…
319 + for (; i.rem; xcb_res_client_id_value_next(&i)) {
320 + spec = i.data->spec;
321 + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID…
322 + uint32_t *t = xcb_res_client_id_value_value(i.d…
323 + result = *t;
324 + break;
325 + }
326 + }
327 +
328 + free(r);
329 +
330 + if (result == (pid_t)-1)
331 + result = 0;
332 + return result;
333 +}
334 +
335 +pid_t
336 +getparentprocess(pid_t p)
337 +{
338 + unsigned int v = 0;
339 +
340 +#if defined(__linux__)
341 + FILE *f;
342 + char buf[256];
343 + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
344 +
345 + if (!(f = fopen(buf, "r")))
346 + return (pid_t)0;
347 +
348 + if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1)
349 + v = (pid_t)0;
350 + fclose(f);
351 +#elif defined(__FreeBSD__)
352 + struct kinfo_proc *proc = kinfo_getproc(p);
353 + if (!proc)
354 + return (pid_t)0;
355 +
356 + v = proc->ki_ppid;
357 + free(proc);
358 +#endif
359 + return (pid_t)v;
360 +}
361 +
362 +int
363 +isdescprocess(pid_t p, pid_t c)
364 +{
365 + while (p != c && c != 0)
366 + c = getparentprocess(c);
367 +
368 + return (int)c;
369 +}
370 +
371 +Client *
372 +termforwin(const Client *w)
373 +{
374 + Client *c;
375 + Monitor *m;
376 +
377 + if (!w->pid || w->isterminal)
378 + return NULL;
379 +
380 + for (m = mons; m; m = m->next) {
381 + for (c = m->clients; c; c = c->next) {
382 + if (c->isterminal && !c->swallowing && c->pid &…
383 + return c;
384 + }
385 + }
386 +
387 + return NULL;
388 +}
389 +
390 +Client *
391 +swallowingclient(Window w)
392 +{
393 + Client *c;
394 + Monitor *m;
395 +
396 + for (m = mons; m; m = m->next) {
397 + for (c = m->clients; c; c = c->next) {
398 + if (c->swallowing && c->swallowing->win == w)
399 + return c;
400 + }
401 + }
402 +
403 + return NULL;
404 +}
405 +
406 Client *
407 wintoclient(Window w)
408 {
409 @@ -2138,6 +2344,8 @@ main(int argc, char *argv[])
410 fputs("warning: no locale support\n", stderr);
411 if (!(dpy = XOpenDisplay(NULL)))
412 die("dwm: cannot open display");
413 + if (!(xcon = XGetXCBConnection(dpy)))
414 + die("dwm: cannot get xcb connection\n");
415 checkotherwm();
416 setup();
417 #ifdef __OpenBSD__
418 --
419 2.26.2
420
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.