Hi,
I verified the attached patch with a quick-and-dirty Xlib app which
XMapWindow()'d and then XWithdrawWindow()'d immediately afterward. Without this
patch, the bug described in FS#699 happened, with it the bug didn't appear.
Uli
From 2282cac598734ff3dd47c02e174b522df9c505cd Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Mon, 28 Dec 2009 16:23:19 +0100
Subject: [PATCH] Handle synthetic UnmapNotify events
According to the Inter-Client Communication Conventions Manual, if you want to
switch your window to withdrawn state, you unmap it and send a synthetic
UnmapNotify to the root window.
This synthetic event fixes a race condition. When you map and unmap a window
quickly, the map will generate a MapRequest for the WM but won't actually map
the window. Thus, the unmap will be discarded (-> window not yet mapped) and the
window stays map once the WM handles the MapRequest
Before this patch, awesome just ignored the synthetic unmap notify which caused
the bug to appear again. With this patch it doesn't happen anymore.
Signed-off-by: Uli Schlachter <[email protected]>
---
event.c | 21 +++++++++++++++++----
1 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/event.c b/event.c
index 370d9ae..38e61a1 100644
--- a/event.c
+++ b/event.c
@@ -665,10 +665,23 @@ event_handle_unmapnotify(void *data __attribute__
((unused)),
if((c = client_getbywin(ev->window)))
{
- if(ev->event == xutil_screen_get(connection, c->phys_screen)->root
- && XCB_EVENT_SENT(ev)
- && xwindow_get_state_reply(xwindow_get_state_unchecked(c->window))
== XCB_WM_STATE_NORMAL)
- client_unmanage(c);
+ if(ev->event == xutil_screen_get(connection, c->phys_screen)->root)
+ {
+ if(!XCB_EVENT_SENT(ev))
+ {
+ /* A regular UnmapNotify, remove that client from our lists */
+ client_unmanage(c);
+ }
+ else
+ {
+ /* According to ICCCM 4.1.4 a client sends a synthetic
+ * UnmapNotify when it wants to switch to Widthdrawn state.
+ * We handle these by unmapping the client and waiting for the
+ * "real" UnmapNotify.
+ */
+ xcb_unmap_window(connection, ev->window);
+ }
+ }
}
else
for(int i = 0; i < globalconf.embedded.len; i++)
--
1.6.5.7