Introduction
Introduction Statistics Contact Development Disclaimer Help
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
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.