dwm-alttab2+winview-6.4.diff (5898B)
1 diff --git a/config.def.h b/config.def.h 2 index 9efa774..95499bd 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -2,6 +2,8 @@ 6 7 /* appearance */ 8 static const unsigned int borderpx = 1; /* border pixel of windows */ 9 +static const unsigned int tabModKey = 0x40; 10 +static const unsigned int tabCycleKey = 0x17; 11 static const unsigned int snap = 32; /* snap pixel */ 12 static const int showbar = 1; /* 0 means no bar */ 13 static const int topbar = 1; /* 0 means bottom bar */ 14 @@ -95,6 +97,8 @@ static const Key keys[] = { 15 TAGKEYS( XK_8, 7) 16 TAGKEYS( XK_9, 8) 17 { MODKEY|ShiftMask, XK_q, quit, {0} }, 18 + { MODKEY, XK_o, winview, {0} }, 19 + { Mod1Mask, XK_Tab, alttab, {0} }, 20 }; 21 22 /* button definitions */ 23 diff --git a/dwm.1 b/dwm.1 24 index ddc8321..f8a809e 100644 25 --- a/dwm.1 26 +++ b/dwm.1 27 @@ -110,6 +110,9 @@ Increase master area size. 28 .B Mod1\-h 29 Decrease master area size. 30 .TP 31 +.B Mod1\-o 32 +Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. 33 +.TP 34 .B Mod1\-Return 35 Zooms/cycles focused window to/from master area (tiled layouts only). 36 .TP 37 diff --git a/dwm.c b/dwm.c 38 index f1d86b2..71d0ebc 100644 39 --- a/dwm.c 40 +++ b/dwm.c 41 @@ -28,6 +28,7 @@ 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 +#include <time.h> 46 #include <sys/types.h> 47 #include <sys/wait.h> 48 #include <X11/cursorfont.h> 49 @@ -142,6 +143,7 @@ typedef struct { 50 } Rule; 51 52 /* function declarations */ 53 +static void alttab(const Arg *arg); 54 static void applyrules(Client *c); 55 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); 56 static void arrange(Monitor *m); 57 @@ -168,6 +170,7 @@ static void expose(XEvent *e); 58 static void focus(Client *c); 59 static void focusin(XEvent *e); 60 static void focusmon(const Arg *arg); 61 +static void focusnext(const Arg *arg); 62 static void focusstack(const Arg *arg); 63 static Atom getatomprop(Client *c, Atom prop); 64 static int getrootptr(int *x, int *y); 65 @@ -229,6 +232,7 @@ static void updatewmhints(Client *c); 66 static void view(const Arg *arg); 67 static Client *wintoclient(Window w); 68 static Monitor *wintomon(Window w); 69 +static void winview(const Arg* arg); 70 static int xerror(Display *dpy, XErrorEvent *ee); 71 static int xerrordummy(Display *dpy, XErrorEvent *ee); 72 static int xerrorstart(Display *dpy, XErrorEvent *ee); 73 @@ -268,6 +272,8 @@ static Drw *drw; 74 static Monitor *mons, *selmon; 75 static Window root, wmcheckwin; 76 77 +static int alt_tab_direction = 0; 78 + 79 /* configuration, allows nested code to access above variables */ 80 #include "config.h" 81 82 @@ -275,6 +281,79 @@ static Window root, wmcheckwin; 83 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; 84 85 /* function implementations */ 86 + 87 +static void 88 +alttab(const Arg *arg) { 89 + 90 + view(&(Arg){ .ui = ~0 }); 91 + focusnext(&(Arg){ .i = alt_tab_direction }); 92 + 93 + int grabbed = 1; 94 + int grabbed_keyboard = 1000; 95 + for (int i = 0; i < 100; i += 1) { 96 + struct timespec ts; 97 + ts.tv_sec = 0; 98 + ts.tv_nsec = 1000000; 99 + 100 + if (grabbed_keyboard != GrabSuccess) { 101 + grabbed_keyboard = XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, 102 + GrabModeAsync, GrabModeAsync, CurrentTime); 103 + } 104 + if (grabbed_keyboard == GrabSuccess) { 105 + XGrabButton(dpy, AnyButton, AnyModifier, None, False, 106 + BUTTONMASK, GrabModeAsync, GrabModeAsync, 107 + None, None); 108 + break; 109 + } 110 + nanosleep(&ts, NULL); 111 + if (i == 100 - 1) 112 + grabbed = 0; 113 + } 114 + 115 + XEvent event; 116 + Client *c; 117 + Monitor *m; 118 + XButtonPressedEvent *ev; 119 + 120 + while (grabbed) { 121 + XNextEvent(dpy, &event); 122 + switch (event.type) { 123 + case KeyPress: 124 + if (event.xkey.keycode == tabCycleKey) 125 + focusnext(&(Arg){ .i = alt_tab_direction }); 126 + break; 127 + case KeyRelease: 128 + if (event.xkey.keycode == tabModKey) { 129 + XUngrabKeyboard(dpy, CurrentTime); 130 + XUngrabButton(dpy, AnyButton, AnyModifier, None); 131 + grabbed = 0; 132 + alt_tab_direction = !alt_tab_direction; 133 + winview(0); 134 + } 135 + break; 136 + case ButtonPress: 137 + ev = &(event.xbutton); 138 + if ((m = wintomon(ev->window)) && m != selmon) { 139 + unfocus(selmon->sel, 1); 140 + selmon = m; 141 + focus(NULL); 142 + } 143 + if ((c = wintoclient(ev->window))) 144 + focus(c); 145 + XAllowEvents(dpy, AsyncBoth, CurrentTime); 146 + break; 147 + case ButtonRelease: 148 + XUngrabKeyboard(dpy, CurrentTime); 149 + XUngrabButton(dpy, AnyButton, AnyModifier, None); 150 + grabbed = 0; 151 + alt_tab_direction = !alt_tab_direction; 152 + winview(0); 153 + break; 154 + } 155 + } 156 + return; 157 +} 158 + 159 void 160 applyrules(Client *c) 161 { 162 @@ -835,6 +914,28 @@ focusmon(const Arg *arg) 163 focus(NULL); 164 } 165 166 +static void 167 +focusnext(const Arg *arg) { 168 + Monitor *m; 169 + Client *c; 170 + m = selmon; 171 + c = m->sel; 172 + 173 + if (arg->i) { 174 + if (c->next) 175 + c = c->next; 176 + else 177 + c = m->clients; 178 + } else { 179 + Client *last = c; 180 + if (last == m->clients) 181 + last = NULL; 182 + for (c = m->clients; c->next != last; c = c->next); 183 + } 184 + focus(c); 185 + return; 186 +} 187 + 188 void 189 focusstack(const Arg *arg) 190 { 191 @@ -2092,6 +2193,26 @@ wintomon(Window w) 192 return selmon; 193 } 194 195 +/* Selects for the view of the focused window. The list of tags */ 196 +/* to be displayed is matched to the focused window tag list. */ 197 +void 198 +winview(const Arg* arg){ 199 + Window win, win_r, win_p, *win_c; 200 + unsigned nc; 201 + int unused; 202 + Client* c; 203 + Arg a; 204 + 205 + if (!XGetInputFocus(dpy, &win, &unused)) return; 206 + while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) 207 + && win_p != win_r) win = win_p; 208 + 209 + if (!(c = wintoclient(win))) return; 210 + 211 + a.ui = c->tags; 212 + view(&a); 213 +} 214 + 215 /* There's no way to check accesses to destroyed windows, thus those cases are 216 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs 217 * default error handler, which may call exit. */