aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Guihot2026-09-16 05:22:50 +1000
committerDaniel Guihot2026-09-16 05:22:50 +1000
commit2c336f99d14660cb656892875b3431604359ade3 (patch)
treef9b74ed465ee09134318d1abcc99a3f7b5a9e5ea
downloaddwm-unmapfullscreen-2c336f99d14660cb656892875b3431604359ade3.tar.gz
dwm-unmapfullscreen-2c336f99d14660cb656892875b3431604359ade3.zip
dwm 6.8 unmapfullscreen patch
-rw-r--r--README.md31
-rw-r--r--dwm-unmapfullscreen-6.8.diff76
2 files changed, 107 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c827164
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+# unmapfullscreen
+
+## Description
+
+This patch hides fullscreen clients by unmapping them instead of moving them
+off-screen. It applies to dwm 6.8.
+
+`showhide()` hides a window by moving it to `-2 * width`. Some games and
+Wine/Proton builds treat that as a broken or minimized state and do not
+recover fullscreen when the tag returns. With this patch a hidden fullscreen
+client is unmapped and mapped again when it becomes visible.
+
+dwm selects `StructureNotifyMask` on clients and `SubstructureNotifyMask` on
+the root, so calling `XUnmapWindow()` directly reaches `unmapnotify()` and
+unmanages the client. The patch adds a small `unmapclient()` helper that
+suppresses both masks around the unmap, the same technique the windowmap
+patch uses. Hidden fullscreen clients are still parked off-screen so the
+initial map from `manage()` does not put them on the wrong tag.
+
+## Testing
+
+Applies and builds against dwm 6.8. Runtime tested under Xvfb: a hidden
+fullscreen client reports map state unmapped and stays managed.
+
+## Download
+
+* [dwm-unmapfullscreen-6.8.diff](dwm-unmapfullscreen-6.8.diff)
+
+## Author
+
+* Daniel Guihot - [daniel@guihot.net](mailto:daniel@guihot.net)
diff --git a/dwm-unmapfullscreen-6.8.diff b/dwm-unmapfullscreen-6.8.diff
new file mode 100644
index 0000000..30eb3ae
--- /dev/null
+++ b/dwm-unmapfullscreen-6.8.diff
@@ -0,0 +1,76 @@
+From d175466d1ecff304ff32ae3ba852e1eec29a9561 Mon Sep 17 00:00:00 2001
+From: Daniel Guihot <daniel@guihot.net>
+Date: Wed, 16 Sep 2026 05:20:00 +1000
+Subject: [PATCH] unmapfullscreen: unmap hidden fullscreen clients
+
+showhide() hides windows by moving them off-screen, which some games
+and Wine builds treat as a broken or minimized state and do not recover
+from when the tag returns. Unmap and map fullscreen clients instead.
+
+dwm selects StructureNotifyMask on clients and SubstructureNotifyMask on
+the root, so the unmap would reach unmapnotify() and unmanage the
+client. unmapclient() suppresses both masks around the unmap, the same
+approach the windowmap patch uses.
+
+Hidden fullscreen clients are still parked off-screen so the initial map
+from manage() does not put them on the wrong tag.
+---
+ dwm.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/dwm.c b/dwm.c
+index 53b393e..4bd3988 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -214,6 +214,7 @@ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unfocus(Client *c, int setfocus);
+ static void unmanage(Client *c, int destroyed);
++static void unmapclient(Client *c);
+ static void unmapnotify(XEvent *e);
+ static void updatebarpos(Monitor *m);
+ static void updatebars(void);
+@@ -1634,12 +1635,16 @@ showhide(Client *c)
+ if (ISVISIBLE(c)) {
+ /* show clients top down */
+ XMoveWindow(dpy, c->win, c->x, c->y);
++ if (c->isfullscreen)
++ XMapWindow(dpy, c->win);
+ if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
+ resize(c, c->x, c->y, c->w, c->h, 0);
+ showhide(c->snext);
+ } else {
+ /* hide clients bottom up */
+ showhide(c->snext);
++ if (c->isfullscreen)
++ unmapclient(c);
+ XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
+ }
+ }
+@@ -1801,6 +1806,23 @@ unmanage(Client *c, int destroyed)
+ arrange(m);
+ }
+
++void
++unmapclient(Client *c)
++{
++ static XWindowAttributes ra, ca;
++
++ if (!XGetWindowAttributes(dpy, c->win, &ca) || ca.map_state == IsUnmapped)
++ return;
++ XGrabServer(dpy);
++ XGetWindowAttributes(dpy, root, &ra);
++ XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
++ XSelectInput(dpy, c->win, ca.your_event_mask & ~StructureNotifyMask);
++ XUnmapWindow(dpy, c->win);
++ XSelectInput(dpy, root, ra.your_event_mask);
++ XSelectInput(dpy, c->win, ca.your_event_mask);
++ XUngrabServer(dpy);
++}
++
+ void
+ unmapnotify(XEvent *e)
+ {
+--
+2.55.0
+