summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-01-17 18:41:51 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-01-17 18:41:51 +0000
commit5302cfe44d126ff354e5c8c679c5d10f9dec8e99 (patch)
tree8296f869508a27e4657787f422e89e3c18f9fd5c
parent619cd8c5112a42e233b3033c9eb9d2a1ff1fddfb (diff)
Finally fix the really annoying race where if you rapidly switch groups several
times you'd end up losing clients (thinking they had gone away). From the ICCCM (which should not be read without a stiff drink in hand, I made this mistake so you don't have to): to request a window to be withdrawn one should send a synthetic UnmapRequest event when iconified. To request iconification one should just unmap the window. The ICCM further recommends that the synthetic event should just be taken as a cue to withdraw, to deal with legacy clients. Taking a hint from this, rework xev_handle_unmaprequest to correctly detect these situations. A Withdrawn window may come back anywhere, even as a subwindow of something else, so the correct way to handle this state is to forget it ever existed. While i'm here, kill a dumb attempt to notice this in client_delete, and nuke the very unnecessary arguments. Todd confirmed this fixes the `race'. ok todd@, ok ok okan@
-rw-r--r--app/cwm/calmwm.h4
-rw-r--r--app/cwm/client.c7
-rw-r--r--app/cwm/xevents.c37
3 files changed, 26 insertions, 22 deletions
diff --git a/app/cwm/calmwm.h b/app/cwm/calmwm.h
index 4bda7bc67..b13187af4 100644
--- a/app/cwm/calmwm.h
+++ b/app/cwm/calmwm.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: calmwm.h,v 1.74 2009/01/16 15:24:14 okan Exp $
+ * $Id: calmwm.h,v 1.75 2009/01/17 18:41:50 oga Exp $
*/
#ifndef _CALMWM_H_
@@ -310,7 +310,7 @@ __dead void usage(void);
struct client_ctx *client_find(Window);
void client_setup(void);
struct client_ctx *client_new(Window, struct screen_ctx *, int);
-int client_delete(struct client_ctx *, int, int);
+int client_delete(struct client_ctx *);
void client_setactive(struct client_ctx *, int);
void client_resize(struct client_ctx *);
void client_lower(struct client_ctx *);
diff --git a/app/cwm/client.c b/app/cwm/client.c
index 25498486d..147d93d07 100644
--- a/app/cwm/client.c
+++ b/app/cwm/client.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: client.c,v 1.43 2009/01/16 15:24:14 okan Exp $
+ * $Id: client.c,v 1.44 2009/01/17 18:41:50 oga Exp $
*/
#include "headers.h"
@@ -144,14 +144,11 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
}
int
-client_delete(struct client_ctx *cc, int sendevent, int ignorewindow)
+client_delete(struct client_ctx *cc)
{
struct screen_ctx *sc = CCTOSC(cc);
struct winname *wn;
- if (cc->state == IconicState && !sendevent)
- return (1);
-
group_client_delete(cc);
XGrabServer(X_Dpy);
diff --git a/app/cwm/xevents.c b/app/cwm/xevents.c
index 28e88fdb3..cc322ad06 100644
--- a/app/cwm/xevents.c
+++ b/app/cwm/xevents.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: xevents.c,v 1.34 2009/01/16 16:49:17 okan Exp $
+ * $Id: xevents.c,v 1.35 2009/01/17 18:41:50 oga Exp $
*/
/*
@@ -36,12 +36,8 @@ void
xev_handle_maprequest(struct xevent *xev, XEvent *ee)
{
XMapRequestEvent *e = &ee->xmaprequest;
- XWindowAttributes xattr;
struct client_ctx *cc = NULL, *old_cc;
-
-#ifdef notyet
- int state;
-#endif
+ XWindowAttributes xattr;
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
@@ -51,12 +47,6 @@ xev_handle_maprequest(struct xevent *xev, XEvent *ee)
cc = client_new(e->window, screen_fromroot(xattr.root), 1);
}
-#ifdef notyet /* XXX - possibly, we shouldn't map if
- * the window is withdrawn. */
- if (xu_getstate(cc, &state) == 0 && state == WithdrawnState)
- warnx("WITHDRAWNSTATE for %s", cc->name);
-#endif
-
client_ptrwarp(cc);
xev_register(xev);
}
@@ -65,10 +55,27 @@ void
xev_handle_unmapnotify(struct xevent *xev, XEvent *ee)
{
XUnmapEvent *e = &ee->xunmap;
+ XEvent ev;
struct client_ctx *cc;
- if ((cc = client_find(e->window)) != NULL)
- client_delete(cc, e->send_event, 0);
+ /* XXX, we need a recursive locking wrapper around grab server */
+ XGrabServer(X_Dpy);
+ if ((cc = client_find(e->window)) != NULL) {
+ /*
+ * If it's going to die anyway, nuke it.
+ *
+ * Else, if it's a synthetic event delete state, since they
+ * want it to be withdrawn. ICCM recommends you withdraw on
+ * this even if we haven't alredy been told to iconify, to
+ * deal with legacy clients.
+ */
+ if (XCheckTypedWindowEvent(X_Dpy, cc->win,
+ DestroyNotify, &ev) || e->send_event != 0) {
+ client_delete(cc);
+ } else
+ client_hide(cc);
+ }
+ XUngrabServer(X_Dpy);
xev_register(xev);
}
@@ -80,7 +87,7 @@ xev_handle_destroynotify(struct xevent *xev, XEvent *ee)
struct client_ctx *cc;
if ((cc = client_find(e->window)) != NULL)
- client_delete(cc, 1, 1);
+ client_delete(cc);
xev_register(xev);
}