diff options
| author | LM-LCL <hello@exaltedelite.club> | 2024-09-15 20:30:27 +0200 |
|---|---|---|
| committer | LM-LCL <hello@exaltedelite.club> | 2024-09-15 20:30:27 +0200 |
| commit | 9e53bbff78a133bc53a4358510a928fa973cb0a9 (patch) | |
| tree | ddd987851c50d4c3edec3c796f9af79eaa8afcfb | |
| parent | 43f2350c971d59690d97c6e5923bf5be0d1d5284 (diff) | |
alttab2+winview patch & custom implementation of shiftTab (tabCycleKey2 + arg->i)
| -rw-r--r-- | config.def.h | 4 | ||||
| -rw-r--r-- | config.h | 123 | ||||
| -rw-r--r-- | dwm.1 | 3 | ||||
| -rw-r--r-- | dwm.c | 131 | ||||
| -rw-r--r-- | patches/dwm-alttab2+winview-6.4.diff | 217 |
5 files changed, 419 insertions, 59 deletions
diff --git a/config.def.h b/config.def.h index ec547a7..1833f13 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,8 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int tabModKey = 0x40; +static const unsigned int tabCycleKey = 0x17; 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 */ @@ -105,6 +107,8 @@ static const Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY, XK_o, winview, {0} }, + { Mod1Mask, XK_Tab, alttab, {0} }, }; /* button definitions */ @@ -1,23 +1,26 @@ /* See LICENSE file for copyright and license details. */ /* 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 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] = { +static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int tabModKey = 0x40; +static const unsigned int tabCycleKey = 0x17; +static const unsigned int tabCycleKey2 = 0x31; +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_white, col_gray1, col_gray2 }, [SchemeSel] = { col_white, col_gray2, col_orange }, @@ -70,57 +73,59 @@ static const char *termcmd[] = { "st", NULL }; #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_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {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, 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_Tab, view, {0} }, + { 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 } }, - 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} }, + 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} }, + { Mod1Mask, XK_Tab, alttab, {.i = 0} }, + { Mod1Mask|ShiftMask, XK_Tab, alttab, {.i = 1} }, }; /* 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} }, }; @@ -113,6 +113,9 @@ Increase master area size. .B Mod1\-h Decrease master area size. .TP +.B Mod1\-o +Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <time.h> #include <sys/types.h> #include <sys/wait.h> #include <X11/cursorfont.h> @@ -165,6 +166,7 @@ struct Systray { }; /* function declarations */ +static void alttab(const Arg *arg); static void applyrules(Client *c); static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); static void arrange(Monitor *m); @@ -191,6 +193,7 @@ static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); +static void focusnext(const Arg *arg); static void focusstack(const Arg *arg); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); @@ -259,6 +262,7 @@ static void updatewmhints(Client *c); static void view(const Arg *arg); static Client *wintoclient(Window w); static Monitor *wintomon(Window w); +static void winview(const Arg* arg); static Client *wintosystrayicon(Window w); static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); @@ -299,6 +303,8 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +static int alt_tab_direction = 0; + /* configuration, allows nested code to access above variables */ #include "config.h" @@ -315,6 +321,89 @@ struct Pertag { struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; /* function implementations */ + +static void +alttab(const Arg *arg) { + + view(&(Arg){ .ui = ~0 }); + if (arg->i) + focusnext(&(Arg){ !alt_tab_direction }); + else { + focusnext(&(Arg){ alt_tab_direction }); + } + + int grabbed = 1; + int grabbed_keyboard = 1000; + for (int i = 0; i < 100; i += 1) { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 1000000; + + if (grabbed_keyboard != GrabSuccess) { + grabbed_keyboard = XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, + GrabModeAsync, GrabModeAsync, CurrentTime); + } + if (grabbed_keyboard == GrabSuccess) { + XGrabButton(dpy, AnyButton, AnyModifier, None, False, + BUTTONMASK, GrabModeAsync, GrabModeAsync, + None, None); + break; + } + nanosleep(&ts, NULL); + if (i == 100 - 1) + grabbed = 0; + } + + XEvent event; + Client *c; + Monitor *m; + XButtonPressedEvent *ev; + + while (grabbed) { + XNextEvent(dpy, &event); + switch (event.type) { + case KeyPress: + if (event.xkey.keycode == tabCycleKey) + if (event.xkey.keycode == tabCycleKey || event.xkey.keycode == tabCycleKey2) { + if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state)) + focusnext(&(Arg){ .i = !alt_tab_direction }); + else { + focusnext(&(Arg){ .i = alt_tab_direction }); + } + } + break; + case KeyRelease: + if (event.xkey.keycode == tabModKey) { + XUngrabKeyboard(dpy, CurrentTime); + XUngrabButton(dpy, AnyButton, AnyModifier, None); + grabbed = 0; + alt_tab_direction = !alt_tab_direction; + winview(0); + } + break; + case ButtonPress: + ev = &(event.xbutton); + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if ((c = wintoclient(ev->window))) + focus(c); + XAllowEvents(dpy, AsyncBoth, CurrentTime); + break; + case ButtonRelease: + XUngrabKeyboard(dpy, CurrentTime); + XUngrabButton(dpy, AnyButton, AnyModifier, None); + grabbed = 0; + alt_tab_direction = !alt_tab_direction; + winview(0); + break; + } + } + return; +} + void applyrules(Client *c) { @@ -955,6 +1044,28 @@ focusmon(const Arg *arg) focus(NULL); } +static void +focusnext(const Arg *arg) { + Monitor *m; + Client *c; + m = selmon; + c = m->sel; + + if (arg->i) { + if (c->next) + c = c->next; + else + c = m->clients; + } else { + Client *last = c; + if (last == m->clients) + last = NULL; + for (c = m->clients; c->next != last; c = c->next); + } + focus(c); + return; +} + void focusstack(const Arg *arg) { @@ -2499,6 +2610,26 @@ wintomon(Window w) return selmon; } +/* Selects for the view of the focused window. The list of tags */ +/* to be displayed is matched to the focused window tag list. */ +void +winview(const Arg* arg){ + Window win, win_r, win_p, *win_c; + unsigned nc; + int unused; + Client* c; + Arg a; + + if (!XGetInputFocus(dpy, &win, &unused)) return; + while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) + && win_p != win_r) win = win_p; + + if (!(c = wintoclient(win))) return; + + a.ui = c->tags; + view(&a); +} + /* There's no way to check accesses to destroyed windows, thus those cases are * ignored (especially on UnmapNotify's). Other types of errors call Xlibs * default error handler, which may call exit. */ diff --git a/patches/dwm-alttab2+winview-6.4.diff b/patches/dwm-alttab2+winview-6.4.diff new file mode 100644 index 0000000..38cb482 --- /dev/null +++ b/patches/dwm-alttab2+winview-6.4.diff @@ -0,0 +1,217 @@ +diff --git a/config.def.h b/config.def.h +index 9efa774..95499bd 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,8 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int tabModKey = 0x40; ++static const unsigned int tabCycleKey = 0x17; + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +@@ -95,6 +97,8 @@ static const Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_o, winview, {0} }, ++ { Mod1Mask, XK_Tab, alttab, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index ddc8321..f8a809e 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -110,6 +110,9 @@ Increase master area size. + .B Mod1\-h + Decrease master area size. + .TP ++.B Mod1\-o ++Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. ++.TP + .B Mod1\-Return + Zooms/cycles focused window to/from master area (tiled layouts only). + .TP +diff --git a/dwm.c b/dwm.c +index f1d86b2..71d0ebc 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -28,6 +28,7 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#include <time.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <X11/cursorfont.h> +@@ -142,6 +143,7 @@ typedef struct { + } Rule; + + /* function declarations */ ++static void alttab(const Arg *arg); + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); + static void arrange(Monitor *m); +@@ -168,6 +170,7 @@ static void expose(XEvent *e); + static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); ++static void focusnext(const Arg *arg); + static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); +@@ -229,6 +232,7 @@ static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static void winview(const Arg* arg); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); +@@ -268,6 +272,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static int alt_tab_direction = 0; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -275,6 +281,79 @@ static Window root, wmcheckwin; + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + + /* function implementations */ ++ ++static void ++alttab(const Arg *arg) { ++ ++ view(&(Arg){ .ui = ~0 }); ++ focusnext(&(Arg){ .i = alt_tab_direction }); ++ ++ int grabbed = 1; ++ int grabbed_keyboard = 1000; ++ for (int i = 0; i < 100; i += 1) { ++ struct timespec ts; ++ ts.tv_sec = 0; ++ ts.tv_nsec = 1000000; ++ ++ if (grabbed_keyboard != GrabSuccess) { ++ grabbed_keyboard = XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, ++ GrabModeAsync, GrabModeAsync, CurrentTime); ++ } ++ if (grabbed_keyboard == GrabSuccess) { ++ XGrabButton(dpy, AnyButton, AnyModifier, None, False, ++ BUTTONMASK, GrabModeAsync, GrabModeAsync, ++ None, None); ++ break; ++ } ++ nanosleep(&ts, NULL); ++ if (i == 100 - 1) ++ grabbed = 0; ++ } ++ ++ XEvent event; ++ Client *c; ++ Monitor *m; ++ XButtonPressedEvent *ev; ++ ++ while (grabbed) { ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case KeyPress: ++ if (event.xkey.keycode == tabCycleKey) ++ focusnext(&(Arg){ .i = alt_tab_direction }); ++ break; ++ case KeyRelease: ++ if (event.xkey.keycode == tabModKey) { ++ XUngrabKeyboard(dpy, CurrentTime); ++ XUngrabButton(dpy, AnyButton, AnyModifier, None); ++ grabbed = 0; ++ alt_tab_direction = !alt_tab_direction; ++ winview(0); ++ } ++ break; ++ case ButtonPress: ++ ev = &(event.xbutton); ++ if ((m = wintomon(ev->window)) && m != selmon) { ++ unfocus(selmon->sel, 1); ++ selmon = m; ++ focus(NULL); ++ } ++ if ((c = wintoclient(ev->window))) ++ focus(c); ++ XAllowEvents(dpy, AsyncBoth, CurrentTime); ++ break; ++ case ButtonRelease: ++ XUngrabKeyboard(dpy, CurrentTime); ++ XUngrabButton(dpy, AnyButton, AnyModifier, None); ++ grabbed = 0; ++ alt_tab_direction = !alt_tab_direction; ++ winview(0); ++ break; ++ } ++ } ++ return; ++} ++ + void + applyrules(Client *c) + { +@@ -835,6 +914,28 @@ focusmon(const Arg *arg) + focus(NULL); + } + ++static void ++focusnext(const Arg *arg) { ++ Monitor *m; ++ Client *c; ++ m = selmon; ++ c = m->sel; ++ ++ if (arg->i) { ++ if (c->next) ++ c = c->next; ++ else ++ c = m->clients; ++ } else { ++ Client *last = c; ++ if (last == m->clients) ++ last = NULL; ++ for (c = m->clients; c->next != last; c = c->next); ++ } ++ focus(c); ++ return; ++} ++ + void + focusstack(const Arg *arg) + { +@@ -2092,6 +2193,26 @@ wintomon(Window w) + return selmon; + } + ++/* Selects for the view of the focused window. The list of tags */ ++/* to be displayed is matched to the focused window tag list. */ ++void ++winview(const Arg* arg){ ++ Window win, win_r, win_p, *win_c; ++ unsigned nc; ++ int unused; ++ Client* c; ++ Arg a; ++ ++ if (!XGetInputFocus(dpy, &win, &unused)) return; ++ while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) ++ && win_p != win_r) win = win_p; ++ ++ if (!(c = wintoclient(win))) return; ++ ++ a.ui = c->tags; ++ view(&a); ++} ++ + /* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ |
