summaryrefslogtreecommitdiff
path: root/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwm.c')
-rw-r--r--dwm.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/dwm.c b/dwm.c
index 0994f9f..cb1e6f2 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>
@@ -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. */