diff options
author | Po Lu <luangruo@yahoo.com> | 2022-05-06 11:01:39 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-05-06 11:01:39 +0800 |
commit | e379d2e8c18e8d9a0f859a8d90621fc898a9caf7 (patch) | |
tree | 8901ea609d461446ad0735d3a25686913fd935cf | |
parent | e2fcbd8dbd091bb72915297c92a801cbe66f13c9 (diff) | |
download | emacs-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.c | 106 |
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); |