summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLM-LCL <hello@exaltedelite.club>2024-09-15 20:30:27 +0200
committerLM-LCL <hello@exaltedelite.club>2024-09-15 20:30:27 +0200
commit9e53bbff78a133bc53a4358510a928fa973cb0a9 (patch)
treeddd987851c50d4c3edec3c796f9af79eaa8afcfb
parent43f2350c971d59690d97c6e5923bf5be0d1d5284 (diff)
alttab2+winview patch & custom implementation of shiftTab (tabCycleKey2 + arg->i)
-rw-r--r--config.def.h4
-rw-r--r--config.h123
-rw-r--r--dwm.13
-rw-r--r--dwm.c131
-rw-r--r--patches/dwm-alttab2+winview-6.4.diff217
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 */
diff --git a/config.h b/config.h
index 190850c..6705b60 100644
--- a/config.h
+++ b/config.h
@@ -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} },
};
diff --git a/dwm.1 b/dwm.1
index b0fc8c3..4f18555 100644
--- a/dwm.1
+++ b/dwm.1
@@ -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
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. */
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. */