I am using this minor mode to scroll and keep cursor on same line, mwheel-scroll however screws up the smooth scroll since it moves the cursor to a different line, scrolling return the cursor back to original line but the visual is not smooth.

I tried:

scroll-preserve-screen-position 'always

But that didn't help.

This is the minor mode I am using:

(define-minor-mode centered-point-mode
  "Always center the cursor in the 1/3rd of the screen."
  :lighter "..."
  (cond (centered-point-mode (add-hook 'post-command-hook 'line-change))
    (t (remove-hook 'post-command-hook 'line-change))))

(setq recenter-positions '(0.35))
(defun line-change ()
  (unless (memq this-command '(mwheel-scroll mac-mwheel-scroll)) 

(define-globalized-minor-mode my-global-centered-point-mode centered-point-mode
  (lambda () (centered-point-mode 1)))
(my-global-centered-point-mode 1)

1 Answer 1


If you add the built-in scroll-lock-mode to your code, you should get behavior like what you want.

Here's a slightly more-expansive update to your mode that fixes two other issues I found (the buffer-local version works normally and it doesn't change recenter-positions globally). Following your comments, I've also updated it not to rely directly on scroll-lock-mode, so it doesn't add any key bindings.

(defcustom centered-point-position 0.35
  "Percentage of screen where `centered-point-mode' keeps point."
  :type 'float)

(setq centered-point--preserve-pos nil)

(define-minor-mode centered-point-mode
  "Keep the cursor at `centered-point-position' in the window"
  :lighter " centerpoint"
  (cond (centered-point-mode (add-hook 'post-command-hook 'center-point nil t)
                             (setq centered-point--preserve-pos
                             (setq-local scroll-preserve-screen-position 'all))
        (t (remove-hook 'post-command-hook 'center-point t)
           (setq-local scroll-preserve-screen-position

(defun center-point ()
  "Move point to the line at `centered-point-position'."
  (when (eq (current-buffer) (window-buffer))
    (let ((recenter-positions (list centered-point-position)))

(defun centered-point-mode-on ()
  (centered-point-mode 1))

(define-globalized-minor-mode global-centered-point-mode centered-point-mode

Then use (global-centered-point-mode 1) to enable the mode globally.

centered-mouse-mode seems to provide this functionality, so you might want to take a look at that as well.

  • I came across another problem. I use Ivy and when searching and trying to go through match candidates in the minibuffer C-n is now mapped to scroll-lock-next-line which doesnt move the cursor to the next line. Where when disabling the mode C-n is mapped to ivy-next-line. How to fix that?
    – SFbay007
    Jan 7, 2020 at 1:38
  • 1
    I've updated my answer again. Instead of using scroll-lock-mode, it now uses the same variable that mode does, so it doesn't use scroll-lock-mode-map, and no keys are rebound at all.
    – jirassimok
    Jan 7, 2020 at 20:34
  • jirassimok, Your implementation has been going strong and no issues. But today I decided to use my macbook and found that the laptop mouse scrolling doesn't work properly. I have the scrolling on the mouse mapped to mac-mwheel-scroll. Is it possible to have that fixed? Much appreciation.
    – SFbay007
    Jan 10, 2020 at 22:35
  • You think I should go back to doing this: (unless (memq this-command '(mwheel-scroll mac-mwheel-scroll)) ? I feel this would not be efficient.
    – SFbay007
    Jan 12, 2020 at 5:35
  • I don't have mac-mwheel-scroll. If you're having problems with that, I recommend asking a new question so someone else can help you. The simplest solution is probably to just rebind the scroll "keys" to the commands you want.
    – jirassimok
    Jan 13, 2020 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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