diff options
Diffstat (limited to 'patch')
| -rw-r--r-- | patch/alttab.c | 222 | ||||
| -rw-r--r-- | patch/alttab.h | 5 | ||||
| -rw-r--r-- | patch/include.c | 3 | ||||
| -rw-r--r-- | patch/include.h | 3 |
4 files changed, 233 insertions, 0 deletions
diff --git a/patch/alttab.c b/patch/alttab.c new file mode 100644 index 0000000..861ab2f --- /dev/null +++ b/patch/alttab.c @@ -0,0 +1,222 @@ +int alttabn; /* move that many clients forward */ +int ntabs; /* number of active clients in tag */ +int isalt; +Client **altsnext; /* array of all clients in the tag */ +Window alttabwin; + +void +alttab() +{ + Monitor *m = selmon; + + /* move to next window */ + if (m->sel && m->sel->snext) { + alttabn++; + if (alttabn >= ntabs) + alttabn = 0; /* reset alttabn */ + + focus(altsnext[alttabn]); + restack(m); + } + + /* redraw tab */ + XRaiseWindow(dpy, alttabwin); + drawtab(ntabs, 0, m); +} + +void +alttabend() +{ + Monitor *m = selmon; + Client *buff; + int i; + + if (!isalt) + return; + + /* Move all clients between first 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 (ntabs > 1) { + if (alttabn != 0) { /* if user picked original client do nothing */ + buff = altsnext[alttabn]; + if (alttabn > 1) + for (i = alttabn; i > 0; i--) + altsnext[i] = altsnext[i - 1]; + else /* swap them if there are just 2 clients */ + altsnext[alttabn] = altsnext[0]; + altsnext[0] = buff; + } + + /* restack clients */ + for (i = ntabs - 1; i >= 0; i--) { + focus(altsnext[i]); + restack(m); + } + + free(altsnext); /* free list of clients */ + } + + /* destroy the window */ + isalt = 0; + ntabs = 0; + XUnmapWindow(dpy, alttabwin); + XDestroyWindow(dpy, alttabwin); +} + +void +drawtab(int nwins, int first, Monitor *m) +{ + Client *c; + int i, h; + int y = 0; + int px = m->mx; + int py = m->my; + + if (first) { + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + .event_mask = ButtonPressMask|ExposureMask + }; + + /* decide position of tabwin */ + if (tabposx == 1) + px = m->mx + (m->mw / 2) - (maxwtab / 2); + else if (tabposx == 2) + px = m->mx + m->mw - maxwtab; + + if (tabposy == 1) + py = m->my + (m->mh / 2) - (maxhtab / 2); + else if (tabposy == 2) + py = m->my + m->mh - maxhtab; + + h = maxhtab; + + #if BAR_ALPHA_PATCH + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + #else + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + + XDefineCursor(dpy, alttabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, alttabwin); + } + + h = maxhtab / ntabs; + for (i = 0; i < ntabs; i++) { /* draw all clients into tabwin */ + c = altsnext[i]; + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + drw_setscheme(drw, scheme[c == m->sel ? SchemeSel : SchemeNorm]); + drw_text(drw, 0, y, maxwtab, h, 0, c->name, 0, 0); + y += h; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_map(drw, alttabwin, 0, 0, maxwtab, maxhtab); +} + +void +alttabstart(const Arg *arg) +{ + Client *c; + Monitor *m = selmon; + int grabbed; + int i; + + altsnext = NULL; + if (alttabwin) + alttabend(); + + if (isalt == 1) { + alttabend(); + return; + } + + isalt = 1; + alttabn = 0; + ntabs = 0; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + ++ntabs; + } + + if (!ntabs) { + alttabend(); + return; + } + + altsnext = (Client **) malloc(ntabs * sizeof(Client *)); + + for (i = 0, c = m->stack; c; c = c->snext, i++) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + altsnext[i] = c; + } + + drawtab(ntabs, 1, m); + + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + + /* grab keyboard (take all input from keyboard) */ + grabbed = 1; + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) + break; + nanosleep(&ts, NULL); + if (i == 1000 - 1) + grabbed = 0; + } + + XEvent event; + alttab(); + + if (grabbed == 0) { + alttabend(); + return; + } + + while (grabbed) { + XNextEvent(dpy, &event); + if (event.type == KeyPress || event.type == KeyRelease) { + if (event.type == KeyRelease && event.xkey.keycode == tabmodkey) /* if mod key is released break cycle */ + break; + + if (event.type == KeyPress) { + if (event.xkey.keycode == tabcyclekey) { /* if tab is pressed move to the next window */ + alttab(); + } + } + } + } + + c = m->sel; + alttabend(); + + XUngrabKeyboard(dpy, CurrentTime); + focus(c); + restack(m); +} diff --git a/patch/alttab.h b/patch/alttab.h new file mode 100644 index 0000000..2951d04 --- /dev/null +++ b/patch/alttab.h @@ -0,0 +1,5 @@ +#include <time.h> + +static void drawtab(int nwins, int first, Monitor *m); +static void alttabstart(const Arg *arg); +static void alttabend(); diff --git a/patch/include.c b/patch/include.c index 4263f45..326323c 100644 --- a/patch/include.c +++ b/patch/include.c @@ -98,6 +98,9 @@ #endif /* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.c" +#endif #if ASPECTRESIZE_PATCH #include "aspectresize.c" #endif diff --git a/patch/include.h b/patch/include.h index 65e0eda..9ab7527 100644 --- a/patch/include.h +++ b/patch/include.h @@ -98,6 +98,9 @@ #endif /* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.h" +#endif #if ASPECTRESIZE_PATCH #include "aspectresize.h" #endif |
