From 64256d29234b0fc3012d07cb189ebeccc2dfc187 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jul 2023 17:29:58 +0800 Subject: [PATCH] Update Android port * doc/lispref/commands.texi (Touchscreen Events): Improve documentation. * lisp/tab-bar.el (tab-bar-map): Bind `[tab-bar touchscreen-hold]'. * lisp/touch-screen.el (touch-screen-hold, touch-screen-drag): New functions. (touch-screen-handle-timeout): Generate a `touchscreen-hold' event instead. (touch-screen-handle-point-update): Generate a `touchscreen-drag' event upon dragging. (touch-screen-translate-touch): Cancel touch screen timer upon exit. * src/keyboard.c (access_keymap_keyremap): Take unsigned int start and end instead. --- doc/lispref/commands.texi | 43 +++++++---- lisp/tab-bar.el | 4 +- lisp/touch-screen.el | 159 ++++++++++++++++++++------------------ src/keyboard.c | 2 +- 4 files changed, 117 insertions(+), 91 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 725ca900165..025ac197feb 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2080,25 +2080,42 @@ selected, as a compromise for packages which assume @code{mouse-drag-region} has already set point to the location of any mouse click and selected the window where it took place. +If touch gestures are detected during translation, one of the +following input events may be generated: + +@table @code @cindex @code{touchscreen-scroll} event +@item (touchscreen-scroll @var{window} @var{dx} @var{dy}) If a ``scrolling'' gesture is detected during the translation process, each subsequent @code{touchscreen-update} event is translated to a -@code{touchscreen-scroll} event of the form: - -@example -@w{@code{(touchscreen-scroll @var{window} @var{dx} @var{dy})}} -@end example - -where @var{dx} and @var{dy} specify, in pixels, the relative motion of -the tool from the position of the @code{touchscreen-begin} event that -started the sequence or the last @code{touchscreen-scroll} event, -whichever came later. +@code{touchscreen-scroll} event, where @var{dx} and @var{dy} specify, +in pixels, the relative motion of the touchpoint from the position of +the @code{touchscreen-begin} event that started the sequence or the +last @code{touchscreen-scroll} event, whichever came later. + +@cindex @code{touchscreen-hold} event +@item (touchscreen-hold @var{posn}) +If the single active touchpoint remains stationary for more than +@code{touch-screen-delay} seconds after a @code{touchscreen-begin} is +generated, a ``long-press'' gesture is detected during the translation +process, and a @code{touchscreen-hold} event is sent, with @var{posn} +set to a mouse position list containing the position of the +@code{touchscreen-begin} event. + +@cindex @code{touchscreen-drag} event +@item (touchscreen-drag @var{posn}) +If a ``long-press'' gesture is detected while translating the current +touch sequence, a @code{touchscreen-drag} event is sent upon each +subsequent @code{touchscreen-update} event, with @var{posn} set to the +new position of the touchpoint. +@end table @cindex handling touch screen events @cindex tap and drag, touch screen gestures -Emacs provides two functions to handle touch screen events. They are -intended to be used by a command bound to @code{touchscreen-begin} to -handle common gestures. +Emacs provides two functions to handle touch screen events independent +of gesture recognition or mouse event translation. They are intended +to be used by commands bound to @code{touchscreen-begin}, to recognize +and handle common gestures. @defun touch-screen-track-tap event &optional update data This function is used to track a single ``tap'' gesture originating diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 044337260ce..a81f42fc751 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -493,7 +493,9 @@ appropriate." "S-" #'tab-bar-move-tab "S-" #'tab-bar-move-tab-backward "S-" #'tab-bar-move-tab - "" #'tab-bar-touchscreen-begin) + "" #'tab-bar-touchscreen-begin + ;; Trying to set this in `touch-screen.el' runs afoul of the filter. + "" 'touchscreen-drag) (global-set-key [tab-bar] `(menu-item ,(purecopy "tab bar") ,(make-sparse-keymap) diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index 0f584269931..ef9b14f27ce 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -234,15 +234,69 @@ the event." (global-set-key [touchscreen-scroll] #'touch-screen-scroll) +(defun touch-screen-hold (event) + "Handle a long press EVENT. +Beep, select the window at EVENT, set point there, and activate +the mark." + (interactive "e") + (let* ((posn (cadr event)) + (point (posn-point posn))) + (when point + (beep) + (select-window (posn-window posn)) + (set-mark point) + (goto-char point) + (activate-mark)))) + +(defun touch-screen-drag (event) + "Handle a drag EVENT by setting the region to its new point. +Scroll the window if necessary." + (interactive "e") + (let* ((posn (cadr event)) ; Position of the tool. + ; Window where the tap originated. + (window (nth 1 touch-screen-current-tool))) + ;; Keep dragging. + (with-selected-window window + ;; Figure out what character to go to. If this posn is + ;; in the window, go to (posn-point posn). If not, + ;; then go to the line before either window start or + ;; window end. + (if (and (eq (posn-window posn) window) + (posn-point posn)) + (goto-char (posn-point posn)) + (let ((relative-xy + (touch-screen-relative-xy posn window))) + (let ((scroll-conservatively 101)) + (cond + ((< (cdr relative-xy) 0) + (ignore-errors + (goto-char (1- (window-start)))) + (redisplay)) + ((> (cdr relative-xy) + (let ((edges (window-inside-pixel-edges))) + (- (nth 3 edges) (cadr edges)))) + (ignore-errors + (goto-char (1+ (window-end nil t)))) + (redisplay))))))))) + +(global-set-key [touchscreen-hold] #'touch-screen-hold) +(global-set-key [touchscreen-drag] #'touch-screen-drag) + +;; Bind this to most of the virtual prefix keys as well. +(global-set-key [tool-bar touchscreen-drag] #'touch-screen-drag) +(global-set-key [header-line touchscreen-drag] #'touch-screen-drag) +(global-set-key [mode-line touchscreen-drag] #'touch-screen-drag) +(global-set-key [tab-line touchscreen-drag] #'touch-screen-drag) + (defun touch-screen-handle-timeout (arg) "Start the touch screen timeout or handle it depending on ARG. When ARG is nil, start the `touch-screen-current-timer' to go off in `touch-screen-delay' seconds, and call this function with ARG t. -When ARG is t, beep. Then, set the fourth element of -touch-screen-current-tool to `held', and the mark to the last -known position of the tool." +When ARG is t, set the fourth element of +`touch-screen-current-tool' to `held', and generate a +`touchscreen-hold' event at the original position of that tool." (if (not arg) ;; Cancel the touch screen long-press timer, if it is still ;; there by any chance. @@ -253,19 +307,16 @@ known position of the tool." (run-at-time touch-screen-delay nil #'touch-screen-handle-timeout t))) - ;; Beep. - (beep) ;; Set touch-screen-current-timer to nil. (setq touch-screen-current-timer nil) (when touch-screen-current-tool ;; Set the state to `held'. (setcar (nthcdr 3 touch-screen-current-tool) 'held) - ;; Go to the initial position of the touchpoint and activate the - ;; mark. - (select-window (cadr touch-screen-current-tool)) - (set-mark (posn-point (nth 4 touch-screen-current-tool))) - (goto-char (mark)) - (activate-mark)))) + ;; Generate an input event at the original position of the mark. + ;; This assumes that the timer is running within + ;; `touch-screen-translate-touch'. + (let ((posn (nth 4 touch-screen-current-tool))) + (throw 'input-event (list 'touchscreen-hold posn)))))) (defun touch-screen-handle-point-update (point) "Notice that the touch point POINT has changed position. @@ -297,7 +348,7 @@ If the fourth element of `touch-screen-current-tool' is If the fourth element of `touch-screen-current-tool' is `held', then the touch has been held down for some time. If motion happens, cancel `touch-screen-current-timer', and set the field -to `drag'. Then, activate the mark and start dragging. +to `drag'. Then, generate a `touchscreen-drag' event. If the fourth element of `touch-screen-current-tool' is `drag', then move point to the position of POINT." @@ -319,16 +370,16 @@ then move point to the position of POINT." 'scroll) (setcar (nthcdr 2 touch-screen-current-tool) relative-xy) - ;; Generate a `touchscreen-scroll' event with `diff-x' - ;; and `diff-y'. - (throw 'input-event - (list 'touchscreen-scroll - window diff-x diff-y)) ;; Cancel the touch screen long-press timer, if it is ;; still there by any chance. (when touch-screen-current-timer (cancel-timer touch-screen-current-timer) - (setq touch-screen-current-timer nil))))) + (setq touch-screen-current-timer nil)) + ;; Generate a `touchscreen-scroll' event with `diff-x' + ;; and `diff-y'. + (throw 'input-event + (list 'touchscreen-scroll + window diff-x diff-y))))) ((eq what 'scroll) ;; Cancel the touch screen long-press timer, if it is still ;; there by any chance. @@ -361,67 +412,17 @@ then move point to the position of POINT." (throw 'input-event (list 'mouse-movement (cdr point))))) ((eq what 'held) - (let* ((posn (cdr point)) - (relative-xy - (touch-screen-relative-xy posn window))) - (when touch-screen-current-timer - (cancel-timer touch-screen-current-timer) - (setq touch-screen-current-timer nil)) + (let* ((posn (cdr point))) ;; Now start dragging. (setcar (nthcdr 3 touch-screen-current-tool) 'drag) - (setcar (nthcdr 2 touch-screen-current-tool) - relative-xy) - (with-selected-window window - ;; Activate the mark. It should have been set by the - ;; time `touch-screen-timeout' was called. - (activate-mark) - ;; Figure out what character to go to. If this posn is - ;; in the window, go to (posn-point posn). If not, - ;; then go to the line before either window start or - ;; window end. - (if (and (eq (posn-window posn) window) - (posn-point posn)) - (goto-char (posn-point posn)) - (let ((relative-xy - (touch-screen-relative-xy posn window))) - (let ((scroll-conservatively 101)) - (cond - ((< (cdr relative-xy) 0) - (ignore-errors - (goto-char (1- (window-start)))) - (redisplay)) - ((> (cdr relative-xy) - (let ((edges (window-inside-pixel-edges))) - (- (nth 3 edges) (cadr edges)))) - (ignore-errors - (goto-char (1+ (window-end nil t)))) - (redisplay))))))))) + ;; Generate a (touchscreen-drag POSN) event. `touchscreen-hold' + ;; was generated when the timeout fired. + (throw 'input-event (list 'touchscreen-drag posn)))) ((eq what 'drag) (let* ((posn (cdr point))) - ;; Keep dragging. - (with-selected-window window - ;; Figure out what character to go to. If this posn is - ;; in the window, go to (posn-point posn). If not, - ;; then go to the line before either window start or - ;; window end. - (if (and (eq (posn-window posn) window) - (posn-point posn)) - (goto-char (posn-point posn)) - (let ((relative-xy - (touch-screen-relative-xy posn window))) - (let ((scroll-conservatively 101)) - (cond - ((< (cdr relative-xy) 0) - (ignore-errors - (goto-char (1- (window-start)))) - (redisplay)) - ((> (cdr relative-xy) - (let ((edges (window-inside-pixel-edges))) - (- (nth 3 edges) (cadr edges)))) - (ignore-errors - (goto-char (1+ (window-end nil t)))) - (redisplay)))))))))))) + ;; Generate a (touchscreen-drag POSN) event. + (throw 'input-event (list 'touchscreen-drag posn))))))) (defun touch-screen-window-selection-changed (frame) "Notice that FRAME's selected window has changed. @@ -681,7 +682,7 @@ where POSN is the position of the mouse button press or click. where POSN is the position of the mouse click, either `mouse-2' if POSN is on a link or a button, or `mouse-1' otherwise." - (if (> (length current-key-remap-sequence) 0) + (unwind-protect ;; Save the virtual function key if this is a mode line event. (let* ((prefix (and (> (length current-key-remap-sequence) 1) (aref current-key-remap-sequence 0))) @@ -721,7 +722,13 @@ if POSN is on a link or a button, or `mouse-1' otherwise." ;; the appropriate function key. (vector prefix event)) (vector event)) - "")))) + "")) + ;; Cancel the touch screen long-press timer, if it is still there + ;; by any chance. If the timer is to operate correctly, it must + ;; fire within the catch block above. + (when touch-screen-current-timer + (cancel-timer touch-screen-current-timer) + (setq touch-screen-current-timer nil)))) (define-key function-key-map [touchscreen-begin] #'touch-screen-translate-touch) diff --git a/src/keyboard.c b/src/keyboard.c index e10128def13..fa5eea31c3b 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -10001,7 +10001,7 @@ typedef struct keyremap static Lisp_Object access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt, - bool do_funcall, ptrdiff_t start, ptrdiff_t end, + bool do_funcall, unsigned int start, unsigned int end, Lisp_Object *keybuf) { Lisp_Object next; -- 2.39.2