diff options
| author | Po Lu | 2022-04-19 15:47:34 +0800 |
|---|---|---|
| committer | Po Lu | 2022-04-19 15:49:27 +0800 |
| commit | d168decab4a03cd48b8b96257c36ffa575c720e6 (patch) | |
| tree | 8e01b34a7d1d486b2ae2f4a23cfc07616e4fcacb /src | |
| parent | 7f2ef27f49e2ea22cf38b84efc8e927c0240f16d (diff) | |
| download | emacs-d168decab4a03cd48b8b96257c36ffa575c720e6.tar.gz emacs-d168decab4a03cd48b8b96257c36ffa575c720e6.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 55 |
1 files 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, | |||
| 1366 | PropModeReplace, (unsigned char *) buf, 8); | 1366 | PropModeReplace, (unsigned char *) buf, 8); |
| 1367 | } | 1367 | } |
| 1368 | 1368 | ||
| 1369 | static int | ||
| 1370 | xm_drag_window_error_handler (Display *display, XErrorEvent *event) | ||
| 1371 | { | ||
| 1372 | return 0; | ||
| 1373 | } | ||
| 1374 | |||
| 1369 | static Window | 1375 | static Window |
| 1370 | xm_get_drag_window (struct x_display_info *dpyinfo) | 1376 | xm_get_drag_window (struct x_display_info *dpyinfo) |
| 1371 | { | 1377 | { |
| 1372 | Atom actual_type; | 1378 | Atom actual_type, _MOTIF_DRAG_WINDOW; |
| 1373 | int rc, actual_format; | 1379 | int rc, actual_format; |
| 1374 | unsigned long nitems, bytes_remaining; | 1380 | unsigned long nitems, bytes_remaining; |
| 1375 | unsigned char *tmp_data = NULL; | 1381 | unsigned char *tmp_data = NULL; |
| @@ -1377,6 +1383,7 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1377 | XSetWindowAttributes attrs; | 1383 | XSetWindowAttributes attrs; |
| 1378 | XWindowAttributes wattrs; | 1384 | XWindowAttributes wattrs; |
| 1379 | Display *temp_display; | 1385 | Display *temp_display; |
| 1386 | void *old_handler; | ||
| 1380 | 1387 | ||
| 1381 | drag_window = None; | 1388 | drag_window = None; |
| 1382 | rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, | 1389 | rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, |
| @@ -1420,16 +1427,44 @@ xm_get_drag_window (struct x_display_info *dpyinfo) | |||
| 1420 | 1427 | ||
| 1421 | XGrabServer (temp_display); | 1428 | XGrabServer (temp_display); |
| 1422 | XSetCloseDownMode (temp_display, RetainPermanent); | 1429 | XSetCloseDownMode (temp_display, RetainPermanent); |
| 1423 | attrs.override_redirect = True; | 1430 | |
| 1424 | drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), | 1431 | /* We can't use XErrorHandler since it's not in the Xlib |
| 1425 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, | 1432 | specification, and Emacs tries to be portable. */ |
| 1426 | CopyFromParent, CWOverrideRedirect, &attrs); | 1433 | old_handler = (void *) XSetErrorHandler (xm_drag_window_error_handler); |
| 1427 | XChangeProperty (temp_display, DefaultRootWindow (temp_display), | 1434 | |
| 1428 | XInternAtom (temp_display, | 1435 | _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, |
| 1429 | "_MOTIF_DRAG_WINDOW", False), | 1436 | "_MOTIF_DRAG_WINDOW", False); |
| 1430 | XA_WINDOW, 32, PropModeReplace, | 1437 | |
| 1431 | (unsigned char *) &drag_window, 1); | 1438 | /* Some other program might've created a drag window between now |
| 1439 | and when we first looked. Use that if it exists. */ | ||
| 1440 | |||
| 1441 | tmp_data = NULL; | ||
| 1442 | rc = XGetWindowProperty (temp_display, DefaultRootWindow (temp_display), | ||
| 1443 | _MOTIF_DRAG_WINDOW, 0, 1, False, XA_WINDOW, | ||
| 1444 | &actual_type, &actual_format, &nitems, | ||
| 1445 | &bytes_remaining, &tmp_data) == Success; | ||
| 1446 | |||
| 1447 | if (rc && actual_type == XA_WINDOW | ||
| 1448 | && actual_format == 32 && nitems == 1 | ||
| 1449 | && tmp_data) | ||
| 1450 | drag_window = *(Window *) tmp_data; | ||
| 1451 | |||
| 1452 | if (tmp_data) | ||
| 1453 | XFree (tmp_data); | ||
| 1454 | |||
| 1455 | if (drag_window == None) | ||
| 1456 | { | ||
| 1457 | attrs.override_redirect = True; | ||
| 1458 | drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), | ||
| 1459 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, | ||
| 1460 | CopyFromParent, CWOverrideRedirect, &attrs); | ||
| 1461 | XChangeProperty (temp_display, DefaultRootWindow (temp_display), | ||
| 1462 | _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, | ||
| 1463 | (unsigned char *) &drag_window, 1); | ||
| 1464 | } | ||
| 1465 | |||
| 1432 | XCloseDisplay (temp_display); | 1466 | XCloseDisplay (temp_display); |
| 1467 | XSetErrorHandler (old_handler); | ||
| 1433 | 1468 | ||
| 1434 | /* Make sure the drag window created is actually valid for the | 1469 | /* Make sure the drag window created is actually valid for the |
| 1435 | current display, and the XOpenDisplay above didn't | 1470 | current display, and the XOpenDisplay above didn't |