commit: 4adb5a21cd5c9e9bda117ee35a7cf3dfdb97db45
parent: 20dfe7b29b934e8814f80174cc82a00b0d6638b0
author: Chris Noxz <chris@noxz.tech>
date: Sat, 10 Jun 2023 10:21:51 +0200
Allow overlapping borders
M | dwm.c | 83 | +++++++++++++------- |
1 file changed, 53 insertions(+), 30 deletions(-)
diff --git a/dwm.c b/dwm.c
@@ -165,7 +165,7 @@ typedef struct {
/* function declarations */
static void applyrules(Client *c);
-static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int *bw, int interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
@@ -218,8 +218,8 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
-static void resize(Client *c, int x, int y, int w, int h, int interact);
-static void resizeclient(Client *c, int x, int y, int w, int h);
+static void resize(Client *c, int x, int y, int w, int h, int bw, int interact);
+static void resizeclient(Client *c, int x, int y, int w, int h, int bw);
static void resizemouse(const Arg *arg);
static void resourceload(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
static void restack(Monitor *m);
@@ -362,7 +362,7 @@ applyrules(Client *c)
}
int
-applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
+applysizehints(Client *c, int *x, int *y, int *w, int *h, int *bw, int interact)
{
int baseismin;
Monitor *m = c->mon;
@@ -375,18 +375,18 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
*x = sw - WIDTH(c);
if (*y > sh)
*y = sh - HEIGHT(c);
- if (*x + *w + 2 * c->bw < 0)
+ if (*x + *w + 2 * *bw < 0)
*x = 0;
- if (*y + *h + 2 * c->bw < 0)
+ if (*y + *h + 2 * *bw < 0)
*y = 0;
} else {
if (*x >= m->wx + m->ww)
*x = m->wx + m->ww - WIDTH(c);
if (*y >= m->wy + m->wh)
*y = m->wy + m->wh - HEIGHT(c);
- if (*x + *w + 2 * c->bw <= m->wx)
+ if (*x + *w + 2 * *bw <= m->wx)
*x = m->wx;
- if (*y + *h + 2 * c->bw <= m->wy)
+ if (*y + *h + 2 * *bw <= m->wy)
*y = m->wy;
}
if (*h < bh)
@@ -424,7 +424,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
if (c->maxh)
*h = MIN(*h, c->maxh);
}
- return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
+ return *x != c->x || *y != c->y || *w != c->w || *h != c->h || *bw != c->bw;
}
void
@@ -444,8 +444,14 @@ arrange(Monitor *m)
void
arrangemon(Monitor *m)
{
+ Client *c;
+
if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m);
+ else
+ for (c = selmon->clients; c; c = c->next)
+ if (ISVISIBLE(c) && c->bw == 0)
+ resize(c, c->x, c->y, c->w - 2*borderpx, c->h - 2*borderpx, borderpx, 0);
}
void
@@ -638,7 +644,7 @@ configurenotify(XEvent *e)
for (m = mons; m; m = m->next) {
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
- resizeclient(c, m->mx, m->my, m->mw, m->mh);
+ resizeclient(c, m->mx, m->my, m->mw, m->mh, 0);
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
}
focus(NULL);
@@ -1049,6 +1055,8 @@ expose(XEvent *e)
void
focus(Client *c)
{
+ XWindowChanges wc;
+
if (!c || !ISVISIBLE(c))
for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
if (selmon->sel && selmon->sel != c)
@@ -1063,8 +1071,12 @@ focus(Client *c)
grabbuttons(c, 1);
if (c->isfloating)
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
- else
+ else {
+ wc.sibling = selmon->barwin;
+ wc.stack_mode = Below;
+ XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
+ }
setfocus(c);
} else {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
@@ -1392,7 +1404,7 @@ monocle(Monitor *m)
{
Client *c;
for (c = nextinstack(m->clients); c; c = nextinstack(c->next))
- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
+ resize(c, m->wx, m->wy, m->ww, m->wh, 0, 0);
}
void
@@ -1443,7 +1455,7 @@ movemouse(const Arg *arg)
&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
togglefloating(NULL);
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, nx, ny, c->w, c->h, 1);
+ resize(c, nx, ny, c->w, c->h, c->bw, 1);
break;
}
} while (ev.type != ButtonRelease);
@@ -1527,14 +1539,14 @@ recttomon(int x, int y, int w, int h)
}
void
-resize(Client *c, int x, int y, int w, int h, int interact)
+resize(Client *c, int x, int y, int w, int h, int bw, int interact)
{
- if (applysizehints(c, &x, &y, &w, &h, interact))
- resizeclient(c, x, y, w, h);
+ if (applysizehints(c, &x, &y, &w, &h, &bw, interact))
+ resizeclient(c, x, y, w, h, bw);
}
void
-resizeclient(Client *c, int x, int y, int w, int h)
+resizeclient(Client *c, int x, int y, int w, int h, int bw)
{
XWindowChanges wc;
@@ -1542,7 +1554,7 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldy = c->y; c->y = wc.y = y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
- wc.border_width = c->bw;
+ c->oldbw = c->bw; c->bw = wc.border_width = bw;
if (((nextinstack(c->mon->clients) == c && !nextinstack(c->next))
|| &monocle == c->mon->lt[c->mon->sellt]->arrange)
&& !c->isfullscreen
@@ -1600,7 +1612,7 @@ resizemouse(const Arg *arg)
togglefloating(NULL);
}
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, c->x, c->y, nw, nh, 1);
+ resize(c, c->x, c->y, nw, nh, c->bw, 1);
break;
}
} while (ev.type != ButtonRelease);
@@ -1857,22 +1869,20 @@ setfullscreen(Client *c, int fullscreen)
PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
c->isfullscreen = 1;
c->oldstate = c->isfloating;
- c->oldbw = c->bw;
- c->bw = 0;
c->isfloating = 1;
- resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
+ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh, 0);
XRaiseWindow(dpy, c->win);
} else if (!fullscreen && c->isfullscreen){
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
PropModeReplace, (unsigned char*)0, 0);
c->isfullscreen = 0;
c->isfloating = c->oldstate;
- c->bw = c->oldbw;
c->x = c->oldx;
c->y = c->oldy;
c->w = c->oldw;
c->h = c->oldh;
- resizeclient(c, c->x, c->y, c->w, c->h);
+ c->bw = c->oldbw;
+ resizeclient(c, c->x, c->y, c->w, c->h, c->bw);
arrange(c->mon);
}
}
@@ -2042,7 +2052,7 @@ showhide(Client *c)
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
- resize(c, c->x, c->y, c->w, c->h, 0);
+ resize(c, c->x, c->y, c->w, c->h, c->bw, 0);
showhide(c->snext);
} else {
/* hide clients bottom up */
@@ -2139,7 +2149,9 @@ nrowgrid(Monitor *m)
unsigned int n, ri = 0, ci = 0; /* counters */
unsigned int cx, cy, cw, ch, cg; /* client geometry */
unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
+ unsigned int bw = borderpx;
unsigned int cols, rows;
+ Bool gaps;
Client *c;
for (n = 0, c = nextinstack(m->clients); c; c = nextinstack(c->next), n++);
@@ -2154,16 +2166,21 @@ nrowgrid(Monitor *m)
cols = n / rows;
getgap(m, n, &cg, rows, cols);
+ gaps = cg && m->pertag->enablegaps[m->pertag->curtag];
+
+ /* hide border when single client without gaps */
+ if (n == 1 && !gaps)
+ bw = 0;
/* define first row */
uc = cols;
- cy = m->wy + cg;
+ cy = m->wy + cg + (gaps ? 0 : bw);
ch = (m->wh - 2*cg - (cg * (rows - 1))) / rows;
- uh = ch + cg;
+ uw = gaps ? 0 : bw;
+ uh = ch + cg + (gaps ? 0 : bw);
for (c = nextinstack(m->clients); c; c = nextinstack(c->next), ci++) {
if (ci == cols) {
- uw = 0;
ci = 0;
ri++;
@@ -2172,6 +2189,7 @@ nrowgrid(Monitor *m)
uc += cols;
cy = m->wy + uh + cg;
ch = ((m->wh - 2*cg) - uh - (cg * (rows - ri - 1))) / (rows - ri);
+ uw = gaps ? 0 : bw;
uh += ch + cg;
}
@@ -2179,7 +2197,10 @@ nrowgrid(Monitor *m)
cw = ((m->ww - 2*cg) - uw - (cg * (cols - ci - 1))) / (cols - ci);
uw += cw + cg;
- resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
+ if (gaps)
+ resize(c, cx, cy, cw - (2*bw), ch - (2*bw), bw, 0);
+ else
+ resize(c, cx - bw, cy - bw, cw - bw, ch - (rows == 1 ? 2 : 1)*bw, bw, 0);
}
}
@@ -2206,7 +2227,9 @@ togglefloating(const Arg *arg)
XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColBorder].pixel);
if (selmon->sel->isfloating)
resize(selmon->sel, selmon->sel->x, selmon->sel->y,
- selmon->sel->w, selmon->sel->h, 0);
+ selmon->sel->w - 2 * (borderpx - selmon->sel->bw),
+ selmon->sel->h - 2 * (borderpx - selmon->sel->bw),
+ borderpx, 0);
arrange(selmon);
}