2

Is it possible to activate a blocking 'scroll' mode that uses the vertical position of the cursor and a timer?

This is handy because you can move the cursor to a certain Y-delta to maintain a fixed scroll speed (In Firefox it's enabled by the "Use autoscrolling" preference).

Since emacs uses this terminology in a different way, it's hard tell if this feature exists for emacs.

ideasman42
  • 8,786
  • 1
  • 32
  • 114
  • Emacs has timers, can scroll and interact with the mouse cursor. That's basically all that's needed if I don't overlook something. I don't know if someone realized and released the functionality you ask for. Possibly you can start the project. – Marco Wahl Jul 08 '19 at 19:29

1 Answers1

2

Update: made this into a more comprehensive scroll-on-drag package.


Here is a simple implementation of modal scrolling.

(defvar modal-scroll--timer nil)
(defvar modal-scroll--delay 0.01)

(defun modal-scroll--up-update (y-init)
  (let ((delta (- (cdr (cdr (mouse-position))) y-init)))
    (ignore-errors (scroll-up delta)))
  (setq modal-scroll--timer
    (run-with-timer modal-scroll--delay nil 'modal-scroll--up-update y-init)))
(defun modal-scroll--down-update (y-init)
  (let ((delta (- y-init (cdr (cdr (mouse-position))))))
    (ignore-errors (scroll-down delta)))
  (setq modal-scroll--timer
    (run-with-timer modal-scroll--delay nil 'modal-scroll--down-update y-init)))


(defun modal-scroll-stop--internal ()
  (when modal-scroll--timer
    (cancel-timer modal-scroll--timer)
    (setq modal-scroll--timer nil)
    )
  )

(defun modal-scroll-drag () ""
  (interactive)
  (when modal-scroll--timer
    (modal-scroll-stop--internal))

  (let
    (
      (y-init (cdr (cdr (mouse-position))))
      (delta-prev 0)
      )

    (track-mouse
      (while
        (progn (setq event  (read-event))
          (or
            (mouse-movement-p event)
            (memq (car-safe event) '(switch-frame select-window)))
          )
        (unless (memq (car-safe event) '(switch-frame select-window))
          (let ((delta (- (cdr (cdr (mouse-position))) y-init)))
            (cond
              ((> delta 0)
                (unless (> delta delta-prev 0)
                  (modal-scroll-stop--internal)
                  (setq modal-scroll--timer
                    (run-with-timer 0.0 nil 'modal-scroll--up-update y-init))))
              ((< delta 0)
                (unless (< delta-prev 0)
                  (modal-scroll-stop--internal)
                  (setq modal-scroll--timer
                    (run-with-timer 0.0 nil 'modal-scroll--down-update y-init))))
              ((eq delta 0)
                (modal-scroll-stop--internal))
              )
            (setq delta-prev delta)
            )
          )
        )
      (modal-scroll-stop--internal)
      )
    )
  )

(global-set-key [mouse-2] 'modal-scroll-drag)

Note that I didn't figure out how to make this co-exist with click events (so click events can be triggered as well as drag). See How to handle & differentiate both click & drag mouse button events?

ideasman42
  • 8,786
  • 1
  • 32
  • 114