aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-02-12 20:25:00 +0800
committerPo Lu2022-02-12 20:28:20 +0800
commitbe06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40 (patch)
treed9e39c9ee8ff639dc65ee7df0af9aaf3ebe1ba65 /src
parente2f9c27f9ac880aa321c3467c67a6c7394576781 (diff)
downloademacs-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.c53
-rw-r--r--src/xterm.c11
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