-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathdwm-floatpos-6.2.diff
368 lines (357 loc) · 13.3 KB
/
dwm-floatpos-6.2.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
From f36404de22ffddca320fc0f550ac289d0d83cc77 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Wed, 26 Jun 2024 10:00:53 +0200
Subject: [PATCH] floatpos: Control the size and position of floating windows
This patch offers a comprehensive and monitor size agnostic way
of positioning new and existing floating windows.
Refer to:
/~https://github.com/bakkeby/patches/wiki/floatpos/
---
config.def.h | 46 +++++++++++-
dwm.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 233 insertions(+), 5 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..8605e95 100644
--- a/config.def.h
+++ b/config.def.h
@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
+static int floatposgrid_x = 5; /* float grid columns */
+static int floatposgrid_y = 5; /* float grid rows */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
@@ -26,9 +28,9 @@ static const Rule rules[] = {
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
- /* class instance title tags mask isfloating monitor */
- { "Gimp", NULL, NULL, 0, 1, -1 },
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
+ /* class instance title tags mask isfloating floatpos monitor */
+ { "Gimp", NULL, NULL, 0, 1, NULL, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, NULL, -1 },
};
/* layout(s) */
@@ -84,6 +86,44 @@ static Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ /* Client position is limited to monitor window area */
+ { Mod4Mask, XK_u, floatpos, {.v = "-26x -26y" } }, // ↖
+ { Mod4Mask, XK_i, floatpos, {.v = " 0x -26y" } }, // ↑
+ { Mod4Mask, XK_o, floatpos, {.v = " 26x -26y" } }, // ↗
+ { Mod4Mask, XK_j, floatpos, {.v = "-26x 0y" } }, // ←
+ { Mod4Mask, XK_l, floatpos, {.v = " 26x 0y" } }, // →
+ { Mod4Mask, XK_m, floatpos, {.v = "-26x 26y" } }, // ↙
+ { Mod4Mask, XK_comma, floatpos, {.v = " 0x 26y" } }, // ↓
+ { Mod4Mask, XK_period, floatpos, {.v = " 26x 26y" } }, // ↘
+ /* Absolute positioning (allows moving windows between monitors) */
+ { Mod4Mask|ControlMask, XK_u, floatpos, {.v = "-26a -26a" } }, // ↖
+ { Mod4Mask|ControlMask, XK_i, floatpos, {.v = " 0a -26a" } }, // ↑
+ { Mod4Mask|ControlMask, XK_o, floatpos, {.v = " 26a -26a" } }, // ↗
+ { Mod4Mask|ControlMask, XK_j, floatpos, {.v = "-26a 0a" } }, // ←
+ { Mod4Mask|ControlMask, XK_l, floatpos, {.v = " 26a 0a" } }, // →
+ { Mod4Mask|ControlMask, XK_m, floatpos, {.v = "-26a 26a" } }, // ↙
+ { Mod4Mask|ControlMask, XK_comma, floatpos, {.v = " 0a 26a" } }, // ↓
+ { Mod4Mask|ControlMask, XK_period, floatpos, {.v = " 26a 26a" } }, // ↘
+ /* Resize client, client center position is fixed which means that client expands in all directions */
+ { Mod4Mask|ShiftMask, XK_u, floatpos, {.v = "-26w -26h" } }, // ↖
+ { Mod4Mask|ShiftMask, XK_i, floatpos, {.v = " 0w -26h" } }, // ↑
+ { Mod4Mask|ShiftMask, XK_o, floatpos, {.v = " 26w -26h" } }, // ↗
+ { Mod4Mask|ShiftMask, XK_j, floatpos, {.v = "-26w 0h" } }, // ←
+ { Mod4Mask|ShiftMask, XK_k, floatpos, {.v = "800W 800H" } }, // ·
+ { Mod4Mask|ShiftMask, XK_l, floatpos, {.v = " 26w 0h" } }, // →
+ { Mod4Mask|ShiftMask, XK_m, floatpos, {.v = "-26w 26h" } }, // ↙
+ { Mod4Mask|ShiftMask, XK_comma, floatpos, {.v = " 0w 26h" } }, // ↓
+ { Mod4Mask|ShiftMask, XK_period, floatpos, {.v = " 26w 26h" } }, // ↘
+ /* Client is positioned in a floating grid, movement is relative to client's current position */
+ { Mod4Mask|Mod1Mask, XK_u, floatpos, {.v = "-1p -1p" } }, // ↖
+ { Mod4Mask|Mod1Mask, XK_i, floatpos, {.v = " 0p -1p" } }, // ↑
+ { Mod4Mask|Mod1Mask, XK_o, floatpos, {.v = " 1p -1p" } }, // ↗
+ { Mod4Mask|Mod1Mask, XK_j, floatpos, {.v = "-1p 0p" } }, // ←
+ { Mod4Mask|Mod1Mask, XK_k, floatpos, {.v = " 0p 0p" } }, // ·
+ { Mod4Mask|Mod1Mask, XK_l, floatpos, {.v = " 1p 0p" } }, // →
+ { Mod4Mask|Mod1Mask, XK_m, floatpos, {.v = "-1p 1p" } }, // ↙
+ { Mod4Mask|Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p" } }, // ↓
+ { Mod4Mask|Mod1Mask, XK_period, floatpos, {.v = " 1p 1p" } }, // ↘
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
diff --git a/dwm.c b/dwm.c
index 4465af1..d56622e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -93,6 +93,7 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ int ignoresizehints;
Client *next;
Client *snext;
Monitor *mon;
@@ -138,6 +139,7 @@ typedef struct {
const char *title;
unsigned int tags;
int isfloating;
+ const char *floatpos;
int monitor;
} Rule;
@@ -165,10 +167,12 @@ static void drawbar(Monitor *m);
static void drawbars(void);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
+static void floatpos(const Arg *arg);
static void focus(Client *c);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
+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);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@@ -197,6 +201,7 @@ static void scan(void);
static int sendevent(Client *c, Atom proto);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
+static void setfloatpos(Client *c, const char *floatpos);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg);
@@ -302,6 +307,8 @@ applyrules(Client *c)
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
+ if (c->isfloating && r->floatpos)
+ setfloatpos(c, r->floatpos);
}
}
if (ch.res_class)
@@ -343,7 +350,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
*h = bh;
if (*w < bh)
*w = bh;
- if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
+ if (!c->ignoresizehints && (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange)) {
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh;
if (!baseismin) { /* temporarily remove base dimensions */
@@ -780,6 +787,21 @@ expose(XEvent *e)
drawbar(m);
}
+void
+floatpos(const Arg *arg)
+{
+ Client *c = selmon->sel;
+
+ if (!c || (selmon->lt[selmon->sellt]->arrange && !c->isfloating))
+ return;
+
+ setfloatpos(c, (char *)arg->v);
+ resizeclient(c, c->x, c->y, c->w, c->h);
+
+ XRaiseWindow(dpy, c->win);
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
+}
+
void
focus(Client *c)
{
@@ -871,6 +893,124 @@ getatomprop(Client *c, Atom prop)
return atom;
}
+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(pCh) {
+ case 'A': // absolute position
+ cp = pos;
+ break;
+ case 'a': // absolute relative position
+ cp += pos;
+ break;
+ case 'y':
+ case 'x': // client relative position
+ cp = MIN(cp + pos, min_p + max_s);
+ break;
+ case 'Y':
+ case 'X': // client position relative to monitor
+ cp = min_p + MIN(pos, max_s);
+ break;
+ case 'S': // fixed client position (sticky)
+ case 'C': // fixed client position (center)
+ case 'Z': // fixed client right-hand position (position + size)
+ if (pos == -1)
+ break;
+ pos = MAX(MIN(pos, max_s), 0);
+ if (pCh == 'Z')
+ cs = abs((cp + cs) - (min_p + pos));
+ else if (pCh == 'C')
+ cs = abs((cp + cs / 2) - (min_p + pos));
+ else
+ cs = abs(cp - (min_p + pos));
+ cp = min_p + pos;
+ sCh = 0; // size determined by position, override defined size
+ break;
+ case 'G': // grid
+ if (pos <= 0)
+ pos = defgrid; // default configurable
+ if (size == 0 || pos < 2 || (sCh != 'p' && sCh != 'P'))
+ break;
+ delta = (max_s - cs) / (pos - 1);
+ rest = max_s - cs - delta * (pos - 1);
+ if (sCh == 'P') {
+ if (size < 1 || size > pos)
+ break;
+ cp = min_p + delta * (size - 1);
+ } else {
+ for (i = 0; i < pos && cp >= min_p + delta * i + (i > pos - rest ? i + rest - pos + 1 : 0); i++);
+ cp = min_p + delta * (MAX(MIN(i + size, pos), 1) - 1) + (i > pos - rest ? i + rest - pos + 1 : 0);
+ }
+ break;
+ }
+
+ switch(sCh) {
+ case 'A': // absolute size
+ cs = size;
+ break;
+ case 'a': // absolute relative size
+ cs = MAX(1, cs + size);
+ break;
+ case '%': // client size percentage in relation to monitor window area size
+ if (size <= 0)
+ break;
+ size = max_s * MIN(size, 100) / 100;
+ /* falls through */
+ case 'h':
+ case 'w': // size relative to client
+ if (sCh == 'w' || sCh == 'h') {
+ if (size == 0)
+ break;
+ size += cs;
+ }
+ /* falls through */
+ case 'H':
+ case 'W': // normal size, position takes precedence
+ if (pCh == 'S' && cp + size > min_p + max_s)
+ size = min_p + max_s - cp;
+ else if (size > max_s)
+ size = max_s;
+
+ if (pCh == 'C') { // fixed client center, expand or contract client
+ delta = size - cs;
+ if (delta < 0 || (cp - delta / 2 + size <= min_p + max_s))
+ cp -= delta / 2;
+ else if (cp - delta / 2 < min_p)
+ cp = min_p;
+ else if (delta)
+ cp = min_p + max_s;
+ } else if (pCh == 'Z')
+ cp -= size - cs;
+
+ cs = size;
+ break;
+ }
+
+ if (pCh == '%') // client mid-point position in relation to monitor window area size
+ cp = min_p + max_s * MAX(MIN(pos, 100), 0) / 100 - (cs) / 2;
+ if (pCh == 'm' || pCh == 'M')
+ cp = pos - cs / 2;
+
+ if (!abs_p && cp < min_p)
+ cp = min_p;
+ if (cp + cs > min_p + max_s && !(abs_p && abs_s)) {
+ if (abs_p || cp == min_p)
+ cs = min_p + max_s - cp;
+ else
+ cp = min_p + max_s - cs;
+ }
+
+ *out_p = cp;
+ *out_s = MAX(cs - 2*cbw, 1);
+}
+
int
getrootptr(int *x, int *y)
{
@@ -1029,8 +1169,10 @@ manage(Window w, XWindowAttributes *wa)
c->w = c->oldw = wa->width;
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
+ c->ignoresizehints = 0;
updatetitle(c);
+ c->bw = borderpx;
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
c->tags = t->tags;
@@ -1047,7 +1189,6 @@ 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);
- c->bw = borderpx;
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
@@ -1457,6 +1598,53 @@ sendevent(Client *c, Atom proto)
return exists;
}
+void
+setfloatpos(Client *c, const char *floatpos)
+{
+ char xCh, yCh, wCh, hCh;
+ int x, y, w, h, wx, ww, wy, wh;
+
+ 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 = -1; xCh = 'C';
+ y = -1; yCh = 'C';
+ } else if (xCh == 'p' || xCh == 'P') {
+ w = x; wCh = xCh;
+ h = y; hCh = yCh;
+ x = 0; xCh = 'G';
+ y = 0; yCh = 'G';
+ } else if (xCh == 'm' || xCh == 'M') {
+ getrootptr(&x, &y);
+ } else {
+ w = 0; wCh = 0;
+ h = 0; hCh = 0;
+ }
+ break;
+ case 8:
+ if (xCh == 'm' || xCh == 'M')
+ getrootptr(&x, &y);
+ break;
+ default:
+ return;
+ }
+
+ wx = c->mon->wx;
+ wy = c->mon->wy;
+ ww = c->mon->ww;
+ wh = c->mon->wh;
+ c->ignoresizehints = 1;
+
+ getfloatpos(x, xCh, w, wCh, wx, ww, c->x, c->w, c->bw, floatposgrid_x, &c->x, &c->w);
+ getfloatpos(y, yCh, h, hCh, wy, wh, c->y, c->h, c->bw, floatposgrid_y, &c->y, &c->h);
+}
+
void
setfocus(Client *c)
{
--
2.45.2