| dwm-betterswallow-20250116-89eeca1.diff - sites - public wiki contents of suckl… | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| dwm-betterswallow-20250116-89eeca1.diff (8161B) | |
| --- | |
| 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 2025-01-16 21:07:02.942737362 +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,55 @@ 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 + Client **prev = &c->swallower->swallowed; | |
| 247 + for(; *prev != c; prev = &(*prev)->next_swallowed) | |
| 248 + ; | |
| 249 + *prev = c->next_swallowed; | |
| 250 + c->next_swallowed = NULL; | |
| 251 + | |
| 252 + if(c->swallower->swallowed == NULL) { | |
| 253 + detach(c->swallower); | |
| 254 + detachstack(c->swallower); | |
| 255 + | |
| 256 + c->swallower->next = c->next; | |
| 257 + c->next = c->swallower; | |
| 258 + c->swallower->snext = c->snext; | |
| 259 + c->snext = c->swallower; | |
| 260 + | |
| 261 + copyclientpos(c->swallower, c); | |
| 262 + } | |
| 263 + } | |
| 264 + | |
| 265 detach(c); | |
| 266 detachstack(c); | |
| 267 if (!destroyed) { | |
| 268 @@ -1783,9 +1925,10 @@ unmanage(Client *c, int destroyed) | |
| 269 XSync(dpy, False); | |
| 270 XSetErrorHandler(xerror); | |
| 271 XUngrabServer(dpy); | |
| 272 - } | |
| 273 + } else deleteswallower(c); | |
| 274 + if(c->swallower) focus(c->swallower); | |
| 275 + else focus(NULL); | |
| 276 free(c); | |
| 277 - focus(NULL); | |
| 278 updateclientlist(); | |
| 279 arrange(m); | |
| 280 } |