diff options
| author | Daniel Guihot | 2026-09-16 05:22:50 +1000 |
|---|---|---|
| committer | Daniel Guihot | 2026-09-16 05:22:50 +1000 |
| commit | 2c336f99d14660cb656892875b3431604359ade3 (patch) | |
| tree | f9b74ed465ee09134318d1abcc99a3f7b5a9e5ea | |
| download | dwm-unmapfullscreen-2c336f99d14660cb656892875b3431604359ade3.tar.gz dwm-unmapfullscreen-2c336f99d14660cb656892875b3431604359ade3.zip | |
dwm 6.8 unmapfullscreen patch
| -rw-r--r-- | README.md | 31 | ||||
| -rw-r--r-- | dwm-unmapfullscreen-6.8.diff | 76 |
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 + |
