diff options
author | Po Lu <luangruo@yahoo.com> | 2022-02-12 20:25:00 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-02-12 20:28:20 +0800 |
commit | be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40 (patch) | |
tree | d9e39c9ee8ff639dc65ee7df0af9aaf3ebe1ba65 /src | |
parent | e2f9c27f9ac880aa321c3467c67a6c7394576781 (diff) | |
download | emacs-be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40.tar.gz emacs-be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40.tar.bz2 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, && 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 (); { 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, 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 |