]> git.eshelyaron.com Git - emacs.git/commitdiff
On X, avoid reporting unrepresentable touch IDs to Lisp
authorPo Lu <luangruo@yahoo.com>
Sat, 1 Jun 2024 05:53:37 +0000 (13:53 +0800)
committerEshel Yaron <me@eshelyaron.com>
Sat, 1 Jun 2024 17:04:59 +0000 (19:04 +0200)
* src/xterm.c (xi_link_touch_point): Assign a Lisp-representable
identifier to the new touch point and return the same.
(xi_unlink_touch_point): New arg LOCAL_DETAIL.  Return such an
identifier if there is a matching touch point record.
(handle_one_xevent): Adjust as is proper.

* src/xterm.h (struct xi_touch_point_t) <local_detail>:
New field.  Reorder fields for alignment.

(cherry picked from commit b1692e23edc32ce8938d3af200c0c42c8aa6b313)

src/xterm.c
src/xterm.h

index 11ef9a4bd940b1a168652f626ba163642cd827f3..2f5e54f63d523ac5a9e7b5add2bc2023dc79c1b8 100644 (file)
@@ -5820,37 +5820,50 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
 #ifdef HAVE_XINPUT2_2
 
 /* Record a touch sequence with the identifier DETAIL from the given
-   FRAME on the specified DEVICE.  Round X and Y and record them as
-   its current position.  */
+   FRAME on the specified DEVICE.  Round X and Y and record them as its
+   current position, assign an identifier to the touch sequence suitable
+   for reporting to Lisp, and return the same.  */
 
-static void
+static EMACS_INT
 xi_link_touch_point (struct xi_device_t *device,
                     int detail, double x, double y,
                     struct frame *frame)
 {
   struct xi_touch_point_t *touchpoint;
+  static EMACS_INT local_detail;
+
+  /* Assign an identifier suitable for reporting to Lisp.  On builds
+     with 64-bit Lisp_Object, this is largely a theoretical problem, but
+     CARD32s easily overflow 32-bit systems, as they are not specific to
+     X clients (e.g. Emacs) but grow uniformly across all of them.  */
+
+  if (FIXNUM_OVERFLOW_P (local_detail))
+    local_detail = 0;
 
   touchpoint = xmalloc (sizeof *touchpoint);
   touchpoint->next = device->touchpoints;
   touchpoint->x = lrint (x);
   touchpoint->y = lrint (y);
   touchpoint->number = detail;
+  touchpoint->local_detail = local_detail++;
   touchpoint->frame = frame;
   touchpoint->ownership = TOUCH_OWNERSHIP_NONE;
-
   device->touchpoints = touchpoint;
+  return touchpoint->local_detail;
 }
 
 /* Free and remove the touch sequence with the identifier DETAIL.
    DEVICE is the device in which the touch sequence should be
-   recorded.
+   recorded.  If such a touch sequence exists, return its local
+   identifier in *LOCAL_DETAIL.
 
    Value is 0 if no touch sequence by that identifier exists inside
    DEVICE, 1 if a touch sequence has been found but is not owned by
    Emacs, and 2 otherwise.  */
 
 static int
-xi_unlink_touch_point (int detail, struct xi_device_t *device)
+xi_unlink_touch_point (int detail, struct xi_device_t *device,
+                      EMACS_INT *local_detail)
 {
   struct xi_touch_point_t *last, *tem;
   enum xi_touch_ownership ownership;
@@ -5866,6 +5879,7 @@ xi_unlink_touch_point (int detail, struct xi_device_t *device)
            last->next = tem->next;
 
          ownership = tem->ownership;
+         *local_detail = tem->local_detail;
          xfree (tem);
 
          if (ownership == TOUCH_OWNERSHIP_SELF)
@@ -24781,6 +24795,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef HAVE_GTK3
              GdkRectangle test_rect;
 #endif
+             EMACS_INT local_detail;
              device = xi_device_from_id (dpyinfo, xev->deviceid);
              source = xi_device_from_id (dpyinfo, xev->sourceid);
              x_display_set_last_user_time (dpyinfo, xev->time,
@@ -24905,16 +24920,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
                      if (!x_had_errors_p (dpyinfo->display))
                        {
-                         xi_link_touch_point (device, xev->detail,
-                                              xev->event_x,
-                                              xev->event_y, f);
+                         local_detail
+                           = xi_link_touch_point (device, xev->detail,
+                                                  xev->event_x,
+                                                  xev->event_y, f);
 
                          inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
                          inev.ie.timestamp = xev->time;
                          XSETFRAME (inev.ie.frame_or_window, f);
                          XSETINT (inev.ie.x, lrint (xev->event_x));
                          XSETINT (inev.ie.y, lrint (xev->event_y));
-                         XSETINT (inev.ie.arg, xev->detail);
+                         XSETINT (inev.ie.arg, local_detail);
 
                          if (source)
                            inev.ie.device = source->name;
@@ -25032,7 +25048,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                    {
                      if (touchpoint->frame == f)
                        arg = Fcons (list3i (touchpoint->x, touchpoint->y,
-                                            lrint (touchpoint->number)),
+                                            touchpoint->local_detail),
                                     arg);
                    }
 
@@ -25049,6 +25065,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            {
              struct xi_device_t *device, *source;
              int state;
+             EMACS_INT local_detail;
 
              device = xi_device_from_id (dpyinfo, xev->deviceid);
              source = xi_device_from_id (dpyinfo, xev->sourceid);
@@ -25064,7 +25081,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              if (!device || device->use == XIMasterPointer)
                goto XI_OTHER;
 
-             state = xi_unlink_touch_point (xev->detail, device);
+             state = xi_unlink_touch_point (xev->detail, device,
+                                            &local_detail);
 
              if (state)
                {
@@ -25079,7 +25097,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                      XSETFRAME (inev.ie.frame_or_window, f);
                      XSETINT (inev.ie.x, lrint (xev->event_x));
                      XSETINT (inev.ie.y, lrint (xev->event_y));
-                     XSETINT (inev.ie.arg, xev->detail);
+                     XSETINT (inev.ie.arg, local_detail);
 
                      if (source)
                        inev.ie.device = source->name;
index bf402de326bdfaa33a0726907a03138bf17cadca..8d5c9917749325b200aefd4b8fe725c070c9f106 100644 (file)
@@ -305,6 +305,15 @@ enum xi_touch_ownership
 
 struct xi_touch_point_t
 {
+  /* The detail code reported to Lisp.  */
+  EMACS_INT local_detail;
+
+  /* The frame associated with this touch point.  */
+  struct frame *frame;
+
+  /* The next touch point in this list.  */
+  struct xi_touch_point_t *next;
+
   /* The touchpoint detail.  */
   int number;
 
@@ -314,12 +323,6 @@ struct xi_touch_point_t
 
   /* The last known rounded X and Y positions of the touchpoint.  */
   int x, y;
-
-  /* The frame associated with this touch point.  */
-  struct frame *frame;
-
-  /* The next touch point in this list.  */
-  struct xi_touch_point_t *next;
 };
 
 #endif