Dwm responds to focus requests from clients by setting their urgent flag, rather than actually focusing that window. This is a matter of taste, but basically the correct behaviour as far as I'm concerned. However, it breaks some functionality in Emacs and probably other programs where there can be multiple windows attached to a single instance of the program.

I've written a small patch adding a flag to the window ruleset which gives those client permission to take focus on the current desktop. If the window is attached to an unselected tag it will be flagged urgent instead to avoid messing about with the user's tag setup. All other windows without the stealfocus flag will behave as normal. The way focus events are handled could be more nuanced, but this should be sufficient for most use cases.

I've seen at least one other person ask about about the Emacs frame issue, so hopefully this makes it more usable under dwm

diff --git a/dwm/config.def.h b/dwm-local/config.def.h
index 1c0b587..d1dbfb7 100644
--- a/dwm/config.def.h
+++ b/dwm-local/config.def.h
@@ -26,9 +26,10 @@ static const Rule rules[] = {
 	 *	WM_CLASS(STRING) = instance, class
 	 *	WM_NAME(STRING) = title
 	 */
-	/* class      instance    title       tags mask     isfloating   monitor */
-	{ "Gimp",     NULL,       NULL,       0,            1,           -1 },
-	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
+	/* class      instance    title       tags mask     isfloating   monitor stealfocus */
+	{ "Gimp",     NULL,       NULL,       0,            1,           -1,     0 },
+	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1,     0 },
+	{ "Emacs",    NULL,       NULL,       0,            0,           -1,     1 },
 };
 
 /* layout(s) */
diff --git a/dwm/dwm.c b/dwm-local/dwm.c
index 4465af1..b873584 100644
--- a/dwm/dwm.c
+++ b/dwm-local/dwm.c
@@ -92,7 +92,7 @@ struct Client {
 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
 	int bw, oldbw;
 	unsigned int tags;
-	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, stealfocus;
 	Client *next;
 	Client *snext;
 	Monitor *mon;
@@ -139,6 +139,7 @@ typedef struct {
 	unsigned int tags;
 	int isfloating;
 	int monitor;
+	int stealfocus;
 } Rule;
 
 /* function declarations */
@@ -298,6 +299,7 @@ applyrules(Client *c)
 		&& (!r->instance || strstr(instance, r->instance)))
 		{
 			c->isfloating = r->isfloating;
+			c->stealfocus = r->stealfocus;
 			c->tags |= r->tags;
 			for (m = mons; m && m->num != r->monitor; m = m->next);
 			if (m)
@@ -523,8 +525,12 @@ clientmessage(XEvent *e)
 			setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD    */
 				|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
 	} else if (cme->message_type == netatom[NetActiveWindow]) {
-		if (c != selmon->sel && !c->isurgent)
-			seturgent(c, 1);
+		if (c != selmon->sel) {
+			if (c->stealfocus && ISVISIBLE(c))
+				focus(c);
+			else if (!c->isurgent)
+				seturgent(c, 1);
+		}
 	}
 }
 

Reply via email to