summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLM-LCL <hello@exaltedelite.club>2024-11-25 04:16:28 +0100
committerLM-LCL <hello@exaltedelite.club>2024-11-25 04:16:28 +0100
commit4487767884544aa089bd2509f8565f72973197f0 (patch)
tree94fcbe0c9b02e021e4afd0e73d4837e642c87367
parent7267c642c64a79f33c425a15e78892554b38f6d4 (diff)
Custom alt-tab
-rw-r--r--config.def.h158
-rw-r--r--config.h36
-rw-r--r--dwm.c329
-rw-r--r--patches/dwm-alttab-6.4.diff322
-rw-r--r--patches/dwm-alttabclass-6.4.diff304
5 files changed, 86 insertions, 1063 deletions
diff --git a/config.def.h b/config.def.h
index 7873a78..4278ea7 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,36 +1,26 @@
/* See LICENSE file for copyright and license details. */
-/* alt-tab configuration */
-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 `*/
-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 */
-static const unsigned int tabCycleKey2 = 0x31; /* grave key */
-static const unsigned int tabPosY = 1; /* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
-static const unsigned int tabPosX = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */
-static const unsigned int maxWTab = 600; /* tab menu width */
-static const unsigned int maxHTab = 200; /* tab menu height */
-
/* appearance */
-static const unsigned int borderpx = 1; /* border pixel of windows */
-static const unsigned int snap = 32; /* snap pixel */
-static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
-static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
-static const unsigned int systrayspacing = 2; /* systray spacing */
-static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
-static const int showsystray = 1; /* 0 means no systray */
-static const int showbar = 1; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
-static const int focusonwheel = 0;
-static const char *fonts[] = { "monospace:size=10" };
-static const char dmenufont[] = "monospace:size=10";
-static const char col_gray1[] = "#222222";
-static const char col_gray2[] = "#444444";
-static const char col_gray3[] = "#bbbbbb";
-static const char col_gray4[] = "#eeeeee";
-static const char col_cyan[] = "#005577";
-static const char *colors[][3] = {
+static const unsigned int borderpx = 1; /* border pixel of windows */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayonleft = 1; /* 0: systray in the right corner, >0: systray on left of status text */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
+static const int showbar = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
+static const int focusonwheel = 0;
+static const char *fonts[] = { "monospace:size=12" };
+static const char dmenufont[] = "monospace:size=12";
+static const char col_gray1[] = "#282c34";
+static const char col_gray2[] = "#353b45";
+static const char col_white[] = "#abb2bf";
+static const char col_orange[] = "#ff6a00";
+static const char *colors[][3] = {
/* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+ [SchemeNorm] = { col_white, col_gray1, col_gray2 },
+ [SchemeSel] = { col_white, col_gray2, col_orange },
};
/* tagging */
@@ -43,15 +33,16 @@ static const Rule rules[] = {
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
+ { "scrcpy", NULL, NULL, 0, 1, -1 },
+ /* { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, */
};
/* layout(s) */
-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
-static const int nmaster = 1; /* number of clients in master area */
-static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
-static const int attachbelow = 1; /* 1 means attach after the currently active window */
-static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
+static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
+static const int nmaster = 1; /* number of clients in master area */
+static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
+static const int attachbelow = 1; /* 1 means attach after the currently active window */
+static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const Layout layouts[] = {
/* symbol arrange function */
@@ -73,69 +64,66 @@ static const Layout layouts[] = {
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_white, "-sb", col_gray2, "-sf", col_white, NULL };
static const char *termcmd[] = { "st", NULL };
+static const char *rofitab[] = { "alt-tab" };
#include "movestack.c"
static const Key keys[] = {
/* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_j, focusstack, {.i = +1 } },
- { MODKEY, XK_k, focusstack, {.i = -1 } },
- { MODKEY, XK_i, incnmaster, {.i = +1 } },
- { MODKEY, XK_d, incnmaster, {.i = -1 } },
- { MODKEY, XK_h, setmfact, {.f = -0.05} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
- { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
- { MODKEY, XK_Return, zoom, {0} },
- { MODKEY, XK_q, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
+ { MODKEY, XK_p, spawn, {.v = dmenucmd} },
+ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd} },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1} },
+ { MODKEY, XK_k, focusstack, {.i = -1} },
+ { MODKEY, XK_i, incnmaster, {.i = +1} },
+ { MODKEY, XK_d, incnmaster, {.i = -1} },
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1} },
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1} },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, spawn, {.v = rofitab} },
+ { MODKEY|ShiftMask, XK_c, killclient, {0} },
+ { MODKEY, XK_n, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY, XK_comma, focusmon, {.i = -1 } },
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
-+ { MODKEY, XK_Left, viewtoleft, {0} },
-+ { MODKEY, XK_Right, viewtoright, {0} },
-+ { MODKEY|ShiftMask, XK_Left, tagtoleft, {0} },
-+ { MODKEY|ShiftMask, XK_Right, tagtoright, {0} },
- { Mod1Mask, XK_Tab, altTabStart, {.i = 1} },
- { Mod1Mask, XK_grave, altTabStart, {.i = 0} },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
- TAGKEYS( XK_4, 3)
- TAGKEYS( XK_5, 4)
- TAGKEYS( XK_6, 5)
- TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
- TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_q, quit, {0} },
+ { MODKEY, XK_space, setlayout, {0} },
+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY, XK_0, view, {.ui = ~0} },
+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0} },
+ { MODKEY, XK_comma, focusmon, {.i = -1} },
+ { MODKEY, XK_period, focusmon, {.i = +1} },
+ { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1} },
+ { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1} },
+ { MODKEY, XK_h, viewtoleft, {0} },
+ { MODKEY, XK_l, viewtoright, {0} },
+ { MODKEY|ShiftMask, XK_h, tagtoleft, {0} },
+ { MODKEY|ShiftMask, XK_l, tagtoright, {0} },
+ TAGKEYS( XK_1, 0 )
+ TAGKEYS( XK_2, 1 )
+ TAGKEYS( XK_3, 2 )
+ TAGKEYS( XK_4, 3 )
+ TAGKEYS( XK_5, 4 )
+ TAGKEYS( XK_6, 5 )
+ TAGKEYS( XK_7, 6 )
+ TAGKEYS( XK_8, 7 )
+ TAGKEYS( XK_9, 8 )
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static const Button buttons[] = {
/* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
+ { ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
- { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
- { ClkTagBar, 0, Button1, view, {0} },
- { ClkTagBar, 0, Button3, toggleview, {0} },
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd} },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+ { ClkTagBar, 0, Button1, view, {0} },
+ { ClkTagBar, 0, Button3, toggleview, {0} },
+ { ClkTagBar, MODKEY, Button1, tag, {0} },
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
diff --git a/config.h b/config.h
index b492963..4278ea7 100644
--- a/config.h
+++ b/config.h
@@ -1,23 +1,15 @@
/* See LICENSE file for copyright and license details. */
-/* alt-tab configuration */
-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 `*/
-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 */
-static const unsigned int tabCycleKey2 = 0x31; /* grave key */
-static const unsigned int tabPosY = 1; /* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
-static const unsigned int tabPosX = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */
-static const unsigned int maxWTab = 600; /* tab menu width */
-static const unsigned int maxHTab = 200; /* tab menu height */
/* appearance */
-static const unsigned int borderpx = 1; /* border pixel of windows */
-static const unsigned int snap = 32; /* snap pixel */
-static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
-static const unsigned int systrayonleft = 1; /* 0: systray in the right corner, >0: systray on left of status text */
-static const unsigned int systrayspacing = 2; /* systray spacing */
-static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
-static const int showsystray = 1; /* 0 means no systray */
-static const int showbar = 1; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
+static const unsigned int borderpx = 1; /* border pixel of windows */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayonleft = 1; /* 0: systray in the right corner, >0: systray on left of status text */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
+static const int showbar = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
static const int focusonwheel = 0;
static const char *fonts[] = { "monospace:size=12" };
static const char dmenufont[] = "monospace:size=12";
@@ -50,7 +42,7 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.9
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
static const int attachbelow = 1; /* 1 means attach after the currently active window */
-static const int lockfullscreen = 0; /* 1 will force focus on the fullscreen window */
+static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const Layout layouts[] = {
/* symbol arrange function */
@@ -73,14 +65,13 @@ static const Layout layouts[] = {
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_white, "-sb", col_gray2, "-sf", col_white, NULL };
-static const char *roficmd[] = { "rofi", "-show", "drun" };
-static const char *rofitab[] = { "rofi", "-show", "window" };
static const char *termcmd[] = { "st", NULL };
+static const char *rofitab[] = { "alt-tab" };
#include "movestack.c"
static const Key keys[] = {
/* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = roficmd} },
+ { MODKEY, XK_p, spawn, {.v = dmenucmd} },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd} },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1} },
@@ -90,6 +81,7 @@ static const Key keys[] = {
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1} },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1} },
{ MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, spawn, {.v = rofitab} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_n, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
@@ -102,8 +94,6 @@ static const Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1} },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1} },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1} },
- { MODKEY, XK_Tab, spawn, {.v = rofitab} },
- { MODKEY, XK_grave, spawn, {.v = rofitab} },
{ MODKEY, XK_h, viewtoleft, {0} },
{ MODKEY, XK_l, viewtoright, {0} },
{ MODKEY|ShiftMask, XK_h, tagtoleft, {0} },
diff --git a/dwm.c b/dwm.c
index d655e0a..a020561 100644
--- a/dwm.c
+++ b/dwm.c
@@ -40,7 +40,6 @@
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */
#include <X11/Xft/Xft.h>
-#include <time.h>
#include "drw.h"
#include "util.h"
@@ -102,7 +101,6 @@ typedef struct Monitor Monitor;
typedef struct Client Client;
struct Client {
char name[256];
- char class[256];
float mina, maxa;
int x, y, w, h;
int oldx, oldy, oldw, oldh;
@@ -137,13 +135,6 @@ struct Monitor {
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
- int altTabN; /* move that many clients forward */
- int altTabNc; /* move that many clients forward when using tab for same class */
- int nTabs; /* number of active clients in tag */
- int ncTabs; /* number of active clients under same class in tag */
- int isAlt; /* 1,0 */
- int maxWTab;
- int maxHTab;
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
@@ -152,11 +143,8 @@ struct Monitor {
Client *clients;
Client *sel;
Client *stack;
- Client ** altsnext; /* array of all clients in the tag */
- Client ** altsnextclass; /* array of all clients under same class in the tag */
Monitor *next;
Window barwin;
- Window tabwin;
const Layout *lt[2];
Pertag *pertag;
};
@@ -280,10 +268,6 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
-void drawTab(int nwins, int first, Monitor *m);
-void altTabStart(const Arg *arg);
-static void altTabEnd();
-static void getclassname(Client *c);
/* variables */
static Systray *systray = NULL;
@@ -552,7 +536,6 @@ cleanup(void)
Monitor *m;
size_t i;
- altTabEnd();
view(&a);
selmon->lt[selmon->sellt] = &foo;
for (m = mons; m; m = m->next)
@@ -784,8 +767,6 @@ createmon(void)
m->topbar = topbar;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
- m->nTabs = 0;
- m->ncTabs = 0;
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
m->pertag = ecalloc(1, sizeof(Pertag));
m->pertag->curtag = m->pertag->prevtag = 1;
@@ -1214,7 +1195,6 @@ manage(Window w, XWindowAttributes *wa)
c->oldbw = wa->border_width;
updatetitle(c);
- getclassname(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
c->tags = t->tags;
@@ -1900,306 +1880,6 @@ spawn(const Arg *arg)
}
void
-altTab()
-{
- /* move to next window */
- if (selmon->sel != NULL && selmon->sel->snext != NULL) {
- selmon->altTabN++;
- if (selmon->altTabN >= selmon->nTabs)
- selmon->altTabN = 0; /* reset altTabN */
-
- focus(selmon->altsnext[selmon->altTabN]);
- /* restack(selmon); */
- }
-
- /* redraw tab */
- XRaiseWindow(dpy, selmon->tabwin);
- drawTab(selmon->nTabs, 0, selmon);
-}
-
-void
-altTabClass()
-{
- /* move to next window */
- if (selmon->sel != NULL) {
- selmon->altTabNc++;
- if (selmon->altTabNc >= selmon->ncTabs)
- selmon->altTabNc = 0; /* reset altTabNc */
-
- focus(selmon->altsnextclass[selmon->altTabNc]);
- }
-
- /* redraw tab */
- XRaiseWindow(dpy, selmon->tabwin);
- drawTab(selmon->ncTabs, 0, selmon);
-}
-
-void
-altTabShift()
-{
- /* move to prev window */
- if (selmon->sel != NULL) {
- selmon->altTabN--;
- if (selmon->altTabN < 0)
- selmon->altTabN = selmon->nTabs - 1; /* reset altTabN */
-
- if (selmon->altsnext[selmon->altTabN]) {
- focus(selmon->altsnext[selmon->altTabN]);
- }
- }
-
- /* redraw tab */
- XRaiseWindow(dpy, selmon->tabwin);
- drawTab(selmon->nTabs, 0, selmon);
-}
-
-void
-altTabShiftClass()
-{
- /* move to prev window */
- if (selmon->sel != NULL) {
- selmon->altTabNc--;
- if (selmon->altTabNc < 0)
- selmon->altTabNc = selmon->ncTabs - 1; /* reset altTabNc */
-
- if (selmon->altsnextclass[selmon->altTabNc]) {
- focus(selmon->altsnextclass[selmon->altTabNc]);
- }
- }
-
- /* redraw tab */
- XRaiseWindow(dpy, selmon->tabwin);
- drawTab(selmon->ncTabs, 0, selmon);
-}
-
-void
-altTabEnd()
-{
- Client *buff = NULL;
- if (selmon->isAlt == 0)
- return;
-
- /*
- * move all clients between 1st and choosen position,
- * one down in stack and put choosen client to the first position
- * so they remain in right order for the next time that alt-tab is used
- */
- if (selmon->nTabs > 1) {
- if (selmon->altTabN != 0)
- buff = selmon->altsnext[selmon->altTabN];
- else if (selmon->altTabNc != 0) {
- buff = selmon->altsnextclass[selmon->altTabNc];
- for (; selmon->altTabN < selmon->nTabs; selmon->altTabN++)
- if (selmon->altsnext[selmon->altTabN] == selmon->altsnextclass[selmon->altTabNc])
- break;
- }
- if (buff) { /* if user picked original client do nothing */
- if (selmon->altTabN > 1)
- for (int i = selmon->altTabN;i > 0;i--)
- selmon->altsnext[i] = selmon->altsnext[i - 1];
- else /* swap them if there are just 2 clients */
- selmon->altsnext[selmon->altTabN] = selmon->altsnext[0];
- selmon->altsnext[0] = buff;
- }
-
- /* restack clients */
- for (int i = selmon->nTabs - 1;i >= 0;i--) {
- focus(selmon->altsnext[i]);
- restack(selmon);
- }
-
- free(selmon->altsnext); /* free list of clients */
- free(selmon->altsnextclass); /* free list of clients */
- }
-
- /* turn off/destroy the window */
- selmon->isAlt = 0;
- selmon->nTabs = 0;
- XUnmapWindow(dpy, selmon->tabwin);
- XDestroyWindow(dpy, selmon->tabwin);
-}
-
-void
-drawTab(int nwins, int first, Monitor *m)
-{
- /* little documentation of functions */
- /* void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); */
- /* int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); */
- /* void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); */
-
- Client *c;
- int h;
-
- if (first) {
- Monitor *m = selmon;
- XSetWindowAttributes wa = {
- .override_redirect = True,
- .background_pixmap = ParentRelative,
- .event_mask = ButtonPressMask|ExposureMask
- };
-
- selmon->maxWTab = maxWTab;
- selmon->maxHTab = maxHTab;
-
- /* decide position of tabwin */
- int posX = selmon->mx;
- int posY = selmon->my;
- if (tabPosX == 0)
- posX += 0;
- if (tabPosX == 1)
- posX += (selmon->mw / 2) - (maxWTab / 2);
- if (tabPosX == 2)
- posX += selmon->mw - maxWTab;
-
- if (tabPosY == 0)
- posY += selmon->mh - maxHTab;
- if (tabPosY == 1)
- posY += (selmon->mh / 2) - (maxHTab / 2);
- if (tabPosY == 2)
- posY += 0;
-
- h = selmon->maxHTab;
- /* XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes); just reference */
- m->tabwin = XCreateWindow(dpy, root, posX, posY, selmon->maxWTab, selmon->maxHTab, 2, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); /* create tabwin */
-
- XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor);
- XMapRaised(dpy, m->tabwin);
-
- }
-
- h = selmon->maxHTab / nwins;
-
- int y = 0;
- for (int i = 0; i < nwins; i++) { /* draw all clients into tabwin */
- if (nwins == m->nTabs)
- c = m->altsnext[i];
- else
- c = m->altsnextclass[i];
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
- drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
- drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
- y += h;
- }
-
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_map(drw, m->tabwin, 0, 0, selmon->maxWTab, selmon->maxHTab);
-}
-
-void
-altTabStart(const Arg *arg)
-{
- if (selmon->tabwin)
- altTabEnd();
-
- if (selmon->isAlt == 1) {
- altTabEnd();
- } else {
- selmon->isAlt = 1;
- selmon->altTabN = 0;
- selmon->altTabNc = 0;
-
- Client *c;
- Monitor *m = selmon;
-
- char tempclass[256] = {'\0'};
- if (selmon->sel)
- strncpy(tempclass, selmon->sel->class, 256);
-
- m->nTabs = 0;
- m->ncTabs = 0;
- for(c = m->clients; c; c = c->next) { /* count clients */
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
- ++m->nTabs;
-
- if (!strcmp(c->class, tempclass))
- ++m->ncTabs;
- }
-
- if (m->nTabs > 0) {
- m->altsnext = (Client **) malloc(m->nTabs * sizeof(Client *));
- m->altsnextclass = (Client **) malloc(m->ncTabs * sizeof(Client *));
-
- int listIndex = 0;
- int listIndexc = 0;
- for(c = m->stack; c; c = c->snext) { /* add clients to the list */
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
- m->altsnext[listIndex++] = c;
-
- if (!strcmp(c->class, tempclass))
- m->altsnextclass[listIndexc++] = c;
- }
-
- if (arg->i)
- drawTab(m->nTabs, 1, m);
- else
- drawTab(m->ncTabs, 1, m);
-
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
-
- /* grab keyboard (take all input from keyboard) */
- int grabbed = 1;
- for (int i = 0;i < 1000;i++) {
- if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
- break;
- nanosleep(&ts, NULL);
- if (i == 1000 - 1)
- grabbed = 0;
- }
-
- XEvent event;
- if (arg->i)
- altTab();
- else
- altTabClass();
- if (grabbed == 0) {
- altTabEnd();
- } else {
- while (grabbed) {
- XNextEvent(dpy, &event);
- if (event.type == KeyPress || event.type == KeyRelease) {
- if (event.type == KeyRelease && event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
- break;
- } else if (event.type == KeyPress) {
- if (event.xkey.keycode == tabCycleKey || event.xkey.keycode == tabCycleKey2 ) { /* if XK_s is pressed move to the next window */
- if (arg->i) {
- if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
- altTabShift();
- else
- altTab();
- } else {
- if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
- altTabShiftClass();
- else
- altTabClass();
- }
-
- }
- }
- }
- }
-
- c = selmon->sel;
- altTabEnd(); /* end the alt-tab functionality */
- /* XUngrabKeyboard(display, time); just a reference */
- XUngrabKeyboard(dpy, CurrentTime); /* stop taking all input from keyboard */
- focus(c);
- restack(selmon);
- }
- } else {
- altTabEnd(); /* end the alt-tab functionality */
- }
- }
-}
-
-void
tag(const Arg *arg)
{
if (selmon->sel && arg->ui & TAGMASK) {
@@ -2744,15 +2424,6 @@ updatetitle(Client *c)
}
void
-getclassname(Client *c)
-{
- gettextprop(c->win, XA_WM_CLASS, c->class, sizeof c->class);
-
- if (c->class[0] == '\0') /* hack to mark broken clients */
- strcpy(c->name, broken);
-}
-
-void
updatewindowtype(Client *c)
{
Atom state = getatomprop(c, netatom[NetWMState]);
diff --git a/patches/dwm-alttab-6.4.diff b/patches/dwm-alttab-6.4.diff
deleted file mode 100644
index 9bb834e..0000000
--- a/patches/dwm-alttab-6.4.diff
+++ /dev/null
@@ -1,322 +0,0 @@
-From 8b1d33db9cbc03bf12df398bb14e62389efc70a3 Mon Sep 17 00:00:00 2001
-From: ViliamKovac1223 <viliamkovac1223@gmail.com>
-Date: Sun, 9 Oct 2022 16:29:28 -0400
-Subject: [PATCH] add alt-tab functionality
-
-Co-authored-by: Daniel Gerblick <daniel.gerblick@gmail.com>
----
- config.def.h | 11 ++-
- dwm.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 228 insertions(+), 1 deletion(-)
-
-diff --git a/config.def.h b/config.def.h
-index 061ad66..7a9e3b1 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -1,5 +1,13 @@
- /* See LICENSE file for copyright and license details. */
-
-+/* alt-tab configuration */
-+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 `*/
-+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 */
-+static const unsigned int tabPosY = 1; /* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
-+static const unsigned int tabPosX = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */
-+static const unsigned int maxWTab = 600; /* tab menu width */
-+static const unsigned int maxHTab = 200; /* tab menu height */
-+
- /* appearance */
- static const unsigned int borderpx = 1; /* border pixel of windows */
- static const unsigned int snap = 32; /* snap pixel */
-@@ -71,7 +79,7 @@ static const Key keys[] = {
- { MODKEY, XK_h, setmfact, {.f = -0.05} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY, XK_Return, zoom, {0} },
-- { MODKEY, XK_Tab, view, {0} },
-+ { MODKEY, XK_q, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
-@@ -84,6 +92,7 @@ static const Key keys[] = {
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
-+ { Mod1Mask, XK_Tab, altTabStart, {0} },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
-diff --git a/dwm.c b/dwm.c
-index e5efb6a..f606311 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -40,6 +40,7 @@
- #include <X11/extensions/Xinerama.h>
- #endif /* XINERAMA */
- #include <X11/Xft/Xft.h>
-+#include <time.h>
-
- #include "drw.h"
- #include "util.h"
-@@ -119,6 +120,11 @@ struct Monitor {
- int by; /* bar geometry */
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
-+ int altTabN; /* move that many clients forward */
-+ int nTabs; /* number of active clients in tag */
-+ int isAlt; /* 1,0 */
-+ int maxWTab;
-+ int maxHTab;
- unsigned int seltags;
- unsigned int sellt;
- unsigned int tagset[2];
-@@ -127,8 +133,10 @@ struct Monitor {
- Client *clients;
- Client *sel;
- Client *stack;
-+ Client ** altsnext; /* array of all clients in the tag */
- Monitor *next;
- Window barwin;
-+ Window tabwin;
- const Layout *lt[2];
- };
-
-@@ -234,6 +242,9 @@ static int xerror(Display *dpy, XErrorEvent *ee);
- static int xerrordummy(Display *dpy, XErrorEvent *ee);
- static int xerrorstart(Display *dpy, XErrorEvent *ee);
- static void zoom(const Arg *arg);
-+void drawTab(int nwins, int first, Monitor *m);
-+void altTabStart(const Arg *arg);
-+static void altTabEnd();
-
- /* variables */
- static const char broken[] = "broken";
-@@ -477,6 +488,7 @@ cleanup(void)
- Monitor *m;
- size_t i;
-
-+ altTabEnd();
- view(&a);
- selmon->lt[selmon->sellt] = &foo;
- for (m = mons; m; m = m->next)
-@@ -644,6 +656,7 @@ createmon(void)
- m->topbar = topbar;
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % LENGTH(layouts)];
-+ m->nTabs = 0;
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
- return m;
- }
-@@ -1648,6 +1661,211 @@ spawn(const Arg *arg)
- }
- }
-
-+void
-+altTab()
-+{
-+ /* move to next window */
-+ if (selmon->sel != NULL && selmon->sel->snext != NULL) {
-+ selmon->altTabN++;
-+ if (selmon->altTabN >= selmon->nTabs)
-+ selmon->altTabN = 0; /* reset altTabN */
-+
-+ focus(selmon->altsnext[selmon->altTabN]);
-+ restack(selmon);
-+ }
-+
-+ /* redraw tab */
-+ XRaiseWindow(dpy, selmon->tabwin);
-+ drawTab(selmon->nTabs, 0, selmon);
-+}
-+
-+void
-+altTabEnd()
-+{
-+ if (selmon->isAlt == 0)
-+ return;
-+
-+ /*
-+ * move all clients between 1st and choosen position,
-+ * one down in stack and put choosen client to the first position
-+ * so they remain in right order for the next time that alt-tab is used
-+ */
-+ if (selmon->nTabs > 1) {
-+ if (selmon->altTabN != 0) { /* if user picked original client do nothing */
-+ Client *buff = selmon->altsnext[selmon->altTabN];
-+ if (selmon->altTabN > 1)
-+ for (int i = selmon->altTabN;i > 0;i--)
-+ selmon->altsnext[i] = selmon->altsnext[i - 1];
-+ else /* swap them if there are just 2 clients */
-+ selmon->altsnext[selmon->altTabN] = selmon->altsnext[0];
-+ selmon->altsnext[0] = buff;
-+ }
-+
-+ /* restack clients */
-+ for (int i = selmon->nTabs - 1;i >= 0;i--) {
-+ focus(selmon->altsnext[i]);
-+ restack(selmon);
-+ }
-+
-+ free(selmon->altsnext); /* free list of clients */
-+ }
-+
-+ /* turn off/destroy the window */
-+ selmon->isAlt = 0;
-+ selmon->nTabs = 0;
-+ XUnmapWindow(dpy, selmon->tabwin);
-+ XDestroyWindow(dpy, selmon->tabwin);
-+}
-+
-+void
-+drawTab(int nwins, int first, Monitor *m)
-+{
-+ /* little documentation of functions */
-+ /* void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); */
-+ /* int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); */
-+ /* void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); */
-+
-+ Client *c;
-+ int h;
-+
-+ if (first) {
-+ Monitor *m = selmon;
-+ XSetWindowAttributes wa = {
-+ .override_redirect = True,
-+ .background_pixmap = ParentRelative,
-+ .event_mask = ButtonPressMask|ExposureMask
-+ };
-+
-+ selmon->maxWTab = maxWTab;
-+ selmon->maxHTab = maxHTab;
-+
-+ /* decide position of tabwin */
-+ int posX = selmon->mx;
-+ int posY = selmon->my;
-+ if (tabPosX == 0)
-+ posX += 0;
-+ if (tabPosX == 1)
-+ posX += (selmon->mw / 2) - (maxWTab / 2);
-+ if (tabPosX == 2)
-+ posX += selmon->mw - maxWTab;
-+
-+ if (tabPosY == 0)
-+ posY += selmon->mh - maxHTab;
-+ if (tabPosY == 1)
-+ posY += (selmon->mh / 2) - (maxHTab / 2);
-+ if (tabPosY == 2)
-+ posY += 0;
-+
-+ h = selmon->maxHTab;
-+ /* XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes); just reference */
-+ m->tabwin = XCreateWindow(dpy, root, posX, posY, selmon->maxWTab, selmon->maxHTab, 2, DefaultDepth(dpy, screen),
-+ CopyFromParent, DefaultVisual(dpy, screen),
-+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); /* create tabwin */
-+
-+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor);
-+ XMapRaised(dpy, m->tabwin);
-+
-+ }
-+
-+ h = selmon->maxHTab / m->nTabs;
-+
-+ int y = 0;
-+ int n = 0;
-+ for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tabwin */
-+ c = m->altsnext[i];
-+ if(!ISVISIBLE(c)) continue;
-+ /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-+
-+ n++;
-+ drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
-+ drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
-+ y += h;
-+ }
-+
-+ drw_setscheme(drw, scheme[SchemeNorm]);
-+ drw_map(drw, m->tabwin, 0, 0, selmon->maxWTab, selmon->maxHTab);
-+}
-+
-+void
-+altTabStart(const Arg *arg)
-+{
-+ selmon->altsnext = NULL;
-+ if (selmon->tabwin)
-+ altTabEnd();
-+
-+ if (selmon->isAlt == 1) {
-+ altTabEnd();
-+ } else {
-+ selmon->isAlt = 1;
-+ selmon->altTabN = 0;
-+
-+ Client *c;
-+ Monitor *m = selmon;
-+
-+ m->nTabs = 0;
-+ for(c = m->clients; c; c = c->next) { /* count clients */
-+ if(!ISVISIBLE(c)) continue;
-+ /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-+
-+ ++m->nTabs;
-+ }
-+
-+ if (m->nTabs > 0) {
-+ m->altsnext = (Client **) malloc(m->nTabs * sizeof(Client *));
-+
-+ int listIndex = 0;
-+ for(c = m->stack; c; c = c->snext) { /* add clients to the list */
-+ if(!ISVISIBLE(c)) continue;
-+ /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-+
-+ m->altsnext[listIndex++] = c;
-+ }
-+
-+ drawTab(m->nTabs, 1, m);
-+
-+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
-+
-+ /* grab keyboard (take all input from keyboard) */
-+ int grabbed = 1;
-+ for (int i = 0;i < 1000;i++) {
-+ if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
-+ break;
-+ nanosleep(&ts, NULL);
-+ if (i == 1000 - 1)
-+ grabbed = 0;
-+ }
-+
-+ XEvent event;
-+ altTab();
-+ if (grabbed == 0) {
-+ altTabEnd();
-+ } else {
-+ while (grabbed) {
-+ XNextEvent(dpy, &event);
-+ if (event.type == KeyPress || event.type == KeyRelease) {
-+ if (event.type == KeyRelease && event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
-+ break;
-+ } else if (event.type == KeyPress) {
-+ if (event.xkey.keycode == tabCycleKey) {/* if XK_s is pressed move to the next window */
-+ altTab();
-+ }
-+ }
-+ }
-+ }
-+
-+ c = selmon->sel;
-+ altTabEnd(); /* end the alt-tab functionality */
-+ /* XUngrabKeyboard(display, time); just a reference */
-+ XUngrabKeyboard(dpy, CurrentTime); /* stop taking all input from keyboard */
-+ focus(c);
-+ restack(selmon);
-+ }
-+ } else {
-+ altTabEnd(); /* end the alt-tab functionality */
-+ }
-+ }
-+}
-+
- void
- tag(const Arg *arg)
- {
---
-2.37.3
-
diff --git a/patches/dwm-alttabclass-6.4.diff b/patches/dwm-alttabclass-6.4.diff
deleted file mode 100644
index 0236de4..0000000
--- a/patches/dwm-alttabclass-6.4.diff
+++ /dev/null
@@ -1,304 +0,0 @@
-diff -up a/config.def.h b/config.def.h
---- a/config.def.h 2023-08-17 17:35:28.333393605 +0400
-+++ b/config.def.h 2023-08-17 17:24:46.724435876 +0400
-@@ -3,6 +3,7 @@
- /* alt-tab configuration */
- 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 `*/
- 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 */
-+static const unsigned int tabCycleKey2 = 0x31; /* grave key */
- static const unsigned int tabPosY = 1; /* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
- static const unsigned int tabPosX = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */
- static const unsigned int maxWTab = 600; /* tab menu width */
-@@ -93,7 +94,8 @@ static const Key keys[] = {
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
-- { Mod1Mask, XK_Tab, altTabStart, {0} },
-+ { Mod1Mask, XK_Tab, altTabStart, {.i = 1} },
-+ { Mod1Mask, XK_grave, altTabStart, {.i = 0} },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
-diff -up a/dwm.c b/dwm.c
---- a/dwm.c 2023-08-17 17:24:19.753640383 +0400
-+++ b/dwm.c 2023-08-18 09:41:00.834187121 +0400
-@@ -87,6 +87,7 @@ typedef struct Monitor Monitor;
- typedef struct Client Client;
- struct Client {
- char name[256];
-+ char class[256];
- float mina, maxa;
- int x, y, w, h;
- int oldx, oldy, oldw, oldh;
-@@ -121,7 +122,9 @@ struct Monitor {
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
- int altTabN; /* move that many clients forward */
-+ int altTabNc; /* move that many clients forward when using tab for same class */
- int nTabs; /* number of active clients in tag */
-+ int ncTabs; /* number of active clients under same class in tag */
- int isAlt; /* 1,0 */
- int maxWTab;
- int maxHTab;
-@@ -134,6 +137,7 @@ struct Monitor {
- Client *sel;
- Client *stack;
- Client ** altsnext; /* array of all clients in the tag */
-+ Client ** altsnextclass; /* array of all clients under same class in the tag */
- Monitor *next;
- Window barwin;
- Window tabwin;
-@@ -245,6 +249,7 @@ static void zoom(const Arg *arg);
- void drawTab(int nwins, int first, Monitor *m);
- void altTabStart(const Arg *arg);
- static void altTabEnd();
-+static void getclassname(Client *c);
-
- /* variables */
- static const char broken[] = "broken";
-@@ -657,6 +662,7 @@ createmon(void)
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % LENGTH(layouts)];
- m->nTabs = 0;
-+ m->ncTabs = 0;
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
- return m;
- }
-@@ -1059,6 +1065,7 @@ manage(Window w, XWindowAttributes *wa)
- c->oldbw = wa->border_width;
-
- updatetitle(c);
-+ getclassname(c);
- if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
- c->mon = t->mon;
- c->tags = t->tags;
-@@ -1683,7 +1690,7 @@ altTab()
- selmon->altTabN = 0; /* reset altTabN */
-
- focus(selmon->altsnext[selmon->altTabN]);
-- restack(selmon);
-+ /* restack(selmon); */
- }
-
- /* redraw tab */
-@@ -1692,8 +1699,64 @@ altTab()
- }
-
- void
-+altTabClass()
-+{
-+ /* move to next window */
-+ if (selmon->sel != NULL) {
-+ selmon->altTabNc++;
-+ if (selmon->altTabNc >= selmon->ncTabs)
-+ selmon->altTabNc = 0; /* reset altTabNc */
-+
-+ focus(selmon->altsnextclass[selmon->altTabNc]);
-+ }
-+
-+ /* redraw tab */
-+ XRaiseWindow(dpy, selmon->tabwin);
-+ drawTab(selmon->ncTabs, 0, selmon);
-+}
-+
-+void
-+altTabShift()
-+{
-+ /* move to prev window */
-+ if (selmon->sel != NULL) {
-+ selmon->altTabN--;
-+ if (selmon->altTabN < 0)
-+ selmon->altTabN = selmon->nTabs - 1; /* reset altTabN */
-+
-+ if (selmon->altsnext[selmon->altTabN]) {
-+ focus(selmon->altsnext[selmon->altTabN]);
-+ }
-+ }
-+
-+ /* redraw tab */
-+ XRaiseWindow(dpy, selmon->tabwin);
-+ drawTab(selmon->nTabs, 0, selmon);
-+}
-+
-+void
-+altTabShiftClass()
-+{
-+ /* move to prev window */
-+ if (selmon->sel != NULL) {
-+ selmon->altTabNc--;
-+ if (selmon->altTabNc < 0)
-+ selmon->altTabNc = selmon->ncTabs - 1; /* reset altTabNc */
-+
-+ if (selmon->altsnextclass[selmon->altTabNc]) {
-+ focus(selmon->altsnextclass[selmon->altTabNc]);
-+ }
-+ }
-+
-+ /* redraw tab */
-+ XRaiseWindow(dpy, selmon->tabwin);
-+ drawTab(selmon->ncTabs, 0, selmon);
-+}
-+
-+void
- altTabEnd()
- {
-+ Client *buff = NULL;
- if (selmon->isAlt == 0)
- return;
-
-@@ -1703,8 +1766,15 @@ altTabEnd()
- * so they remain in right order for the next time that alt-tab is used
- */
- if (selmon->nTabs > 1) {
-- if (selmon->altTabN != 0) { /* if user picked original client do nothing */
-- Client *buff = selmon->altsnext[selmon->altTabN];
-+ if (selmon->altTabN != 0)
-+ buff = selmon->altsnext[selmon->altTabN];
-+ else if (selmon->altTabNc != 0) {
-+ buff = selmon->altsnextclass[selmon->altTabNc];
-+ for (; selmon->altTabN < selmon->nTabs; selmon->altTabN++)
-+ if (selmon->altsnext[selmon->altTabN] == selmon->altsnextclass[selmon->altTabNc])
-+ break;
-+ }
-+ if (buff) { /* if user picked original client do nothing */
- if (selmon->altTabN > 1)
- for (int i = selmon->altTabN;i > 0;i--)
- selmon->altsnext[i] = selmon->altsnext[i - 1];
-@@ -1720,6 +1790,7 @@ altTabEnd()
- }
-
- free(selmon->altsnext); /* free list of clients */
-+ free(selmon->altsnextclass); /* free list of clients */
- }
-
- /* turn off/destroy the window */
-@@ -1779,16 +1850,17 @@ drawTab(int nwins, int first, Monitor *m
-
- }
-
-- h = selmon->maxHTab / m->nTabs;
-+ h = selmon->maxHTab / nwins;
-
- int y = 0;
-- int n = 0;
-- for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tabwin */
-- c = m->altsnext[i];
-+ for (int i = 0; i < nwins; i++) { /* draw all clients into tabwin */
-+ if (nwins == m->nTabs)
-+ c = m->altsnext[i];
-+ else
-+ c = m->altsnextclass[i];
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
-- n++;
- drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
- drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
- y += h;
-@@ -1801,7 +1873,6 @@ drawTab(int nwins, int first, Monitor *m
- void
- altTabStart(const Arg *arg)
- {
-- selmon->altsnext = NULL;
- if (selmon->tabwin)
- altTabEnd();
-
-@@ -1810,30 +1881,47 @@ altTabStart(const Arg *arg)
- } else {
- selmon->isAlt = 1;
- selmon->altTabN = 0;
-+ selmon->altTabNc = 0;
-
- Client *c;
- Monitor *m = selmon;
-
-+ char tempclass[256] = {'\0'};
-+ if (selmon->sel)
-+ strncpy(tempclass, selmon->sel->class, 256);
-+
- m->nTabs = 0;
-+ m->ncTabs = 0;
- for(c = m->clients; c; c = c->next) { /* count clients */
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
- ++m->nTabs;
-+
-+ if (!strcmp(c->class, tempclass))
-+ ++m->ncTabs;
- }
-
- if (m->nTabs > 0) {
- m->altsnext = (Client **) malloc(m->nTabs * sizeof(Client *));
-+ m->altsnextclass = (Client **) malloc(m->ncTabs * sizeof(Client *));
-
- int listIndex = 0;
-+ int listIndexc = 0;
- for(c = m->stack; c; c = c->snext) { /* add clients to the list */
- if(!ISVISIBLE(c)) continue;
- /* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
-
- m->altsnext[listIndex++] = c;
-+
-+ if (!strcmp(c->class, tempclass))
-+ m->altsnextclass[listIndexc++] = c;
- }
-
-- drawTab(m->nTabs, 1, m);
-+ if (arg->i)
-+ drawTab(m->nTabs, 1, m);
-+ else
-+ drawTab(m->ncTabs, 1, m);
-
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
-
-@@ -1848,7 +1936,10 @@ altTabStart(const Arg *arg)
- }
-
- XEvent event;
-- altTab();
-+ if (arg->i)
-+ altTab();
-+ else
-+ altTabClass();
- if (grabbed == 0) {
- altTabEnd();
- } else {
-@@ -1858,8 +1949,19 @@ altTabStart(const Arg *arg)
- if (event.type == KeyRelease && event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
- break;
- } else if (event.type == KeyPress) {
-- if (event.xkey.keycode == tabCycleKey) {/* if XK_s is pressed move to the next window */
-- altTab();
-+ if (event.xkey.keycode == tabCycleKey || event.xkey.keycode == tabCycleKey2 ) { /* if XK_s is pressed move to the next window */
-+ if (arg->i) {
-+ if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
-+ altTabShift();
-+ else
-+ altTab();
-+ } else {
-+ if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
-+ altTabShiftClass();
-+ else
-+ altTabClass();
-+ }
-+
- }
- }
- }
-@@ -2231,6 +2333,15 @@ updatetitle(Client *c)
- strcpy(c->name, broken);
- }
-
-+void
-+getclassname(Client *c)
-+{
-+ gettextprop(c->win, XA_WM_CLASS, c->class, sizeof c->class);
-+
-+ if (c->class[0] == '\0') /* hack to mark broken clients */
-+ strcpy(c->name, broken);
-+}
-+
- void
- updatewindowtype(Client *c)
- {