aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Guihot2026-09-16 06:18:28 +1000
committerDaniel Guihot2026-09-16 06:18:49 +1000
commit79e6a3a2b4daf7017f1a1ccada912ffcd57a054e (patch)
tree120d95c295bd2940ce35c2eb178311d17255c40b
parent572fae56b30e86c686b61aa1e31ca9d0803cf313 (diff)
downloaddwm-focusguard-main.tar.gz
dwm-focusguard-main.zip
Guard all fullscreen focus pathsHEADmain
Keep a visible fullscreen client focused and raised when focus would move to a normal client. Update the runtime test notes.
-rw-r--r--README.md22
-rw-r--r--dwm-focusguard-6.8.diff66
2 files changed, 38 insertions, 50 deletions
diff --git a/README.md b/README.md
index 471fb86..d9eda30 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,14 @@
## Description
-This patch keeps focus on a fullscreen client when a new window appears. It
-applies to dwm 6.8.
+This patch keeps focus on a visible fullscreen client when focus would
+otherwise move to a normal client. It applies to dwm 6.8.
-`manage()` calls `focus(NULL)` for every new client on the selected monitor,
-so Steam update dialogs, chat windows and notifications pull focus off a
-running fullscreen game. Many games then drop fullscreen. With this patch the
-fullscreen client stays selected and focused. The new client is still
-attached, arranged and mapped, and can be reached after the game leaves
-fullscreen or by switching tags.
+When focus would move to a normal client, `focus()` checks that client's
+monitor for a visible fullscreen client. If one exists, the fullscreen client
+keeps focus and is raised above the blocked window. This covers newly managed
+windows and other focus paths. The blocked client remains managed and can be
+reached after the game leaves fullscreen or by switching tags.
## Configuration
@@ -19,9 +18,10 @@ The patch uses the existing `lockfullscreen` option in `config.h`. Set it to
## Testing
-Applies and builds against dwm 6.8. Runtime tested under Xvfb: with a
-fullscreen client focused, a new window no longer becomes
-`_NET_ACTIVE_WINDOW`.
+Applies and builds against dwm 6.8. Runtime tested under Xvfb. A new window
+remained managed, but the fullscreen client kept X input focus, stayed
+`_NET_ACTIVE_WINDOW`, and remained above the new window. Setting
+`lockfullscreen` to 0 restored the original focus behaviour.
## Download
diff --git a/dwm-focusguard-6.8.diff b/dwm-focusguard-6.8.diff
index 1ad7f72..3c85f3d 100644
--- a/dwm-focusguard-6.8.diff
+++ b/dwm-focusguard-6.8.diff
@@ -1,53 +1,41 @@
-From a4409c4cb987e486501043e5c1de34833ce15a14 Mon Sep 17 00:00:00 2001
+From 2d620e25e309d539136379e94e65f89c573ba01c Mon Sep 17 00:00:00 2001
From: Daniel Guihot <daniel@guihot.net>
Date: Wed, 16 Sep 2026 05:06:53 +1000
-Subject: [PATCH] focusguard: keep focus on fullscreen clients when windows
- spawn
+Subject: [PATCH] focusguard: keep focus on visible fullscreen clients
-manage() focuses every new client on the selected monitor, which pulls
-focus off a running fullscreen game and makes many games drop
-fullscreen. Keep the fullscreen client selected and focused while
-lockfullscreen is set. The new client is still attached, arranged and
-mapped, and can be reached after the game leaves fullscreen.
+When focus would move to a normal client, keep it on a visible
+fullscreen client on the same monitor while lockfullscreen is set.
+This covers newly managed windows and other focus paths. Raise the
+fullscreen client after focusing it so the blocked window cannot
+obscure it.
---
- dwm.c | 14 ++++++++++----
- 1 file changed, 10 insertions(+), 4 deletions(-)
+ dwm.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
diff --git a/dwm.c b/dwm.c
-index 53b393e..0654ea2 100644
+index 53b393e..15913cc 100644
--- a/dwm.c
+++ b/dwm.c
-@@ -1031,7 +1031,7 @@ killclient(const Arg *arg)
+@@ -788,8 +788,19 @@ expose(XEvent *e)
void
- manage(Window w, XWindowAttributes *wa)
+ focus(Client *c)
{
-- Client *c, *t = NULL;
-+ Client *c, *t = NULL, *fs = NULL;
- Window trans = None;
- XWindowChanges wc;
-
-@@ -1080,12 +1080,18 @@ manage(Window w, XWindowAttributes *wa)
- (unsigned char *) &(c->win), 1);
- XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
- setclientstate(c, NormalState);
-- if (c->mon == selmon)
-+ if (c->mon == selmon && lockfullscreen && selmon->sel
-+ && selmon->sel->isfullscreen)
-+ fs = selmon->sel;
-+ if (c->mon == selmon && !fs)
++ Client *f;
++
+ if (!c || !ISVISIBLE(c))
+ for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
++ if (lockfullscreen && c && !c->isfullscreen) {
++ for (f = c->mon->stack; f; f = f->snext) {
++ if (ISVISIBLE(f) && f->isfullscreen) {
++ c = f;
++ XRaiseWindow(dpy, c->win);
++ break;
++ }
++ }
++ }
+ if (selmon->sel && selmon->sel != c)
unfocus(selmon->sel, 0);
-- c->mon->sel = c;
-+ c->mon->sel = fs ? fs : c;
- arrange(c->mon);
- XMapWindow(dpy, c->win);
-- focus(NULL);
-+ if (fs)
-+ focus(fs);
-+ else
-+ focus(NULL);
- }
-
- void
+ if (c) {
--
2.55.0