From f07f6e80d5c490616d0b8e099d2018614e7f6536 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 1 Jun 2024 13:53:37 +0800 Subject: [PATCH] On X, avoid reporting unrepresentable touch IDs to Lisp * 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) : New field. Reorder fields for alignment. (cherry picked from commit b1692e23edc32ce8938d3af200c0c42c8aa6b313) --- src/xterm.c | 44 +++++++++++++++++++++++++++++++------------- src/xterm.h | 15 +++++++++------ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 11ef9a4bd94..2f5e54f63d5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -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; diff --git a/src/xterm.h b/src/xterm.h index bf402de326b..8d5c9917749 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -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 -- 2.39.2