dwm-alttab-20220709-d3f93c7.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-alttab-20220709-d3f93c7.diff (10048B) | |
--- | |
1 From ec9fcfe019623ec6aff6476b6838eb4863098cf0 Mon Sep 17 00:00:00 2001 | |
2 From: ViliamKovac1223 <[email protected]> | |
3 Date: Sat, 9 Jul 2022 02:58:18 +0200 | |
4 Subject: [PATCH] add alt-tab functionality | |
5 | |
6 --- | |
7 config.def.h | 11 ++- | |
8 dwm.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++ | |
9 2 files changed, 228 insertions(+), 1 deletion(-) | |
10 | |
11 diff --git a/config.def.h b/config.def.h | |
12 index a2ac963..3760870 100644 | |
13 --- a/config.def.h | |
14 +++ b/config.def.h | |
15 @@ -1,5 +1,13 @@ | |
16 /* See LICENSE file for copyright and license details. */ | |
17 | |
18 +/* alt-tab configuration */ | |
19 +static const unsigned int tabModKey = 0x40; /* i… | |
20 +static const unsigned int tabCycleKey = 0x17; /*… | |
21 +static const unsigned int tabPosY = 1; /… | |
22 +static const unsigned int tabPosX = 1; /… | |
23 +static const unsigned int maxWTab = 600; … | |
24 +static const unsigned int maxHTab = 200; … | |
25 + | |
26 /* appearance */ | |
27 static const unsigned int borderpx = 1; /* border pixel of wind… | |
28 static const unsigned int snap = 32; /* snap pixel */ | |
29 @@ -72,7 +80,7 @@ static Key keys[] = { | |
30 { MODKEY, XK_h, setmfact, {.f … | |
31 { MODKEY, XK_l, setmfact, {.f … | |
32 { MODKEY, XK_Return, zoom, {0} … | |
33 - { MODKEY, XK_Tab, view, {0} … | |
34 + { MODKEY, XK_q, view, … | |
35 { MODKEY|ShiftMask, XK_c, killclient, {0} … | |
36 { MODKEY, XK_t, setlayout, {.v … | |
37 { MODKEY, XK_f, setlayout, {.v … | |
38 @@ -85,6 +93,7 @@ static Key keys[] = { | |
39 { MODKEY, XK_period, focusmon, {.i … | |
40 { MODKEY|ShiftMask, XK_comma, tagmon, {.i … | |
41 { MODKEY|ShiftMask, XK_period, tagmon, {.i … | |
42 + { Mod1Mask, XK_Tab, altTabStart,… | |
43 TAGKEYS( XK_1, 0) | |
44 TAGKEYS( XK_2, 1) | |
45 TAGKEYS( XK_3, 2) | |
46 diff --git a/dwm.c b/dwm.c | |
47 index 5646a5c..90edf9b 100644 | |
48 --- a/dwm.c | |
49 +++ b/dwm.c | |
50 @@ -40,6 +40,7 @@ | |
51 #include <X11/extensions/Xinerama.h> | |
52 #endif /* XINERAMA */ | |
53 #include <X11/Xft/Xft.h> | |
54 +#include <time.h> | |
55 | |
56 #include "drw.h" | |
57 #include "util.h" | |
58 @@ -119,6 +120,11 @@ struct Monitor { | |
59 int by; /* bar geometry */ | |
60 int mx, my, mw, mh; /* screen size */ | |
61 int wx, wy, ww, wh; /* window area */ | |
62 + int altTabN; /* move that many clients forward… | |
63 + int nTabs; /* number of active clients… | |
64 + int isAlt; /* 1,0 */ | |
65 + int maxWTab; | |
66 + int maxHTab; | |
67 unsigned int seltags; | |
68 unsigned int sellt; | |
69 unsigned int tagset[2]; | |
70 @@ -127,8 +133,10 @@ struct Monitor { | |
71 Client *clients; | |
72 Client *sel; | |
73 Client *stack; | |
74 + Client ** altsnext; /* array of all clients in the tag */ | |
75 Monitor *next; | |
76 Window barwin; | |
77 + Window tabwin; | |
78 const Layout *lt[2]; | |
79 }; | |
80 | |
81 @@ -234,6 +242,9 @@ static int xerror(Display *dpy, XErrorEvent *ee); | |
82 static int xerrordummy(Display *dpy, XErrorEvent *ee); | |
83 static int xerrorstart(Display *dpy, XErrorEvent *ee); | |
84 static void zoom(const Arg *arg); | |
85 +void drawTab(int nwins, int first, Monitor *m); | |
86 +void altTabStart(const Arg *arg); | |
87 +static void altTabEnd(); | |
88 | |
89 /* variables */ | |
90 static const char broken[] = "broken"; | |
91 @@ -477,6 +488,7 @@ cleanup(void) | |
92 Monitor *m; | |
93 size_t i; | |
94 | |
95 + altTabEnd(); | |
96 view(&a); | |
97 selmon->lt[selmon->sellt] = &foo; | |
98 for (m = mons; m; m = m->next) | |
99 @@ -644,6 +656,7 @@ createmon(void) | |
100 m->topbar = topbar; | |
101 m->lt[0] = &layouts[0]; | |
102 m->lt[1] = &layouts[1 % LENGTH(layouts)]; | |
103 + m->nTabs = 0; | |
104 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | |
105 return m; | |
106 } | |
107 @@ -1659,6 +1672,211 @@ spawn(const Arg *arg) | |
108 } | |
109 } | |
110 | |
111 +void | |
112 +altTab() | |
113 +{ | |
114 + /* move to next window */ | |
115 + if (selmon->sel != NULL && selmon->sel->snext != NULL) { | |
116 + selmon->altTabN++; | |
117 + if (selmon->altTabN >= selmon->nTabs) | |
118 + selmon->altTabN = 0; /* reset altTabN */ | |
119 + | |
120 + focus(selmon->altsnext[selmon->altTabN]); | |
121 + restack(selmon); | |
122 + } | |
123 + | |
124 + /* redraw tab */ | |
125 + XRaiseWindow(dpy, selmon->tabwin); | |
126 + drawTab(selmon->nTabs, 0, selmon); | |
127 +} | |
128 + | |
129 +void | |
130 +altTabEnd() | |
131 +{ | |
132 + if (selmon->isAlt == 0) | |
133 + return; | |
134 + | |
135 + /* | |
136 + * move all clients between 1st and choosen position, | |
137 + * one down in stack and put choosen client to the first positio… | |
138 + * so they remain in right order for the next time that alt-tab … | |
139 + */ | |
140 + if (selmon->nTabs > 1) { | |
141 + if (selmon->altTabN != 0) { /* if user picked original … | |
142 + Client *buff = selmon->altsnext[selmon->altTabN… | |
143 + if (selmon->altTabN > 1) | |
144 + for (int i = selmon->altTabN;i > 0;i--) | |
145 + selmon->altsnext[i] = selmon->a… | |
146 + else /* swap them if there are just 2 clients */ | |
147 + selmon->altsnext[selmon->altTabN] = sel… | |
148 + selmon->altsnext[0] = buff; | |
149 + } | |
150 + | |
151 + /* restack clients */ | |
152 + for (int i = selmon->nTabs - 1;i >= 0;i--) { | |
153 + focus(selmon->altsnext[i]); | |
154 + restack(selmon); | |
155 + } | |
156 + | |
157 + free(selmon->altsnext); /* free list of clients */ | |
158 + } | |
159 + | |
160 + /* turn off/destroy the window */ | |
161 + selmon->isAlt = 0; | |
162 + selmon->nTabs = 0; | |
163 + XUnmapWindow(dpy, selmon->tabwin); | |
164 + XDestroyWindow(dpy, selmon->tabwin); | |
165 +} | |
166 + | |
167 +void | |
168 +drawTab(int nwins, int first, Monitor *m) | |
169 +{ | |
170 + /* little documentation of functions */ | |
171 + /* void drw_rect(Drw *drw, int x, int y, unsigned int w, unsign… | |
172 + /* int drw_text(Drw *drw, int x, int y, unsigned int w, unsigne… | |
173 + /* void drw_map(Drw *drw, Window win, int x, int y, unsigned in… | |
174 + | |
175 + Client *c; | |
176 + int h; | |
177 + | |
178 + if (first) { | |
179 + Monitor *m = selmon; | |
180 + XSetWindowAttributes wa = { | |
181 + .override_redirect = True, | |
182 + .background_pixmap = ParentRelative, | |
183 + .event_mask = ButtonPressMask|ExposureMask | |
184 + }; | |
185 + | |
186 + selmon->maxWTab = maxWTab; | |
187 + selmon->maxHTab = maxHTab; | |
188 + | |
189 + /* decide position of tabwin */ | |
190 + int posX = 0; | |
191 + int posY = 0; | |
192 + if (tabPosX == 0) | |
193 + posX = 0; | |
194 + if (tabPosX == 1) | |
195 + posX = (selmon->mw / 2) - (maxWTab / 2); | |
196 + if (tabPosX == 2) | |
197 + posX = selmon->mw - maxWTab; | |
198 + | |
199 + if (tabPosY == 0) | |
200 + posY = selmon->mh - maxHTab; | |
201 + if (tabPosY == 1) | |
202 + posY = (selmon->mh / 2) - (maxHTab / 2); | |
203 + if (tabPosY == 2) | |
204 + posY = 0; | |
205 + | |
206 + h = selmon->maxHTab; | |
207 + /* XCreateWindow(display, parent, x, y, width, height, … | |
208 + m->tabwin = XCreateWindow(dpy, root, posX, posY, selmon… | |
209 + CopyFro… | |
210 + CWOverr… | |
211 + | |
212 + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor… | |
213 + XMapRaised(dpy, m->tabwin); | |
214 + | |
215 + } | |
216 + | |
217 + h = selmon->maxHTab / m->nTabs; | |
218 + | |
219 + int y = 0; | |
220 + int n = 0; | |
221 + for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tab… | |
222 + c = m->altsnext[i]; | |
223 + if(!ISVISIBLE(c)) continue; | |
224 + /* if (HIDDEN(c)) continue; uncomment if you're using a… | |
225 + | |
226 + n++; | |
227 + drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : S… | |
228 + drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0); | |
229 + y += h; | |
230 + } | |
231 + | |
232 + drw_setscheme(drw, scheme[SchemeNorm]); | |
233 + drw_map(drw, m->tabwin, 0, 0, selmon->maxWTab, selmon->maxHTab); | |
234 +} | |
235 + | |
236 +void | |
237 +altTabStart(const Arg *arg) | |
238 +{ | |
239 + selmon->altsnext = NULL; | |
240 + if (selmon->tabwin) | |
241 + altTabEnd(); | |
242 + | |
243 + if (selmon->isAlt == 1) { | |
244 + altTabEnd(); | |
245 + } else { | |
246 + selmon->isAlt = 1; | |
247 + selmon->altTabN = 0; | |
248 + | |
249 + Client *c; | |
250 + Monitor *m = selmon; | |
251 + | |
252 + m->nTabs = 0; | |
253 + for(c = m->clients; c; c = c->next) { /* count clients … | |
254 + if(!ISVISIBLE(c)) continue; | |
255 + /* if (HIDDEN(c)) continue; uncomment if you're… | |
256 + | |
257 + ++m->nTabs; | |
258 + } | |
259 + | |
260 + if (m->nTabs > 0) { | |
261 + m->altsnext = (Client **) malloc(m->nTabs * siz… | |
262 + | |
263 + int listIndex = 0; | |
264 + for(c = m->stack; c; c = c->snext) { /* add cli… | |
265 + if(!ISVISIBLE(c)) continue; | |
266 + /* if (HIDDEN(c)) continue; uncomment i… | |
267 + | |
268 + m->altsnext[listIndex++] = c; | |
269 + } | |
270 + | |
271 + drawTab(m->nTabs, 1, m); | |
272 + | |
273 + struct timespec ts = { .tv_sec = 0, .tv_nsec = … | |
274 + | |
275 + /* grab keyboard (take all input from keyboard)… | |
276 + int grabbed = 1; | |
277 + for (int i = 0;i < 1000;i++) { | |
278 + if (XGrabKeyboard(dpy, DefaultRootWindo… | |
279 + break; | |
280 + nanosleep(&ts, NULL); | |
281 + if (i == 1000 - 1) | |
282 + grabbed = 0; | |
283 + } | |
284 + | |
285 + XEvent event; | |
286 + altTab(); | |
287 + if (grabbed == 0) { | |
288 + altTabEnd(); | |
289 + } else { | |
290 + while (grabbed) { | |
291 + XNextEvent(dpy, &event); | |
292 + if (event.type == KeyPress || e… | |
293 + if (event.type == KeyRe… | |
294 + break; | |
295 + } else if (event.type =… | |
296 + if (event.xkey.… | |
297 + altTab(… | |
298 + } | |
299 + } | |
300 + } | |
301 + } | |
302 + | |
303 + c = selmon->sel; | |
304 + altTabEnd(); /* end the alt-tab functio… | |
305 + /* XUngrabKeyboard(display, time); just… | |
306 + XUngrabKeyboard(dpy, CurrentTime); /* s… | |
307 + focus(c); | |
308 + restack(selmon); | |
309 + } | |
310 + } else { | |
311 + altTabEnd(); /* end the alt-tab functionality */ | |
312 + } | |
313 + } | |
314 +} | |
315 + | |
316 void | |
317 tag(const Arg *arg) | |
318 { | |
319 -- | |
320 2.35.1 | |
321 |