]> git.eshelyaron.com Git - emacs.git/commitdiff
Make XInput 2 features work on GTK 2 builds
authorPo Lu <luangruo@yahoo.com>
Wed, 9 Mar 2022 13:29:17 +0000 (21:29 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 9 Mar 2022 13:29:17 +0000 (21:29 +0800)
* src/xfns.c (setup_xi_event_mask): On GTK 2, select for
button, motion, entry/exit and key events.
* src/xmenu.c (create_and_show_popup_menu): Clear XI grab if
appropriate.
* src/xterm.c (handle_one_xevent): Pass some kinds of input
extension events to GTK manually on versions of GTK+ that don't
understand them.

src/xfns.c
src/xmenu.c
src/xterm.c

index cf5823c645b38786775765bee88c230b6ad7ab6e..a3236efbcc60f1efc9610e39503f6049487130b1 100644 (file)
@@ -3579,7 +3579,7 @@ setup_xi_event_mask (struct frame *f)
   mask.mask_len = l;
 
   block_input ();
-#ifndef USE_GTK
+#ifndef HAVE_GTK3
   mask.deviceid = XIAllMasterDevices;
 
   XISetMask (m, XI_ButtonPress);
@@ -3587,8 +3587,10 @@ setup_xi_event_mask (struct frame *f)
   XISetMask (m, XI_Motion);
   XISetMask (m, XI_Enter);
   XISetMask (m, XI_Leave);
+#ifndef USE_GTK
   XISetMask (m, XI_FocusIn);
   XISetMask (m, XI_FocusOut);
+#endif
   XISetMask (m, XI_KeyPress);
   XISetMask (m, XI_KeyRelease);
   XISelectEvents (FRAME_X_DISPLAY (f),
@@ -3596,7 +3598,7 @@ setup_xi_event_mask (struct frame *f)
                  &mask, 1);
 
   memset (m, 0, l);
-#endif /* !USE_GTK */
+#endif /* !HAVE_GTK3 */
 
 #ifdef USE_X_TOOLKIT
   XISetMask (m, XI_KeyPress);
index 4d0e5bd81c2d1ad30afe73eed386a0e287e920aa..d19fe13c29540a789d638c20f8ffe66cb0041402 100644 (file)
@@ -1527,6 +1527,23 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
       if (i == 5) i = 0;
     }
 
+#if !defined HAVE_GTK3 && defined HAVE_XINPUT2
+  if (FRAME_DISPLAY_INFO (f)->num_devices)
+    {
+      for (int i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
+       {
+         if (FRAME_DISPLAY_INFO (f)->devices[i].grab)
+           {
+             FRAME_DISPLAY_INFO (f)->devices[i].grab = 0;
+
+             XIUngrabDevice (FRAME_X_DISPLAY (f),
+                             FRAME_DISPLAY_INFO (f)->devices[i].device_id,
+                             CurrentTime);
+           }
+       }
+    }
+#endif
+
   /* Display the menu.  */
   gtk_widget_show_all (menu);
 
index 772a9238a7e2edaba9a4fa5d495dfa3f5797fee9..68f7588af4a8b62cc3944e00d429c3de78bb040e 100644 (file)
@@ -10021,6 +10021,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
      being passed to XtDispatchEvent.  */
   bool use_copy = false;
   XEvent copy;
+#elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
+  GdkEvent *copy = NULL;
+  GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
 #endif
 
   *finish = X_EVENT_NORMAL;
@@ -12186,6 +12189,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                    {
                      x_display_set_last_user_time (dpyinfo, xev->time);
 
+#if defined USE_GTK && !defined HAVE_GTK3
+                     /* Unlike on Motif, we can't select for XI
+                        events on the scroll bar window under GTK+ 2.
+                        So instead of that, just ignore XI wheel
+                        events which land on a scroll bar.
+
+                       Here we assume anything which isn't the edit
+                       widget window is a scroll bar.  */
+
+                     if (xev->child != None
+                         && xev->child != FRAME_X_WINDOW (f))
+                       goto OTHER;
+#endif
+
                      if (fabs (total_x) > 0 || fabs (total_y) > 0)
                        {
                          inev.ie.kind = (fabs (total_y) >= fabs (total_x)
@@ -12390,6 +12407,37 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                  if (XIMaskIsSet (xev->buttons.mask, 3))
                    copy.xbutton.state |= Button3Mask;
                }
+#elif defined USE_GTK && !defined HAVE_GTK3
+             copy = gdk_event_new (xev->evtype == XI_ButtonPress
+                                   ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
+
+             copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event);
+             copy->button.send_event = xev->send_event;
+             copy->button.time = xev->time;
+             copy->button.x = xev->event_x;
+             copy->button.y = xev->event_y;
+             copy->button.x_root = xev->root_x;
+             copy->button.y_root = xev->root_y;
+             copy->button.state = xev->mods.effective;
+             copy->button.button = xev->detail;
+
+             if (xev->buttons.mask_len)
+               {
+                 if (XIMaskIsSet (xev->buttons.mask, 1))
+                   copy->button.state |= GDK_BUTTON1_MASK;
+                 if (XIMaskIsSet (xev->buttons.mask, 2))
+                   copy->button.state |= GDK_BUTTON2_MASK;
+                 if (XIMaskIsSet (xev->buttons.mask, 3))
+                   copy->button.state |= GDK_BUTTON3_MASK;
+               }
+
+             if (!copy->button.window)
+               emacs_abort ();
+
+             g_object_ref (copy->button.window);
+
+             gtk_main_do_event (copy);
+             gdk_event_free (copy);
 #endif
 
 #ifdef HAVE_XINPUT2_1