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]);

Reply via email to