:group 'mouse
:version "30.1")
+(defcustom touch-screen-extend-selection nil
+ "If non-nil, restart drag-to-select upon a tap on point or mark.
+When enabled, tapping on the character containing the point or
+mark will resume dragging where it left off while the region is
+active."
+ :type 'boolean
+ :group 'mouse
+ :version "30.1")
+
(defvar-local touch-screen-word-select-bounds nil
"The start and end positions of the word last selected.
Normally a cons of those two positions or nil if no word was
(setq touch-screen-word-select-bounds nil))
(redisplay)))))))))
+(defun touch-screen-restart-drag (event)
+ "Restart dragging to select text.
+Set point to the location of EVENT within its window while
+keeping the bounds of the region intact, and set up state for
+`touch-screen-drag'."
+ (interactive "e")
+ (let* ((posn (event-start event))
+ (window (posn-window posn))
+ (point (posn-point posn)))
+ (with-selected-window window
+ (let ((current-point (point))
+ (current-mark (mark)))
+ ;; Ensure that mark and point haven't changed since EVENT was
+ ;; generated, and the region is still active.
+ (when (or (eq point current-point)
+ (eq point current-mark)
+ (region-active-p))
+ (when (eq point current-mark)
+ ;; Exchange point and mark.
+ (exchange-point-and-mark))
+ ;; Clear the state necessary to set up dragging. Don't try
+ ;; to select entire words immediately after dragging starts,
+ ;; to allow for fine grained selection inside a word.
+ (setq touch-screen-word-select-bounds nil
+ touch-screen-word-select-initial-word nil))))))
+
(global-set-key [touchscreen-hold] #'touch-screen-hold)
(global-set-key [touchscreen-drag] #'touch-screen-drag)
+(global-set-key [touchscreen-restart-drag] #'touch-screen-restart-drag)
\f
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, generate a `touchscreen-drag' event.
+happens, set the field to `drag'. Then, generate a
+`touchscreen-drag' event.
+
+If the fourth element of `touch-screen-current-tool' is
+`restart-drag', set the field to `drag' and generate a
+`touchscreen-drag'.
If the fourth element of `touch-screen-current-tool' is `drag',
then move point to the position of POINT."
;; `touchscreen-hold' was generated when the timeout
;; fired.
(throw 'input-event (list 'touchscreen-drag posn))))
+ ((eq what 'restart-drag)
+ (let* ((posn (cdr point)))
+ ;; Now start dragging.
+ (setcar (nthcdr 3 touch-screen-current-tool)
+ 'drag)
+ ;; Generate a (touchscreen-drag POSN) event.
+ ;; `touchscreen-restart-drag' was generated when the
+ ;; timeout fired.
+ (throw 'input-event (list 'touchscreen-drag posn))))
((eq what 'drag)
(let* ((posn (cdr point)))
;; Generate a (touchscreen-drag POSN) event.
(position (cdadr event))
(window (posn-window position))
(point (posn-point position))
- binding)
+ binding tool-list)
;; Cancel the touch screen timer, if it is still there by any
;; chance.
(when touch-screen-current-timer
(setq touch-screen-current-timer nil))
;; Replace any previously ongoing gesture. If POSITION has no
;; window or position, make it nil instead.
- (setq touch-screen-current-tool (and (windowp window)
- (list touchpoint window
- (posn-x-y position)
- nil position
- nil nil nil nil)))
- ;; Determine if there is a command bound to `down-mouse-1' at
- ;; the position of the tap and that command is not a command
- ;; whose functionality is replaced by the long-press
- ;; mechanism. If so, set the fourth element of
- ;; `touch-screen-current-tool' to `mouse-drag' and generate an
- ;; emulated `mouse-1' event.
- ;;
- ;; If the command in question is a keymap, use `mouse-1-menu'
- ;; instead of `mouse-drag', and don't generate a
- ;; `down-mouse-1' event immediately. Instead, wait for the
- ;; touch point to be released.
- (if (and touch-screen-current-tool
- (with-selected-window window
+ (setq tool-list (and (windowp window)
+ (list touchpoint window
+ (posn-x-y position)
+ nil position
+ nil nil nil nil))
+ touch-screen-current-tool tool-list)
+
+ ;; Select the window underneath the event as the checks below
+ ;; will look up keymaps and markers inside its buffer.
+ (save-selected-window
+ ;; Check if `touch-screen-extend-selection' is enabled, the
+ ;; tap lies on the point or the mark, and the region is
+ ;; active. If that's the case, set the fourth element of
+ ;; `touch-screen-current-tool' to `restart-drag', then
+ ;; generate a `touchscreen-restart-drag' event.
+ (when tool-list
+ ;; tool-list is always non-nil where the selected window
+ ;; matters.
+ (select-window window)
+ (when (and touch-screen-extend-selection
+ (or (eq point (point))
+ (eq point (mark)))
+ (region-active-p))
+ ;; Indicate that a drag is about to restart.
+ (setcar (nthcdr 3 tool-list) 'restart-drag)
+ ;; Generate the `restart-drag' event.
+ (throw 'input-event (list 'touchscreen-restart-drag
+ position))))
+ ;; Determine if there is a command bound to `down-mouse-1'
+ ;; at the position of the tap and that command is not a
+ ;; command whose functionality is replaced by the long-press
+ ;; mechanism. If so, set the fourth element of
+ ;; `touch-screen-current-tool' to `mouse-drag' and generate
+ ;; an emulated `mouse-1' event.
+ ;;
+ ;; If the command in question is a keymap, set that element
+ ;; to `mouse-1-menu' instead of `mouse-drag', and don't
+ ;; generate a `down-mouse-1' event immediately. Instead,
+ ;; wait for the touch point to be released.
+ (if (and tool-list
(and (setq binding
(key-binding (if prefix
(vector prefix
[down-mouse-1])
t nil position))
(not (and (symbolp binding)
- (get binding 'ignored-mouse-command))))))
- (if (or (keymapp binding)
- (and (symbolp binding)
- (get binding 'mouse-1-menu-command)))
- ;; binding is a keymap, or a command that does almost
- ;; the same thing. If a `mouse-1' event is generated
- ;; after the keyboard command loop displays it as a
- ;; menu, that event could cause unwanted commands to
- ;; be run. Set what to `mouse-1-menu' instead and
- ;; wait for the up event to display the menu.
- (setcar (nthcdr 3 touch-screen-current-tool)
- 'mouse-1-menu)
- (progn (setcar (nthcdr 3 touch-screen-current-tool)
- 'mouse-drag)
- (throw 'input-event (list 'down-mouse-1 position))))
- (and point
- ;; Start the long-press timer.
- (touch-screen-handle-timeout nil)))))
+ (get binding 'ignored-mouse-command)))))
+ (if (or (keymapp binding)
+ (and (symbolp binding)
+ (get binding 'mouse-1-menu-command)))
+ ;; binding is a keymap, or a command that does
+ ;; almost the same thing. If a `mouse-1' event is
+ ;; generated after the keyboard command loop
+ ;; displays it as a menu, that event could cause
+ ;; unwanted commands to be run. Set what to
+ ;; `mouse-1-menu' instead and wait for the up event
+ ;; to display the menu.
+ (setcar (nthcdr 3 tool-list) 'mouse-1-menu)
+ (progn (setcar (nthcdr 3 tool-list) 'mouse-drag)
+ (throw 'input-event (list 'down-mouse-1 position))))
+ (and point
+ ;; Start the long-press timer.
+ (touch-screen-handle-timeout nil))))))
((eq (car event) 'touchscreen-update)
(unless touch-screen-current-tool
;; If a stray touchscreen-update event arrives (most likely
where POSN is the position of the long-press or touchpoint
motion,
+ (touchscreen-restart-drag POSN)
+
+where POSN is the position of the tap,
+
(down-mouse-1 POSN)
(drag-mouse-1 POSN)
## lastfile.o on Cygwin and MinGW, empty elsewhere.
POST_ALLOC_OBJ=@POST_ALLOC_OBJ@
-## Builds using libemacs.so (Android) don't dump Emacs within this
-## Makefile, but on device. Make sure the library hash changes for
-## each change in shortlisp by linking an object that changes
-## accordingly to it.
-BUILD_COUNTER_OBJ =
-ifeq ($(XCONFIGURE),android)
-BUILD_COUNTER_OBJ = build-counter.o
-
-# This file is then compiled into build-counter.so
-build-counter.c: $(abs_top_builddir)/src/lisp.mk $(shortlisp)
- $(AM_V_GEN) $(top_srcdir)/build-aux/makecounter.sh $@
-endif
-
## List of object files that make-docfile should not be told about.
otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
- $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS) $(BUILD_COUNTER_OBJ)
+ $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
## All object files linked into temacs. $(VMLIMIT_OBJ) should be first.
## (On MinGW, firstfile.o should be before vm-limit.o.)
## up-to-date. Although since charprop depends on bootstrap-emacs,
## and emacs depends on charprop, in practice this rule was always run
## anyway.
+ifneq ($(XCONFIGURE),android)
$(lispsource)/international/charprop.el: \
FORCE | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
$(MAKE) -C ../admin/unidata all EMACS="../$(bootstrap_exe)"
+endif
## We require charprop.el to exist before ucs-normalize.el is
## byte-compiled, because ucs-normalize.el needs to load 2 uni-*.el files.
include $(old_top_builddir)/ndk-build/ndk-build.mk
top_builddir := $(old_top_builddir)
-libemacs.so: $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(EMACSRES) \
- $(MAKE_PDUMPER_FINGERPRINT) $(NDK_BUILD_SHARED) \
- $(NDK_BUILD_STATIC) $(etc)/DOC
+## Builds using libemacs.so (Android) don't dump Emacs within this
+## Makefile, but on device. Make sure the library hash changes for
+## each change in shortlisp by linking an object that changes
+## accordingly to it.
+BUILD_COUNTER_OBJ = build-counter.o
+
+# This file is then compiled into libemacs.so
+build-counter.c: $(abs_top_builddir)/src/lisp.mk $(lisp)
+ $(AM_V_GEN) $(top_srcdir)/build-aux/makecounter.sh $@
+
+libemacs.so: $(ALLOBJS) $(BUILD_COUNTER_OBJ) $(LIBEGNU_ARCHIVE) \
+ $(EMACSRES) $(MAKE_PDUMPER_FINGERPRINT) \
+ $(NDK_BUILD_SHARED) $(NDK_BUILD_STATIC) $(etc)/DOC
$(AM_V_CCLD)$(CC) -o $@ $(ALL_CFLAGS) $(TEMACS_LDFLAGS) \
$(ANDROID_LDFLAGS) $(LDFLAGS) -shared $(ALLOBJS) \
- $(LIBEGNU_ARCHIVE) $(LIBES)
+ $(BUILD_COUNTER_OBJ) $(LIBEGNU_ARCHIVE) $(LIBES)
$(AM_V_at)$(MAKE_PDUMPER_FINGERPRINT) $@
# There is also a binary named `android-emacs' which simply calls
## To solve the freshness issue, in the past we tried various clever tricks,
## but now that we require GNU make, we can simply specify
## bootstrap-emacs$(EXEEXT) as an order-only prerequisite.
+##
+## bootstrap-emacs doesn't have to be built when cross-compiling
+## libemacs.so for Android, however, as the Lisp files have already
+## been compiled by the top level `src' Makefile.
+ifneq ($(XCONFIGURE),android)
%.elc: %.el | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
@$(MAKE) $(AM_V_NO_PD) -C ../lisp EMACS="$(bootstrap_exe)"\
THEFILE=$< $<c
+endif
ifeq ($(HAVE_NATIVE_COMP):$(NATIVE_DISABLED),yes:)
## The following rules are used only when building a source tarball
fi
endif
+ifneq ($(XCONFIGURE),android)
$(lispsource)/loaddefs.el: | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
$(MAKE) -C ../lisp autoloads EMACS="$(bootstrap_exe)"
+endif
## Dump an Emacs executable named bootstrap-emacs containing the
## files from loadup.el in source form.