foxygit / dotfiles Log in
commits tags

/net-active-window.patch · 1.46 KB

raw
diff --git a/src/sxwm.c b/src/sxwm.c
index de43ce3..b170567 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -1011,6 +1011,34 @@ void hdl_client_msg(XEvent *xev)
 		}
 		return;
 	}
+
+	if (xev->xclient.message_type == atoms[ATOM_NET_ACTIVE_WINDOW]) {
+		/* external activation request (pagers/taskbars, e.g. `wmctrl -a`)
+		 * -- _NET_ACTIVE_WINDOW is advertised in _NET_SUPPORTED and we
+		 * already publish it read-only to reflect our own focus, but
+		 * nothing accepted requests to change it until now. Switch to
+		 * the client's workspace first if it's not the current one, same
+		 * as a pager would expect, then focus/raise it exactly like
+		 * focus_next/focus_prev do.
+		 *
+		 * data.l[0] is the EWMH source indication: 2 means a pager/taskbar
+		 * acting on an explicit user click (mouse already elsewhere, so
+		 * warp it to the window), 1 means the application is requesting
+		 * its own activation. Chromium/Electron apps (VS Code, among
+		 * others) send the latter when clicked while unfocused -- warping
+		 * there yanks the pointer away from right where the user just
+		 * clicked, so only warp for real pager/taskbar requests. */
+		XClientMessageEvent *client_msg_ev = &xev->xclient;
+		Window w = client_msg_ev->window;
+		Client *c = find_client(find_toplevel(w));
+		if (!c)
+			return;
+
+		if (c->ws != current_ws)
+			change_workspace(c->ws);
+		set_input_focus(c, True, client_msg_ev->data.l[0] == 2);
+		return;
+	}
 }

 void hdl_config_ntf(XEvent *xev)