From 68b8df57c720bb1a9fdde2c31afac9602e7491ed Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 11 Nov 2023 18:03:33 +0800 Subject: [PATCH] Enable canceling tap gestures * doc/lispref/commands.texi (Touchscreen Events): Relate new THRESHOLD argument to touch-screen-track-tap. * lisp/button.el (push-button): * lisp/wid-edit.el (widget-button--check-and-call-button): Provide a threshold to enable canceling button presses. * lisp/touch-screen.el (touch-screen-track-tap): Enable canceling tap gestures and resuming touch sequence translation if the touch point exceeds a set threshold. --- doc/lispref/commands.texi | 10 +++++++++- lisp/button.el | 2 +- lisp/touch-screen.el | 39 ++++++++++++++++++++++++++++++++++----- lisp/wid-edit.el | 2 +- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 41c30437dce..2518740ad3b 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2207,7 +2207,7 @@ below is from commands bound directly to @code{touchscreen-begin} events; they allow responding to commonly used touch screen gestures separately from mouse event translation. -@defun touch-screen-track-tap event &optional update data +@defun touch-screen-track-tap event &optional update data threshold This function is used to track a single ``tap'' gesture originating from the @code{touchscreen-begin} event @var{event}, often used to set the point or to activate a button. It waits for a @@ -2220,6 +2220,14 @@ contains at least one touchpoint with the same identifier as in the list of touchpoints in that @code{touchscreen-update} event, and @var{data}. +If @var{threshold} is non-@code{nil} and such an event indicates that +the touchpoint represented by @var{event} has moved beyond a threshold +of either @var{threshold} or 10 pixels if it is not a number from the +position of @var{event}, @code{nil} is returned and mouse event +translation is resumed for that touchpoint, so as not to impede the +recognition of any subsequent touchscreen gesture arising from its +sequence. + If any other event arrives in the mean time, @code{nil} is returned. The caller should not perform any action in that case. @end defun diff --git a/lisp/button.el b/lisp/button.el index bfe6ccc8d1f..ed11c9583d8 100644 --- a/lisp/button.el +++ b/lisp/button.el @@ -495,7 +495,7 @@ pushing a button, use the `button-describe' command." (if (eq (car-safe pos) 'touchscreen-down) ;; If touch-screen-track tap returns nil, then the ;; tap was cancelled. - (when (touch-screen-track-tap pos) + (when (touch-screen-track-tap pos nil nil t) (push-button (posn-point posn) t)) (push-button (posn-point posn) t)))))) ;; POS is just normal position diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index ea1e27a263b..f838e3bff3d 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -1539,7 +1539,7 @@ if POSN is on a link or a button, or `mouse-1' otherwise." ;; Exports. These functions are intended for use externally. -(defun touch-screen-track-tap (event &optional update data) +(defun touch-screen-track-tap (event &optional update data threshold) "Track a single tap starting from EVENT. EVENT should be a `touchscreen-begin' event. @@ -1549,16 +1549,45 @@ a `touchscreen-update' event is received in the mean time and contains a touch point with the same ID as in EVENT, call UPDATE with that event and DATA. +If THRESHOLD is non-nil, enforce a threshold of movement that is +either itself or 10 pixels when it is not a number. If the touch +point moves beyond that threshold EVENT on any axis, return nil +immediately, and further resume mouse event translation for the +touch point at hand. + Return nil immediately if any other kind of event is received; otherwise, return t once the `touchscreen-end' event arrives." - (let ((disable-inhibit-text-conversion t)) + (let ((disable-inhibit-text-conversion t) + (threshold (and threshold (or (and (numberp threshold) + threshold) + 10))) + (original-x-y (posn-x-y (cdadr event))) + (original-window (posn-window (cdadr event)))) (catch 'finish (while t - (let ((new-event (read-event nil))) + (let ((new-event (read-event nil)) + touch-point) (cond ((eq (car-safe new-event) 'touchscreen-update) - (when (and update (assq (caadr event) (cadr new-event))) - (funcall update new-event data))) + (when (setq touch-point (assq (caadr event) (cadr new-event))) + (when update + (funcall update new-event data)) + (when threshold + (setq touch-point (cdr touch-point)) + ;; Detect the touch point moving past the threshold. + (let* ((x-y (touch-screen-relative-xy touch-point + original-window)) + (x (car x-y)) (y (cdr x-y))) + (when (or (> (abs (- x (car original-x-y))) threshold) + (> (abs (- y (cdr original-x-y))) threshold)) + ;; Resume normal touch-screen to mouse event + ;; translation for this touch sequence by + ;; supplying both the event starting it and the + ;; motion event that overstepped the threshold to + ;; touch-screen-handle-touch. + (touch-screen-handle-touch event nil t) + (touch-screen-handle-touch new-event nil t) + (throw 'finish nil)))))) ((eq (car-safe new-event) 'touchscreen-end) (throw 'finish ;; Now determine whether or not the `touchscreen-end' diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 74412414113..6ae00171d84 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -1127,7 +1127,7 @@ If nothing was called, return non-nil." ;; This a touchscreen event and must be handled ;; specially through `touch-screen-track-tap'. (progn - (unless (touch-screen-track-tap event) + (unless (touch-screen-track-tap event nil nil t) (throw 'button-press-cancelled t))) (unless (widget-apply button :mouse-down-action event) (let ((track-mouse t)) -- 2.39.2