dwm-functionalgaps+pertag-6.2.diff (14038B)
1 diff -pu dwm.git/config.def.h dwm.functionalgapspertag/config.def.h 2 --- dwm.git/config.def.h 2021-02-27 21:17:53.862314811 -0600 3 +++ dwm.functionalgapspertag/config.def.h 2021-03-01 15:40:07.312696974 -0600 4 @@ -2,6 +2,8 @@ 5 6 /* appearance */ 7 static const unsigned int borderpx = 1; /* border pixel of windows */ 8 +static const int startwithgaps[] = { 0 }; /* 1 means gaps are used by default, this can be customized for each tag */ 9 +static const unsigned int gappx[] = { 10 }; /* default gap between windows in pixels, this can be customized for each tag */ 10 static const unsigned int snap = 32; /* snap pixel */ 11 static const int showbar = 1; /* 0 means no bar */ 12 static const int topbar = 1; /* 0 means bottom bar */ 13 @@ -84,6 +86,10 @@ static Key keys[] = { 14 { MODKEY, XK_period, focusmon, {.i = +1 } }, 15 { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 16 { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 17 + { MODKEY, XK_minus, setgaps, {.i = -5 } }, 18 + { MODKEY, XK_equal, setgaps, {.i = +5 } }, 19 + { MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } }, 20 + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} }, 21 TAGKEYS( XK_1, 0) 22 TAGKEYS( XK_2, 1) 23 TAGKEYS( XK_3, 2) 24 diff -pu dwm.git/dwm.c dwm.functionalgapspertag/dwm.c 25 --- dwm.git/dwm.c 2021-02-27 21:17:53.862314811 -0600 26 +++ dwm.functionalgapspertag/dwm.c 2021-03-01 17:10:10.402964866 -0600 27 @@ -57,6 +57,9 @@ 28 #define TAGMASK ((1 << LENGTH(tags)) - 1) 29 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 30 31 +#define GAP_TOGGLE 100 32 +#define GAP_RESET 0 33 + 34 /* enums */ 35 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 36 enum { SchemeNorm, SchemeSel }; /* color schemes */ 37 @@ -111,6 +114,8 @@ typedef struct { 38 void (*arrange)(Monitor *); 39 } Layout; 40 41 +typedef struct Pertag Pertag; 42 + 43 struct Monitor { 44 char ltsymbol[16]; 45 float mfact; 46 @@ -130,6 +135,7 @@ struct Monitor { 47 Monitor *next; 48 Window barwin; 49 const Layout *lt[2]; 50 + Pertag *pertag; 51 }; 52 53 typedef struct { 54 @@ -200,6 +206,7 @@ static void sendmon(Client *c, Monitor * 55 static void setclientstate(Client *c, long state); 56 static void setfocus(Client *c); 57 static void setfullscreen(Client *c, int fullscreen); 58 +static void setgaps(const Arg *arg); 59 static void setlayout(const Arg *arg); 60 static void setmfact(const Arg *arg); 61 static void setup(void); 62 @@ -272,6 +279,18 @@ static Window root, wmcheckwin; 63 /* configuration, allows nested code to access above variables */ 64 #include "config.h" 65 66 +struct Pertag { 67 + unsigned int curtag, prevtag; /* current and previous tag */ 68 + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ 69 + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ 70 + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ 71 + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ 72 + int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ 73 + 74 + int drawwithgaps[LENGTH(tags) + 1]; /* gaps toggle for each tag */ 75 + int gappx[LENGTH(tags) + 1]; /* gaps for each tag */ 76 +}; 77 + 78 /* compile-time check if all tags fit into an unsigned int bit array. */ 79 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; 80 81 @@ -632,6 +651,7 @@ Monitor * 82 createmon(void) 83 { 84 Monitor *m; 85 + unsigned int i; 86 87 m = ecalloc(1, sizeof(Monitor)); 88 m->tagset[0] = m->tagset[1] = 1; 89 @@ -642,6 +662,26 @@ createmon(void) 90 m->lt[0] = &layouts[0]; 91 m->lt[1] = &layouts[1 % LENGTH(layouts)]; 92 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); 93 + m->pertag = ecalloc(1, sizeof(Pertag)); 94 + m->pertag->curtag = m->pertag->prevtag = 1; 95 + 96 + for (i = 0; i <= LENGTH(tags); i++) { 97 + m->pertag->nmasters[i] = m->nmaster; 98 + m->pertag->mfacts[i] = m->mfact; 99 + 100 + m->pertag->ltidxs[i][0] = m->lt[0]; 101 + m->pertag->ltidxs[i][1] = m->lt[1]; 102 + m->pertag->sellts[i] = m->sellt; 103 + 104 + m->pertag->showbars[i] = m->showbar; 105 + if (i > 0) { 106 + m->pertag->drawwithgaps[i] = startwithgaps[(i - 1) % LENGTH(gappx)]; 107 + m->pertag->gappx[i] = gappx[(i - 1) % LENGTH(gappx)]; 108 + } 109 + } 110 + m->pertag->drawwithgaps[0] = startwithgaps[0]; 111 + m->pertag->gappx[0] = gappx[0]; 112 + 113 return m; 114 } 115 116 @@ -797,6 +837,12 @@ focus(Client *c) 117 attachstack(c); 118 grabbuttons(c, 1); 119 XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); 120 + if (!selmon->pertag->drawwithgaps[selmon->pertag->curtag] && !c->isfloating) { 121 + XWindowChanges wc; 122 + wc.sibling = selmon->barwin; 123 + wc.stack_mode = Below; 124 + XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); 125 + } 126 setfocus(c); 127 } else { 128 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); 129 @@ -967,7 +1013,7 @@ grabkeys(void) 130 void 131 incnmaster(const Arg *arg) 132 { 133 - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); 134 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); 135 arrange(selmon); 136 } 137 138 @@ -1113,7 +1159,10 @@ monocle(Monitor *m) 139 if (n > 0) /* override layout symbol */ 140 snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); 141 for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) 142 - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); 143 + if (selmon->pertag->drawwithgaps[selmon->pertag->curtag]) 144 + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); 145 + else 146 + resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); 147 } 148 149 void 150 @@ -1283,6 +1332,15 @@ resizeclient(Client *c, int x, int y, in 151 c->oldw = c->w; c->w = wc.width = w; 152 c->oldh = c->h; c->h = wc.height = h; 153 wc.border_width = c->bw; 154 + if (!selmon->pertag->drawwithgaps[selmon->pertag->curtag] && /* this is the noborderfloatingfix patch, slightly modified so that it will work if, and only if, gaps are disabled. */ 155 + (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) /* these two first lines are the only ones changed. if you are manually patching and have noborder installed already, just change these lines; or conversely, just remove this section if the noborder patch is not desired;) */ 156 + || &monocle == c->mon->lt[c->mon->sellt]->arrange)) 157 + && !c->isfullscreen && !c->isfloating 158 + && NULL != c->mon->lt[c->mon->sellt]->arrange) { 159 + c->w = wc.width += c->bw * 2; 160 + c->h = wc.height += c->bw * 2; 161 + wc.border_width = 0; 162 + } 163 XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); 164 configure(c); 165 XSync(dpy, False); 166 @@ -1499,12 +1557,35 @@ setfullscreen(Client *c, int fullscreen) 167 } 168 169 void 170 +setgaps(const Arg *arg) 171 +{ 172 + switch(arg->i) 173 + { 174 + case GAP_TOGGLE: 175 + selmon->pertag->drawwithgaps[selmon->pertag->curtag] = !selmon->pertag->drawwithgaps[selmon->pertag->curtag]; 176 + break; 177 + case GAP_RESET: 178 + if (selmon->pertag->curtag > 0) 179 + selmon->pertag->gappx[selmon->pertag->curtag] = gappx[selmon->pertag->curtag - 1 % LENGTH(gappx)]; 180 + else 181 + selmon->pertag->gappx[0] = gappx[0]; 182 + break; 183 + default: 184 + if (selmon->pertag->gappx[selmon->pertag->curtag] + arg->i < 0) 185 + selmon->pertag->gappx[selmon->pertag->curtag] = 0; 186 + else 187 + selmon->pertag->gappx[selmon->pertag->curtag] += arg->i; 188 + } 189 + arrange(selmon); 190 +} 191 + 192 +void 193 setlayout(const Arg *arg) 194 { 195 if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) 196 - selmon->sellt ^= 1; 197 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; 198 if (arg && arg->v) 199 - selmon->lt[selmon->sellt] = (Layout *)arg->v; 200 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; 201 strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); 202 if (selmon->sel) 203 arrange(selmon); 204 @@ -1523,7 +1604,7 @@ setmfact(const Arg *arg) 205 f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; 206 if (f < 0.05 || f > 0.95) 207 return; 208 - selmon->mfact = f; 209 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; 210 arrange(selmon); 211 } 212 213 @@ -1680,29 +1761,48 @@ tile(Monitor *m) 214 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 215 if (n == 0) 216 return; 217 - 218 - if (n > m->nmaster) 219 - mw = m->nmaster ? m->ww * m->mfact : 0; 220 - else 221 - mw = m->ww; 222 - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 223 - if (i < m->nmaster) { 224 - h = (m->wh - my) / (MIN(n, m->nmaster) - i); 225 - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); 226 - if (my + HEIGHT(c) < m->wh) 227 - my += HEIGHT(c); 228 - } else { 229 - h = (m->wh - ty) / (n - i); 230 - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); 231 - if (ty + HEIGHT(c) < m->wh) 232 - ty += HEIGHT(c); 233 - } 234 + if (m->pertag->drawwithgaps[m->pertag->curtag]) { /* draw with fullgaps logic */ 235 + if (n > m->nmaster) 236 + mw = m->nmaster ? m->ww * m->mfact : 0; 237 + else 238 + mw = m->ww - m->pertag->gappx[m->pertag->curtag]; 239 + for (i = 0, my = ty = m->pertag->gappx[m->pertag->curtag], c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 240 + if (i < m->nmaster) { 241 + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->pertag->gappx[m->pertag->curtag]; 242 + resize(c, m->wx + m->pertag->gappx[m->pertag->curtag], m->wy + my, mw - (2*c->bw) - m->pertag->gappx[m->pertag->curtag], h - (2*c->bw), 0); 243 + if (my + HEIGHT(c) + m->pertag->gappx[m->pertag->curtag] < m->wh) 244 + my += HEIGHT(c) + m->pertag->gappx[m->pertag->curtag]; 245 + } else { 246 + h = (m->wh - ty) / (n - i) - m->pertag->gappx[m->pertag->curtag]; 247 + resize(c, m->wx + mw + m->pertag->gappx[m->pertag->curtag], m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->pertag->gappx[m->pertag->curtag], h - (2*c->bw), 0); 248 + if (ty + HEIGHT(c) + m->pertag->gappx[m->pertag->curtag] < m->wh) 249 + ty += HEIGHT(c) + m->pertag->gappx[m->pertag->curtag]; 250 + } 251 + } else { /* draw with singularborders logic */ 252 + if (n > m->nmaster) 253 + mw = m->nmaster ? m->ww * m->mfact : 0; 254 + else 255 + mw = m->ww; 256 + for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 257 + if (i < m->nmaster) { 258 + h = (m->wh - my) / (MIN(n, m->nmaster) - i); 259 + if (n == 1) 260 + resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); 261 + else 262 + resize(c, m->wx - c->bw, m->wy + my, mw - c->bw, h - c->bw, False); 263 + my += HEIGHT(c) - c->bw; 264 + } else { 265 + h = (m->wh - ty) / (n - i); 266 + resize(c, m->wx + mw - c->bw, m->wy + ty, m->ww - mw, h - c->bw, False); 267 + ty += HEIGHT(c) - c->bw; 268 + } 269 + } 270 } 271 272 void 273 togglebar(const Arg *arg) 274 { 275 - selmon->showbar = !selmon->showbar; 276 + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; 277 updatebarpos(selmon); 278 XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); 279 arrange(selmon); 280 @@ -1741,9 +1841,33 @@ void 281 toggleview(const Arg *arg) 282 { 283 unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); 284 + int i; 285 286 if (newtagset) { 287 selmon->tagset[selmon->seltags] = newtagset; 288 + 289 + if (newtagset == ~0) { 290 + selmon->pertag->prevtag = selmon->pertag->curtag; 291 + selmon->pertag->curtag = 0; 292 + } 293 + 294 + /* test if the user did not select the same tag */ 295 + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { 296 + selmon->pertag->prevtag = selmon->pertag->curtag; 297 + for (i = 0; !(newtagset & 1 << i); i++) ; 298 + selmon->pertag->curtag = i + 1; 299 + } 300 + 301 + /* apply settings for this view */ 302 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; 303 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; 304 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; 305 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; 306 + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; 307 + 308 + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) 309 + togglebar(NULL); 310 + 311 focus(NULL); 312 arrange(selmon); 313 } 314 @@ -2038,11 +2162,37 @@ updatewmhints(Client *c) 315 void 316 view(const Arg *arg) 317 { 318 + int i; 319 + unsigned int tmptag; 320 + 321 if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) 322 return; 323 selmon->seltags ^= 1; /* toggle sel tagset */ 324 - if (arg->ui & TAGMASK) 325 + if (arg->ui & TAGMASK) { 326 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; 327 + selmon->pertag->prevtag = selmon->pertag->curtag; 328 + 329 + if (arg->ui == ~0) 330 + selmon->pertag->curtag = 0; 331 + else { 332 + for (i = 0; !(arg->ui & 1 << i); i++) ; 333 + selmon->pertag->curtag = i + 1; 334 + } 335 + } else { 336 + tmptag = selmon->pertag->prevtag; 337 + selmon->pertag->prevtag = selmon->pertag->curtag; 338 + selmon->pertag->curtag = tmptag; 339 + } 340 + 341 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; 342 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; 343 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; 344 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; 345 + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; 346 + 347 + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) 348 + togglebar(NULL); 349 + 350 focus(NULL); 351 arrange(selmon); 352 }