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

From: Tassilo Horn <[email-masked]>
Date: Fri, 10 Apr 2015 15:13:49 +0200

Eli Zaretskii <[email-masked]> writes:

>> 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.
>
> But "was redisplay performed?" does not have a simple yes/no answer.
> Depending on the circumstances, the display engine can decide to
> redisplay one or more windows on one or more frames.  By contrast, you
> (in this case) are only interested in the selected window on the
> selected frame.  So I don't think a simple counter will cut it; you
> might need a counter per window or some such.  And other use cases
> might want something even more fine-granular, perhaps.

In the blink-cursor-mode case, only selected window of the selected
frame is of interest because only there the cursor blinks, and I assume
that the selected window is probably preferred by redisplay, no?  But
you are right that this might very well depend on the use-case.

>> 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))
>
> What happens if the blink-cursor timer doesn't get run?

Then you are out of luck.

>> 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.
>
> If it started with the cursor visible, yes.  But what if the heavy
> processing started with the cursor blinked off, and the timer function
> didn't get to run for a long time?

Again, you are out of luck then.

But I just verified that the timer function runs pretty regularly.  It
might not always be exactly 0.5 seconds between the runs but it's never
deferred for a time which would be clearly observable by a user.

In contrast, it's not seldom that redisplay doesn't happen for up to 10
seconds when emacs is idle but doing heavy processing in the background.
I can easily provoke that situation by compiling a large TeX document
with AUCTeX which puts the tex output in a buffer and has a process
filter on it.

Bye,
Tassilo