floatpos: refactoring

dwm-flexipatch-1.0
bakkeby 4 years ago
parent aecfff3a00
commit 6c2d1518ab

@ -1044,43 +1044,43 @@ static Key keys[] = {
/* Note that due to key limitations the below example kybindings are defined with a Mod3Mask, /* Note that due to key limitations the below example kybindings are defined with a Mod3Mask,
* which is not always readily available. Refer to the patch wiki for more details. */ * which is not always readily available. Refer to the patch wiki for more details. */
/* Client position is limited to monitor window area */ /* Client position is limited to monitor window area */
{ Mod3Mask, XK_u, floatpos, {.v = "-26x -26y" } }, { Mod3Mask, XK_u, floatpos, {.v = "-26x -26y" } }, // ↖
{ Mod3Mask, XK_i, floatpos, {.v = " 0x -26y" } }, { Mod3Mask, XK_i, floatpos, {.v = " 0x -26y" } }, // ↑
{ Mod3Mask, XK_o, floatpos, {.v = " 26x -26y" } }, { Mod3Mask, XK_o, floatpos, {.v = " 26x -26y" } }, // ↗
{ Mod3Mask, XK_j, floatpos, {.v = "-26x 0y" } }, { Mod3Mask, XK_j, floatpos, {.v = "-26x 0y" } }, // ←
{ Mod3Mask, XK_l, floatpos, {.v = " 26x 0y" } }, { Mod3Mask, XK_l, floatpos, {.v = " 26x 0y" } }, // →
{ Mod3Mask, XK_m, floatpos, {.v = "-26x 26y" } }, { Mod3Mask, XK_m, floatpos, {.v = "-26x 26y" } }, // ↙
{ Mod3Mask, XK_comma, floatpos, {.v = " 0x 26y" } }, { Mod3Mask, XK_comma, floatpos, {.v = " 0x 26y" } }, // ↓
{ Mod3Mask, XK_period, floatpos, {.v = " 26x 26y" } }, { Mod3Mask, XK_period, floatpos, {.v = " 26x 26y" } }, // ↘
/* Absolute positioning (allows moving windows between monitors) */ /* Absolute positioning (allows moving windows between monitors) */
{ Mod3Mask|ControlMask, XK_u, floatpos, {.v = "-26a -26a" } }, { Mod3Mask|ControlMask, XK_u, floatpos, {.v = "-26a -26a" } }, // ↖
{ Mod3Mask|ControlMask, XK_i, floatpos, {.v = " 0a -26a" } }, { Mod3Mask|ControlMask, XK_i, floatpos, {.v = " 0a -26a" } }, // ↑
{ Mod3Mask|ControlMask, XK_o, floatpos, {.v = " 26a -26a" } }, { Mod3Mask|ControlMask, XK_o, floatpos, {.v = " 26a -26a" } }, // ↗
{ Mod3Mask|ControlMask, XK_j, floatpos, {.v = "-26a 0a" } }, { Mod3Mask|ControlMask, XK_j, floatpos, {.v = "-26a 0a" } }, // ←
{ Mod3Mask|ControlMask, XK_l, floatpos, {.v = " 26a 0a" } }, { Mod3Mask|ControlMask, XK_l, floatpos, {.v = " 26a 0a" } }, // →
{ Mod3Mask|ControlMask, XK_m, floatpos, {.v = "-26a 26a" } }, { Mod3Mask|ControlMask, XK_m, floatpos, {.v = "-26a 26a" } }, // ↙
{ Mod3Mask|ControlMask, XK_comma, floatpos, {.v = " 0a 26a" } }, { Mod3Mask|ControlMask, XK_comma, floatpos, {.v = " 0a 26a" } }, // ↓
{ Mod3Mask|ControlMask, XK_period, floatpos, {.v = " 26a 26a" } }, { Mod3Mask|ControlMask, XK_period, floatpos, {.v = " 26a 26a" } }, // ↘
/* Resize client, client center position is fixed which means that client expands in all directions */ /* Resize client, client center position is fixed which means that client expands in all directions */
{ Mod3Mask|ShiftMask, XK_u, floatpos, {.v = "-26w -26h" } }, { Mod3Mask|ShiftMask, XK_u, floatpos, {.v = "-26w -26h" } }, // ↖
{ Mod3Mask|ShiftMask, XK_i, floatpos, {.v = " 0w -26h" } }, { Mod3Mask|ShiftMask, XK_i, floatpos, {.v = " 0w -26h" } }, // ↑
{ Mod3Mask|ShiftMask, XK_o, floatpos, {.v = " 26w -26h" } }, { Mod3Mask|ShiftMask, XK_o, floatpos, {.v = " 26w -26h" } }, // ↗
{ Mod3Mask|ShiftMask, XK_j, floatpos, {.v = "-26w 0h" } }, { Mod3Mask|ShiftMask, XK_j, floatpos, {.v = "-26w 0h" } }, // ←
{ Mod3Mask|ShiftMask, XK_k, floatpos, {.v = "800W 800H" } }, { Mod3Mask|ShiftMask, XK_k, floatpos, {.v = "800W 800H" } }, // ·
{ Mod3Mask|ShiftMask, XK_l, floatpos, {.v = " 26w 0h" } }, { Mod3Mask|ShiftMask, XK_l, floatpos, {.v = " 26w 0h" } }, // →
{ Mod3Mask|ShiftMask, XK_m, floatpos, {.v = "-26w 26h" } }, { Mod3Mask|ShiftMask, XK_m, floatpos, {.v = "-26w 26h" } }, // ↙
{ Mod3Mask|ShiftMask, XK_comma, floatpos, {.v = " 0w 26h" } }, { Mod3Mask|ShiftMask, XK_comma, floatpos, {.v = " 0w 26h" } }, // ↓
{ Mod3Mask|ShiftMask, XK_period, floatpos, {.v = " 26w 26h" } }, { Mod3Mask|ShiftMask, XK_period, floatpos, {.v = " 26w 26h" } }, // ↘
/* Client is positioned in a floating grid, movement is relative to client's current position */ /* Client is positioned in a floating grid, movement is relative to client's current position */
{ Mod3Mask|Mod1Mask, XK_u, floatpos, {.v = "-1p -1p" } }, { Mod3Mask|Mod1Mask, XK_u, floatpos, {.v = "-1p -1p" } }, // ↖
{ Mod3Mask|Mod1Mask, XK_i, floatpos, {.v = " 0p -1p" } }, { Mod3Mask|Mod1Mask, XK_i, floatpos, {.v = " 0p -1p" } }, // ↑
{ Mod3Mask|Mod1Mask, XK_o, floatpos, {.v = " 1p -1p" } }, { Mod3Mask|Mod1Mask, XK_o, floatpos, {.v = " 1p -1p" } }, // ↗
{ Mod3Mask|Mod1Mask, XK_j, floatpos, {.v = "-1p 0p" } }, { Mod3Mask|Mod1Mask, XK_j, floatpos, {.v = "-1p 0p" } }, // ←
{ Mod3Mask|Mod1Mask, XK_k, floatpos, {.v = " 0p 0p" } }, { Mod3Mask|Mod1Mask, XK_k, floatpos, {.v = " 0p 0p" } }, // ·
{ Mod3Mask|Mod1Mask, XK_l, floatpos, {.v = " 1p 0p" } }, { Mod3Mask|Mod1Mask, XK_l, floatpos, {.v = " 1p 0p" } }, // →
{ Mod3Mask|Mod1Mask, XK_m, floatpos, {.v = "-1p 1p" } }, { Mod3Mask|Mod1Mask, XK_m, floatpos, {.v = "-1p 1p" } }, // ↙
{ Mod3Mask|Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p" } }, { Mod3Mask|Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p" } }, // ↓
{ Mod3Mask|Mod1Mask, XK_period, floatpos, {.v = " 1p 1p" } }, { Mod3Mask|Mod1Mask, XK_period, floatpos, {.v = " 1p 1p" } }, // ↘
#endif // FLOATPOS_PATCH #endif // FLOATPOS_PATCH
#if SETBORDERPX_PATCH #if SETBORDERPX_PATCH
{ MODKEY|ControlMask, XK_minus, setborderpx, {.i = -1 } }, { MODKEY|ControlMask, XK_minus, setborderpx, {.i = -1 } },

@ -19,13 +19,11 @@ void
setfloatpos(Client *c, const char *floatpos) setfloatpos(Client *c, const char *floatpos)
{ {
char xCh, yCh, wCh, hCh; char xCh, yCh, wCh, hCh;
int x, y, w, h, cx, cy, cw, ch, wx, ww, wy, wh, bw; int x, y, w, h, wx, ww, wy, wh;
unsigned int i;
#if FLOATPOS_RESPECT_GAPS_PATCH #if FLOATPOS_RESPECT_GAPS_PATCH
int oh, ov, ih, iv; int oh, ov, ih, iv;
unsigned int n; unsigned int n;
#endif // FLOATPOS_RESPECT_GAPS_PATCH #endif // FLOATPOS_RESPECT_GAPS_PATCH
int absx, absy, absw, absh, delta, rest;
if (!c || !floatpos) if (!c || !floatpos)
return; return;
@ -54,11 +52,6 @@ setfloatpos(Client *c, const char *floatpos)
return; return;
} }
absx = xCh == 'A' || xCh == 'a';
absy = yCh == 'A' || yCh == 'a';
absw = wCh == 'A' || wCh == 'a';
absh = hCh == 'A' || hCh == 'a';
#if FLOATPOS_RESPECT_GAPS_PATCH #if FLOATPOS_RESPECT_GAPS_PATCH
getgaps(c->mon, &oh, &ov, &ih, &iv, &n); getgaps(c->mon, &oh, &ov, &ih, &iv, &n);
wx = c->mon->wx + ov; wx = c->mon->wx + ov;
@ -72,260 +65,127 @@ setfloatpos(Client *c, const char *floatpos)
wh = c->mon->wh; wh = c->mon->wh;
#endif // FLOATPOS_RESPECT_GAPS_PATCH #endif // FLOATPOS_RESPECT_GAPS_PATCH
cx = (!absx && c->x < wx ? wx : c->x); getfloatpos(x, xCh, w, wCh, wx, ww, c->x, c->w, c->bw, floatposgrid_x, &c->x, &c->w);
cy = (!absy && c->y < wy ? wy : c->y); getfloatpos(y, yCh, h, hCh, wy, wh, c->y, c->h, c->bw, floatposgrid_y, &c->y, &c->h);
cw = (!absw && c->w > ww ? ww : c->w); }
ch = (!absh && c->h > wh ? wh : c->h);
/* p - position, s - size, cp and cs represents current position and size */
void
getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s)
{
int abs_p, abs_s, i, delta, rest;
abs_p = pCh == 'A' || pCh == 'a';
abs_s = sCh == 'A' || sCh == 'a';
cs += 2*cbw;
switch(xCh) { switch(pCh) {
case 'A': // absolute position case 'A': // absolute position
cx = x; cp = pos;
break; break;
case 'a': // absolute relative position case 'a': // absolute relative position
cx += x; cp += pos;
break; break;
case 'y':
case 'x': // client relative position case 'x': // client relative position
if (cx + x > ww) cp = MIN(cp + pos, min_p + max_s);
cx = ww;
else
cx += x;
break; break;
case 'Y':
case 'X': // client position relative to monitor case 'X': // client position relative to monitor
if (x > ww) cp = min_p + MIN(pos, max_s);
x = ww;
cx = wx + x;
break; break;
case 'S': // fixed client position (sticky) case 'S': // fixed client position (sticky)
case 'C': // fixed client position (center) case 'C': // fixed client position (center)
case 'Z': // fixed client right-hand position (position + width) case 'Z': // fixed client right-hand position (position + size)
if (x == -1) if (pos == -1)
break; break;
if (x > ww) if (pos > max_s)
x = ww; pos = max_s;
if (x < 0) if (pos < 0)
x = 0; pos = 0;
if (xCh == 'Z') if (pCh == 'Z')
cw = abs((cx + cw) - (wx + x)); cs = abs((cp + cs) - (min_p + pos));
else if (xCh == 'C') else if (pCh == 'C')
cw = abs((cx + cw / 2) - (wx + x)); cs = abs((cp + cs / 2) - (min_p + pos));
else else
cw = abs(cx - (wx + x)); cs = abs(cp - (min_p + pos));
cx = wx + x; cp = min_p + pos;
wCh = 0; // size determined by position, override defined width sCh = 0; // size determined by position, override defined size
break; break;
case 'G': // grid case 'G': // grid
if (x <= 0) if (pos <= 0)
x = floatposgrid_x; // default configurable pos = defgrid; // default configurable
if (w == 0 || x < 2 || (wCh != 'p' && wCh != 'P')) if (size == 0 || pos < 2 || (sCh != 'p' && sCh != 'P'))
break; break;
delta = (ww - cw - 2*c->bw) / (x - 1); delta = (max_s - cs) / (pos - 1);
rest = ww - cw - 2*c->bw - delta * (x - 1); rest = max_s - cs - delta * (pos - 1);
if (wCh == 'P') { if (sCh == 'P') {
if (w < 1 || w > x) if (size < 1 || size > pos)
break; break;
cx = wx + delta * (w - 1); cp = min_p + delta * (size - 1);
} else { } else {
for (i = 0; i < x -1 && cx >= wx + delta * i + (i > x - rest ? i + rest - x + 1 : 0); i++); for (i = 0; i < pos -1 && cp >= min_p + delta * i + (i > pos - rest ? i + rest - pos + 1 : 0); i++);
cx = wx + delta * (MAX(MIN(i + w, x), 1) - 1) + (i > x - rest ? i + rest - x + 1 : 0); cp = min_p + delta * (MAX(MIN(i + size, pos), 1) - 1) + (i > pos - rest ? i + rest - pos + 1 : 0);
} }
break; break;
} }
switch(yCh) { switch(sCh) {
case 'A': // absolute position case 'A': // absolute size
cy = y; cs = size;
break; break;
case 'a': // absolute relative position case 'a': // absolute relative size
cy += y; cs = MAX(1, cs + size);
break; break;
case 'y': // client relative position case '%': // client size percentage in relation to monitor window area size
if (cy + y > wh) if (size <= 0)
cy = wh;
else
cy += y;
break;
case 'Y': // client position relative to monitor
if (y > wh)
y = wh;
cy = wy + y;
break;
case 'S': // fixed client y position (sticky)
case 'C': // fixed client position (center)
case 'Z': // fixed client right-hand position (position + height)
if (y == -1)
break; break;
if (y > wh) size = max_s * MIN(size, 100) / 100;
y = wh;
if (y < 0)
y = 0;
if (yCh == 'Z')
ch = abs((cy + ch) - (wy + y));
else if (yCh == 'C')
ch = abs((cy + ch / 2) - (wy + y));
else
ch = abs(cy - (wy + y));
cy = wy + y;
hCh = 0; // size determined by position, override defined width
break;
case 'G': // grid
if (y <= 0)
y = floatposgrid_y; // default configurable
if (h == 0 || y < 1 || (hCh != 'p' && hCh != 'P'))
break;
delta = (wh - ch - 2*c->bw) / (y - 1);
rest = wh - ch - 2*c->bw - delta * (y - 1);
if (hCh == 'P') {
if (h < 1 || h > y)
break;
cy = wy + delta * (h - 1);
} else {
for (i = 0; i < y - 1 && cy >= wy + delta * i + (i > y - rest ? i + rest - y + 1: 0); i++);
cy = wy + delta * (MAX(MIN(i + h, y), 1) - 1) + (i > y - rest ? i + rest - y + 1: 0);
}
hCh = 0; // size determined by position, override defined width
break;
}
bw = 2*c->bw;
switch(wCh) {
case 'A': // absolute width
cw = w - 2*c->bw;
break;
case 'a': // absolute relative width
if (cw + w < 1)
cw = 1;
else
cw += w;
break;
case '%': // client width percentage in relation to monitor window area width
if (w > 100)
w = 100;
if (w <= 0)
break;
w = ww * w / 100;
/* falls through */
case 'w': // width relative to client
if (wCh == 'w') {
if (w == 0)
break;
else {
w += cw;
bw = 0;
}
}
/* falls through */
case 'W': // normal width, position takes precedence
if (xCh == 'S' && cx + w > wx + ww)
w = wx + ww - cx;
else if (xCh == 'C' && cx + cw / 2 + w / 2 > wx + ww)
w = wx + ww - cx + cw / 2;
else if (xCh == 'Z' && w > cx - ww)
w = cx - wx;
else if (w > ww)
w = ww;
if (xCh == 'C') { // fixed client center, expand or contract client
delta = w - bw - cw;
if (delta < 0 || (cx - delta / 2 + w + 2*c->bw <= wx + ww))
cx -= delta / 2;
else if (cx - delta / 2 < wx)
cx = wx;
else if (delta)
cx = wx + ww - cw - bw;
}
cw = w - bw;
break;
}
bw = 2*c->bw;
switch(hCh) {
case 'A': // absolute height
ch = h - 2*c->bw;
break;
case 'a': // absolute relative height
if (ch + h < 1)
ch = 1;
else
ch += h;
break;
case '%': // client height percentage in relation to monitor window area height
if (h > 100)
h = 100;
if (h <= 0)
break;
h = wh * h / 100;
/* falls through */ /* falls through */
case 'h': // height relative to client case 'h':
if (hCh == 'h') { case 'w': // size relative to client
if (h == 0) if (sCh == 'w' || sCh == 'h') {
if (size == 0)
break; break;
else { size += cs;
h += ch;
bw = 0;
}
} }
/* falls through */ /* falls through */
case 'H': /* normal height, position takes precedence */ case 'H':
if (yCh == 'S' && cy + h > wy + wh) case 'W': // normal size, position takes precedence
h = wy + wh - cy; if (pCh == 'S' && cp + size > min_p + max_s)
else if (yCh == 'C' && cy + ch / 2 + h / 2 > wy + wh) size = min_p + max_s - cp;
h = wy + wh - cy + ch / 2; else if (pCh == 'Z' && size > cp - max_s)
else if (yCh == 'Z' && h > cy - wh) size = cp - min_p;
h = cy - wy; else if (size > max_s)
else if (h > wh) size = max_s;
h = wh;
if (pCh == 'C') { // fixed client center, expand or contract client
if (yCh == 'C') { // fixed client center, expand or contract client delta = size - cs;
delta = h - bw - ch; if (delta < 0 || (cp - delta / 2 + size <= min_p + max_s))
if (delta < 0 || (cy - delta / 2 + ch + 2*c->bw <= wy + wh)) cp -= delta / 2;
cy -= delta / 2; else if (cp - delta / 2 < min_p)
else if (cy - delta / 2 < wy) cp = min_p;
cy = wy;
else if (delta) else if (delta)
cy = wy + wh - ch - bw; cp = min_p + max_s;
} }
ch = h - bw; cs = size;
break; break;
} }
if (xCh == '%') { // client mid-point position in relation to monitor window area width if (pCh == '%') // client mid-point position in relation to monitor window area size
if (x > 100) cp = min_p + max_s * MAX(MIN(pos, 100), 0) / 100 - (cs) / 2;
x = 100;
if (x < 0)
x = 0;
cx = wx + ww * x / 100 - (cw + 2*c->bw) / 2;
}
if (yCh == '%') { // client mid-point position in relation to monitor window area height if (!abs_p && cp < min_p)
if (y > 100) cp = min_p;
y = 100; if (cp + cs > min_p + max_s && !(abs_p && abs_s)) {
if (y < 0) if (abs_p || cp == min_p)
y = 0; cs = min_p + max_s - cp;
cy = wy + wh * y / 100 - (ch + 2*c->bw) / 2;
}
if (!absx && cx < wx)
cx = wx;
if (cx + cw + 2*c->bw > wx + ww && !(absx && absw)) {
if (absx || cx == wx)
cw = ww - cx + wx - 2*c->bw;
else
cx = wx + ww - cw - 2*c->bw;
}
if (!absy && cy < wy)
cy = wy;
if (cy + ch + 2*c->bw > wy + wh && !(absy && absh)) {
if (absy || cy == wy)
ch = wh - cy + wy - 2*c->bw;
else else
cy = wy + wh - ch - 2*c->bw; cp = min_p + max_s - cs;
} }
c->x = cx; *out_p = cp;
c->y = cy; *out_s = MAX(cs - 2*cbw, 1);
c->w = MAX(cw, 1); }
c->h = MAX(ch, 1);
}

@ -1,2 +1,3 @@
static void floatpos(const Arg *arg); static void floatpos(const Arg *arg);
static void setfloatpos(Client *c, const char *floatpos); static void setfloatpos(Client *c, const char *floatpos);
static void getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s);
Loading…
Cancel
Save