Hey Manolo, On Thu, Dec 13, 2012 at 03:04:01PM -0500, Manolo Martínez wrote: > I was wondering if anyone knows of a patch that provides the means to > return to the previously focused window (if it exists). That is, for > example, if I'm > on window1 and launch a window2, MOD+p (say) would take me back to > window1.
There's the swapfocus patch at http://dwm.suckless.org/patches/swapfocus. The downside to this patch is that it remembers _only_ the most recently selected window, and changing tag sets or opening and closing windows will often strip you of the ability to go back to a previously selected client. I wrote an alternate version of swapfocus that sorta works on a per-tag basis. See the patch comments for an explanation of the "sorta" part. That patch had its own problems as well, specifically that due to the way I wrote it, opening a new window would throw of the previous client selection at times. Some days ago, I decided to take a completely different approach and wrote the "lastclient.diff" patch that is also attached. With this patch, every time a window is focused, the time the window was focused is recorded. When you call the lastclient function, the most recently focused window is selected which eliminates problems with changing tags, but depending on your workflow, the focused timestamp base approach may throw you off at times. Eric
Author: Eric Pruitt, https://github.com/jameseric/ Description: Switch focus between the currently focused window and a previously focused window. This is a rewrite of the swapfocus patch at http://dwm.suckless.org/patches/swapfocus, but attempts (given the nature of tags in dwm, it is not trivial to implement focus history for every combination of previously selected set of tags) to keep focus history on a per tag basis. --- a/dwm.c 2012-11-25 10:18:52.000000000 -0600 +++ b/dwm.c 2012-11-25 14:30:57.000000000 -0600 @@ -143,6 +143,7 @@ Monitor *next; Window barwin; const Layout *lt[2]; + Client *prevclient[32]; }; typedef struct { @@ -224,6 +225,7 @@ static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); +static void swapfocus(); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static int textnw(const char *text, unsigned int len); @@ -657,6 +659,7 @@ m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + for(int i = 0; i < 31; i++, m->prevclient[i] = NULL); return m; } @@ -844,6 +847,12 @@ focus(Client *c) { if(!c || !ISVISIBLE(c)) for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + else { + int n = 0, i; + for (i = c->tags & c->mon->tagset[c->mon->seltags]; i; i >>= 1, n++); + if (selmon->sel != selmon->prevclient[n - 1]) + selmon->prevclient[n - 1] = selmon->sel; + } /* was if(selmon->sel) */ if(selmon->sel && selmon->sel != c) unfocus(selmon->sel, False); @@ -1675,6 +1684,14 @@ } void +swapfocus() { + Client *c = selmon->sel; + int n = 0, i; + for (i = c->tags & c->mon->tagset[c->mon->seltags]; i; i >>= 1, n++); + if(n) focus(selmon->prevclient[n - 1]); +} + +void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK;
Author: Eric Pruitt, https://github.com/jameseric/ Description: Switch to most recently, previously focused window that is currently visible. --- a/dwm.c 2012-12-09 23:48:53.000000000 -0600 +++ b/dwm.c 2012-12-09 23:48:53.000000000 -0600 @@ -30,6 +30,7 @@ #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> +#include <sys/time.h> #include <X11/cursorfont.h> #include <X11/keysym.h> #include <X11/Xatom.h> @@ -95,6 +96,7 @@ Client *snext; Monitor *mon; Window win; + struct timeval ft; }; typedef struct { @@ -224,6 +226,7 @@ static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); +static void lastclient(); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static int textnw(const char *text, unsigned int len); @@ -865,6 +868,21 @@ } void +lastclient() { + Client *c, *o; + for (o = selmon->sel, c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c) && c != selmon->sel && (o == selmon->sel || + ((double)c->ft.tv_sec + c->ft.tv_usec * 0.000001) > + ((double)o->ft.tv_sec + o->ft.tv_usec * 0.000001))) { + o = c; + } + } + + if(o != selmon->sel) + focus(o); +} + +void focusin(XEvent *e) { /* there are some broken focus acquiring clients */ XFocusChangeEvent *ev = &e->xfocus; @@ -1520,6 +1538,8 @@ void setfocus(Client *c) { + if(gettimeofday(&c->ft, NULL)) + perror("gettimeofday(&c->ft, NULL) failed"); if(!c->neverfocus) XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); sendevent(c, wmatom[WMTakeFocus]);
