17

Blinking is a common practice since the early time of computing, especially for cursors.

However, when I run strace to check their system calls, both a terminal emulator konsole and a shell bash, don't register any kind of timer (through timer_settime()), or interval timer (through setitimer()). Meanwhile, these programs could not use spinlock to wait through a certain time.

Real terminals are capable of doing this, as their controllers can understand the blink escape control sequence. But graphical monitors cannot do these things apparently.

So how do these programs get their text blinking, especially in a graphical environment? Text can also blink in the non-X graphical terminal (like if you press Ctrl+Alt+F2).

How was the blinking terminal cursor invented? This question shows the reason why they were invented, and technical details on how real terminals implement them.

0

2 Answers 2

35

Your question mixes up two concepts: blinking cursor and blinking text.

GNOME Terminal (VTE) had supported blinking cursor for a very long time, and I added blinking text support 5 years ago. Let me share three hopefully interesting details about blinking text support, hoping that you'll like them :)

This is not an answer to your question (I've posted an actual answer separately), this is rather just an additional lateral comment.


One interesting aspect was: when exactly to blink the text?

Should the text blinking speed be tied to the cursor blinking speed, or be a different property? We went with the same speed, hijacking that option. IIRC konsole uses different frequency for the two.

Should multiple terminals with blinking text blink them at the same time? Our conclusion was that yes, they should, otherwise it could be very annoying (as if blinking text wasn't annoying to begin with). When to turn "on" or "off" the text is tied to the system clock.

Blinking the cursor always restarts with a full "on" state after every keypress. Should we keep this behavior? The conclusion was to yes, keep this behavior.

Should the cursor and the text blink synchronously? It's hopefully easy to see that we can't have everything at the same time, one of the possible criteria has to be relaxed. So no, these two aren't synchronized.

This is not the only possible way to answer these questions, but the way we found to make the most sense.


For implementing blinking text support, it doesn't matter when we see the corresponding \e[5m or \e[25m escape sequences. The scrollbar might be set to its nondefault position, showing scrollback contents. Obviously for each cell we need to track all the colors and decorational attributes, including whether to blink that cell. What matters is if there is such a cell inside the current viewport at the moment.

VTE sometimes needs to repaint the entire screen, however, sometimes only a part of the screen (where the contents changed) is repainted.

One of the criteria was: if there's no blinking text in the viewport (as in the vast majority of cases), we shouldn't wake up the terminal every 0.6 or so seconds to do nothing (or worse: repaint the same). This is important to save energy, laptop battery life, etc.

For a long time, I was thinking about a periodic timer. Whenever blinking text is painted, start a periodic timer that kicks in every time the blinking state changes. Then we repaint the screen (ideally only the relevant parts).

But then: How do we know when to stop this periodic timer? For a long time I didn't see a clean, easy answer for this.

Then the penny dropped. Let's not think in periodic timer. Let's install a one-shot timer only, for the moment the currently on-screen blinking text needs to change its state. That repaint, if there's still blinking text in the viewport, will install the next one-shot timer, and so on, until the contents there no longer want to blink. The price for this rock solid and super simple solution is one additional unnecessary repaint at the end that no one cares about (unless you debug or strace, and study those poll() calls in presence of blinking text).


Many people want to see blinking text if that's what the application emits. Many people hate this feature and never want to see blinking text. Presumably, similarly to how the cursor only blinks in the focused terminal, many people would want to see blinking text only in the focused terminal.

However, GNOME Terminal also offers a fourth, unusual option: only blink text in the unfocused windows. This was my idea, the thought process being: blinking is presumably used to draw your attention into something truly unexpected and alarming. In your focused vision this is not necessary and might be distracting (e.g. if you're trying to fix that problem you're alerted of). However, your peripheral vision is much more sensitive to changes, like blinking, rather than just some static alert being printed once.

We don't do analytics in our software, don't send up statistics (it would cause an outrage), so I don't have info about the popularity of these four options, especially if anyone finds this "only when unfocused" option useful.

4
  • For one who strongly dislikes blinking text, this is a very interesting story! Commented Apr 4, 2023 at 21:02
  • 4
    Interesting idea to only show blinking in unfocused windows. I wonder if you could also make the blink amplitude configurable? For example, instead of blinking between 100% foreground and 100% background color, maybe do between 100% foreground and 80% fore + 20% background?
    – G. Sliepen
    Commented Apr 4, 2023 at 22:46
  • 1
    @G.Sliepen Sure it'd be easy to implement that, or even fade in / fade out or alike. The feature was implemented after HTML deprecated and removed blink support, considering it uncool. It was primarily implemented to have complete coverage of the ANSI SGR sequences, and secondarily for the fun and little challenge in its implementation. I didn't want to go any further than a single robust reliable solution, I surely could have but wouldn't want to introduce tons of config parameters for this obscure feature.
    – egmont
    Commented Apr 5, 2023 at 6:14
  • 1
    @G.Sliepen: Many terminals that supported blinking text would have have the brightness of text change, rather than having the text appear and disappear (as on the MDA/CGA) or alternate between regular and reverse video (as on the Apple II series). It's a shame IMHO that personal computers didn't follow that lead.
    – supercat
    Commented Apr 5, 2023 at 20:48
32

I've strace'd gnome-terminal-server, which is the actual process of GNOME Terminal.

When otherwise idle, just blinking the cursor, it resides in a poll(..., 598) or similar kernel call, i.e. a poll() with a slightly shorter than 0.6 second timeout. (GNOME's default for the full blink cycle is 1.2 seconds, therefore 0.6 seconds for each "on" or "off" state. This is shortened by the amount of the actual work it did the last time, like repainting the cursor area.)

This poll() waits until there's activity on one of the given file descriptors, or the timer elapses, or a signal arrives.

This poll() is not implemented "manually", rather VTE (the terminal emulation widget behind GNOME Terminal and quite a few others) registers an event handler in GLib's main loop, and GLib takes care of the actual underlying implementation. It's up to GLib to decide what method to use, e.g. it could use select, or epoll with timerfd, or presumably there are other choices as well.

I see pretty much identical poll() calls when strace'ing konsole, and I suspect most other terminal emulators do something similar, too.

The programs running on the terminal (Bash or other) only output the appropriate escape codes asking for blinking but are not involved in actually making it happen after that. The program printing the escapes might be long gone while the blinking text is still visible on the terminal.

3
  • FWIW, timers in a lot of programming languages like Javascript, Tcl etc. also use this trick of using poll/select timeout parameter to schedule timer events. The language has an event loop anyway, why not use/abuse the free timer that comes with it? I've had the joy/pain of implementing asynchronous programming (including timers) for the Ferite programming language and it was how I did it as well.
    – slebetman
    Commented Apr 5, 2023 at 1:44
  • @slebetman Yup, low level interfaces (such as poll) focus on being simple (i.e. simple to implement in the kernel), stateless, and provide the simplest possible building block that's flexible enough to build upon. In this particular case: you have to tell exactly what you're interested in right now. Higher level interfaces (e.g. JS, GLib's main loop) focus on being simple and convenient to use by app developers, among others by making it stateful, being able to individually register multiple events that you're interested in. Implementing the latter on top of the former is surely joy/pain.
    – egmont
    Commented Apr 5, 2023 at 6:10
  • 1
    I never expected my two answers to receive more than 1 upvote from OP. This is overwhelming, thanks everybody! :)
    – egmont
    Commented Apr 5, 2023 at 6:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .