emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master be06b40ebd: Fix entry and exit events with XI2 grabs on X toolkit


From: Po Lu
Subject: master be06b40ebd: Fix entry and exit events with XI2 grabs on X toolkit menus
Date: Sat, 12 Feb 2022 07:28:31 -0500 (EST)

branch: master
commit be06b40ebdd6cfbd23558ce210a8a7ad2b4c7a40
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 src/xmenu.c | 53 +++++++++++++++++++++++++++++++++++++++++++----------
 src/xterm.c | 11 +++++++++++
 2 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/src/xmenu.c b/src/xmenu.c
index eaec6efc26..28fafa108d 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 22c1438076..20ea746820 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]