1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
From f45beb0d921ecc3f14f9e41ceccc05bf9f274822 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() normally hides windows by moving them off-screen. Some
games and Wine builds do not recover from that state when the tag
returns. Unmap fullscreen clients when hidden and map them when shown
instead.
Suppress StructureNotifyMask and SubstructureNotifyMask while
unmapping so dwm does not mistake its own UnmapNotify for a withdrawn
client. Map before restoring input focus, and preserve normal
off-screen hiding when a hidden client leaves fullscreen.
---
dwm.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 49 insertions(+), 4 deletions(-)
diff --git a/dwm.c b/dwm.c
index 53b393e..f1c2d9f 100644
--- a/dwm.c
+++ b/dwm.c
@@ -91,7 +91,8 @@ struct Client {
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw;
unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate;
+ int isfullscreen, isunmapped;
Client *next;
Client *snext;
Monitor *mon;
@@ -214,6 +215,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);
@@ -1084,7 +1086,8 @@ manage(Window w, XWindowAttributes *wa)
unfocus(selmon->sel, 0);
c->mon->sel = c;
arrange(c->mon);
- XMapWindow(dpy, c->win);
+ if (ISVISIBLE(c) || !c->isfullscreen)
+ XMapWindow(dpy, c->win);
focus(NULL);
}
@@ -1490,8 +1493,11 @@ setfullscreen(Client *c, int fullscreen)
c->oldbw = c->bw;
c->bw = 0;
c->isfloating = 1;
+ if (!ISVISIBLE(c))
+ unmapclient(c);
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
- XRaiseWindow(dpy, c->win);
+ if (ISVISIBLE(c))
+ XRaiseWindow(dpy, c->win);
} else if (!fullscreen && c->isfullscreen){
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
PropModeReplace, (unsigned char*)0, 0);
@@ -1634,13 +1640,27 @@ showhide(Client *c)
if (ISVISIBLE(c)) {
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
+ if (c->isunmapped) {
+ XMapWindow(dpy, c->win);
+ c->isunmapped = 0;
+ if (c == selmon->sel)
+ setfocus(c);
+ }
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);
- XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
+ if (c->isfullscreen)
+ unmapclient(c);
+ else {
+ XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
+ if (c->isunmapped) {
+ XMapWindow(dpy, c->win);
+ c->isunmapped = 0;
+ }
+ }
}
}
@@ -1801,6 +1821,31 @@ unmanage(Client *c, int destroyed)
arrange(m);
}
+void
+unmapclient(Client *c)
+{
+ XWindowAttributes ca, ra;
+
+ XGrabServer(dpy);
+ if (!XGetWindowAttributes(dpy, root, &ra)
+ || !XGetWindowAttributes(dpy, c->win, &ca)) {
+ XUngrabServer(dpy);
+ return;
+ }
+ if (ca.map_state == IsUnmapped) {
+ c->isunmapped = 1;
+ XUngrabServer(dpy);
+ return;
+ }
+ XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
+ XSelectInput(dpy, c->win, ca.your_event_mask & ~StructureNotifyMask);
+ XUnmapWindow(dpy, c->win);
+ c->isunmapped = 1;
+ XSelectInput(dpy, root, ra.your_event_mask);
+ XSelectInput(dpy, c->win, ca.your_event_mask);
+ XUngrabServer(dpy);
+}
+
void
unmapnotify(XEvent *e)
{
--
2.55.0
|