diff options
| author | Po Lu | 2023-11-15 20:58:46 +0800 |
|---|---|---|
| committer | Po Lu | 2023-11-15 21:07:14 +0800 |
| commit | a9a8d5e95992ab63a63305e2a0b2d2b36bb2c698 (patch) | |
| tree | 3c8317f4e782afd2b988141231f199ac0eaf2c53 | |
| parent | 03d2e26108b21b4a9c86a30e5552f9535f4245ac (diff) | |
| download | emacs-a9a8d5e95992ab63a63305e2a0b2d2b36bb2c698.tar.gz emacs-a9a8d5e95992ab63a63305e2a0b2d2b36bb2c698.zip | |
Register ``pinch to zoom'' touch screen gestures
* doc/emacs/input.texi (Touchscreens): Address pinch gestures.
* doc/lispref/commands.texi (Touchscreen Events): Address touch
screen pinch events and the process by which they are produced.
* java/org/gnu/emacs/EmacsWindow.java (figureChange)
<ACTION_POINTER_DOWN>: Supply pointer index to getX and getY,
correcting a mistake where the first touch point's coordinate
was saved here in lieu of the pointer that was pressed's.
* lisp/touch-screen.el (touch-screen-current-tool): Revise doc
string.
(touch-screen-aux-tool): New variable.
(touch-screen-scroll-point-to-y, touch-screen-pinch): New
functions.
(global-map): Bind [touchscreen-pinch] to touch-screen-pinch.
(touch-screen-handle-point-update): Revise doc string; set new
tenth field of t-s-c-t to POINT relative to its window, without
regard to whether an event has been sent.
(touch-screen-distance, touch-screen-centrum): New functions.
(touch-screen-handle-aux-point-update): New function; generate
and send touchscreen-pinch if need be.
(touch-screen-handle-point-up): If an ancillary tool exists,
transfer the information there into touch-screen-current-tool
and clear t-s-a-t.
(touch-screen-handle-touch): Call t-s-a-p-u as is proper; set
t-s-a-t if a touchscreen-down event arrives and t-s-c-t is set.
* src/androidterm.c (handle_one_android_event): Properly save
the event's X and Y when a new touch point is registered.
| -rw-r--r-- | doc/emacs/input.texi | 7 | ||||
| -rw-r--r-- | doc/lispref/commands.texi | 38 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 4 | ||||
| -rw-r--r-- | lisp/touch-screen.el | 739 | ||||
| -rw-r--r-- | src/androidterm.c | 4 |
5 files changed, 557 insertions, 235 deletions
diff --git a/doc/emacs/input.texi b/doc/emacs/input.texi index 0dd7fca41cc..e4d595caf84 100644 --- a/doc/emacs/input.texi +++ b/doc/emacs/input.texi | |||
| @@ -62,6 +62,13 @@ commence selecting text under the tool as it continues its motion, as | |||
| 62 | if @code{mouse-1} were to be held down and a mouse moved analogously. | 62 | if @code{mouse-1} were to be held down and a mouse moved analogously. |
| 63 | @xref{Mouse Commands}. | 63 | @xref{Mouse Commands}. |
| 64 | 64 | ||
| 65 | @item | ||
| 66 | @cindex pinching, touchscreens | ||
| 67 | @dfn{Pinching}, which is placing two tools apart on the screen and | ||
| 68 | adjusting their position such as to increase or decrease the distance | ||
| 69 | between them will modify the text scale (@xref{Text Scale}) in | ||
| 70 | proportion to the change in that distance. | ||
| 71 | |||
| 65 | @vindex touch-screen-word-select | 72 | @vindex touch-screen-word-select |
| 66 | @cindex word selection mode, touchscreens | 73 | @cindex word selection mode, touchscreens |
| 67 | To the detriment of text selection, it can prove challenging to | 74 | To the detriment of text selection, it can prove challenging to |
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 2518740ad3b..75685ffe5dc 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi | |||
| @@ -2106,8 +2106,9 @@ When no command is bound to @code{touchscreen-begin}, | |||
| 2106 | translate key sequences containing touch screen events into ordinary | 2106 | translate key sequences containing touch screen events into ordinary |
| 2107 | mouse events (@pxref{Mouse Events}.) Since Emacs doesn't support | 2107 | mouse events (@pxref{Mouse Events}.) Since Emacs doesn't support |
| 2108 | distinguishing events originating from separate mouse devices, it | 2108 | distinguishing events originating from separate mouse devices, it |
| 2109 | assumes that only one touchpoint is active while translation takes | 2109 | assumes that a maximum of two touchpoints are active while translation |
| 2110 | place; breaking this assumption may lead to unexpected behavior. | 2110 | takes place, and does not place any guarantees on the results of event |
| 2111 | translation when that restriction is overstepped. | ||
| 2111 | 2112 | ||
| 2112 | Emacs applies two different strategies for translating touch events | 2113 | Emacs applies two different strategies for translating touch events |
| 2113 | into mouse events, contingent on factors such as the commands bound to | 2114 | into mouse events, contingent on factors such as the commands bound to |
| @@ -2159,6 +2160,15 @@ purpose of displaying pop-up menus, Emacs additionally behaves as | |||
| 2159 | illustrated in the last paragraph if @code{down-mouse-1} is bound to a | 2160 | illustrated in the last paragraph if @code{down-mouse-1} is bound to a |
| 2160 | command whose name has the property @code{mouse-1-menu-command}. | 2161 | command whose name has the property @code{mouse-1-menu-command}. |
| 2161 | 2162 | ||
| 2163 | @cindex pinch-to-zoom touchscreen gesture translation | ||
| 2164 | When a second touch point is registered as a touch point is already | ||
| 2165 | being translated, gesture translation is terminated, and the distance | ||
| 2166 | from the second touch point (the @dfn{ancillary tool}) to the first is | ||
| 2167 | measured. Subsequent motion from either of those touch points will | ||
| 2168 | yield @code{touchscreen-pinch} events incorporating the ratio formed | ||
| 2169 | by the distance between their new positions and the distance measured | ||
| 2170 | at the outset, as illustrated in the following table. | ||
| 2171 | |||
| 2162 | @cindex touchscreen gesture events | 2172 | @cindex touchscreen gesture events |
| 2163 | If touch gestures are detected during translation, one of the | 2173 | If touch gestures are detected during translation, one of the |
| 2164 | following input events may be generated: | 2174 | following input events may be generated: |
| @@ -2197,6 +2207,30 @@ This event is sent upon the start of a touch sequence resulting in the | |||
| 2197 | continuation of a ``drag-to-select'' gesture (subject to the | 2207 | continuation of a ``drag-to-select'' gesture (subject to the |
| 2198 | aformentioned user option) with @var{posn} set to the position list of | 2208 | aformentioned user option) with @var{posn} set to the position list of |
| 2199 | the initial @code{touchscreen-begin} event within that touch sequence. | 2209 | the initial @code{touchscreen-begin} event within that touch sequence. |
| 2210 | |||
| 2211 | @cindex @code{touchscreen-pinch} event | ||
| 2212 | @item (touchscreen-pinch @var{posn} @var{ratio} @var{pan-x} @var{pan-y}) | ||
| 2213 | This event is delivered upon significant changes to the positions of | ||
| 2214 | either active touch point when an ancillary tool is active. | ||
| 2215 | |||
| 2216 | @var{posn} is a mouse position list for the midpoint of a line drawn | ||
| 2217 | from the ancillary tool to the other touch point being observed. | ||
| 2218 | |||
| 2219 | @var{ratio} is the distance between both touch points being observed | ||
| 2220 | divided by that distance when the ancillary point was first | ||
| 2221 | registered; which is to say, the scale of the ``pinch'' gesture. | ||
| 2222 | |||
| 2223 | @var{pan-x} and @var{pan-y} are the difference between the pixel | ||
| 2224 | position of @var{posn} and this position within the last event | ||
| 2225 | delivered appertaining to this series of touch events, or in the case | ||
| 2226 | that no such event exists, the centerpoint between both touch points | ||
| 2227 | when the ancillary tool was first registered. | ||
| 2228 | |||
| 2229 | Such events are sent when the magnitude of the changes they represent | ||
| 2230 | will yield a @code{ratio} which differs by more than @code{0.2} from | ||
| 2231 | that in the previous event, or the sum of @var{pan-x} and @var{pan-y} | ||
| 2232 | will surpass half the frame's character width in pixels (@pxref{Frame | ||
| 2233 | Font}). | ||
| 2200 | @end table | 2234 | @end table |
| 2201 | 2235 | ||
| 2202 | @cindex handling touch screen events | 2236 | @cindex handling touch screen events |
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index d7a37a8d57f..013f09cb756 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java | |||
| @@ -918,8 +918,8 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 918 | it in the map. */ | 918 | it in the map. */ |
| 919 | pointerIndex = event.getActionIndex (); | 919 | pointerIndex = event.getActionIndex (); |
| 920 | pointerID = event.getPointerId (pointerIndex); | 920 | pointerID = event.getPointerId (pointerIndex); |
| 921 | coordinate = new Coordinate ((int) event.getX (0), | 921 | coordinate = new Coordinate ((int) event.getX (pointerIndex), |
| 922 | (int) event.getY (0), | 922 | (int) event.getY (pointerIndex), |
| 923 | buttonForEvent (event), | 923 | buttonForEvent (event), |
| 924 | pointerID); | 924 | pointerID); |
| 925 | pointerMap.put (pointerID, coordinate); | 925 | pointerMap.put (pointerID, coordinate); |
diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index 2e5a88da071..605ae475257 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el | |||
| @@ -33,15 +33,41 @@ | |||
| 33 | 33 | ||
| 34 | (defvar touch-screen-current-tool nil | 34 | (defvar touch-screen-current-tool nil |
| 35 | "The touch point currently being tracked, or nil. | 35 | "The touch point currently being tracked, or nil. |
| 36 | If non-nil, this is a list of nine elements: the ID of the touch | 36 | If non-nil, this is a list of ten elements: the ID of the touch |
| 37 | point being tracked, the window where the touch began, a cons | 37 | point being tracked, the window where the touch began, a cons |
| 38 | containing the last known position of the touch point, relative | 38 | holding the last registered position of the touch point, relative |
| 39 | to that window, a field used to store data while tracking the | 39 | to that window, a field used to store data while tracking the |
| 40 | touch point, the initial position of the touchpoint, and another | 40 | touch point, the initial position of the touchpoint, another four |
| 41 | four fields to used store data while tracking the touch point. | 41 | fields to used store data while tracking the touch point, and the |
| 42 | last known position of the touch point. | ||
| 43 | |||
| 42 | See `touch-screen-handle-point-update' and | 44 | See `touch-screen-handle-point-update' and |
| 43 | `touch-screen-handle-point-up' for the meanings of the fourth | 45 | `touch-screen-handle-point-up' for the meanings of the fourth |
| 44 | element.") | 46 | element. |
| 47 | |||
| 48 | The third and last elements differ in that the former is not | ||
| 49 | modified until after a gesture is recognized in reaction to an | ||
| 50 | update, whereas the latter is updated upon each apposite | ||
| 51 | `touchscreen-update' event.") | ||
| 52 | |||
| 53 | (defvar touch-screen-aux-tool nil | ||
| 54 | "The ancillary tool being tracked, or nil. | ||
| 55 | If non-nil, this is a vector of eight elements: the ID of the | ||
| 56 | touch point being tracked, the window where the touch began, a | ||
| 57 | cons holding the initial position of the touch point, and the | ||
| 58 | last known position of the touch point, all in the same format as | ||
| 59 | in `touch-screen-current-tool', the distance in pixels between | ||
| 60 | the current tool and the aformentioned initial position, the | ||
| 61 | center of the line formed between those two points, the ratio | ||
| 62 | between the present distance between both tools and the aforesaid | ||
| 63 | initial distance when a pinch gesture was last sent, and an | ||
| 64 | element into which commands can save data particular to a tool. | ||
| 65 | |||
| 66 | The ancillary tool is a second tool whose movement is interpreted | ||
| 67 | in unison with that of the current tool to recognize gestures | ||
| 68 | comprising the motion of both such as \"pinch\" gestures, in | ||
| 69 | which the text scale is adjusted in proportion to the distance | ||
| 70 | between both tools.") | ||
| 45 | 71 | ||
| 46 | (defvar touch-screen-set-point-commands '(mouse-set-point) | 72 | (defvar touch-screen-set-point-commands '(mouse-set-point) |
| 47 | "List of commands known to set the point. | 73 | "List of commands known to set the point. |
| @@ -844,6 +870,68 @@ keeping the bounds of the region intact, and set up state for | |||
| 844 | 870 | ||
| 845 | 871 | ||
| 846 | 872 | ||
| 873 | ;; Pinch gesture. | ||
| 874 | |||
| 875 | (defvar text-scale-mode) | ||
| 876 | (defvar text-scale-mode-amount) | ||
| 877 | (defvar text-scale-mode-step) | ||
| 878 | |||
| 879 | (defun touch-screen-scroll-point-to-y (target-point target-y) | ||
| 880 | "Move the row surrounding TARGET-POINT to TARGET-Y. | ||
| 881 | Scroll the current window such that the position of TARGET-POINT | ||
| 882 | within it on the Y axis approaches TARGET-Y." | ||
| 883 | (condition-case nil | ||
| 884 | (let* ((last-point (point)) | ||
| 885 | (current-y (cadr (pos-visible-in-window-p target-point | ||
| 886 | nil t))) | ||
| 887 | (direction (if (if current-y | ||
| 888 | (< target-y current-y) | ||
| 889 | (< (window-start) target-point)) | ||
| 890 | -1 1))) | ||
| 891 | (while (< 0 (* direction (if current-y | ||
| 892 | (- target-y current-y) | ||
| 893 | (- (window-start) target-point)))) | ||
| 894 | (scroll-down direction) | ||
| 895 | (setq last-point (point)) | ||
| 896 | (setq current-y (cadr (pos-visible-in-window-p target-point nil t)))) | ||
| 897 | (unless (and (< direction 0) current-y) | ||
| 898 | (scroll-up direction) | ||
| 899 | (goto-char last-point))) | ||
| 900 | ;; Ignore BOB and EOB. | ||
| 901 | ((beginning-of-buffer end-of-buffer) nil))) | ||
| 902 | |||
| 903 | (defun touch-screen-pinch (event) | ||
| 904 | "Scroll the window in the touchscreen-pinch event EVENT. | ||
| 905 | Pan the display by the pan deltas in EVENT, and adjust the | ||
| 906 | text scale by the ratio therein." | ||
| 907 | (interactive "e") | ||
| 908 | (require 'face-remap) | ||
| 909 | (let* ((posn (cadr event)) | ||
| 910 | (window (posn-window posn)) | ||
| 911 | (current-scale (if text-scale-mode | ||
| 912 | text-scale-mode-amount | ||
| 913 | 0)) | ||
| 914 | (start-scale (or (aref touch-screen-aux-tool 7) | ||
| 915 | (aset touch-screen-aux-tool 7 | ||
| 916 | current-scale))) | ||
| 917 | (scale (nth 2 event))) | ||
| 918 | (with-selected-window window | ||
| 919 | ;; Set the text scale. | ||
| 920 | (text-scale-set (+ start-scale | ||
| 921 | (round (log scale text-scale-mode-step)))) | ||
| 922 | ;; Subsequently move the row which was at the centrum to its Y | ||
| 923 | ;; position. TODO: pan by the deltas in EVENT when the text | ||
| 924 | ;; scale has not changed, and hscroll to the centrum as well. | ||
| 925 | (when (and (not (eq current-scale | ||
| 926 | text-scale-mode-amount)) | ||
| 927 | (posn-point posn)) | ||
| 928 | (touch-screen-scroll-point-to-y (posn-point posn) | ||
| 929 | (cdr (posn-x-y posn))))))) | ||
| 930 | |||
| 931 | (define-key global-map [touchscreen-pinch] #'touch-screen-pinch) | ||
| 932 | |||
| 933 | |||
| 934 | |||
| 847 | ;; Touch screen event translation. The code here translates raw touch | 935 | ;; Touch screen event translation. The code here translates raw touch |
| 848 | ;; screen events into `touchscreen-scroll' events and mouse events in | 936 | ;; screen events into `touchscreen-scroll' events and mouse events in |
| 849 | ;; a ``DWIM'' fashion, consulting the keymaps at the position of the | 937 | ;; a ``DWIM'' fashion, consulting the keymaps at the position of the |
| @@ -886,6 +974,11 @@ Perform the editing operations or throw to the input translation | |||
| 886 | function with an input event tied to any gesture that is | 974 | function with an input event tied to any gesture that is |
| 887 | recognized. | 975 | recognized. |
| 888 | 976 | ||
| 977 | Update the tenth element of `touch-screen-current-tool' with | ||
| 978 | POINT relative to the window it was placed on. Update the third | ||
| 979 | element in like fashion, once sufficient motion has accumulated | ||
| 980 | that an event is generated. | ||
| 981 | |||
| 889 | POINT must be the touch point currently being tracked as | 982 | POINT must be the touch point currently being tracked as |
| 890 | `touch-screen-current-tool'. | 983 | `touch-screen-current-tool'. |
| 891 | 984 | ||
| @@ -899,7 +992,7 @@ has moved relative to its previous position in the X and Y axes. | |||
| 899 | 992 | ||
| 900 | If the fourth element of `touchscreen-current-tool' is `scroll', | 993 | If the fourth element of `touchscreen-current-tool' is `scroll', |
| 901 | then generate a `touchscreen-scroll' event with the window that | 994 | then generate a `touchscreen-scroll' event with the window that |
| 902 | qPOINT was initially placed upon, and pixel deltas describing how | 995 | POINT was initially placed upon, and pixel deltas describing how |
| 903 | much point has moved relative to its previous position in the X | 996 | much point has moved relative to its previous position in the X |
| 904 | and Y axes. | 997 | and Y axes. |
| 905 | 998 | ||
| @@ -918,16 +1011,17 @@ If the fourth element of `touch-screen-current-tool' is | |||
| 918 | 1011 | ||
| 919 | If the fourth element of `touch-screen-current-tool' is `drag', | 1012 | If the fourth element of `touch-screen-current-tool' is `drag', |
| 920 | then move point to the position of POINT." | 1013 | then move point to the position of POINT." |
| 921 | (let ((window (nth 1 touch-screen-current-tool)) | 1014 | (let* ((window (nth 1 touch-screen-current-tool)) |
| 922 | (what (nth 3 touch-screen-current-tool))) | 1015 | (what (nth 3 touch-screen-current-tool)) |
| 1016 | (posn (cdr point)) | ||
| 1017 | ;; Now get the position of X and Y relative to WINDOW. | ||
| 1018 | (relative-xy | ||
| 1019 | (touch-screen-relative-xy posn window))) | ||
| 1020 | ;; Update the 10th field of the tool list with RELATIVE-XY. | ||
| 1021 | (setcar (nthcdr 9 touch-screen-current-tool) relative-xy) | ||
| 923 | (cond ((null what) | 1022 | (cond ((null what) |
| 924 | (let* ((posn (cdr point)) | 1023 | (let* ((last-posn (nth 2 touch-screen-current-tool)) |
| 925 | (last-posn (nth 2 touch-screen-current-tool)) | ||
| 926 | (original-posn (nth 4 touch-screen-current-tool)) | 1024 | (original-posn (nth 4 touch-screen-current-tool)) |
| 927 | ;; Now get the position of X and Y relative to | ||
| 928 | ;; WINDOW. | ||
| 929 | (relative-xy | ||
| 930 | (touch-screen-relative-xy posn window)) | ||
| 931 | (col (and (not (posn-area original-posn)) | 1025 | (col (and (not (posn-area original-posn)) |
| 932 | (car (posn-col-row original-posn | 1026 | (car (posn-col-row original-posn |
| 933 | (posn-window posn))))) | 1027 | (posn-window posn))))) |
| @@ -966,12 +1060,7 @@ then move point to the position of POINT." | |||
| 966 | (when touch-screen-current-timer | 1060 | (when touch-screen-current-timer |
| 967 | (cancel-timer touch-screen-current-timer) | 1061 | (cancel-timer touch-screen-current-timer) |
| 968 | (setq touch-screen-current-timer nil)) | 1062 | (setq touch-screen-current-timer nil)) |
| 969 | (let* ((posn (cdr point)) | 1063 | (let* ((last-posn (nth 2 touch-screen-current-tool)) |
| 970 | (last-posn (nth 2 touch-screen-current-tool)) | ||
| 971 | ;; Now get the position of X and Y relative to | ||
| 972 | ;; WINDOW. | ||
| 973 | (relative-xy | ||
| 974 | (touch-screen-relative-xy posn window)) | ||
| 975 | (diff-x (- (car last-posn) (car relative-xy))) | 1064 | (diff-x (- (car last-posn) (car relative-xy))) |
| 976 | (diff-y (- (cdr last-posn) (cdr relative-xy)))) | 1065 | (diff-y (- (cdr last-posn) (cdr relative-xy)))) |
| 977 | (setcar (nthcdr 3 touch-screen-current-tool) | 1066 | (setcar (nthcdr 3 touch-screen-current-tool) |
| @@ -1014,6 +1103,100 @@ then move point to the position of POINT." | |||
| 1014 | ;; Generate a (touchscreen-drag POSN) event. | 1103 | ;; Generate a (touchscreen-drag POSN) event. |
| 1015 | (throw 'input-event (list 'touchscreen-drag posn))))))) | 1104 | (throw 'input-event (list 'touchscreen-drag posn))))))) |
| 1016 | 1105 | ||
| 1106 | (defsubst touch-screen-distance (pos1 pos2) | ||
| 1107 | "Compute the distance in pixels between POS1 and POS2. | ||
| 1108 | Each is a coordinate whose car and cdr are respectively its X and | ||
| 1109 | Y values." | ||
| 1110 | (let ((v1 (- (cdr pos2) (cdr pos1))) | ||
| 1111 | (v2 (- (car pos2) (car pos1)))) | ||
| 1112 | (abs (sqrt (+ (* v1 v1) (* v2 v2)))))) | ||
| 1113 | |||
| 1114 | (defsubst touch-screen-centrum (pos1 pos2) | ||
| 1115 | "Compute the center of a line between the points POS1 and POS2. | ||
| 1116 | Each, and value, is a coordinate whose car and cdr are | ||
| 1117 | respectively its X and Y values." | ||
| 1118 | (let ((v1 (+ (cdr pos2) (cdr pos1))) | ||
| 1119 | (v2 (+ (car pos2) (car pos1)))) | ||
| 1120 | (cons (/ v2 2) (/ v1 2)))) | ||
| 1121 | |||
| 1122 | (defun touch-screen-handle-aux-point-update (point number) | ||
| 1123 | "Notice that a point being observed has moved. | ||
| 1124 | Register motion from either the current or ancillary tool while | ||
| 1125 | an ancillary tool is present. | ||
| 1126 | |||
| 1127 | POINT must be the cdr of an element of a `touchscreen-update' | ||
| 1128 | event's list of touch points. NUMBER must be its touch ID. | ||
| 1129 | |||
| 1130 | Calculate the distance between POINT's position and that of the | ||
| 1131 | other tool (which is to say the ancillary tool of POINT is the | ||
| 1132 | current tool, and vice versa). Compare this distance to that | ||
| 1133 | between both points at the time they were placed on the screen, | ||
| 1134 | and signal a pinch event to adjust the text scale and scroll the | ||
| 1135 | window by the factor so derived. Such events are lists formed as | ||
| 1136 | so illustrated: | ||
| 1137 | |||
| 1138 | (touchscreen-pinch CENTRUM RATIO PAN-X PAN-Y) | ||
| 1139 | |||
| 1140 | in which CENTRUM is a posn representing the midpoint of a line | ||
| 1141 | between the present locations of both tools, PAN-X is the number | ||
| 1142 | of pixels on the X axis that centrum has moved since the last | ||
| 1143 | event, and PAN-Y is that on the Y axis." | ||
| 1144 | (let (this-point-position | ||
| 1145 | other-point-position | ||
| 1146 | (window (cadr touch-screen-current-tool))) | ||
| 1147 | (when (windowp window) | ||
| 1148 | (if (eq number (aref touch-screen-aux-tool 0)) | ||
| 1149 | (progn | ||
| 1150 | ;; The point pressed is the ancillary tool. Set | ||
| 1151 | ;; other-point-position to that of the current tool. | ||
| 1152 | (setq other-point-position (nth 9 touch-screen-current-tool)) | ||
| 1153 | ;; Update the position within touch-screen-aux-tool. | ||
| 1154 | (aset touch-screen-aux-tool 3 | ||
| 1155 | (setq this-point-position | ||
| 1156 | (touch-screen-relative-xy point window)))) | ||
| 1157 | (setq other-point-position (aref touch-screen-aux-tool 3)) | ||
| 1158 | (setcar (nthcdr 2 touch-screen-current-tool) | ||
| 1159 | (setq this-point-position | ||
| 1160 | (touch-screen-relative-xy point window))) | ||
| 1161 | (setcar (nthcdr 9 touch-screen-current-tool) | ||
| 1162 | this-point-position)) | ||
| 1163 | ;; Now compute, and take the absolute of, this distance. | ||
| 1164 | (let ((distance (touch-screen-distance this-point-position | ||
| 1165 | other-point-position)) | ||
| 1166 | (centrum (touch-screen-centrum this-point-position | ||
| 1167 | other-point-position)) | ||
| 1168 | (initial-distance (aref touch-screen-aux-tool 4)) | ||
| 1169 | (initial-centrum (aref touch-screen-aux-tool 5))) | ||
| 1170 | (let* ((ratio (/ distance initial-distance)) | ||
| 1171 | (diff (abs (- ratio (aref touch-screen-aux-tool 6)))) | ||
| 1172 | (centrum-diff (+ (abs (- (car initial-centrum) | ||
| 1173 | (car centrum))) | ||
| 1174 | (abs (- (cdr initial-centrum) | ||
| 1175 | (cdr centrum)))))) | ||
| 1176 | ;; If the difference in ratio has surpassed a threshold of | ||
| 1177 | ;; 0.2 or the centrum difference exceeds the frame's char | ||
| 1178 | ;; width, send a touchscreen-pinch event with this | ||
| 1179 | ;; information and update that saved in | ||
| 1180 | ;; touch-screen-aux-tool. | ||
| 1181 | (when (or (> diff 0.2) | ||
| 1182 | (> centrum-diff | ||
| 1183 | (/ (frame-char-width) 2))) | ||
| 1184 | (aset touch-screen-aux-tool 5 centrum) | ||
| 1185 | (aset touch-screen-aux-tool 6 ratio) | ||
| 1186 | (throw 'input-event (list 'touchscreen-pinch | ||
| 1187 | (if (or (<= (car centrum) 0) | ||
| 1188 | (<= (cdr centrum) 0)) | ||
| 1189 | (list window centrum nil nil nil | ||
| 1190 | nil nil nil) | ||
| 1191 | (posn-at-x-y (car centrum) | ||
| 1192 | (cdr centrum) | ||
| 1193 | window)) | ||
| 1194 | ratio | ||
| 1195 | (- (car centrum) | ||
| 1196 | (car initial-centrum)) | ||
| 1197 | (- (cdr centrum) | ||
| 1198 | (cdr initial-centrum)))))))))) | ||
| 1199 | |||
| 1017 | (defun touch-screen-window-selection-changed (frame) | 1200 | (defun touch-screen-window-selection-changed (frame) |
| 1018 | "Notice that FRAME's selected window has changed. | 1201 | "Notice that FRAME's selected window has changed. |
| 1019 | Cancel any timer that is supposed to hide the keyboard in | 1202 | Cancel any timer that is supposed to hide the keyboard in |
| @@ -1037,6 +1220,13 @@ POINT should be the point currently tracked as | |||
| 1037 | PREFIX should be a virtual function key used to look up key | 1220 | PREFIX should be a virtual function key used to look up key |
| 1038 | bindings. | 1221 | bindings. |
| 1039 | 1222 | ||
| 1223 | If an ancillary touch point is being observed, transfer touch | ||
| 1224 | information from `touch-screen-aux-tool' to | ||
| 1225 | `touch-screen-current-tool' and set it to nil, thereby resuming | ||
| 1226 | gesture recognition with that tool replacing the tool removed. | ||
| 1227 | |||
| 1228 | Otherwise: | ||
| 1229 | |||
| 1040 | If the fourth element of `touch-screen-current-tool' is nil or | 1230 | If the fourth element of `touch-screen-current-tool' is nil or |
| 1041 | `restart-drag', move point to the position of POINT, selecting | 1231 | `restart-drag', move point to the position of POINT, selecting |
| 1042 | the window under POINT as well, and deactivate the mark; if there | 1232 | the window under POINT as well, and deactivate the mark; if there |
| @@ -1061,140 +1251,161 @@ If the command being executed is listed in | |||
| 1061 | `touch-screen-set-point-commands' also display the on-screen | 1251 | `touch-screen-set-point-commands' also display the on-screen |
| 1062 | keyboard if the current buffer and the character at the new point | 1252 | keyboard if the current buffer and the character at the new point |
| 1063 | is not read-only." | 1253 | is not read-only." |
| 1064 | (let ((what (nth 3 touch-screen-current-tool)) | 1254 | (if touch-screen-aux-tool |
| 1065 | (posn (cdr point)) window point) | 1255 | (progn |
| 1066 | (cond ((or (null what) | 1256 | (let ((posn (cdr point)) |
| 1067 | ;; If dragging has been restarted but the touch point | 1257 | (window (cadr touch-screen-current-tool)) |
| 1068 | ;; hasn't been moved, translate the sequence into a | 1258 | (point-no (aref touch-screen-aux-tool 0))) |
| 1069 | ;; regular mouse click. | 1259 | ;; Replace the current position of touch-screen-current-tool |
| 1070 | (eq what 'restart-drag)) | 1260 | ;; with posn and its number with point-no, but leave other |
| 1071 | (when (windowp (posn-window posn)) | 1261 | ;; information (such as its starting position) intact: this |
| 1072 | (setq point (posn-point posn) | 1262 | ;; touchpoint is meant to continue the gesture interrupted |
| 1073 | window (posn-window posn)) | 1263 | ;; by the removal of the last, not to commence a new one. |
| 1074 | ;; Select the window that was tapped given that it isn't | 1264 | (setcar touch-screen-current-tool point-no) |
| 1075 | ;; an inactive minibuffer window. | 1265 | (setcar (nthcdr 2 touch-screen-current-tool) |
| 1076 | (when (or (not (eq window | 1266 | (touch-screen-relative-xy posn window)) |
| 1077 | (minibuffer-window | 1267 | (setcar (nthcdr 9 touch-screen-current-tool) |
| 1078 | (window-frame window)))) | 1268 | (touch-screen-relative-xy posn window))) |
| 1079 | (minibuffer-window-active-p window)) | 1269 | (setq touch-screen-aux-tool nil)) |
| 1080 | (select-window window)) | 1270 | (let ((what (nth 3 touch-screen-current-tool)) |
| 1081 | ;; Now simulate a mouse click there. If there is a link | 1271 | (posn (cdr point)) window point) |
| 1082 | ;; or a button, use mouse-2 to push it. | 1272 | (cond ((or (null what) |
| 1083 | (let* ((event (list (if (or (mouse-on-link-p posn) | 1273 | ;; If dragging has been restarted but the touch point |
| 1084 | (and point (button-at point))) | 1274 | ;; hasn't been moved, translate the sequence into a |
| 1085 | 'mouse-2 | 1275 | ;; regular mouse click. |
| 1086 | 'mouse-1) | 1276 | (eq what 'restart-drag)) |
| 1087 | posn)) | 1277 | (when (windowp (posn-window posn)) |
| 1088 | ;; Look for the command bound to this event. | 1278 | (setq point (posn-point posn) |
| 1089 | (command (key-binding (if prefix | 1279 | window (posn-window posn)) |
| 1090 | (vector prefix | 1280 | ;; Select the window that was tapped given that it |
| 1091 | (car event)) | 1281 | ;; isn't an inactive minibuffer window. |
| 1092 | (vector (car event))) | 1282 | (when (or (not (eq window |
| 1093 | t nil posn))) | 1283 | (minibuffer-window |
| 1094 | (deactivate-mark) | 1284 | (window-frame window)))) |
| 1095 | (when point | 1285 | (minibuffer-window-active-p window)) |
| 1096 | ;; This is necessary for following links. | 1286 | (select-window window)) |
| 1097 | (goto-char point)) | 1287 | ;; Now simulate a mouse click there. If there is a |
| 1098 | ;; Figure out if the on screen keyboard needs to be | 1288 | ;; link or a button, use mouse-2 to push it. |
| 1099 | ;; displayed. | 1289 | (let* ((event (list (if (or (mouse-on-link-p posn) |
| 1100 | (when command | 1290 | (and point (button-at point))) |
| 1101 | (if (memq command touch-screen-set-point-commands) | 1291 | 'mouse-2 |
| 1102 | (if touch-screen-translate-prompt | 1292 | 'mouse-1) |
| 1103 | ;; When a `mouse-set-point' command is | 1293 | posn)) |
| 1104 | ;; encountered and | 1294 | ;; Look for the command bound to this event. |
| 1105 | ;; `touch-screen-handle-touch' is being | 1295 | (command (key-binding (if prefix |
| 1106 | ;; called from the keyboard command loop, | 1296 | (vector prefix |
| 1107 | ;; call it immediately so that point is set | 1297 | (car event)) |
| 1108 | ;; prior to the on screen keyboard being | 1298 | (vector (car event))) |
| 1109 | ;; displayed. | 1299 | t nil posn))) |
| 1110 | (call-interactively command nil | 1300 | (deactivate-mark) |
| 1111 | (vector event)) | 1301 | (when point |
| 1112 | (if (and (or (not buffer-read-only) | 1302 | ;; This is necessary for following links. |
| 1113 | touch-screen-display-keyboard) | 1303 | (goto-char point)) |
| 1114 | ;; Detect the splash screen and avoid | 1304 | ;; Figure out if the on screen keyboard needs to be |
| 1115 | ;; displaying the on screen keyboard | 1305 | ;; displayed. |
| 1116 | ;; there. | 1306 | (when command |
| 1117 | (not (equal (buffer-name) "*GNU Emacs*"))) | 1307 | (if (memq command touch-screen-set-point-commands) |
| 1118 | ;; Once the on-screen keyboard has been | 1308 | (if touch-screen-translate-prompt |
| 1119 | ;; opened, add | 1309 | ;; When a `mouse-set-point' command is |
| 1120 | ;; `touch-screen-window-selection-changed' | 1310 | ;; encountered and |
| 1121 | ;; as a window selection change function | 1311 | ;; `touch-screen-handle-touch' is being |
| 1122 | ;; This then prevents it from being hidden | 1312 | ;; called from the keyboard command loop, |
| 1123 | ;; after exiting the minibuffer. | 1313 | ;; call it immediately so that point is set |
| 1124 | (progn | 1314 | ;; prior to the on screen keyboard being |
| 1125 | (add-hook 'window-selection-change-functions | 1315 | ;; displayed. |
| 1126 | #'touch-screen-window-selection-changed) | 1316 | (call-interactively command nil |
| 1127 | (frame-toggle-on-screen-keyboard (selected-frame) | 1317 | (vector event)) |
| 1128 | nil)) | 1318 | (if (and (or (not buffer-read-only) |
| 1129 | ;; Otherwise, hide the on screen keyboard | 1319 | touch-screen-display-keyboard) |
| 1130 | ;; now. | 1320 | ;; Detect the splash screen and |
| 1131 | (frame-toggle-on-screen-keyboard (selected-frame) t)) | 1321 | ;; avoid displaying the on screen |
| 1132 | ;; But if it's being called from `describe-key' | 1322 | ;; keyboard there. |
| 1133 | ;; or some such, return it as a key sequence. | 1323 | (not (equal (buffer-name) "*GNU Emacs*"))) |
| 1134 | (throw 'input-event event))) | 1324 | ;; Once the on-screen keyboard has been |
| 1135 | ;; If not, return the event. | 1325 | ;; opened, add |
| 1136 | (throw 'input-event event))))) | 1326 | ;; `touch-screen-window-selection-changed' |
| 1137 | ((eq what 'mouse-drag) | 1327 | ;; as a window selection change function |
| 1138 | ;; Generate a corresponding `mouse-1' event. | 1328 | ;; This then prevents it from being |
| 1139 | (let* ((new-window (posn-window posn)) | 1329 | ;; hidden after exiting the minibuffer. |
| 1140 | (new-point (posn-point posn)) | 1330 | (progn |
| 1141 | (old-posn (nth 4 touch-screen-current-tool)) | 1331 | (add-hook |
| 1142 | (old-window (posn-window posn)) | 1332 | 'window-selection-change-functions |
| 1143 | (old-point (posn-point posn))) | 1333 | #'touch-screen-window-selection-changed) |
| 1334 | (frame-toggle-on-screen-keyboard | ||
| 1335 | (selected-frame) nil)) | ||
| 1336 | ;; Otherwise, hide the on screen keyboard | ||
| 1337 | ;; now. | ||
| 1338 | (frame-toggle-on-screen-keyboard (selected-frame) | ||
| 1339 | t)) | ||
| 1340 | ;; But if it's being called from `describe-key' | ||
| 1341 | ;; or some such, return it as a key sequence. | ||
| 1342 | (throw 'input-event event))) | ||
| 1343 | ;; If not, return the event. | ||
| 1344 | (throw 'input-event event))))) | ||
| 1345 | ((eq what 'mouse-drag) | ||
| 1346 | ;; Generate a corresponding `mouse-1' event. | ||
| 1347 | (let* ((new-window (posn-window posn)) | ||
| 1348 | (new-point (posn-point posn)) | ||
| 1349 | (old-posn (nth 4 touch-screen-current-tool)) | ||
| 1350 | (old-window (posn-window posn)) | ||
| 1351 | (old-point (posn-point posn))) | ||
| 1352 | (throw 'input-event | ||
| 1353 | ;; If the position of the touch point hasn't | ||
| 1354 | ;; changed, or it doesn't start or end on a | ||
| 1355 | ;; window... | ||
| 1356 | (if (and (not old-point) (not new-point)) | ||
| 1357 | ;; Should old-point and new-point both equal | ||
| 1358 | ;; nil, compare the posn areas and nominal | ||
| 1359 | ;; column position. If either are | ||
| 1360 | ;; different, generate a drag event. | ||
| 1361 | (let ((new-col-row (posn-col-row posn)) | ||
| 1362 | (new-area (posn-area posn)) | ||
| 1363 | (old-col-row (posn-col-row old-posn)) | ||
| 1364 | (old-area (posn-area old-posn))) | ||
| 1365 | (if (and (equal new-col-row old-col-row) | ||
| 1366 | (eq new-area old-area)) | ||
| 1367 | ;; ... generate a mouse-1 event... | ||
| 1368 | (list 'mouse-1 posn) | ||
| 1369 | ;; ... otherwise, generate a | ||
| 1370 | ;; drag-mouse-1 event. | ||
| 1371 | (list 'drag-mouse-1 old-posn posn))) | ||
| 1372 | (if (and (eq new-window old-window) | ||
| 1373 | (eq new-point old-point) | ||
| 1374 | (windowp new-window) | ||
| 1375 | (windowp old-window)) | ||
| 1376 | ;; ... generate a mouse-1 event... | ||
| 1377 | (list 'mouse-1 posn) | ||
| 1378 | ;; ... otherwise, generate a drag-mouse-1 | ||
| 1379 | ;; event. | ||
| 1380 | (list 'drag-mouse-1 old-posn posn)))))) | ||
| 1381 | ((eq what 'mouse-1-menu) | ||
| 1382 | ;; Generate a `down-mouse-1' event at the position the tap | ||
| 1383 | ;; took place. | ||
| 1144 | (throw 'input-event | 1384 | (throw 'input-event |
| 1145 | ;; If the position of the touch point hasn't | 1385 | (list 'down-mouse-1 |
| 1146 | ;; changed, or it doesn't start or end on a | 1386 | (nth 4 touch-screen-current-tool)))) |
| 1147 | ;; window... | 1387 | ((or (eq what 'drag) |
| 1148 | (if (and (not old-point) (not new-point)) | 1388 | ;; Merely initiating a drag is sufficient to select a |
| 1149 | ;; Should old-point and new-point both equal | 1389 | ;; word if word selection is enabled. |
| 1150 | ;; nil, compare the posn areas and nominal | 1390 | (eq what 'held)) |
| 1151 | ;; column position. If either are different, | 1391 | ;; Display the on screen keyboard if the region is now |
| 1152 | ;; generate a drag event. | 1392 | ;; active. Check this within the window where the tool |
| 1153 | (let ((new-col-row (posn-col-row posn)) | 1393 | ;; was first place. |
| 1154 | (new-area (posn-area posn)) | 1394 | (setq window (nth 1 touch-screen-current-tool)) |
| 1155 | (old-col-row (posn-col-row old-posn)) | 1395 | (when window |
| 1156 | (old-area (posn-area old-posn))) | 1396 | (with-selected-window window |
| 1157 | (if (and (equal new-col-row old-col-row) | 1397 | (when (and (region-active-p) |
| 1158 | (eq new-area old-area)) | 1398 | (not buffer-read-only)) |
| 1159 | ;; ... generate a mouse-1 event... | 1399 | ;; Once the on-screen keyboard has been opened, add |
| 1160 | (list 'mouse-1 posn) | 1400 | ;; `touch-screen-window-selection-changed' as a |
| 1161 | ;; ... otherwise, generate a drag-mouse-1 event. | 1401 | ;; window selection change function. This then |
| 1162 | (list 'drag-mouse-1 old-posn posn))) | 1402 | ;; prevents it from being hidden after exiting the |
| 1163 | (if (and (eq new-window old-window) | 1403 | ;; minibuffer. |
| 1164 | (eq new-point old-point) | 1404 | (progn |
| 1165 | (windowp new-window) | 1405 | (add-hook 'window-selection-change-functions |
| 1166 | (windowp old-window)) | 1406 | #'touch-screen-window-selection-changed) |
| 1167 | ;; ... generate a mouse-1 event... | 1407 | (frame-toggle-on-screen-keyboard (selected-frame) |
| 1168 | (list 'mouse-1 posn) | 1408 | nil)))))))))) |
| 1169 | ;; ... otherwise, generate a drag-mouse-1 event. | ||
| 1170 | (list 'drag-mouse-1 old-posn posn)))))) | ||
| 1171 | ((eq what 'mouse-1-menu) | ||
| 1172 | ;; Generate a `down-mouse-1' event at the position the tap | ||
| 1173 | ;; took place. | ||
| 1174 | (throw 'input-event | ||
| 1175 | (list 'down-mouse-1 | ||
| 1176 | (nth 4 touch-screen-current-tool)))) | ||
| 1177 | ((or (eq what 'drag) | ||
| 1178 | ;; Merely initiating a drag is sufficient to select a | ||
| 1179 | ;; word if word selection is enabled. | ||
| 1180 | (eq what 'held)) | ||
| 1181 | ;; Display the on screen keyboard if the region is now | ||
| 1182 | ;; active. Check this within the window where the tool was | ||
| 1183 | ;; first place. | ||
| 1184 | (setq window (nth 1 touch-screen-current-tool)) | ||
| 1185 | (when window | ||
| 1186 | (with-selected-window window | ||
| 1187 | (when (and (region-active-p) | ||
| 1188 | (not buffer-read-only)) | ||
| 1189 | ;; Once the on-screen keyboard has been opened, add | ||
| 1190 | ;; `touch-screen-window-selection-changed' as a window | ||
| 1191 | ;; selection change function This then prevents it from | ||
| 1192 | ;; being hidden after exiting the minibuffer. | ||
| 1193 | (progn | ||
| 1194 | (add-hook 'window-selection-change-functions | ||
| 1195 | #'touch-screen-window-selection-changed) | ||
| 1196 | (frame-toggle-on-screen-keyboard (selected-frame) | ||
| 1197 | nil))))))))) | ||
| 1198 | 1409 | ||
| 1199 | (defun touch-screen-handle-touch (event prefix &optional interactive) | 1410 | (defun touch-screen-handle-touch (event prefix &optional interactive) |
| 1200 | "Handle a single touch EVENT, and perform associated actions. | 1411 | "Handle a single touch EVENT, and perform associated actions. |
| @@ -1234,81 +1445,126 @@ the place of EVENT within the key sequence being translated, or | |||
| 1234 | (when touch-screen-current-timer | 1445 | (when touch-screen-current-timer |
| 1235 | (cancel-timer touch-screen-current-timer) | 1446 | (cancel-timer touch-screen-current-timer) |
| 1236 | (setq touch-screen-current-timer nil)) | 1447 | (setq touch-screen-current-timer nil)) |
| 1237 | ;; Replace any previously ongoing gesture. If POSITION has no | 1448 | ;; If a tool already exists... |
| 1238 | ;; window or position, make it nil instead. | 1449 | (if touch-screen-current-tool |
| 1239 | (setq tool-list (and (windowp window) | 1450 | ;; Then record this tool as the ``auxiliary tool''. |
| 1240 | (list touchpoint window | 1451 | ;; Updates to the auxiliary tool are considered in unison |
| 1241 | (posn-x-y position) | 1452 | ;; with those to the current tool; the distance between |
| 1242 | nil position | 1453 | ;; both tools is measured and compared with that when the |
| 1243 | nil nil nil nil)) | 1454 | ;; auxiliary tool was first pressed, then interpreted as a |
| 1244 | touch-screen-current-tool tool-list) | 1455 | ;; scale by which to adjust text within the current tool's |
| 1245 | 1456 | ;; window. | |
| 1246 | ;; Select the window underneath the event as the checks below | 1457 | (progn |
| 1247 | ;; will look up keymaps and markers inside its buffer. | 1458 | ;; Set touch-screen-aux-tool as is proper. Mind that |
| 1248 | (save-selected-window | 1459 | ;; the last field is always relative to the current |
| 1249 | ;; Check if `touch-screen-extend-selection' is enabled, the | 1460 | ;; tool's window. |
| 1250 | ;; tap lies on the point or the mark, and the region is | 1461 | (let* ((window (nth 1 touch-screen-current-tool)) |
| 1251 | ;; active. If that's the case, set the fourth element of | 1462 | (relative-x-y (touch-screen-relative-xy position |
| 1252 | ;; `touch-screen-current-tool' to `restart-drag', then | 1463 | window)) |
| 1253 | ;; generate a `touchscreen-restart-drag' event. | 1464 | (initial-pos (nth 4 touch-screen-current-tool)) |
| 1254 | (when tool-list | 1465 | (initial-x-y (touch-screen-relative-xy initial-pos |
| 1255 | ;; tool-list is always non-nil where the selected window | 1466 | window)) |
| 1256 | ;; matters. | 1467 | computed-distance computed-centrum) |
| 1257 | (select-window window) | 1468 | ;; Calculate the distance and centrum from this point |
| 1258 | (when (and touch-screen-extend-selection | 1469 | ;; to the initial position of the current tool. |
| 1259 | (or (eq point (point)) | 1470 | (setq computed-distance (touch-screen-distance relative-x-y |
| 1260 | (eq point (mark))) | 1471 | initial-x-y) |
| 1261 | (region-active-p) | 1472 | computed-centrum (touch-screen-centrum relative-x-y |
| 1262 | ;; Only restart drag-to-select if the tap falls | 1473 | initial-x-y)) |
| 1263 | ;; on the same row as the selection. This | 1474 | ;; If computed-distance is zero, ignore this tap. |
| 1264 | ;; prevents dragging from starting if the tap | 1475 | (unless (zerop computed-distance) |
| 1265 | ;; is below the last window line with text and | 1476 | (setq touch-screen-aux-tool (vector touchpoint window |
| 1266 | ;; `point' is at ZV, as the user most likely | 1477 | position relative-x-y |
| 1267 | ;; meant to scroll the window instead. | 1478 | computed-distance |
| 1268 | (when-let* ((posn-point (posn-at-point point)) | 1479 | computed-centrum |
| 1269 | (posn-row (cdr (posn-col-row posn-point)))) | 1480 | 1.0 nil))) |
| 1270 | (eq (cdr (posn-col-row position)) posn-row))) | 1481 | ;; When an auxiliary tool is pressed, any gesture |
| 1271 | ;; Indicate that a drag is about to restart. | 1482 | ;; previously in progress must be terminated, so long |
| 1272 | (setcar (nthcdr 3 tool-list) 'restart-drag) | 1483 | ;; as it represents a gesture recognized from the |
| 1273 | ;; Generate the `restart-drag' event. | 1484 | ;; current tool's motion rather than ones detected by |
| 1274 | (throw 'input-event (list 'touchscreen-restart-drag | 1485 | ;; this function from circumstances surrounding its |
| 1275 | position)))) | 1486 | ;; first press, such as the presence of a menu or |
| 1276 | ;; Determine if there is a command bound to `down-mouse-1' | 1487 | ;; down-mouse-1 button beneath its first press. |
| 1277 | ;; at the position of the tap and that command is not a | 1488 | (unless (memq (nth 3 touch-screen-current-tool) |
| 1278 | ;; command whose functionality is replaced by the long-press | 1489 | '(mouse-drag mouse-1-menu)) |
| 1279 | ;; mechanism. If so, set the fourth element of | 1490 | (setcar (nthcdr 3 touch-screen-current-tool) nil)))) |
| 1280 | ;; `touch-screen-current-tool' to `mouse-drag' and generate | 1491 | ;; Replace any previously ongoing gesture. If POSITION has no |
| 1281 | ;; an emulated `mouse-1' event. | 1492 | ;; window or position, make it nil instead. |
| 1282 | ;; | 1493 | (setq tool-list (and (windowp window) |
| 1283 | ;; If the command in question is a keymap, set that element | 1494 | (list touchpoint window |
| 1284 | ;; to `mouse-1-menu' instead of `mouse-drag', and don't | 1495 | (posn-x-y position) |
| 1285 | ;; generate a `down-mouse-1' event immediately. Instead, | 1496 | nil position |
| 1286 | ;; wait for the touch point to be released. | 1497 | nil nil nil nil |
| 1287 | (if (and tool-list | 1498 | (posn-x-y position))) |
| 1288 | (and (setq binding | 1499 | touch-screen-current-tool tool-list) |
| 1289 | (key-binding (if prefix | 1500 | ;; Select the window underneath the event as the checks below |
| 1290 | (vector prefix | 1501 | ;; will look up keymaps and markers inside its buffer. |
| 1291 | 'down-mouse-1) | 1502 | (save-selected-window |
| 1292 | [down-mouse-1]) | 1503 | ;; Check if `touch-screen-extend-selection' is enabled, |
| 1293 | t nil position)) | 1504 | ;; the tap lies on the point or the mark, and the region |
| 1294 | (not (and (symbolp binding) | 1505 | ;; is active. If that's the case, set the fourth element |
| 1295 | (get binding 'ignored-mouse-command))))) | 1506 | ;; of `touch-screen-current-tool' to `restart-drag', then |
| 1296 | (if (or (keymapp binding) | 1507 | ;; generate a `touchscreen-restart-drag' event. |
| 1297 | (and (symbolp binding) | 1508 | (when tool-list |
| 1298 | (get binding 'mouse-1-menu-command))) | 1509 | ;; tool-list is always non-nil where the selected window |
| 1299 | ;; binding is a keymap, or a command that does | 1510 | ;; matters. |
| 1300 | ;; almost the same thing. If a `mouse-1' event is | 1511 | (select-window window) |
| 1301 | ;; generated after the keyboard command loop | 1512 | (when (and touch-screen-extend-selection |
| 1302 | ;; displays it as a menu, that event could cause | 1513 | (or (eq point (point)) |
| 1303 | ;; unwanted commands to be run. Set what to | 1514 | (eq point (mark))) |
| 1304 | ;; `mouse-1-menu' instead and wait for the up event | 1515 | (region-active-p) |
| 1305 | ;; to display the menu. | 1516 | ;; Only restart drag-to-select if the tap |
| 1306 | (setcar (nthcdr 3 tool-list) 'mouse-1-menu) | 1517 | ;; falls on the same row as the selection. |
| 1307 | (progn (setcar (nthcdr 3 tool-list) 'mouse-drag) | 1518 | ;; This prevents dragging from starting if |
| 1308 | (throw 'input-event (list 'down-mouse-1 position)))) | 1519 | ;; the tap is below the last window line with |
| 1309 | (and point | 1520 | ;; text and `point' is at ZV, as the user |
| 1310 | ;; Start the long-press timer. | 1521 | ;; most likely meant to scroll the window |
| 1311 | (touch-screen-handle-timeout nil)))))) | 1522 | ;; instead. |
| 1523 | (when-let* ((posn-point (posn-at-point point)) | ||
| 1524 | (posn-row (cdr | ||
| 1525 | (posn-col-row posn-point)))) | ||
| 1526 | (eq (cdr (posn-col-row position)) posn-row))) | ||
| 1527 | ;; Indicate that a drag is about to restart. | ||
| 1528 | (setcar (nthcdr 3 tool-list) 'restart-drag) | ||
| 1529 | ;; Generate the `restart-drag' event. | ||
| 1530 | (throw 'input-event (list 'touchscreen-restart-drag | ||
| 1531 | position)))) | ||
| 1532 | ;; Determine if there is a command bound to `down-mouse-1' | ||
| 1533 | ;; at the position of the tap and that command is not a | ||
| 1534 | ;; command whose functionality is replaced by the | ||
| 1535 | ;; long-press mechanism. If so, set the fourth element of | ||
| 1536 | ;; `touch-screen-current-tool' to `mouse-drag' and | ||
| 1537 | ;; generate an emulated `mouse-1' event. | ||
| 1538 | ;; | ||
| 1539 | ;; If the command in question is a keymap, set that | ||
| 1540 | ;; element to `mouse-1-menu' instead of `mouse-drag', and | ||
| 1541 | ;; don't generate a `down-mouse-1' event immediately. | ||
| 1542 | ;; Instead, wait for the touch point to be released. | ||
| 1543 | (if (and tool-list | ||
| 1544 | (and (setq binding | ||
| 1545 | (key-binding (if prefix | ||
| 1546 | (vector prefix | ||
| 1547 | 'down-mouse-1) | ||
| 1548 | [down-mouse-1]) | ||
| 1549 | t nil position)) | ||
| 1550 | (not (and (symbolp binding) | ||
| 1551 | (get binding 'ignored-mouse-command))))) | ||
| 1552 | (if (or (keymapp binding) | ||
| 1553 | (and (symbolp binding) | ||
| 1554 | (get binding 'mouse-1-menu-command))) | ||
| 1555 | ;; binding is a keymap, or a command that does | ||
| 1556 | ;; almost the same thing. If a `mouse-1' event is | ||
| 1557 | ;; generated after the keyboard command loop | ||
| 1558 | ;; displays it as a menu, that event could cause | ||
| 1559 | ;; unwanted commands to be run. Set what to | ||
| 1560 | ;; `mouse-1-menu' instead and wait for the up | ||
| 1561 | ;; event to display the menu. | ||
| 1562 | (setcar (nthcdr 3 tool-list) 'mouse-1-menu) | ||
| 1563 | (progn (setcar (nthcdr 3 tool-list) 'mouse-drag) | ||
| 1564 | (throw 'input-event (list 'down-mouse-1 position)))) | ||
| 1565 | (and point | ||
| 1566 | ;; Start the long-press timer. | ||
| 1567 | (touch-screen-handle-timeout nil))))))) | ||
| 1312 | ((eq (car event) 'touchscreen-update) | 1568 | ((eq (car event) 'touchscreen-update) |
| 1313 | (unless touch-screen-current-tool | 1569 | (unless touch-screen-current-tool |
| 1314 | ;; If a stray touchscreen-update event arrives (most likely | 1570 | ;; If a stray touchscreen-update event arrives (most likely |
| @@ -1320,7 +1576,17 @@ the place of EVENT within the key sequence being translated, or | |||
| 1320 | (let ((new-point (assq (car touch-screen-current-tool) | 1576 | (let ((new-point (assq (car touch-screen-current-tool) |
| 1321 | (cadr event)))) | 1577 | (cadr event)))) |
| 1322 | (when new-point | 1578 | (when new-point |
| 1323 | (touch-screen-handle-point-update new-point)))) | 1579 | (if touch-screen-aux-tool |
| 1580 | (touch-screen-handle-aux-point-update (cdr new-point) | ||
| 1581 | (car new-point)) | ||
| 1582 | (touch-screen-handle-point-update new-point)))) | ||
| 1583 | ;; Check for updates to any ancillary point being monitored. | ||
| 1584 | (when touch-screen-aux-tool | ||
| 1585 | (let ((new-point (assq (aref touch-screen-aux-tool 0) | ||
| 1586 | (cadr event)))) | ||
| 1587 | (when new-point | ||
| 1588 | (touch-screen-handle-aux-point-update (cdr new-point) | ||
| 1589 | (car new-point)))))) | ||
| 1324 | ((eq (car event) 'touchscreen-end) | 1590 | ((eq (car event) 'touchscreen-end) |
| 1325 | ;; A tool has been removed from the screen. If it is the tool | 1591 | ;; A tool has been removed from the screen. If it is the tool |
| 1326 | ;; currently being tracked, clear `touch-screen-current-tool'. | 1592 | ;; currently being tracked, clear `touch-screen-current-tool'. |
| @@ -1339,6 +1605,21 @@ the place of EVENT within the key sequence being translated, or | |||
| 1339 | ;; Make sure the tool list is cleared even if | 1605 | ;; Make sure the tool list is cleared even if |
| 1340 | ;; `touch-screen-handle-point-up' throws. | 1606 | ;; `touch-screen-handle-point-up' throws. |
| 1341 | (setq touch-screen-current-tool nil))) | 1607 | (setq touch-screen-current-tool nil))) |
| 1608 | ;; If it is rather the ancillary tool, delete its vector. No | ||
| 1609 | ;; further action is required, for the next update received will | ||
| 1610 | ;; resume regular gesture recognition. | ||
| 1611 | ;; | ||
| 1612 | ;; The what field in touch-screen-current-tool is cleared when | ||
| 1613 | ;; the ancillary tool is pressed, so gesture recognition will | ||
| 1614 | ;; commence with a clean slate, save for when the first touch | ||
| 1615 | ;; landed atop a menu or some other area down-mouse-1 was bound. | ||
| 1616 | ;; | ||
| 1617 | ;; Gesture recognition will be inhibited in that case, so that | ||
| 1618 | ;; menu bar or mouse motion events are generated in its place as | ||
| 1619 | ;; they would be were no ancillary tool ever pressed. | ||
| 1620 | (when (and touch-screen-aux-tool | ||
| 1621 | (eq (caadr event) (aref touch-screen-aux-tool 0))) | ||
| 1622 | (setq touch-screen-aux-tool nil)) | ||
| 1342 | ;; Throw to the key translation function. | 1623 | ;; Throw to the key translation function. |
| 1343 | (throw 'input-event nil))))) | 1624 | (throw 'input-event nil))))) |
| 1344 | 1625 | ||
diff --git a/src/androidterm.c b/src/androidterm.c index 1593cac36ba..cfb64cd69a0 100644 --- a/src/androidterm.c +++ b/src/androidterm.c | |||
| @@ -1377,7 +1377,7 @@ handle_one_android_event (struct android_display_info *dpyinfo, | |||
| 1377 | { | 1377 | { |
| 1378 | /* Simply update the tool position and send an update. */ | 1378 | /* Simply update the tool position and send an update. */ |
| 1379 | touchpoint->x = event->touch.x; | 1379 | touchpoint->x = event->touch.x; |
| 1380 | touchpoint->y = event->touch.x; | 1380 | touchpoint->y = event->touch.y; |
| 1381 | android_update_tools (any, &inev.ie); | 1381 | android_update_tools (any, &inev.ie); |
| 1382 | inev.ie.timestamp = event->touch.time; | 1382 | inev.ie.timestamp = event->touch.time; |
| 1383 | 1383 | ||
| @@ -1390,7 +1390,7 @@ handle_one_android_event (struct android_display_info *dpyinfo, | |||
| 1390 | touchpoint = xmalloc (sizeof *touchpoint); | 1390 | touchpoint = xmalloc (sizeof *touchpoint); |
| 1391 | touchpoint->tool_id = event->touch.pointer_id; | 1391 | touchpoint->tool_id = event->touch.pointer_id; |
| 1392 | touchpoint->x = event->touch.x; | 1392 | touchpoint->x = event->touch.x; |
| 1393 | touchpoint->y = event->touch.x; | 1393 | touchpoint->y = event->touch.y; |
| 1394 | touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points; | 1394 | touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points; |
| 1395 | touchpoint->tool_bar_p = false; | 1395 | touchpoint->tool_bar_p = false; |
| 1396 | FRAME_OUTPUT_DATA (any)->touch_points = touchpoint; | 1396 | FRAME_OUTPUT_DATA (any)->touch_points = touchpoint; |