1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-11 14:01:43 -08:00

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.
This commit is contained in:
Po Lu 2022-02-12 20:25:00 +08:00
parent e2f9c27f9a
commit be06b40ebd
2 changed files with 54 additions and 10 deletions

View file

@ -299,16 +299,16 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
&& event.xgeneric.display == dpyinfo->display
&& event.xgeneric.extension == dpyinfo->xi2_opcode)
{
if (!event.xcookie.data
&& XGetEventData (dpyinfo->display, &event.xcookie))
cookie_claimed_p = true;
if (event.xcookie.data)
{
switch (event.xgeneric.evtype)
{
case XI_ButtonRelease:
{
if (!event.xcookie.data
&& XGetEventData (dpyinfo->display, &event.xcookie))
cookie_claimed_p = true;
xev = (XIDeviceEvent *) event.xcookie.data;
device = xi_device_from_id (dpyinfo, xev->deviceid);
@ -358,6 +358,10 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
{
KeySym keysym;
if (!event.xcookie.data
&& XGetEventData (dpyinfo->display, &event.xcookie))
cookie_claimed_p = true;
xev = (XIDeviceEvent *) event.xcookie.data;
copy.xkey.type = KeyPress;
@ -1578,26 +1582,55 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
XtSetArg (av[ac], (char *) XtNgeometry, 0); ac++;
XtSetValues (menu, av, ac);
#if defined HAVE_XINPUT2 && defined USE_X_TOOLKIT
#if defined HAVE_XINPUT2
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
/* Clear the XI2 grab so lwlib can set a core grab. */
bool any_xi_grab_p = false;
/* Clear the XI2 grab, and if any XI2 grab was set, place a core
grab on the frame's edit widget. */
if (dpyinfo->supports_xi2)
XGrabServer (dpyinfo->display);
if (dpyinfo->num_devices)
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
{
#ifndef USE_MOTIF
if (dpyinfo->devices[i].grab)
#endif
XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
CurrentTime);
{
any_xi_grab_p = true;
dpyinfo->devices[i].grab = 0;
XIUngrabDevice (dpyinfo->display,
dpyinfo->devices[i].device_id,
CurrentTime);
}
}
}
if (any_xi_grab_p)
XGrabPointer (dpyinfo->display,
FRAME_X_WINDOW (f),
False, (PointerMotionMask
| PointerMotionHintMask
| ButtonReleaseMask
| ButtonPressMask),
GrabModeSync, GrabModeAsync,
None, None, CurrentTime);
if (dpyinfo->supports_xi2)
XUngrabServer (dpyinfo->display);
#endif
/* Display the menu. */
lw_popup_menu (menu, &dummy);
popup_activated_flag = 1;
#ifdef HAVE_XINPUT2
if (any_xi_grab_p)
XAllowEvents (dpyinfo->display, AsyncPointer, CurrentTime);
#endif
x_activate_timeout_atimer ();
{

View file

@ -10877,6 +10877,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
ev.window = leave->event;
any = x_top_window_to_frame (dpyinfo, leave->event);
/* This allows us to catch LeaveNotify events generated by
popup menu grabs. FIXME: this is right when there is a
focus menu, but implicit focus tracking can get screwed
up if we get this and no XI_Enter event later. */
#ifdef USE_X_TOOLKIT
if (popup_activated ()
&& leave->mode == XINotifyPassiveUngrab)
any = x_any_window_to_frame (dpyinfo, leave->event);
#endif
/* One problem behind the design of XInput 2 scrolling is
that valuators are not unique to each window, but only
the window that has grabbed the valuator's device or