]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve treatment of toolkit scroll bars with the input extension
authorPo Lu <luangruo@yahoo.com>
Mon, 28 Feb 2022 06:04:23 +0000 (14:04 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 28 Feb 2022 06:06:12 +0000 (14:06 +0800)
* src/xterm.c (x_create_horizontal_toolkit_scroll_bar)
(x_create_toolkit_scroll_bar): Set XI2 event mask appropriately.
(handle_one_xevent): Make sure coordinates are correct for the
frame's window when handling wheel events.

src/xterm.c

index 520de5fcf0f353e17333e9d79f5e22d0f067c4c2..be499f3e26554f0c9ef84abbc24b14875ad6d247 100644 (file)
@@ -7666,6 +7666,30 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
   XDefineCursor (XtDisplay (widget), XtWindow (widget),
                  f->output_data.x->nontext_cursor);
 
+#ifdef HAVE_XINPUT2
+  /* Ask for input extension button and motion events.  This lets us
+     send the proper `wheel-up' or `wheel-down' events to Emacs.  */
+  if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+    {
+      XIEventMask mask;
+      ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+      unsigned char *m;
+
+      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);
+
+      XISelectEvents (XtDisplay (widget), XtWindow (widget),
+                     &mask, 1);
+    }
+#endif
 #else /* !USE_MOTIF i.e. use Xaw */
 
   /* Set resources.  Create the widget.  The background of the
@@ -7867,6 +7891,30 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
   XDefineCursor (XtDisplay (widget), XtWindow (widget),
                  f->output_data.x->nontext_cursor);
 
+#ifdef HAVE_XINPUT2
+  /* Ask for input extension button and motion events.  This lets us
+     send the proper `wheel-up' or `wheel-down' events to Emacs.  */
+  if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+    {
+      XIEventMask mask;
+      ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+      unsigned char *m;
+
+      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);
+
+      XISelectEvents (XtDisplay (widget), XtWindow (widget),
+                     &mask, 1);
+    }
+#endif
 #else /* !USE_MOTIF i.e. use Xaw */
 
   /* Set resources.  Create the widget.  The background of the
@@ -11465,6 +11513,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              double total_x = 0.0;
              double total_y = 0.0;
 
+             int real_x, real_y;
+             Window dummy;
+
              for (int i = 0; i < states->mask_len * 8; i++)
                {
                  if (XIMaskIsSet (states->mask, i))
@@ -11489,7 +11540,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                              f = x_any_window_to_frame (dpyinfo, xev->event);
 
                              if (!f)
-                               goto XI_OTHER;
+                               {
+#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
+                                 struct scroll_bar *bar
+                                   = x_window_to_scroll_bar (xi_event->display,
+                                                             xev->event, 2);
+
+                                 if (bar)
+                                   f = WINDOW_XFRAME (XWINDOW (bar->window));
+
+                                 if (!f)
+#endif
+                                   goto XI_OTHER;
+                               }
+                           }
+
+                         if (FRAME_X_WINDOW (f) != xev->event)
+                           XTranslateCoordinates (dpyinfo->display,
+                                                  xev->event, FRAME_X_WINDOW (f),
+                                                  lrint (xev->event_x),
+                                                  lrint (xev->event_y),
+                                                  &real_x, &real_y, &dummy);
+                         else
+                           {
+                             real_x = lrint (xev->event_x);
+                             real_y = lrint (xev->event_y);
                            }
 
 #ifdef HAVE_XWIDGETS
@@ -11518,8 +11593,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                              && (fabs (delta) > 0))
                            continue;
 
-                         window = window_from_coordinates (f, xev->event_x,
-                                                           xev->event_y, NULL,
+                         window = window_from_coordinates (f, real_x, real_y, NULL,
                                                            false, false);
 
                          if (WINDOWP (window))
@@ -11587,8 +11661,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                          ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
                          inev.ie.timestamp = xev->time;
 
-                         XSETINT (inev.ie.x, lrint (xev->event_x));
-                         XSETINT (inev.ie.y, lrint (xev->event_y));
+                         XSETINT (inev.ie.x, lrint (real_x));
+                         XSETINT (inev.ie.y, lrint (real_y));
                          XSETFRAME (inev.ie.frame_or_window, f);
 
                          inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
@@ -11611,8 +11685,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                          inev.ie.kind = TOUCH_END_EVENT;
                          inev.ie.timestamp = xev->time;
 
-                         XSETINT (inev.ie.x, lrint (xev->event_x));
-                         XSETINT (inev.ie.y, lrint (xev->event_y));
+                         XSETINT (inev.ie.x, lrint (real_x));
+                         XSETINT (inev.ie.y, lrint (real_y));
                          XSETFRAME (inev.ie.frame_or_window, f);
                        }
 
@@ -11644,6 +11718,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              copy.xmotion.x_root = lrint (xev->root_x);
              copy.xmotion.y_root = lrint (xev->root_y);
              copy.xmotion.state = 0;
+
+             if (xev->buttons.mask_len)
+               {
+                 if (XIMaskIsSet (xev->buttons.mask, 1))
+                   copy.xmotion.state |= Button1Mask;
+                 if (XIMaskIsSet (xev->buttons.mask, 2))
+                   copy.xmotion.state |= Button2Mask;
+                 if (XIMaskIsSet (xev->buttons.mask, 3))
+                   copy.xmotion.state |= Button3Mask;
+               }
+
              copy.xmotion.is_hint = False;
              copy.xmotion.same_screen = True;
 #endif
@@ -11743,6 +11828,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              struct xwidget_view *xvw;
 #endif
 
+#ifdef HAVE_XINPUT2_1
+             /* Ignore emulated scroll events when XI2 native
+                scroll events are present.  */
+             if (xev->flags & XIPointerEmulated)
+               {
+                 *finish = X_EVENT_DROP;
+                 goto XI_OTHER;
+               }
+#endif
+
 #ifdef USE_MOTIF
              use_copy = true;
              copy.xbutton.type = (xev->evtype == XI_ButtonPress
@@ -11773,16 +11868,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                }
 #endif
 
-#ifdef HAVE_XINPUT2_1
-             /* Ignore emulated scroll events when XI2 native
-                scroll events are present.  */
-             if (xev->flags & XIPointerEmulated)
-               {
-                 *finish = X_EVENT_DROP;
-                 goto XI_OTHER;
-               }
-#endif
-
              if (xev->evtype == XI_ButtonPress)
                x_display_set_last_user_time (dpyinfo, xev->time);