diff options
| author | LM-LCL <hello@exaltedelite.club> | 2024-11-25 04:16:28 +0100 |
|---|---|---|
| committer | LM-LCL <hello@exaltedelite.club> | 2024-11-25 04:16:28 +0100 |
| commit | 4487767884544aa089bd2509f8565f72973197f0 (patch) | |
| tree | 94fcbe0c9b02e021e4afd0e73d4837e642c87367 | |
| parent | 7267c642c64a79f33c425a15e78892554b38f6d4 (diff) | |
Custom alt-tab
| -rw-r--r-- | config.def.h | 158 | ||||
| -rw-r--r-- | config.h | 36 | ||||
| -rw-r--r-- | dwm.c | 329 | ||||
| -rw-r--r-- | patches/dwm-alttab-6.4.diff | 322 | ||||
| -rw-r--r-- | patches/dwm-alttabclass-6.4.diff | 304 |
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} }, }; @@ -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} }, @@ -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) - { |
