-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Cursor hiding #11
Comments
;;; hide-cursor.el --- Hide cursor when scrolling -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(defvar-local hide-cursor--timer nil)
(defvar-local hide-cursor--undo nil)
(defun hide-cursor--undo (buf)
(when (buffer-live-p buf)
(with-current-buffer buf
(when-let ((win (get-buffer-window buf)))
(with-selected-window win
(goto-char (/ (+ (window-start) (window-end nil t)) 2))
(beginning-of-line)))
(mapc #'funcall hide-cursor--undo)
(kill-local-variable 'hide-cursor--timer)
(kill-local-variable 'hide-cursor--undo))))
(defun hide-cursor (&rest _)
(unless hide-cursor--timer
(setq hide-cursor--timer (timer-create))
(timer-set-function hide-cursor--timer #'hide-cursor--undo (list (current-buffer))))
(cancel-timer hide-cursor--timer)
(timer-set-time hide-cursor--timer (timer-relative-time nil 0.3))
(timer-activate hide-cursor--timer)
(when (and (not hide-cursor--undo)
(or (save-excursion (forward-line -1) (<= (point) (window-start)))
(save-excursion (forward-line 2) (>= (point) (window-end nil t)))))
(when-let ((ov (bound-and-true-p hl-line-overlay)))
(overlay-put ov 'face nil)
(push 'hl-line-highlight hide-cursor--undo)
(push 'hl-line-unhighlight hide-cursor--undo))
(push (if (local-variable-p 'cursor-type)
(let ((orig cursor-type))
(lambda () (setq-local cursor-type orig)))
(lambda () (kill-local-variable 'cursor-type)))
hide-cursor--undo)
(setq-local cursor-type nil)))
(defun hide-cursor--window (event)
(with-selected-window (mwheel-event-window event)
(hide-cursor)))
;;;###autoload
(defun hide-cursor-setup ()
(advice-add #'pixel-scroll-precision-scroll-down-page :after #'hide-cursor)
(advice-add #'pixel-scroll-precision-scroll-up-page :after #'hide-cursor)
(advice-add 'ultra-scroll :after #'hide-cursor--window))
(provide 'hide-cursor)
;;; hide-cursor.el ends here |
I think that should be possible. After all the cursor position is just a detail (an important detail for image scrolling). I think I can do this with either I worry a bit about an idle timer not running and your cursor "going missing" after a scroll. I'm already using an idle timer to lift GC percentage, but that's not user-visible. Thoughts? |
I think using a timer is even nicer than immediately showing the cursor and hl-line again, since this leads to some debouncing effect. The cursor will only appear when you're really finished with scrolling. I quite like the effect. Please try it. The whole feature can also be disabled via a customization variable, which configures the delay.
I use a normal timer so there is no risk that this will go missing. I have a check in place which make sure that the buffer is still alive. See my PR #15. |
I wonder if we should even add the hide cursor functionality here. Maybe it is just better as a simple mode which could even be added upstream, augmenting ;;; hide-cursor.el --- Hide cursor when scrolling -*- lexical-binding: t -*-
;; Copyright (C) 2025 Daniel Mendler
;; Author: Daniel Mendler <[email protected]>
;; Version: 0.1
;; Package-Requires: ((emacs "29.1"))
;; SPDX-License-Identifier: GPL-3.0-or-later
;; URL: https://github.com/minad
;;; Commentary:
;; Provides the small mode `hide-cursor-mode' which hides the cursor when
;; scrolling. Can be used together with `pixel-scroll-precision-mode'.
;;; Code:
(defvar-local hide-cursor--timer nil)
(defvar-local hide-cursor--undo nil)
(defvar-local hide-cursor--start nil)
(defun hide-cursor--undo (buf)
"Undo cursor hiding in BUF."
(when (buffer-live-p buf)
(with-current-buffer buf
(when-let ((win (get-buffer-window buf)))
(with-selected-window win
;; Check for tall image at point, do not recenter.
(unless (get-char-property (point) 'display)
(goto-char (/ (+ (window-start) (window-end nil t)) 2))
(beginning-of-line))))
(mapc #'funcall hide-cursor--undo)
(kill-local-variable 'hide-cursor--start)
(kill-local-variable 'hide-cursor--timer)
(kill-local-variable 'hide-cursor--undo))))
(defun hide-cursor--adv (&rest _)
"Hide cursor in after scrolling advice."
(unless hide-cursor--timer
(setq hide-cursor--start (point)
hide-cursor--timer (timer-create))
(timer-set-function hide-cursor--timer #'hide-cursor--undo (list (current-buffer))))
(cancel-timer hide-cursor--timer)
(timer-set-time hide-cursor--timer (timer-relative-time nil 0.3))
(timer-activate hide-cursor--timer)
(unless (or hide-cursor--undo (equal hide-cursor--start (point)))
(when (bound-and-true-p hl-line-mode)
(hl-line-mode -1)
(push 'hl-line-mode hide-cursor--undo))
(when cursor-type
(push (if (local-variable-p 'cursor-type)
(let ((orig cursor-type))
(lambda () (setq-local cursor-type orig)))
(lambda () (kill-local-variable 'cursor-type)))
hide-cursor--undo)
(setq-local cursor-type nil))))
;;;###autoload
(define-minor-mode hide-cursor-mode
"Hide cursor while scrolling."
:global t :group 'scrolling
(cond
(hide-cursor-mode
(advice-add #'pixel-scroll-precision-scroll-down-page :after #'hide-cursor--adv)
(advice-add #'pixel-scroll-precision-scroll-up-page :after #'hide-cursor--adv))
(t
(advice-remove #'pixel-scroll-precision-scroll-down-page #'hide-cursor--adv)
(advice-remove #'pixel-scroll-precision-scroll-up-page #'hide-cursor--adv))))
(provide 'hide-cursor)
;;; hide-cursor.el ends here |
I could see definitely the argument to keep this as a separate mode (which of course I'd be happy to link to). I hate long-lived advice, but after-advice is pretty darn safe. I don't know if the logic of "cache point, and if it moves, start hiding" will work for all (touch)scrolling packages, but it might! Now that you've planted to seed, I think I may prefer it as a separate mode. |
I find the jumping cursor at the window top or bottom slightly annoying when scrolling. Have you considered hiding the cursor (and also the hl-line overlay) as soon as the cursor hits the top/bottom of the window, until scrolling is finished?
The text was updated successfully, but these errors were encountered: