dwm-alttabclass-6.4.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-alttabclass-6.4.diff (9326B)
---
1 diff -up a/config.def.h b/config.def.h
2 --- a/config.def.h 2023-08-17 17:35:28.333393605 +0400
3 +++ b/config.def.h 2023-08-17 17:24:46.724435876 +0400
4 @@ -3,6 +3,7 @@
5 /* alt-tab configuration */
6 static const unsigned int tabModKey = 0x40; /* if this key is hold the alt-tab functionality stays acitve. This key must be the same as key that is used to active functin altTabStart `*/
7 static const unsigned int tabCycleKey = 0x17; /* if this key is hit the alt-tab program moves one position forward in clients stack. This key must be the same as key that is used to active functin altTabStart */
8 +static const unsigned int tabCycleKey2 = 0x31; /* grave key */
9 static const unsigned int tabPosY = 1; /* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
10 static const unsigned int tabPosX = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */
11 static const unsigned int maxWTab = 600; /* tab menu width */
12 @@ -93,7 +94,8 @@ static const Key keys[] = {
13 { MODKEY, XK_period, focusmon, {.i = +1 } },
14 { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
15 { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
16 - { Mod1Mask, XK_Tab, altTabStart, {0} },
17 + { Mod1Mask, XK_Tab, altTabStart, {.i = 1} },
18 + { Mod1Mask, XK_grave, altTabStart, {.i = 0} },
19 TAGKEYS( XK_1, 0)
20 TAGKEYS( XK_2, 1)
21 TAGKEYS( XK_3, 2)
22 diff -up a/dwm.c b/dwm.c
23 --- a/dwm.c 2023-08-17 17:24:19.753640383 +0400
24 +++ b/dwm.c 2023-08-18 09:41:00.834187121 +0400
25 @@ -87,6 +87,7 @@ typedef struct Monitor Monitor;
26 typedef struct Client Client;
27 struct Client {
28 char name[256];
29 + char class[256];
30 float mina, maxa;
31 int x, y, w, h;
32 int oldx, oldy, oldw, oldh;
33 @@ -121,7 +122,9 @@ struct Monitor {
34 int mx, my, mw, mh; /* screen size */
35 int wx, wy, ww, wh; /* window area */
36 int altTabN; /* move that many clients forward */
37 + int altTabNc; /* move that many clients forward when using tab for same class */
38 int nTabs; /* number of active clients in tag */
39 + int ncTabs; /* number of active clients under same class in tag */
40 int isAlt; /* 1,0 */
41 int maxWTab;
42 int maxHTab;
43 @@ -134,6 +137,7 @@ struct Monitor {
44 Client *sel;
45 Client *stack;
46 Client ** altsnext; /* array of all clients in the tag */
47 + Client ** altsnextclass; /* array of all clients under same class in the tag */
48 Monitor *next;
49 Window barwin;
50 Window tabwin;
51 @@ -245,6 +249,7 @@ static void zoom(const Arg *arg);
52 void drawTab(int nwins, int first, Monitor *m);
53 void altTabStart(const Arg *arg);
54 static void altTabEnd();
55 +static void getclassname(Client *c);
56
57 /* variables */
58 static const char broken[] = "broken";
59 @@ -657,6 +662,7 @@ createmon(void)
60 m->lt[0] = &layouts[0];
61 m->lt[1] = &layouts[1 % LENGTH(layouts)];
62 m->nTabs = 0;
63 + m->ncTabs = 0;
64 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
65 return m;
66 }
67 @@ -1059,6 +1065,7 @@ manage(Window w, XWindowAttributes *wa)
68 c->oldbw = wa->border_width;
69
70 updatetitle(c);
71 + getclassname(c);
72 if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
73 c->mon = t->mon;
74 c->tags = t->tags;
75 @@ -1683,7 +1690,7 @@ altTab()
76 selmon->altTabN = 0; /* reset altTabN */
77
78 focus(selmon->altsnext[selmon->altTabN]);
79 - restack(selmon);
80 + /* restack(selmon); */
81 }
82
83 /* redraw tab */
84 @@ -1692,8 +1699,64 @@ altTab()
85 }
86
87 void
88 +altTabClass()
89 +{
90 + /* move to next window */
91 + if (selmon->sel != NULL) {
92 + selmon->altTabNc++;
93 + if (selmon->altTabNc >= selmon->ncTabs)
94 + selmon->altTabNc = 0; /* reset altTabNc */
95 +
96 + focus(selmon->altsnextclass[selmon->altTabNc]);
97 + }
98 +
99 + /* redraw tab */
100 + XRaiseWindow(dpy, selmon->tabwin);
101 + drawTab(selmon->ncTabs, 0, selmon);
102 +}
103 +
104 +void
105 +altTabShift()
106 +{
107 + /* move to prev window */
108 + if (selmon->sel != NULL) {
109 + selmon->altTabN--;
110 + if (selmon->altTabN < 0)
111 + selmon->altTabN = selmon->nTabs - 1; /* reset altTabN */
112 +
113 + if (selmon->altsnext[selmon->altTabN]) {
114 + focus(selmon->altsnext[selmon->altTabN]);
115 + }
116 + }
117 +
118 + /* redraw tab */
119 + XRaiseWindow(dpy, selmon->tabwin);
120 + drawTab(selmon->nTabs, 0, selmon);
121 +}
122 +
123 +void
124 +altTabShiftClass()
125 +{
126 + /* move to prev window */
127 + if (selmon->sel != NULL) {
128 + selmon->altTabNc--;
129 + if (selmon->altTabNc < 0)
130 + selmon->altTabNc = selmon->ncTabs - 1; /* reset altTabNc */
131 +
132 + if (selmon->altsnextclass[selmon->altTabNc]) {
133 + focus(selmon->altsnextclass[selmon->altTabNc]);
134 + }
135 + }
136 +
137 + /* redraw tab */
138 + XRaiseWindow(dpy, selmon->tabwin);
139 + drawTab(selmon->ncTabs, 0, selmon);
140 +}
141 +
142 +void
143 altTabEnd()
144 {
145 + Client *buff = NULL;
146 if (selmon->isAlt == 0)
147 return;
148
149 @@ -1703,8 +1766,15 @@ altTabEnd()
150 * so they remain in right order for the next time that alt-tab is used
151 */
152 if (selmon->nTabs > 1) {
153 - if (selmon->altTabN != 0) { /* if user picked original client do nothing */
154 - Client *buff = selmon->altsnext[selmon->altTabN];
155 + if (selmon->altTabN != 0)
156 + buff = selmon->altsnext[selmon->altTabN];
157 + else if (selmon->altTabNc != 0) {
158 + buff = selmon->altsnextclass[selmon->altTabNc];
159 + for (; selmon->altTabN < selmon->nTabs; selmon->altTabN++)
160 + if (selmon->altsnext[selmon->altTabN] == selmon->altsnextclass[selmon->altTabNc])
161 + break;
162 + }
163 + if (buff) { /* if user picked original client do nothing */
164 if (selmon->altTabN > 1)
165 for (int i = selmon->altTabN;i > 0;i--)
166 selmon->altsnext[i] = selmon->altsnext[i - 1];
167 @@ -1720,6 +1790,7 @@ altTabEnd()
168 }
169
170 free(selmon->altsnext); /* free list of clients */
171 + free(selmon->altsnextclass); /* free list of clients */
172 }
173
174 /* turn off/destroy the window */
175 @@ -1779,16 +1850,17 @@ drawTab(int nwins, int first, Monitor *m
176
177 }
178
179 - h = selmon->maxHTab / m->nTabs;
180 + h = selmon->maxHTab / nwins;
181
182 int y = 0;
183 - int n = 0;
184 - for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tabwin */
185 - c = m->altsnext[i];
186 + for (int i = 0; i < nwins; i++) { /* draw all clients into tabwin */
187 + if (nwins == m->nTabs)
188 + c = m->altsnext[i];
189 + else
190 + c = m->altsnextclass[i];
191 if(!ISVISIBLE(c)) continue;
192 /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
193
194 - n++;
195 drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
196 drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
197 y += h;
198 @@ -1801,7 +1873,6 @@ drawTab(int nwins, int first, Monitor *m
199 void
200 altTabStart(const Arg *arg)
201 {
202 - selmon->altsnext = NULL;
203 if (selmon->tabwin)
204 altTabEnd();
205
206 @@ -1810,30 +1881,47 @@ altTabStart(const Arg *arg)
207 } else {
208 selmon->isAlt = 1;
209 selmon->altTabN = 0;
210 + selmon->altTabNc = 0;
211
212 Client *c;
213 Monitor *m = selmon;
214
215 + char tempclass[256] = {'\0'};
216 + if (selmon->sel)
217 + strncpy(tempclass, selmon->sel->class, 256);
218 +
219 m->nTabs = 0;
220 + m->ncTabs = 0;
221 for(c = m->clients; c; c = c->next) { /* count clients */
222 if(!ISVISIBLE(c)) continue;
223 /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
224
225 ++m->nTabs;
226 +
227 + if (!strcmp(c->class, tempclass))
228 + ++m->ncTabs;
229 }
230
231 if (m->nTabs > 0) {
232 m->altsnext = (Client **) malloc(m->nTabs * sizeof(Client *));
233 + m->altsnextclass = (Client **) malloc(m->ncTabs * sizeof(Client *));
234
235 int listIndex = 0;
236 + int listIndexc = 0;
237 for(c = m->stack; c; c = c->snext) { /* add clients to the list */
238 if(!ISVISIBLE(c)) continue;
239 /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
240
241 m->altsnext[listIndex++] = c;
242 +
243 + if (!strcmp(c->class, tempclass))
244 + m->altsnextclass[listIndexc++] = c;
245 }
246
247 - drawTab(m->nTabs, 1, m);
248 + if (arg->i)
249 + drawTab(m->nTabs, 1, m);
250 + else
251 + drawTab(m->ncTabs, 1, m);
252
253 struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
254
255 @@ -1848,7 +1936,10 @@ altTabStart(const Arg *arg)
256 }
257
258 XEvent event;
259 - altTab();
260 + if (arg->i)
261 + altTab();
262 + else
263 + altTabClass();
264 if (grabbed == 0) {
265 altTabEnd();
266 } else {
267 @@ -1858,8 +1949,19 @@ altTabStart(const Arg *arg)
268 if (event.type == KeyRelease && event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
269 break;
270 } else if (event.type == KeyPress) {
271 - if (event.xkey.keycode == tabCycleKey) {/* if XK_s is pressed move to the next window */
272 - altTab();
273 + if (event.xkey.keycode == tabCycleKey || event.xkey.keycode == tabCycleKey2 ) { /* if XK_s is pressed move to the next window */
274 + if (arg->i) {
275 + if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
276 + altTabShift();
277 + else
278 + altTab();
279 + } else {
280 + if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
281 + altTabShiftClass();
282 + else
283 + altTabClass();
284 + }
285 +
286 }
287 }
288 }
289 @@ -2231,6 +2333,15 @@ updatetitle(Client *c)
290 strcpy(c->name, broken);
291 }
292
293 +void
294 +getclassname(Client *c)
295 +{
296 + gettextprop(c->win, XA_WM_CLASS, c->class, sizeof c->class);
297 +
298 + if (c->class[0] == '\0') /* hack to mark broken clients */
299 + strcpy(c->name, broken);
300 +}
301 +
302 void
303 updatewindowtype(Client *c)
304 {