diff --git a/calmwm.h b/calmwm.h index 5234376..1343011 100644 --- a/calmwm.h +++ b/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/client.c b/client.c index cf72174..ab3bd3d 100644 --- a/client.c +++ b/client.c @@ -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/xevents.c b/xevents.c index 4add085..8db5862 100644 --- a/xevents.c +++ b/xevents.c @@ -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); }