Function: touch-screen-hold

touch-screen-hold is an autoloaded, interactive and byte-compiled function defined in touch-screen.el.gz.

Signature

(touch-screen-hold EVENT)

Documentation

Handle a long press EVENT.

Ding and select the window at EVENT, then activate the mark. If touch-screen-word-select is enabled, try to select the whole word around EVENT; otherwise, set point to the location of EVENT.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/touch-screen.el.gz
;;; Drag-to-select gesture.

;;;###autoload
(defun touch-screen-hold (event)
  "Handle a long press EVENT.
Ding and select the window at EVENT, then activate the mark.  If
`touch-screen-word-select' is enabled, try to select the whole
word around EVENT; otherwise, set point to the location of EVENT."
  (interactive "e")
  (let* ((posn (cadr event))
         (point (posn-point posn))
         (window (posn-window posn)))
    (when (and point
               ;; Make sure WINDOW is not an inactive minibuffer
               ;; window.
               (or (not (eq window
                            (minibuffer-window
                             (window-frame window))))
                   (minibuffer-window-active-p window)))
      (beep)
      (select-window window)
      (if (or (not touch-screen-word-select)
              (when-let* ((char (char-after point))
                          (class (char-syntax char)))
                ;; Don't select words if point isn't inside a word
                ;; constituent or similar.
                (not (or (eq class ?w) (eq class ?_)))))
          (progn
            ;; Set the mark and activate it.
            (setq touch-screen-word-select-initial-word nil
                  touch-screen-word-select-bounds nil)
            (push-mark point)
            (goto-char point)
            (activate-mark)
            (setq deactivate-mark nil))
        ;; Start word selection by trying to obtain the position
        ;; around point.
        (let ((word-start nil)
              (word-end nil))
          (unless (posn-object posn)
            ;; If there's an object under POSN avoid trying to
            ;; ascertain the bounds of the word surrounding it.
            (save-excursion
              (goto-char point)
              (forward-word-strictly)
              ;; Set word-end to ZV if there is no word after this
              ;; one.
              (setq word-end (point))
              ;; Now try to move backwards.  Set word-start to BEGV if
              ;; this word is there.
              (backward-word-strictly)
              (setq word-start (point))))
          ;; Check if word-start and word-end are identical, if there
          ;; is an object under POSN, or if point is looking at or
          ;; outside a word.
          (if (or (eq word-start word-end)
                  (>= word-start point))
              (progn
                ;; If so, clear the bounds and set and activate the
                ;; mark.
                (setq touch-screen-word-select-bounds nil
                      touch-screen-word-select-initial-word nil)
                (push-mark point)
                (goto-char point)
                (activate-mark)
                (setq deactivate-mark nil))
            ;; Otherwise, select the word.  Move point to either the
            ;; end or the start of the word, depending on which is
            ;; closer to EVENT.
            (let ((diff-beg (- point word-start))
                  (diff-end (- word-end point))
                  use-end)
              (if (> diff-beg diff-end)
                  ;; Set the point to the end of the word.
                  (setq use-end t)
                (if (< diff-end diff-beg)
                    (setq use-end nil)
                  ;; POINT is in the middle of the word.  Use its
                  ;; window coordinates to establish whether or not it
                  ;; is closer to the start of the word or to the end
                  ;; of the word.
                  (let ((posn-beg (posn-at-point word-start))
                        (posn-end (posn-at-point word-end)))
                    ;; Give up if there's an object at either of those
                    ;; positions, or they're not on the same row.
                    ;; If one of the positions isn't visible, use the
                    ;; window end.
                    (if (and posn-beg posn-end
                             (not (posn-object posn-beg))
                             (not (posn-object posn-end))
                             (eq (cdr (posn-col-row posn-beg))
                                 (cdr (posn-col-row posn-end))))
                        (setq use-end nil)
                      ;; Compare the pixel positions.
                      (setq point (car (posn-x-y posn))
                            diff-beg (- point (car (posn-x-y posn-beg)))
                            diff-end (- (car (posn-x-y posn-end)) point))
                      ;; Now determine whether or not point should be
                      ;; moved to the end.
                      (setq use-end (>= diff-beg diff-end))))))
              (if use-end
                  (progn
                    (push-mark word-start)
                    (activate-mark)
                    (setq deactivate-mark nil)
                    (goto-char word-end))
                (progn
                    (push-mark word-end)
                    (activate-mark)
                    (setq deactivate-mark nil)
                    (goto-char word-start)))
              ;; Record the bounds of the selected word.
              (setq touch-screen-word-select-bounds
                    (cons word-start word-end)
                    ;; Save this for the benefit of touch-screen-drag.
                    touch-screen-word-select-initial-word
                    (cons word-start word-end)))))))))