dwm-betterswallow-20241215-89eeca1.diff - sites - public wiki contents of suckl… | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-betterswallow-20241215-89eeca1.diff (8074B) | |
--- | |
1 diff -up -x dwm -x '*.o' -x compile_commands.json dwm-6.3-orig/config.mk… | |
2 --- dwm-6.3-orig/config.mk 2024-06-25 01:55:26.769203813 +0200 | |
3 +++ dwm-6.3/config.mk 2024-12-15 01:12:39.132847648 +0100 | |
4 @@ -24,6 +24,8 @@ FREETYPEINC = /usr/include/freetype2 | |
5 INCS = -I${X11INC} -I${FREETYPEINC} | |
6 LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} | |
7 | |
8 +LIBS += -lXRes | |
9 + | |
10 # flags | |
11 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -D… | |
12 #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} | |
13 diff -up -x dwm -x '*.o' -x compile_commands.json dwm-6.3-orig/dwm.c dwm… | |
14 --- dwm-6.3-orig/dwm.c 2024-06-25 01:55:26.771203825 +0200 | |
15 +++ dwm-6.3/dwm.c 2024-12-15 01:44:35.963138226 +0100 | |
16 @@ -40,6 +40,7 @@ | |
17 #include <X11/extensions/Xinerama.h> | |
18 #endif /* XINERAMA */ | |
19 #include <X11/Xft/Xft.h> | |
20 +#include <X11/extensions/XRes.h> | |
21 | |
22 #include "drw.h" | |
23 #include "util.h" | |
24 @@ -49,7 +50,7 @@ | |
25 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (Shif… | |
26 #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - … | |
27 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - … | |
28 -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->selt… | |
29 +#define ISVISIBLE(C) (C->swallowed == NULL && (C->tags & C->… | |
30 #define LENGTH(X) (sizeof X / sizeof X[0]) | |
31 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) | |
32 #define WIDTH(X) ((X)->w + 2 * (X)->bw) | |
33 @@ -93,6 +94,11 @@ struct Client { | |
34 int bw, oldbw; | |
35 unsigned int tags; | |
36 int isfixed, isfloating, isurgent, neverfocus, oldstate, isfull… | |
37 + | |
38 + Client *swallower; | |
39 + Client *swallowed; | |
40 + Client *next_swallowed; | |
41 + | |
42 Client *next; | |
43 Client *snext; | |
44 Monitor *mon; | |
45 @@ -141,6 +147,12 @@ typedef struct { | |
46 int monitor; | |
47 } Rule; | |
48 | |
49 +typedef struct SwallowDef { | |
50 + pid_t pid; | |
51 + Client *swallower; | |
52 + struct SwallowDef *next; | |
53 +} SwallowDef; | |
54 + | |
55 /* function declarations */ | |
56 static void applyrules(Client *c); | |
57 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, in… | |
58 @@ -260,6 +272,8 @@ static void (*handler[LASTEvent]) (XEven | |
59 [PropertyNotify] = propertynotify, | |
60 [UnmapNotify] = unmapnotify | |
61 }; | |
62 +static Atom swallow_atom; | |
63 +static SwallowDef *swallowlist; | |
64 static Atom wmatom[WMLast], netatom[NetLast]; | |
65 static int running = 1; | |
66 static Cur *cursor[CurLast]; | |
67 @@ -400,6 +414,69 @@ arrangemon(Monitor *m) | |
68 m->lt[m->sellt]->arrange(m); | |
69 } | |
70 | |
71 +pid_t | |
72 +wintopid(Window window) { | |
73 + XResClientIdSpec spec; | |
74 + spec.client = window; | |
75 + spec.mask = XRES_CLIENT_ID_XID; | |
76 + | |
77 + long count; | |
78 + XResClientIdValue *output; | |
79 + XResQueryClientIds(dpy, 1, &spec, &count, &output); | |
80 + | |
81 + pid_t pid = -1; | |
82 + | |
83 + for (int i = 0; i < count; ++i) | |
84 + if (output[i].spec.mask == XRES_CLIENT_ID_PID_MASK) { | |
85 + pid = *(pid_t *)output[i].value; | |
86 + break; | |
87 + } | |
88 + | |
89 + XResClientIdsDestroy(count, output); | |
90 + | |
91 + return pid; | |
92 +} | |
93 + | |
94 +void | |
95 +copyclientpos(Client *dst, Client *src) { | |
96 + dst->bw = src->bw; | |
97 + resizeclient(dst, src->x, src->y, src->w, src->h); | |
98 + dst->oldx = src->oldx; | |
99 + dst->oldy = src->oldy; | |
100 + dst->oldw = src->oldw; | |
101 + dst->oldh = src->oldh; | |
102 + dst->oldbw = src->oldbw; | |
103 + dst->oldstate = src->oldstate; | |
104 + dst->isfullscreen = src->isfullscreen; | |
105 + dst->isfloating = src->isfloating; | |
106 + dst->tags = src->tags; | |
107 + dst->mon = src->mon; | |
108 +} | |
109 + | |
110 +void | |
111 +checkswallowed(Client *c) { | |
112 + pid_t pid = wintopid(c->win); | |
113 + | |
114 + if(pid < 0) return; | |
115 + for(SwallowDef *sd = swallowlist; sd != NULL; sd = sd->next) { | |
116 + if(pid == sd->pid) { | |
117 + c->swallower = sd->swallower; | |
118 + copyclientpos(c, sd->swallower); | |
119 + | |
120 + c->next_swallowed = c->swallower->swallowed; | |
121 + c->swallower->swallowed = c; | |
122 + | |
123 + c->next = c->swallower->next; | |
124 + c->swallower->next = c; | |
125 + | |
126 + c->snext = c->swallower->snext; | |
127 + c->swallower->snext = c; | |
128 + | |
129 + return; | |
130 + } | |
131 + } | |
132 +} | |
133 + | |
134 void | |
135 attach(Client *c) | |
136 { | |
137 @@ -526,7 +603,15 @@ clientmessage(XEvent *e) | |
138 } else if (cme->message_type == netatom[NetActiveWindow]) { | |
139 if (c != selmon->sel && !c->isurgent) | |
140 seturgent(c, 1); | |
141 + } else if(cme->message_type == swallow_atom) { | |
142 + SwallowDef *node = ecalloc(1, sizeof(SwallowDef)); | |
143 + node->pid = cme->data.l[0]; | |
144 + node->swallower = c; | |
145 + node->next = swallowlist; | |
146 + swallowlist = node; | |
147 + return; | |
148 } | |
149 + | |
150 } | |
151 | |
152 void | |
153 @@ -1052,6 +1137,7 @@ manage(Window w, XWindowAttributes *wa) | |
154 c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w /… | |
155 && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh … | |
156 c->bw = borderpx; | |
157 + checkswallowed(c); | |
158 | |
159 wc.border_width = c->bw; | |
160 XConfigureWindow(dpy, w, CWBorderWidth, &wc); | |
161 @@ -1066,8 +1152,10 @@ manage(Window w, XWindowAttributes *wa) | |
162 c->isfloating = c->oldstate = trans != None || c->isfix… | |
163 if (c->isfloating) | |
164 XRaiseWindow(dpy, c->win); | |
165 - attach(c); | |
166 - attachstack(c); | |
167 + if(!c->swallower) { | |
168 + attach(c); | |
169 + attachstack(c); | |
170 + } | |
171 XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 3… | |
172 (unsigned char *) &(c->win), 1); | |
173 XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h)… | |
174 @@ -1164,6 +1252,10 @@ movemouse(const Arg *arg) | |
175 case Expose: | |
176 case MapRequest: | |
177 handler[ev.type](&ev); | |
178 + | |
179 + // A MapRequest could've caused the current win… | |
180 + if(c->swallowed) | |
181 + c = c->swallowed; | |
182 break; | |
183 case MotionNotify: | |
184 if ((ev.xmotion.time - lasttime) <= (1000 / 60)) | |
185 @@ -1318,6 +1410,9 @@ resizemouse(const Arg *arg) | |
186 case Expose: | |
187 case MapRequest: | |
188 handler[ev.type](&ev); | |
189 + | |
190 + if(c->swallowed) | |
191 + c = c->swallowed; | |
192 break; | |
193 case MotionNotify: | |
194 if ((ev.xmotion.time - lasttime) <= (1000 / 60)) | |
195 @@ -1566,6 +1661,7 @@ setup(void) | |
196 netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYP… | |
197 netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WIND… | |
198 netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", F… | |
199 + swallow_atom = XInternAtom(dpy, "_BETTER_SWALLOW", False); | |
200 /* init cursors */ | |
201 cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); | |
202 cursor[CurResize] = drw_cur_create(drw, XC_sizing); | |
203 @@ -1583,6 +1679,8 @@ setup(void) | |
204 PropModeReplace, (unsigned char *) &wmcheckwin, 1); | |
205 XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string… | |
206 PropModeReplace, (unsigned char *) "dwm", 3); | |
207 + XChangeProperty(dpy, root, swallow_atom, utf8string, 8, | |
208 + PropModeReplace, (unsigned char *) "supported", 9); | |
209 XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, | |
210 PropModeReplace, (unsigned char *) &wmcheckwin, 1); | |
211 /* EWMH support per view */ | |
212 @@ -1766,11 +1864,52 @@ unfocus(Client *c, int setfocus) | |
213 } | |
214 | |
215 void | |
216 +deleteswallower(Client *c) { | |
217 + SwallowDef **prevnext = &swallowlist; | |
218 + for(SwallowDef *sd = swallowlist; sd != NULL;) { | |
219 + if(sd->swallower == c) { | |
220 + SwallowDef *next = sd->next; | |
221 + *prevnext = next; | |
222 + free(sd); | |
223 + sd = next; | |
224 + } else { | |
225 + prevnext = &sd->next; | |
226 + sd = sd->next; | |
227 + } | |
228 + } | |
229 + | |
230 + Client *sw = c->swallowed; | |
231 + while(sw) { | |
232 + sw->swallower = NULL; | |
233 + Client *next = sw->next_swallowed; | |
234 + sw->next_swallowed = NULL; | |
235 + sw = next; | |
236 + } | |
237 +} | |
238 + | |
239 +void | |
240 unmanage(Client *c, int destroyed) | |
241 { | |
242 Monitor *m = c->mon; | |
243 XWindowChanges wc; | |
244 | |
245 + if(c->swallower) { | |
246 + c->swallower->swallowed = c->next_swallowed; | |
247 + c->next_swallowed = NULL; | |
248 + | |
249 + if(c->swallower->swallowed == NULL) { | |
250 + detach(c->swallower); | |
251 + detachstack(c->swallower); | |
252 + | |
253 + c->swallower->next = c->next; | |
254 + c->next = c->swallower; | |
255 + c->swallower->snext = c->snext; | |
256 + c->snext = c->swallower; | |
257 + | |
258 + copyclientpos(c->swallower, c); | |
259 + } | |
260 + } | |
261 + | |
262 detach(c); | |
263 detachstack(c); | |
264 if (!destroyed) { | |
265 @@ -1783,9 +1922,10 @@ unmanage(Client *c, int destroyed) | |
266 XSync(dpy, False); | |
267 XSetErrorHandler(xerror); | |
268 XUngrabServer(dpy); | |
269 - } | |
270 + } else deleteswallower(c); | |
271 + if(c->swallower) focus(c->swallower); | |
272 + else focus(NULL); | |
273 free(c); | |
274 - focus(NULL); | |
275 updateclientlist(); | |
276 arrange(m); | |
277 } |