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.
This commit is contained in:
Po Lu 2022-04-19 15:47:34 +08:00
parent 7f2ef27f49
commit d168decab4

View file

@ -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