unmanage: stop listening for events for unmanaged windows - dwm - dynamic windo… | |
git clone git://git.suckless.org/dwm | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 786f6e2a6f8466ad94706781bc93bc6eb6e69512 | |
parent e03248a4d5feaaacb130416be6e467a04de81f78 | |
Author: Stein <[email protected]> | |
Date: Mon, 1 Aug 2022 11:42:44 +0200 | |
unmanage: stop listening for events for unmanaged windows | |
This is in particular to avoid flickering in dwm (and high CPU usage) | |
when hovering the mouse over a tabbed window that was previously | |
managed by dwm. | |
Consider the following two scenarios: | |
1) | |
We start tabbed (window 0xc000003), tabbed is managed by the | |
window manager. | |
We start st being embedded into tabbed. | |
$ st -w 0xc000003 | |
What happens here is that: | |
- tabbed gets a MapRequest for the st window | |
- tabbed reparents the st window | |
- tabbed will receive X events for the window | |
The window manager will have no awareness of the st window and the | |
X server will not send X events to the window manager relating to | |
the st window. | |
There is no flickering or any other issues relating to focus. | |
2) | |
We start tabbed (window 0xc000003), tabbed is managed by the | |
window manager. | |
We start st as normal (window 0xd400005). | |
What happens here is that: | |
- the window manager gets a MapRequest for the st window | |
- dwm manages the st window as a normal client | |
- dwm will receive X events for the window | |
Now we use xdotool to trigger a reparenting of the st window into | |
tabbed. | |
$ xdotool windowreparent 0xd400005 0xc000003 | |
What happens here is that: | |
- tabbed gets a MapRequest for the st window | |
- tabbed reparents the st window | |
- the window manager gets an UnmapNotify | |
- the window manager no longer manages the st window | |
- both the window manager and tabbed will receive X events | |
for the st window | |
In dwm move the mouse cursor over the tabbed window. | |
What happens now is that: | |
- dwm will receive a FocusIn event for the tabbed window | |
- dwm will set input focus for the tabbed window | |
- tabbed will receive a FocusIn event for the main window | |
- tabbed will give focus to the window on the currently selected | |
tab | |
- which again triggers a FocusIn event which dwm receives | |
- dwm determines that the window that the FocusIn event is for | |
(0xd400005) is not the currently selected client (tabbed) | |
- dwm sets input focus for the tabbed window | |
- this causes an infinite loop as long as the mouse cursor hovers | |
the tabbed window, resulting in flickering and high CPU usage | |
The fix here is to tell the X server that we are no longer interested | |
in receiving events for this window when the window manager stops | |
managing the window. | |
Diffstat: | |
M dwm.c | 1 + | |
1 file changed, 1 insertion(+), 0 deletions(-) | |
--- | |
diff --git a/dwm.c b/dwm.c | |
@@ -1780,6 +1780,7 @@ unmanage(Client *c, int destroyed) | |
wc.border_width = c->oldbw; | |
XGrabServer(dpy); /* avoid race conditions */ | |
XSetErrorHandler(xerrordummy); | |
+ XSelectInput(dpy, c->win, NoEventMask); | |
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore … | |
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); | |
setclientstate(c, WithdrawnState); |