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);
+ }
}
}