diff --git a/src/selection_edge.c b/src/selection_edge.c index 2f9aa1eb..60a7c2a8 100644 --- a/src/selection_edge.c +++ b/src/selection_edge.c @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Part of the code comes from the scrot.c file and maintains its authorship. */ +#include #include #include @@ -50,9 +51,6 @@ struct SelectionEdge { XClassHint *classHint; }; -static void waitUnmapWindowNotify(void); -static Bool xeventUnmap(Display *, XEvent *, XPointer); - void selectionEdgeCreate(void) { struct Selection *const sel = *selectionGet(); @@ -130,38 +128,26 @@ void selectionEdgeDestroy(void) const struct Selection *const sel = *selectionGet(); struct SelectionEdge *pe = sel->edge; - if (pe->wndDraw != 0) { - waitUnmapWindowNotify(); - XFree(pe->classHint); + if (pe->wndDraw != None) { + XSelectInput(disp, pe->wndDraw, StructureNotifyMask); XDestroyWindow(disp, pe->wndDraw); - } - - free(pe); -} - -static void waitUnmapWindowNotify(void) -{ - const struct Selection *const sel = *selectionGet(); - const struct SelectionEdge *const pe = sel->edge; - XEvent ev; - - XSelectInput(disp, pe->wndDraw, StructureNotifyMask); - - XUnmapWindow(disp, pe->wndDraw); + bool is_unmapped = false, is_destroyed = false; + for (XEvent ev; !(is_unmapped && is_destroyed);) { + XNextEvent(disp, &ev); + if (ev.type == DestroyNotify && ev.xdestroywindow.window == pe->wndDraw) + is_destroyed = true; + if (ev.type == UnmapNotify && ev.xunmap.window == pe->wndDraw) + is_unmapped = true; + } + /* HACK: although we recived a DestroyNotify event, the frame still + * might not have been updated. a compositor might also buffer frames + * adding latency. so wait a bit for the screen to update and the + * selection borders to go away. */ + struct timespec t = { .tv_nsec = 80 * 1000L * 1000L }; + while (nanosleep(&t, &t) < 0 && errno == EINTR); - struct timespec delay = {0, 80000000L}; // 80ms - - for (short i = 0; i < 30; ++i) { - if (XCheckIfEvent(disp, &ev, &xeventUnmap, (XPointer) & (pe->wndDraw))) - break; - nanosleep(&delay, NULL); + XFree(pe->classHint); } -} - -static Bool xeventUnmap(Display *dpy, XEvent *ev, XPointer arg) -{ - (void)dpy; // unused - Window *win = (Window *)arg; - return (ev->xunmap.window == *win); + free(pe); }