Subject: Re: bug#20285: 25.0.50; blink-cursor-mode sometimes stops blinking

From: Tassilo Horn <[email-masked]>
Date: Fri, 10 Apr 2015 11:28:52 +0200

Eli Zaretskii <[email-masked]> writes:

>> Is it documented somewhere what the individual entries of these vectors
>> mean?
>
> You mean, the structure of a timer object?  You will see that clearly
> near the beginning of timer.el.

Thanks.

>> But anyway, I think even when there's some timer that takes too long,
>> the cursor should never disappear completely.  So maybe a redisplay
>> should be forced whenever the cursor is set to visible again and
>> there has been a redisplay when the cursor has been invisible.
>
> I don't quite understand your idea.  Please keep in mind that there
> are 2 meanings to "cursor is [set to] visible": the internal Emacs
> information about whether the cursor is on or off, and what's actually
> on the glass.  The latter is only changed by redisplay.
>
> With that in mind, can you explain in more detail what you meant?

I think that it should be generically possible from Lisp to check if a
redisplay has been performed within a given time frame.  That might be
useful for other stuff next to `blink-cursor-mode', too.

That could be achieved by `redisplay' increasing some integer
redisplay_counter variable whose value can be accessed from Lisp.

Then `blink-cursor-timer-function' could check if the invisibility of
the cursor has really been manifested (on the glass) and force a
redisplay when toggling it visible again.

--8<---------------cut here---------------start------------->8---
(defvar blink-cursor-redisplay-counter nil)

(defun blink-cursor-timer-function ()
  "Timer function of timer `blink-cursor-timer'."
  (let ((cursor-shown (internal-show-cursor-p)))
    (internal-show-cursor nil (not cursor-shown))
    ;; If the cursor was invisible in the last cycle and a redisplay has been
    ;; performed there, ensure a redisplay now so that it won't end up
    ;; invisible for an indefinite amount of time.
    (unless (or cursor-shown
		(= blink-cursor-redisplay-counter
		   redisplay-counter))
      (redisplay 'force))
    (setq blink-cursor-redisplay-counter redisplay-counter))
  ;; Suspend counting blinks when the w32 menu-bar menu is displayed,
  ;; since otherwise menu tooltips will behave erratically.
  (or (and (fboundp 'w32--menu-bar-in-use)
	   (w32--menu-bar-in-use))
      (setq blink-cursor-blinks-done (1+ blink-cursor-blinks-done)))
  ;; Each blink is two calls to this function.
  (when (and (> blink-cursor-blinks 0)
             (<= (* 2 blink-cursor-blinks) blink-cursor-blinks-done))
    (blink-cursor-suspend)
    (add-hook 'post-command-hook 'blink-cursor-check)))
--8<---------------cut here---------------end--------------->8---

The effect would be that if a timer running too long or processing input
stops the blinking of the cursor, that would at happen at least in the
visible cursor state.

Bye,
Tassilo