From d168decab4a03cd48b8b96257c36ffa575c720e6 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 19 Apr 2022 15:47:34 +0800 Subject: [PATCH] Deal with Motif drag window related races * src/xterm.c (xm_drag_window_error_handler): New function. (xm_get_drag_window): If a drag window was created and we have the temp display grabbed, use that instead. --- src/xterm.c | 55 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index c4652c19c66..3eecd5e204b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1366,10 +1366,16 @@ xm_write_drag_initiator_info (Display *dpy, Window wdesc, PropModeReplace, (unsigned char *) buf, 8); } +static int +xm_drag_window_error_handler (Display *display, XErrorEvent *event) +{ + return 0; +} + static Window xm_get_drag_window (struct x_display_info *dpyinfo) { - Atom actual_type; + Atom actual_type, _MOTIF_DRAG_WINDOW; int rc, actual_format; unsigned long nitems, bytes_remaining; unsigned char *tmp_data = NULL; @@ -1377,6 +1383,7 @@ xm_get_drag_window (struct x_display_info *dpyinfo) XSetWindowAttributes attrs; XWindowAttributes wattrs; Display *temp_display; + void *old_handler; drag_window = None; rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, @@ -1420,16 +1427,44 @@ xm_get_drag_window (struct x_display_info *dpyinfo) XGrabServer (temp_display); XSetCloseDownMode (temp_display, RetainPermanent); - attrs.override_redirect = True; - drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), - -1, -1, 1, 1, 0, CopyFromParent, InputOnly, - CopyFromParent, CWOverrideRedirect, &attrs); - XChangeProperty (temp_display, DefaultRootWindow (temp_display), - XInternAtom (temp_display, - "_MOTIF_DRAG_WINDOW", False), - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &drag_window, 1); + + /* We can't use XErrorHandler since it's not in the Xlib + specification, and Emacs tries to be portable. */ + old_handler = (void *) XSetErrorHandler (xm_drag_window_error_handler); + + _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, + "_MOTIF_DRAG_WINDOW", False); + + /* Some other program might've created a drag window between now + and when we first looked. Use that if it exists. */ + + tmp_data = NULL; + rc = XGetWindowProperty (temp_display, DefaultRootWindow (temp_display), + _MOTIF_DRAG_WINDOW, 0, 1, False, XA_WINDOW, + &actual_type, &actual_format, &nitems, + &bytes_remaining, &tmp_data) == Success; + + if (rc && actual_type == XA_WINDOW + && actual_format == 32 && nitems == 1 + && tmp_data) + drag_window = *(Window *) tmp_data; + + if (tmp_data) + XFree (tmp_data); + + if (drag_window == None) + { + attrs.override_redirect = True; + drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), + -1, -1, 1, 1, 0, CopyFromParent, InputOnly, + CopyFromParent, CWOverrideRedirect, &attrs); + XChangeProperty (temp_display, DefaultRootWindow (temp_display), + _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &drag_window, 1); + } + XCloseDisplay (temp_display); + XSetErrorHandler (old_handler); /* Make sure the drag window created is actually valid for the current display, and the XOpenDisplay above didn't -- 2.39.2