diff options
| author | Daniel Guihot | 2026-09-16 06:18:28 +1000 |
|---|---|---|
| committer | Daniel Guihot | 2026-09-16 06:18:49 +1000 |
| commit | b79b0e587eb85f4ab37cf954c84c9e6730faabe0 (patch) | |
| tree | 7abf530c44eccd574b79d780ba9d6b2fb208be0a | |
| parent | e0bb47559a2913c3b24c289a1471209321acca91 (diff) | |
| download | dwm-fullscreenhook-b79b0e587eb85f4ab37cf954c84c9e6730faabe0.tar.gz dwm-fullscreenhook-b79b0e587eb85f4ab37cf954c84c9e6730faabe0.zip | |
Update the root property on focus and fullscreen changes. Tags,
client exits, and multiple fullscreen clients now remain correct.
| -rw-r--r-- | README.md | 16 | ||||
| -rw-r--r-- | dwm-fullscreenhook-6.8.diff | 76 |
2 files changed, 53 insertions, 39 deletions
@@ -5,21 +5,21 @@ This patch publishes the active fullscreen window on the root window so other programs can react to it. It applies to dwm 6.8. -dwm sets `_DWM_FULLSCREEN` to the window id of the fullscreen client when it -enters fullscreen, and removes the property when it leaves or is unmanaged. A -compositor, notification daemon or GameMode helper can watch it with: +dwm sets `_DWM_FULLSCREEN` to the window id of the selected fullscreen client. +It removes the property when the selected client is not fullscreen. Focus and +fullscreen changes update the property, so it remains correct across tags, +monitors, client exits, and multiple fullscreen clients. A compositor, +notification daemon or GameMode helper can watch it with: xprop -root -spy _DWM_FULLSCREEN No configuration and no spawned commands. -Assumes one fullscreen client at a time. With two, the property tracks the -most recent one to enter. - ## Testing -Applies and builds against dwm 6.8. Runtime tested under Xvfb: the property -is set on enter and cleared on exit and on unmanage. +Applies and builds against dwm 6.8. Runtime tested under Xvfb. Tests covered +fullscreen entry and exit, tag changes, selecting a normal client, and +falling back to another fullscreen client after the active one was destroyed. ## Download diff --git a/dwm-fullscreenhook-6.8.diff b/dwm-fullscreenhook-6.8.diff index 9d267c3..f90def6 100644 --- a/dwm-fullscreenhook-6.8.diff +++ b/dwm-fullscreenhook-6.8.diff @@ -1,22 +1,30 @@ -From 8b2c41af886b758126c7738fbd302fc1dfcc3172 Mon Sep 17 00:00:00 2001 +From 70197161511b1504a6d6d655a288d2d922938a0f Mon Sep 17 00:00:00 2001 From: Daniel Guihot <daniel@guihot.net> Date: Wed, 16 Sep 2026 05:09:22 +1000 -Subject: [PATCH] fullscreenhook: publish the fullscreen window on the root - window +Subject: [PATCH] fullscreenhook: publish the active fullscreen window -Set _DWM_FULLSCREEN on the root window to the window id of the client -that is fullscreen and clear it when the client exits, so a compositor, -notification daemon or GameMode helper can react without scanning every -window. Assumes one fullscreen client at a time. +Set _DWM_FULLSCREEN on the root window to the selected fullscreen +client, and clear it when the selected client is not fullscreen. +Update the property on focus and fullscreen changes so it remains +correct across tags, monitors, client exits, and multiple fullscreen +clients. --- - dwm.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) + dwm.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c -index 53b393e..1868c5c 100644 +index 53b393e..d1cb48c 100644 --- a/dwm.c +++ b/dwm.c -@@ -258,7 +258,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { +@@ -199,6 +199,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void setfullscreenprop(Client *c); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -258,7 +259,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [PropertyNotify] = propertynotify, [UnmapNotify] = unmapnotify }; @@ -25,36 +33,42 @@ index 53b393e..1868c5c 100644 static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; -@@ -1492,9 +1492,12 @@ setfullscreen(Client *c, int fullscreen) - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); +@@ -807,6 +808,7 @@ focus(Client *c) + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; ++ setfullscreenprop(c); + drawbars(); + } + +@@ -1505,6 +1507,18 @@ setfullscreen(Client *c, int fullscreen) + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } ++ if (c == selmon->sel) ++ setfullscreenprop(c); ++} ++ ++void ++setfullscreenprop(Client *c) ++{ ++ if (c && c->isfullscreen) + XChangeProperty(dpy, root, dwmfullscreen, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)&c->win, 1); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); ++ else + XDeleteProperty(dpy, root, dwmfullscreen); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; -@@ -1579,6 +1582,7 @@ setup(void) + } + + void +@@ -1579,6 +1593,8 @@ setup(void) netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + dwmfullscreen = XInternAtom(dpy, "_DWM_FULLSCREEN", False); ++ XDeleteProperty(dpy, root, dwmfullscreen); /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); -@@ -1783,6 +1787,8 @@ unmanage(Client *c, int destroyed) - - detach(c); - detachstack(c); -+ if (c->isfullscreen) -+ XDeleteProperty(dpy, root, dwmfullscreen); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ -- 2.55.0 |
