Hello,
This is my first time posting here so please forgive me if something is not correct. When running cwm you can destroy the client window while you are moving or resizing it, leading to crash of the WM when the prop window is accessed (the one at the top-left that indicates the position/scale). I include a demonstration for the crash and also a patch that fixes it. Hopefully someone with more experience can implement a better fix. Also, should this go into the tech mailing list instead of misc? Demonstration code for the crash: #include <X11/Xlib.h> #include <err.h> #include <unistd.h> int main(void) { Display *dpy; Window win; int scr; XEvent ev; dpy = XOpenDisplay(NULL); if (!dpy) err(1, "XOpenDisplay"); scr = DefaultScreen(dpy); win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 0, 0, 500, 500, 0, 0, WhitePixel(dpy, scr)); if (!win) err(1, "XCreateSimpleWindow"); XSelectInput(dpy, win, StructureNotifyMask | SubstructureNotifyMask | ExposureMask); XMapRaised(dpy, win); while (1) { XNextEvent(dpy, &ev); switch (ev.type) { case CreateNotify: goto end; case Expose: XClearWindow(dpy, win); break; default: break; } } end: XDestroyWindow(dpy, win); XCloseDisplay(dpy); return 0; } Here is the patch: Index: calmwm.h =================================================================== RCS file: /cvs/xenocara/app/cwm/calmwm.h,v retrieving revision 1.379 diff -u -p -r1.379 calmwm.h --- calmwm.h 20 Jul 2023 14:39:34 -0000 1.379 +++ calmwm.h 6 Feb 2024 20:20:22 -0000 @@ -481,7 +481,7 @@ struct geom screen_area(struct screen_ struct screen_ctx *screen_find(Window); void screen_init(int); void screen_prop_win_create(struct screen_ctx *, Window); -void screen_prop_win_destroy(struct screen_ctx *); +void screen_prop_win_destroy(struct screen_ctx *, int); void screen_prop_win_draw(struct screen_ctx *, const char *, ...) __attribute__((__format__ (printf, 2, 3))) Index: kbfunc.c =================================================================== RCS file: /cvs/xenocara/app/cwm/kbfunc.c,v retrieving revision 1.174 diff -u -p -r1.174 kbfunc.c --- kbfunc.c 20 Jul 2023 14:39:34 -0000 1.174 +++ kbfunc.c 6 Feb 2024 20:20:22 -0000 @@ -169,9 +169,23 @@ kbfunc_client_move_mb(void *ctx, struct screen_prop_win_create(sc, cc->win); screen_prop_win_draw(sc, "%+5d%+5d", cc->geom.x, cc->geom.y); - while (move) { - XMaskEvent(X_Dpy, MOUSEMASK, &ev); + while (move > 0) { + XMaskEvent(X_Dpy, MOUSEMASK | SubstructureNotifyMask, &ev); switch (ev.type) { + /* check for destroy events, in case the client window + * gets destroyed, which forcefully closes the prop window. + */ + case DestroyNotify: + /* set move to -1 to specify abrupt exit */ + if (ev.xdestroywindow.window == cc->win) { + screen_prop_win_destroy(sc, 1); + client_remove(cc); + move = -1; + } else if (ev.xdestroywindow.window == sc->prop.win) { + screen_prop_win_destroy(sc, 0); + move = -1; + } + break; case MotionNotify: /* not more than 60 times / second */ if ((ev.xmotion.time - ltime) <= (1000 / 60)) @@ -199,9 +213,11 @@ kbfunc_client_move_mb(void *ctx, struct break; } } - if (ltime) - client_move(cc); - screen_prop_win_destroy(sc); + if (move != -1) { + if (ltime) + client_move(cc); + screen_prop_win_destroy(sc, 1); + } XUngrabPointer(X_Dpy, CurrentTime); } @@ -258,9 +274,22 @@ kbfunc_client_resize_mb(void *ctx, struc screen_prop_win_create(sc, cc->win); screen_prop_win_draw(sc, "%4d x %-4d", cc->dim.w, cc->dim.h); - while (resize) { + while (resize > 0) { XMaskEvent(X_Dpy, MOUSEMASK, &ev); switch (ev.type) { + /* check for destroy events, in case the client window + * gets destroyed, which forcefully closes the prop window. + */ + case DestroyNotify: + if (ev.xdestroywindow.window == cc->win) { + screen_prop_win_destroy(sc, 1); + client_remove(cc); + resize = -1; + } else if (ev.xdestroywindow.window == sc->prop.win) { + screen_prop_win_destroy(sc, 0); + resize = -1; + } + break; case MotionNotify: /* not more than 60 times / second */ if ((ev.xmotion.time - ltime) <= (1000 / 60)) @@ -279,9 +308,11 @@ kbfunc_client_resize_mb(void *ctx, struc break; } } - if (ltime) - client_resize(cc, 1); - screen_prop_win_destroy(sc); + if (resize != -1) { + if (ltime) + client_resize(cc, 1); + screen_prop_win_destroy(sc, 1); + } XUngrabPointer(X_Dpy, CurrentTime); /* Make sure the pointer stays within the window. */ Index: screen.c =================================================================== RCS file: /cvs/xenocara/app/cwm/screen.c,v retrieving revision 1.98 diff -u -p -r1.98 screen.c --- screen.c 27 Jan 2022 18:45:10 -0000 1.98 +++ screen.c 6 Feb 2024 20:20:22 -0000 @@ -278,10 +278,15 @@ screen_prop_win_create(struct screen_ctx } void -screen_prop_win_destroy(struct screen_ctx *sc) +screen_prop_win_destroy(struct screen_ctx *sc, int destroy_window) { XftDrawDestroy(sc->prop.xftdraw); - XDestroyWindow(X_Dpy, sc->prop.win); + /* + * In case the window was already destroyed + * (i.e. DestroyNotify event) + */ + if (destroy_window) + XDestroyWindow(X_Dpy, sc->prop.win); } void