In my patch there were some issues with unhandled events. I upload here a hopefully better patch. Not pretty but fixes the issues.
New 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 7 Feb 2024 20:25:12 -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))) @@ -558,6 +558,7 @@ void conf_screen(struct screen_ctx *) void conf_group(struct screen_ctx *); void xev_process(void); +void xev_process_ev(XEvent *); int xu_get_prop(Window, Atom, Atom, long, unsigned char **); int xu_get_strprop(Window, Atom, char **); 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 7 Feb 2024 20:25:12 -0000 @@ -169,8 +169,8 @@ 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) { case MotionNotify: /* not more than 60 times / second */ @@ -197,11 +197,28 @@ kbfunc_client_move_mb(void *ctx, struct case ButtonRelease: move = 0; break; + /* 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); + move = -1; + } else if (ev.xdestroywindow.window == sc->prop.win) { + screen_prop_win_destroy(sc, 0); + move = -1; + } + xev_process_ev(&ev); + default: /* process event anyway */ + xev_process_ev(&ev); } } - 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,7 +275,7 @@ 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) { case MotionNotify: @@ -277,11 +294,27 @@ kbfunc_client_resize_mb(void *ctx, struc case ButtonRelease: resize = 0; break; + /* 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); + resize = -1; + } else if (ev.xdestroywindow.window == sc->prop.win) { + screen_prop_win_destroy(sc, 0); + resize = -1; + } + default: /* process event anyway */ + xev_process_ev(&ev); + 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 7 Feb 2024 20:25:12 -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 Index: xevents.c =================================================================== RCS file: /cvs/xenocara/app/cwm/xevents.c,v retrieving revision 1.150 diff -u -p -r1.150 xevents.c --- xevents.c 24 Mar 2020 14:47:29 -0000 1.150 +++ xevents.c 7 Feb 2024 20:25:12 -0000 @@ -485,9 +485,15 @@ xev_process(void) while (XPending(X_Dpy)) { XNextEvent(X_Dpy, &e); - if ((e.type - Conf.xrandr_event_base) == RRScreenChangeNotify) - xev_handle_randr(&e); - else if ((e.type < LASTEvent) && (xev_handlers[e.type] != NULL)) - (*xev_handlers[e.type])(&e); + xev_process_ev(&e); } +} + +void +xev_process_ev(XEvent *ev) +{ + if ((ev->type - Conf.xrandr_event_base) == RRScreenChangeNotify) + xev_handle_randr(ev); + else if ((ev->type < LASTEvent) && (xev_handlers[ev->type] != NULL)) + (*xev_handlers[ev->type])(ev); } On Tuesday, February 6th, 2024 at 10:14 PM, ZenitDS <zeni...@proton.me> wrote: > 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