diff options
| author | Po Lu | 2022-02-12 20:25:00 +0800 |
|---|---|---|
| committer | Po Lu | 2022-02-12 20:28:20 +0800 |
| commit | be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40 (patch) | |
| tree | d9e39c9ee8ff639dc65ee7df0af9aaf3ebe1ba65 /src | |
| parent | e2f9c27f9ac880aa321c3467c67a6c7394576781 (diff) | |
| download | emacs-be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40.tar.gz emacs-be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40.zip | |
Fix entry and exit events with XI2 grabs on X toolkit menus
* src/xmenu.c (popup_get_selection): Only claim cookie if new
event will be generated.
(create_and_show_popup_menu): Ungrab XI2 device, then
immediately set core grab on the frame's edit widget window.
* src/xterm.c (handle_one_xevent): Use x_any_window_to_frame to
find exit event frame if a popup menu is active.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 53 | ||||
| -rw-r--r-- | src/xterm.c | 11 |
2 files changed, 54 insertions, 10 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index eaec6efc26c..28fafa108da 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -299,16 +299,16 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, | |||
| 299 | && event.xgeneric.display == dpyinfo->display | 299 | && event.xgeneric.display == dpyinfo->display |
| 300 | && event.xgeneric.extension == dpyinfo->xi2_opcode) | 300 | && event.xgeneric.extension == dpyinfo->xi2_opcode) |
| 301 | { | 301 | { |
| 302 | if (!event.xcookie.data | ||
| 303 | && XGetEventData (dpyinfo->display, &event.xcookie)) | ||
| 304 | cookie_claimed_p = true; | ||
| 305 | |||
| 306 | if (event.xcookie.data) | 302 | if (event.xcookie.data) |
| 307 | { | 303 | { |
| 308 | switch (event.xgeneric.evtype) | 304 | switch (event.xgeneric.evtype) |
| 309 | { | 305 | { |
| 310 | case XI_ButtonRelease: | 306 | case XI_ButtonRelease: |
| 311 | { | 307 | { |
| 308 | if (!event.xcookie.data | ||
| 309 | && XGetEventData (dpyinfo->display, &event.xcookie)) | ||
| 310 | cookie_claimed_p = true; | ||
| 311 | |||
| 312 | xev = (XIDeviceEvent *) event.xcookie.data; | 312 | xev = (XIDeviceEvent *) event.xcookie.data; |
| 313 | device = xi_device_from_id (dpyinfo, xev->deviceid); | 313 | device = xi_device_from_id (dpyinfo, xev->deviceid); |
| 314 | 314 | ||
| @@ -358,6 +358,10 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, | |||
| 358 | { | 358 | { |
| 359 | KeySym keysym; | 359 | KeySym keysym; |
| 360 | 360 | ||
| 361 | if (!event.xcookie.data | ||
| 362 | && XGetEventData (dpyinfo->display, &event.xcookie)) | ||
| 363 | cookie_claimed_p = true; | ||
| 364 | |||
| 361 | xev = (XIDeviceEvent *) event.xcookie.data; | 365 | xev = (XIDeviceEvent *) event.xcookie.data; |
| 362 | 366 | ||
| 363 | copy.xkey.type = KeyPress; | 367 | copy.xkey.type = KeyPress; |
| @@ -1578,26 +1582,55 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, | |||
| 1578 | XtSetArg (av[ac], (char *) XtNgeometry, 0); ac++; | 1582 | XtSetArg (av[ac], (char *) XtNgeometry, 0); ac++; |
| 1579 | XtSetValues (menu, av, ac); | 1583 | XtSetValues (menu, av, ac); |
| 1580 | 1584 | ||
| 1581 | #if defined HAVE_XINPUT2 && defined USE_X_TOOLKIT | 1585 | #if defined HAVE_XINPUT2 |
| 1582 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 1586 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 1583 | /* Clear the XI2 grab so lwlib can set a core grab. */ | 1587 | bool any_xi_grab_p = false; |
| 1588 | |||
| 1589 | /* Clear the XI2 grab, and if any XI2 grab was set, place a core | ||
| 1590 | grab on the frame's edit widget. */ | ||
| 1591 | |||
| 1592 | if (dpyinfo->supports_xi2) | ||
| 1593 | XGrabServer (dpyinfo->display); | ||
| 1584 | 1594 | ||
| 1585 | if (dpyinfo->num_devices) | 1595 | if (dpyinfo->num_devices) |
| 1586 | { | 1596 | { |
| 1587 | for (int i = 0; i < dpyinfo->num_devices; ++i) | 1597 | for (int i = 0; i < dpyinfo->num_devices; ++i) |
| 1588 | { | 1598 | { |
| 1589 | #ifndef USE_MOTIF | ||
| 1590 | if (dpyinfo->devices[i].grab) | 1599 | if (dpyinfo->devices[i].grab) |
| 1591 | #endif | 1600 | { |
| 1592 | XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id, | 1601 | any_xi_grab_p = true; |
| 1593 | CurrentTime); | 1602 | dpyinfo->devices[i].grab = 0; |
| 1603 | |||
| 1604 | XIUngrabDevice (dpyinfo->display, | ||
| 1605 | dpyinfo->devices[i].device_id, | ||
| 1606 | CurrentTime); | ||
| 1607 | } | ||
| 1594 | } | 1608 | } |
| 1595 | } | 1609 | } |
| 1610 | |||
| 1611 | if (any_xi_grab_p) | ||
| 1612 | XGrabPointer (dpyinfo->display, | ||
| 1613 | FRAME_X_WINDOW (f), | ||
| 1614 | False, (PointerMotionMask | ||
| 1615 | | PointerMotionHintMask | ||
| 1616 | | ButtonReleaseMask | ||
| 1617 | | ButtonPressMask), | ||
| 1618 | GrabModeSync, GrabModeAsync, | ||
| 1619 | None, None, CurrentTime); | ||
| 1620 | |||
| 1621 | if (dpyinfo->supports_xi2) | ||
| 1622 | XUngrabServer (dpyinfo->display); | ||
| 1596 | #endif | 1623 | #endif |
| 1597 | 1624 | ||
| 1598 | /* Display the menu. */ | 1625 | /* Display the menu. */ |
| 1599 | lw_popup_menu (menu, &dummy); | 1626 | lw_popup_menu (menu, &dummy); |
| 1600 | popup_activated_flag = 1; | 1627 | popup_activated_flag = 1; |
| 1628 | |||
| 1629 | #ifdef HAVE_XINPUT2 | ||
| 1630 | if (any_xi_grab_p) | ||
| 1631 | XAllowEvents (dpyinfo->display, AsyncPointer, CurrentTime); | ||
| 1632 | #endif | ||
| 1633 | |||
| 1601 | x_activate_timeout_atimer (); | 1634 | x_activate_timeout_atimer (); |
| 1602 | 1635 | ||
| 1603 | { | 1636 | { |
diff --git a/src/xterm.c b/src/xterm.c index 22c14380767..20ea7468202 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -10877,6 +10877,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 10877 | ev.window = leave->event; | 10877 | ev.window = leave->event; |
| 10878 | any = x_top_window_to_frame (dpyinfo, leave->event); | 10878 | any = x_top_window_to_frame (dpyinfo, leave->event); |
| 10879 | 10879 | ||
| 10880 | /* This allows us to catch LeaveNotify events generated by | ||
| 10881 | popup menu grabs. FIXME: this is right when there is a | ||
| 10882 | focus menu, but implicit focus tracking can get screwed | ||
| 10883 | up if we get this and no XI_Enter event later. */ | ||
| 10884 | |||
| 10885 | #ifdef USE_X_TOOLKIT | ||
| 10886 | if (popup_activated () | ||
| 10887 | && leave->mode == XINotifyPassiveUngrab) | ||
| 10888 | any = x_any_window_to_frame (dpyinfo, leave->event); | ||
| 10889 | #endif | ||
| 10890 | |||
| 10880 | /* One problem behind the design of XInput 2 scrolling is | 10891 | /* One problem behind the design of XInput 2 scrolling is |
| 10881 | that valuators are not unique to each window, but only | 10892 | that valuators are not unique to each window, but only |
| 10882 | the window that has grabbed the valuator's device or | 10893 | the window that has grabbed the valuator's device or |