summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-02-12 20:25:00 +0800
committerPo Lu <luangruo@yahoo.com>2022-02-12 20:28:20 +0800
commitbe06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40 (patch)
treed9e39c9ee8ff639dc65ee7df0af9aaf3ebe1ba65 /src
parente2f9c27f9ac880aa321c3467c67a6c7394576781 (diff)
downloademacs-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.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,
&& 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