2

I was looking for a replacement to scroll-up / scroll-down that operates in pixel units.

  • pixel-scroll-mode animates the scroll, I didn't see any functions that apply an offset directly.
  • set-window-vscroll

    • Uses absolute position.
    • It needs the scroll to be split into pixels & characters
    • It doesn't handle moving the cursor.
    • Moving the cursor afterwards resets the scroll position.

    So it seems like it's lower level than a scroll operation.

Is there a function where you can run:

(scroll-down-by-pixels 40)

To scroll which handles constraining the point by scroll margin for eg?

0

How about (require 'pixel-scroll) and then use pixel-scroll-pixel-up ("Scroll text of selected windows up AMT pixels.") and pixel-scroll-pixel-down ("Scroll text of selected windows down AMT pixels.")?

  • This doesn't clamp the cursor position like regular scroll does (when scrolling up, down works), testing, sometimes it resets the scroll location in a strange way too - maybe related to the cursor being out of the view. – ideasman42 Jul 13 at 2:42
  • Perhaps you might be interested in centered-cursor-mode: github.com/emacsmirror/centered-cursor-mode – lawlist Jul 13 at 2:46
  • I'm writing my own mode, so depending on another mode just to clamp the cursor seems overkill. I would like to have the behavior of scroll up/down, just with pixel offsets. – ideasman42 Jul 13 at 2:52
0

There are some constraints on pixel scrolling.

  • You can't use scroll-up as it tags the window to reset the pixel scrolling value.
  • Instead you need to use set-window-start, with the 3rd NOFORCE argument to t.
  • This complicates things because the point then needs to be moved before the window, since, unlike scroll, setting the window-start doesn't move the point to stay in the window bounds.

Here is a function that handles all this.

;; Per-line Scroll.
;; return remainder of lines to scroll (matching forward-line).
(defun my-scroll-by-lines (window lines also-move-point)
  "Line based scroll that optionally move the point.
Argument WINDOW The window to scroll.
Argument LINES The number of lines to scroll (signed).
Argument ALSO-MOVE-POINT When non-nil, move the POINT as well."
  (let ((lines-remainder 0))
    (when also-move-point
      (let ((lines-point-remainder (forward-line lines)))
        (unless (eq 0 lines-point-remainder)
          (setq lines (- lines lines-point-remainder)))))
    (unless (eq 0 lines)
      (set-window-start
        window
        (save-excursion
          (goto-char (window-start))
          (setq lines-remainder (forward-line lines))
          (point))
        t)
      (when also-move-point
        (unless (eq 0 lines-remainder)
          (forward-line (- lines-remainder)))))
    lines-remainder))

;; Per-pixel Scroll.
;; return remainder of lines to scroll (matching forward-line).
(defun my-scroll-by-pixels (window char-height delta-px also-move-point)
  "Line based scroll that optionally move the point.
Argument WINDOW The window to scroll.
Argument CHAR-HEIGHT The result of `frame-char-height'.
Argument DELTA-PX The number of pixels to scroll (signed).
Argument ALSO-MOVE-POINT When non-nil, move the POINT as well."
  (cond
    ((< delta-px 0)
      (let*
        (
          (scroll-px-prev (- char-height (window-vscroll nil t))) ;; flip.
          (scroll-px-next (+ scroll-px-prev (- delta-px))) ;; flip.
          (lines (/ scroll-px-next char-height))
          (scroll-px (- scroll-px-next (* lines char-height)))
          (lines-remainder 0))
        (unless (eq 0 lines)
          (setq lines-remainder
            (- (my-scroll-by-lines window (- lines) also-move-point))) ;; flip
          (unless (eq 0 lines-remainder)
            (setq scroll-px char-height)))
        (set-window-vscroll window (- char-height scroll-px) t)
        (- lines-remainder)))
    ((> delta-px 0)
      (let*
        (
          (scroll-px-prev (window-vscroll nil t))
          (scroll-px-next (+ scroll-px-prev delta-px))
          (lines (/ scroll-px-next char-height))
          (scroll-px (- scroll-px-next (* lines char-height)))
          (lines-remainder 0))
        (unless (eq 0 lines)
          (setq lines-remainder
            (my-scroll-by-lines window lines also-move-point))
          (unless (eq 0 lines-remainder)
            (setq scroll-px char-height)))
        (set-window-vscroll window scroll-px t)
        lines-remainder))
    ;; no lines scrolled.
    (t 0)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.