summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorbakkeby <[email protected]>2020-06-21 15:33:29 +0200
committerbakkeby <[email protected]>2020-06-21 15:33:29 +0200
commit6a683c729e1e0f9eb8901421ef596ef2423ae92b (patch)
tree80c2c36d724fd7940341369103171eb06c1aebc8
parent8645b2ce3568b4628f40fb99466c154edc0e338f (diff)
downloaddwm-flexipatch-6a683c729e1e0f9eb8901421ef596ef2423ae92b.tar.gz
dwm-flexipatch-6a683c729e1e0f9eb8901421ef596ef2423ae92b.zip
Adding floatpos patch.
-rw-r--r--README.md8
-rw-r--r--config.def.h46
-rw-r--r--dwm.c21
-rw-r--r--patch/floatpos.c331
-rw-r--r--patch/floatpos.h2
-rw-r--r--patch/include.c3
-rw-r--r--patch/include.h3
-rw-r--r--patches.def.h11
8 files changed, 423 insertions, 2 deletions
diff --git a/README.md b/README.md
index 23b362e..6c13433 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t
### Changelog:
+2020-06-21 - Added floatpos patch
+
2020-06-19 - Added tagothermonitor patch
2020-06-15 - Added sizehints patch
@@ -232,6 +234,12 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t
- [floatbordercolor](https://dwm.suckless.org/patches/float_border_color/)
- this patch allows a different border color to be chosen for floating windows
+ - [floatpos](https://github.com/bakkeby/patches/wiki/floatpos)
+ - adds a float rule allowing the size and position of floating windows to be specified
+ - control the size and position of floating windows similar to exresize, moveresize, moveplace patches
+ - specify size and position using absolute, relative or fixed co-ordinates or
+ - position floating windows in a grid-like manner
+
- [focusadjacenttag](https://dwm.suckless.org/patches/focusadjacenttag/)
- provides the ability to focus the tag on the immediate left or right of the currently focused tag
- it also allows to send the focused window either on the left or the right tag
diff --git a/config.def.h b/config.def.h
index 0a43c48..34850a3 100644
--- a/config.def.h
+++ b/config.def.h
@@ -28,6 +28,10 @@ static const int sidepad = 10; /* horizontal padding of bar */
#if FOCUSONCLICK_PATCH
static const int focusonwheel = 0;
#endif // FOCUSONCLICK_PATCH
+#if FLOATPOS_PATCH
+static int floatposgrid_x = 5; /* float grid columns */
+static int floatposgrid_y = 5; /* float grid rows */
+#endif // FLOATPOS_PATCH
#if STATUSPADDING_PATCH
static const int horizpadbar = 2; /* horizontal padding for statusbar */
static const int vertpadbar = 0; /* vertical padding for statusbar */
@@ -1033,6 +1037,48 @@ static Key keys[] = {
{ MODKEY|ControlMask, XK_KP_7, togglemaximize, {.i = +1} }, /* XK_KP_Home, */
{ MODKEY|ControlMask, XK_KP_5, togglemaximize, {.i = 0} }, /* XK_KP_Begin, */
#endif // EXRESIZE_PATCH
+ #if FLOATPOS_PATCH
+ /* 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. */
+ /* Client position is limited to monitor window area */
+ { Mod3Mask, XK_u, floatpos, {.v = "-26x -26y" } },
+ { Mod3Mask, XK_i, floatpos, {.v = " 0x -26y" } },
+ { Mod3Mask, XK_o, floatpos, {.v = " 26x -26y" } },
+ { Mod3Mask, XK_j, floatpos, {.v = "-26x 0y" } },
+ { Mod3Mask, XK_l, floatpos, {.v = " 26x 0y" } },
+ { Mod3Mask, XK_m, floatpos, {.v = "-26x 26y" } },
+ { Mod3Mask, XK_comma, floatpos, {.v = " 0x 26y" } },
+ { Mod3Mask, XK_period, floatpos, {.v = " 26x 26y" } },
+ /* Absolute positioning (allows moving windows between monitors) */
+ { Mod3Mask|ControlMask, XK_u, floatpos, {.v = "-26a -26a" } },
+ { Mod3Mask|ControlMask, XK_i, floatpos, {.v = " 0a -26a" } },
+ { Mod3Mask|ControlMask, XK_o, floatpos, {.v = " 26a -26a" } },
+ { Mod3Mask|ControlMask, XK_j, floatpos, {.v = "-26a 0a" } },
+ { Mod3Mask|ControlMask, XK_l, floatpos, {.v = " 26a 0a" } },
+ { Mod3Mask|ControlMask, XK_m, floatpos, {.v = "-26a 26a" } },
+ { Mod3Mask|ControlMask, XK_comma, floatpos, {.v = " 0a 26a" } },
+ { Mod3Mask|ControlMask, XK_period, floatpos, {.v = " 26a 26a" } },
+ /* 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_i, floatpos, {.v = " 0w -26h" } },
+ { Mod3Mask|ShiftMask, XK_o, floatpos, {.v = " 26w -26h" } },
+ { Mod3Mask|ShiftMask, XK_j, floatpos, {.v = "-26w 0h" } },
+ { Mod3Mask|ShiftMask, XK_k, floatpos, {.v = "800W 800H" } },
+ { Mod3Mask|ShiftMask, XK_l, floatpos, {.v = " 26w 0h" } },
+ { Mod3Mask|ShiftMask, XK_m, floatpos, {.v = "-26w 26h" } },
+ { Mod3Mask|ShiftMask, XK_comma, floatpos, {.v = " 0w 26h" } },
+ { Mod3Mask|ShiftMask, XK_period, floatpos, {.v = " 26w 26h" } },
+ /* 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_i, floatpos, {.v = " 0p -1p" } },
+ { Mod3Mask|Mod1Mask, XK_o, floatpos, {.v = " 1p -1p" } },
+ { Mod3Mask|Mod1Mask, XK_j, floatpos, {.v = "-1p 0p" } },
+ { Mod3Mask|Mod1Mask, XK_k, floatpos, {.v = " 0p 0p" } },
+ { Mod3Mask|Mod1Mask, XK_l, floatpos, {.v = " 1p 0p" } },
+ { Mod3Mask|Mod1Mask, XK_m, floatpos, {.v = "-1p 1p" } },
+ { Mod3Mask|Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p" } },
+ { Mod3Mask|Mod1Mask, XK_period, floatpos, {.v = " 1p 1p" } },
+ #endif // FLOATPOS_PATCH
#if SETBORDERPX_PATCH
{ MODKEY|ControlMask, XK_minus, setborderpx, {.i = -1 } },
{ MODKEY|ControlMask, XK_plus, setborderpx, {.i = +1 } },
diff --git a/dwm.c b/dwm.c
index 3d1d1c6..e4fccd9 100644
--- a/dwm.c
+++ b/dwm.c
@@ -319,6 +319,9 @@ typedef struct {
int isterminal;
int noswallow;
#endif // SWALLOW_PATCH
+ #if FLOATPOS_PATCH
+ const char *floatpos;
+ #endif // FLOATPOS_PATCH
int monitor;
} Rule;
@@ -610,6 +613,11 @@ applyrules(Client *c)
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
}
#endif // SCRATCHPADS_PATCH | SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
+ #if FLOATPOS_PATCH
+ if (c->isfloating && r->floatpos)
+ setfloatpos(c, r->floatpos);
+ #endif // FLOATPOS_PATCH
+
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -2230,6 +2238,13 @@ manage(Window w, XWindowAttributes *wa)
c->tags = t->tags;
} else {
c->mon = selmon;
+ #if FLOATPOS_PATCH
+ #if SETBORDERPX_PATCH
+ c->bw = c->mon->borderpx;
+ #else
+ c->bw = borderpx;
+ #endif // SETBORDERPX_PATCH
+ #endif // FLOATPOS_PATCH
applyrules(c);
#if SWALLOW_PATCH
term = termforwin(c);
@@ -2244,11 +2259,13 @@ manage(Window w, XWindowAttributes *wa)
/* only fix client y-offset, if the client center might cover the bar */
c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
&& (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ #if !FLOATPOS_PATCH
#if SETBORDERPX_PATCH
c->bw = c->mon->borderpx;
#else
c->bw = borderpx;
#endif // SETBORDERPX_PATCH
+ #endif // FLOATPOS_PATCH
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
@@ -2266,8 +2283,8 @@ manage(Window w, XWindowAttributes *wa)
updatewmhints(c);
#if CENTER_PATCH
if (c->iscentered) {
- c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2;
- c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2;
+ c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
+ c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
}
#endif // CENTER_PATCH
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
diff --git a/patch/floatpos.c b/patch/floatpos.c
new file mode 100644
index 0000000..65fec9f
--- /dev/null
+++ b/patch/floatpos.c
@@ -0,0 +1,331 @@
+void
+floatpos(const Arg *arg)
+{
+ Client *c = selmon->sel;
+
+ if (!c || !c->isfloating)
+ return;
+
+ setfloatpos(c, (char *)arg->v);
+ resizeclient(c, c->x, c->y, c->w, c->h);
+
+ #if !FOCUSONCLICK_PATCH
+ XRaiseWindow(dpy, c->win);
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
+ #endif // FOCUSONCLICK_PATCH
+}
+
+void
+setfloatpos(Client *c, const char *floatpos)
+{
+ char xCh, yCh, wCh, hCh;
+ int x, y, w, h, cx, cy, cw, ch, wx, ww, wy, wh, bw;
+ unsigned int i;
+ #if FLOATPOS_RESPECT_GAPS_PATCH
+ int oh, ov, ih, iv;
+ unsigned int n;
+ #endif // FLOATPOS_RESPECT_GAPS_PATCH
+ int absx, absy, absw, absh, delta, rest;
+
+ if (!c || !floatpos)
+ return;
+ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
+ return;
+ switch(sscanf(floatpos, "%d%c %d%c %d%c %d%c", &x, &xCh, &y, &yCh, &w, &wCh, &h, &hCh)) {
+ case 4:
+ if (xCh == 'w' || xCh == 'W') {
+ w = x; wCh = xCh;
+ h = y; hCh = yCh;
+ x = 0; xCh = 'x';
+ y = 0; yCh = 'y';
+ } else if (xCh == 'p' || xCh == 'P') {
+ w = x; wCh = xCh;
+ h = y; hCh = yCh;
+ x = 0; xCh = 'G';
+ y = 0; yCh = 'G';
+ } else {
+ w = -1; wCh = 'C';
+ h = -1; hCh = 'C';
+ }
+ break;
+ case 8:
+ break;
+ default:
+ 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
+ getgaps(c->mon, &oh, &ov, &ih, &iv, &n);
+ wx = c->mon->wx + ov;
+ wy = c->mon->wy + oh;
+ ww = c->mon->ww - 2*ov;
+ wh = c->mon->wh - 2*oh;
+ #else
+ wx = c->mon->wx;
+ wy = c->mon->wy;
+ ww = c->mon->ww;
+ wh = c->mon->wh;
+ #endif // FLOATPOS_RESPECT_GAPS_PATCH
+
+ cx = (!absx && c->x < wx ? wx : c->x);
+ cy = (!absy && c->y < wy ? wy : c->y);
+ cw = (!absw && c->w > ww ? ww : c->w);
+ ch = (!absh && c->h > wh ? wh : c->h);
+
+ switch(xCh) {
+ case 'A': // absolute position
+ cx = x;
+ break;
+ case 'a': // absolute relative position
+ cx += x;
+ break;
+ case 'x': // client relative position
+ if (cx + x > ww)
+ cx = ww;
+ else
+ cx += x;
+ break;
+ case 'X': // client position relative to monitor
+ if (x > ww)
+ x = ww;
+ cx = wx + x;
+ break;
+ case 'S': // fixed client position (sticky)
+ case 'C': // fixed client position (center)
+ case 'Z': // fixed client right-hand position (position + width)
+ if (x == -1)
+ break;
+ if (x > ww)
+ x = ww;
+ if (x < 0)
+ x = 0;
+ if (xCh == 'Z')
+ cw = abs((cx + cw) - (wx + x));
+ else if (xCh == 'C')
+ cw = abs((cx + cw / 2) - (wx + x));
+ else
+ cw = abs(cx - (wx + x));
+ cx = wx + x;
+ wCh = 0; // size determined by position, override defined width
+ break;
+ case 'G': // grid
+ if (x <= 0)
+ x = floatposgrid_x; // default configurable
+ if (w == 0 || x < 2 || (wCh != 'p' && wCh != 'P'))
+ break;
+ delta = (ww - cw - 2*c->bw) / (x - 1);
+ rest = ww - cw - 2*c->bw - delta * (x - 1);
+ if (wCh == 'P') {
+ if (w < 1 || w > x)
+ break;
+ cx = wx + delta * (w - 1);
+ } else {
+ for (i = 0; i < x -1 && cx >= wx + delta * i + (i > x - rest ? i + rest - x + 1 : 0); i++);
+ cx = wx + delta * (MAX(MIN(i + w, x), 1) - 1) + (i > x - rest ? i + rest - x + 1 : 0);
+ }
+ break;
+ }
+
+ switch(yCh) {
+ case 'A': // absolute position
+ cy = y;
+ break;
+ case 'a': // absolute relative position
+ cy += y;
+ break;
+ case 'y': // client relative position
+ if (cy + y > wh)
+ 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;
+ if (y > wh)
+ 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 */
+ case 'h': // height relative to client
+ if (hCh == 'h') {
+ if (h == 0)
+ break;
+ else {
+ h += ch;
+ bw = 0;
+ }
+ }
+ /* falls through */
+ case 'H': /* normal height, position takes precedence */
+ if (yCh == 'S' && cy + h > wy + wh)
+ h = wy + wh - cy;
+ else if (yCh == 'C' && cy + ch / 2 + h / 2 > wy + wh)
+ h = wy + wh - cy + ch / 2;
+ else if (yCh == 'Z' && h > cy - wh)
+ h = cy - wy;
+ else if (h > wh)
+ h = wh;
+
+ if (yCh == 'C') { // fixed client center, expand or contract client
+ delta = h - bw - ch;
+ if (delta < 0 || (cy - delta / 2 + ch + 2*c->bw <= wy + wh))
+ cy -= delta / 2;
+ else if (cy - delta / 2 < wy)
+ cy = wy;
+ else if (delta)
+ cy = wy + wh - ch - bw;
+ }
+
+ ch = h - bw;
+ break;
+ }
+
+ if (xCh == '%') { // client mid-point position in relation to monitor window area width
+ if (x > 100)
+ 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 (y > 100)
+ y = 100;
+ if (y < 0)
+ y = 0;
+ 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
+ cy = wy + wh - ch - 2*c->bw;
+ }
+
+ c->x = cx;
+ c->y = cy;
+ c->w = MAX(cw, 1);
+ c->h = MAX(ch, 1);
+} \ No newline at end of file
diff --git a/patch/floatpos.h b/patch/floatpos.h
new file mode 100644
index 0000000..c0a5853
--- /dev/null
+++ b/patch/floatpos.h
@@ -0,0 +1,2 @@
+static void floatpos(const Arg *arg);
+static void setfloatpos(Client *c, const char *floatpos);
diff --git a/patch/include.c b/patch/include.c
index 47136f2..d574fd6 100644
--- a/patch/include.c
+++ b/patch/include.c
@@ -46,6 +46,9 @@
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
#include "fakefullscreenclient.c"
#endif
+#if FLOATPOS_PATCH
+#include "floatpos.c"
+#endif
#if FOCUSADJACENTTAG_PATCH
#include "focusadjacenttag.c"
#endif
diff --git a/patch/include.h b/patch/include.h
index dca2120..97628aa 100644
--- a/patch/include.h
+++ b/patch/include.h
@@ -49,6 +49,9 @@
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
#include "fakefullscreenclient.h"
#endif
+#if FLOATPOS_PATCH
+#include "floatpos.h"
+#endif
#if FOCUSADJACENTTAG_PATCH
#include "focusadjacenttag.h"
#endif
diff --git a/patches.def.h b/patches.def.h
index d7f4e4b..5bf94d3 100644
--- a/patches.def.h
+++ b/patches.def.h
@@ -219,6 +219,17 @@
*/
#define FLOAT_BORDER_COLOR_PATCH 0
+/* This patch adds a float rule allowing the size and position of floating windows to be specified
+ * It also allows the size and position of floating windows to be controlled similar to the
+ * exresize, moveresize, and moveplace patches.
+ * The size and position can be specified using absolute, relative or fixed co-ordinates and
+ * https://github.com/bakkeby/patches/wiki/floatpos/
+ */
+#define FLOATPOS_PATCH 0
+
+/* Add-on functionality for the above: make the float positions respect outer (vanity)gaps. */
+#define FLOATPOS_RESPECT_GAPS_PATCH 0
+
/* This patch provides the ability to focus the tag on the immediate left or right of the
* currently focused tag. It also allows to send the focused window either on the left or
* the right tag.