summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-06 11:01:39 +0800
committerPo Lu <luangruo@yahoo.com>2022-05-06 11:01:39 +0800
commite379d2e8c18e8d9a0f859a8d90621fc898a9caf7 (patch)
tree8901ea609d461446ad0735d3a25686913fd935cf
parente2fcbd8dbd091bb72915297c92a801cbe66f13c9 (diff)
downloademacs-e379d2e8c18e8d9a0f859a8d90621fc898a9caf7.tar.gz
emacs-e379d2e8c18e8d9a0f859a8d90621fc898a9caf7.tar.bz2
emacs-e379d2e8c18e8d9a0f859a8d90621fc898a9caf7.zip
Fix menu dismissal problems on Xt builds with XI2
* src/xmenu.c (prepare_for_entry_into_toolkit_menu) (leave_toolkit_menu): New functions. (create_and_show_popup_menu): Replace some of the grab logic with resetting the XI event mask instead.
-rw-r--r--src/xmenu.c106
1 files changed, 84 insertions, 22 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index 418628d4916..0dbc8058f9e 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1618,6 +1618,84 @@ popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
menu_item_selection = client_data;
}
+
+#ifdef HAVE_XINPUT2
+static void
+prepare_for_entry_into_toolkit_menu (struct frame *f)
+{
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+ Lisp_Object tail, frame;
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (!dpyinfo->supports_xi2)
+ return;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &mask, 1);
+ }
+}
+
+static void
+leave_toolkit_menu (void *data)
+{
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+ Lisp_Object tail, frame;
+ struct x_display_info *dpyinfo;
+ struct frame *f;
+
+ dpyinfo = FRAME_DISPLAY_INFO ((struct frame *) data);
+
+ if (!dpyinfo->supports_xi2)
+ return;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &mask, 1);
+ }
+}
+#endif
+
/* ID is the LWLIB ID of the dialog box. */
static void
@@ -1720,11 +1798,9 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
#ifdef HAVE_XINPUT2
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- 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);
@@ -1735,7 +1811,6 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
{
if (dpyinfo->devices[i].grab)
{
- any_xi_grab_p = true;
dpyinfo->devices[i].grab = 0;
XIUngrabDevice (dpyinfo->display,
@@ -1745,20 +1820,6 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
}
}
- if (any_xi_grab_p)
- {
-#ifndef USE_MOTIF
- XGrabPointer (dpyinfo->display,
- FRAME_X_WINDOW (f),
- False, (PointerMotionMask
- | PointerMotionHintMask
- | ButtonReleaseMask
- | ButtonPressMask),
- GrabModeSync, GrabModeAsync,
- None, None, CurrentTime);
-#endif
- }
-
#ifdef USE_MOTIF
if (dpyinfo->supports_xi2)
{
@@ -1781,6 +1842,9 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
#endif
#endif
+#ifdef HAVE_XINPUT2
+ prepare_for_entry_into_toolkit_menu (f);
+#endif
/* Display the menu. */
lw_popup_menu (menu, &dummy);
@@ -1791,17 +1855,15 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
popup_activated_flag = 1;
-#if defined HAVE_XINPUT2 && !defined USE_MOTIF
- if (any_xi_grab_p)
- XAllowEvents (dpyinfo->display, AsyncPointer, CurrentTime);
-#endif
-
x_activate_timeout_atimer ();
{
specpdl_ref specpdl_count = SPECPDL_INDEX ();
record_unwind_protect_int (pop_down_menu, (int) menu_id);
+#ifdef HAVE_XINPUT2
+ record_unwind_protect_ptr (leave_toolkit_menu, f);
+#endif
/* Process events that apply to the menu. */
popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, true);