/* Motif drag-and-drop protocol support. */
+/* Pointer to a variable which stores whether or not an X error
+ occured while trying to create the Motif drag window. */
+static volatile bool *xm_drag_window_error;
+
typedef enum xm_byte_order
{
XM_BYTE_ORDER_LSB_FIRST = 'l',
static int
xm_drag_window_error_handler (Display *display, XErrorEvent *event)
{
+ if (xm_drag_window_error)
+ *xm_drag_window_error = true;
+
return 0;
}
XSetWindowAttributes attrs;
Display *temp_display;
void *old_handler, *old_io_handler;
+ /* These are volatile because GCC mistakenly warns about them being
+ clobbered by longjmp. */
+ volatile bool error, created;
drag_window = None;
rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
return None;
}
+ error = false;
+ xm_drag_window_error = &error;
+
XGrabServer (temp_display);
XSetCloseDownMode (temp_display, RetainPermanent);
_MOTIF_DRAG_WINDOW = XInternAtom (temp_display,
"_MOTIF_DRAG_WINDOW", False);
+ if (error)
+ goto give_up;
+
/* Some other program might've created a drag window between now
and when we first looked. Use that if it exists. */
if (tmp_data)
XFree (tmp_data);
+ error = false;
+
if (drag_window == None)
{
+ created = true;
+
attrs.override_redirect = True;
drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
-1, -1, 1, 1, 0, CopyFromParent, InputOnly,
_MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &drag_window, 1);
}
+ else
+ created = false;
+
+ /* Handle all errors now. */
+ XSync (temp_display, False);
+
+ give_up:
+
+ /* Some part of the drag window creation process failed, so
+ punt. */
+ if (error)
+ {
+ /* If the drag window was actually created, delete it now.
+ Probably, a BadAlloc happened during the XChangeProperty
+ request. */
+ if (created)
+ {
+ if (drag_window != None)
+ XDestroyWindow (temp_display, drag_window);
+
+ XDeleteProperty (temp_display, DefaultRootWindow (temp_display),
+ _MOTIF_DRAG_WINDOW);
+ }
+
+ drag_window = None;
+ }
+
+ xm_drag_window_error = NULL;
/* FIXME: why does XCloseDisplay hang if SIGIO arrives and there
are multiple displays? */
#endif
#if defined USE_GTK && defined HAVE_GTK3
- if ((event->error_code == BadMatch || event->error_code == BadWindow)
+ if ((event->error_code == BadMatch
+ || event->error_code == BadWindow)
&& event->request_code == X_SetInputFocus)
- {
- return 0;
- }
+ return 0;
#endif
/* If we try to ungrab or grab a device that doesn't exist anymore