On Tue, Feb 6, 2024, at 21:14, ZenitDS wrote: > Hello, > > This is my first time posting here so please forgive me if > something is not correct.
Sending to bugs@ or tech@ might be better, it could be better to get feedback from developers. > > 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