Opening curses-based program disables cursor blinking #218

Closed
opened 11 months ago by ofiala · 4 comments
ofiala commented 11 months ago

When you launch any ncurses-based program, it seems that the library disables cursor blink and it isn't re-enabled even upon the program exit. The only way to re-enable the blinking is either by closing foot or by using the relevant escape sequences I've actually tried this with a few variations and it somehow doesn't work, so I am either doing something wrong or foot doesn't handle cursor escape sequences correctly.

Whether the bug is the disabled blinking in curses, or the absence of re-enabling it after exit from curses is up for discussion. For example mate-terminal's cursor blinks even in curses.

When you launch any ncurses-based program, it seems that the library disables cursor blink and it isn't re-enabled even upon the program exit. The only way to re-enable the blinking is either by closing foot ~~or by using the relevant escape sequences~~ *I've actually tried this with a few variations and it somehow doesn't work, so I am either doing something wrong or foot doesn't handle cursor escape sequences correctly.* Whether the bug is the disabled blinking in curses, or the absence of re-enabling it after exit from curses is up for discussion. For example mate-terminal's cursor blinks even in curses.
Owner

First, the easy part :)

You should be able to restore the default (i.e. cursor settings from foot.ini) with echo -e '\e[ q' (the space is mandatory).

Before we get into why this is happening, let me describe how a blinking cursor is handled in foot.

First of all, there are two different escape sequences that will enable/disable blinking: \e[?12l/\e[?12h and \e[X q' (where X is a number between 0 and 6.

In ctrlseq, \e[0 q (or \e[ q for short) is described to have the exact same semantics as \e[1 q, but foot instead treats 0 to mean "reset to the configuration defaults".

The first two sequences, \e[?12l/h only controls blinking.

The second one, \e[X q, controls both the cursor shape, and blinking (if the least significant bit is set, the cursor blinks, otherwise it does not).

Internally, foot has a single bit that indicates whether the cursor should blink or not. Both the above sequences change this bit. This means you can e.g. enable blinking with \e[1 q] and then disable blinking with \e[?12l.

Setting blink=yes in foot.ini sets the default value of the same bit.

I believe what happens depends on which program you are running. But most likely, the terminfo entries civis (cursor invisible), cnorm (cursor normal) and cvvis (cursor very visible) are to blame here.

In foot, these three terminfo entries are defined as follows:

  • civis=\e[?25l
  • cnorm=\e[?12l\e[?25h
  • cvvis=\e[?12;25h

\e[25l/h hides/shows the cursor. So, if we translate the above to plain english, we have:

  • civis: hide cursor (do not change blink mode)
  • cnorm: show cursor, disable blinking
  • cvvis: show cursor, enable blinking

Note than none of them change the shape of the cursor.

When I tested nmcpcpp it emitted civis on start, and cnorm on exit, thus disabling blinking.

For what it's worth, XTerm behaves identical.

There are a couple of things that can be done here, none more right than the other. But, if I am to decide on one solution that I think works ok for most people, it would be this:

  • Split the internal blink state into two: one controlled by \e[?12X, and one by \e[X q.
  • If one of the two are enabled, the cursor blinks. Only when both are disabled do we disable blinking.
  • blink=yes in foot.ini sets the default value of the state/variable controlled by \e[X q.

Doing this means:

civis et al can be used as intented.

Applications can still use \e[X q to override all aspects of the cursor. If they are correctly written, they will emit the Se terminfo sequence at exit, which in foot is defined to \e[ q - reset to the configuration defaults.

Thoughts?

First, the easy part :) You should be able to restore the default (i.e. cursor settings from `foot.ini`) with `echo -e '\e[ q'` (the <kbd>space</kbd> is **mandatory**). Before we get into why this is happening, let me describe how a blinking cursor is handled in foot. First of all, there are **two** different escape sequences that will enable/disable blinking: `\e[?12l`/`\e[?12h` and `\e[X q'` (where X is a number between 0 and 6. In [ctrlseq](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_), `\e[0 q` (or `\e[ q` for short) is described to have the exact same semantics as `\e[1 q`, but foot instead treats `0` to mean _"reset to the configuration defaults_". The first two sequences, `\e[?12l/h` **only** controls blinking. The second one, `\e[X q`, controls **both** the cursor shape, and blinking (if the least significant bit is set, the cursor blinks, otherwise it does not). Internally, foot has a single bit that indicates whether the cursor should blink or not. **Both** the above sequences change this bit. This means you can e.g. enable blinking with `\e[1 q]` and then disable blinking with `\e[?12l`. Setting `blink=yes` in `foot.ini` sets the default value of the **same** bit. I believe what happens depends on which program you are running. But most likely, the terminfo entries `civis` (cursor invisible), `cnorm` (cursor normal) and `cvvis` (cursor very visible) are to blame here. In foot, these three terminfo entries are defined as follows: * `civis=\e[?25l` * `cnorm=\e[?12l\e[?25h` * `cvvis=\e[?12;25h` `\e[25l/h` hides/shows the cursor. So, if we translate the above to plain english, we have: * `civis`: hide cursor (do **not** change blink mode) * `cnorm`: show cursor, **disable** blinking * `cvvis`: show cursor, **enable** blinking Note than none of them change the _shape_ of the cursor. When I tested _nmcpcpp_ it emitted `civis` on start, and `cnorm` on exit, thus disabling blinking. For what it's worth, XTerm behaves identical. There are a couple of things that can be done here, none more right than the other. But, if I am to decide on one solution that I think works ok for most people, it would be this: * Split the internal blink state into two: one controlled by `\e[?12X`, and one by `\e[X q`. * If **one** of the two are enabled, the cursor blinks. Only when **both** are disabled do we disable blinking. * `blink=yes` in `foot.ini` sets the **default** value of the state/variable controlled by `\e[X q`. Doing this means: `civis` et al can be used as intented. Applications can still use `\e[X q` to override **all** aspects of the cursor. If they are correctly written, they will emit the `Se` terminfo sequence at exit, which in foot is defined to `\e[ q` - reset to the configuration defaults. Thoughts?
Poster

Seems like a good solution :)

Seems like a good solution :)
dnkl referenced this issue from a commit 11 months ago
term: split cursor blink state into two There are two different escape sequences that can be used to set the cursor blink state: ‘CSI ? 12 h/l’ and ‘CSI Ps SP q’. Up until now, they both modified the same internal state in foot. This meant you could enable a blinking cursor with e.g. ‘CSI ? 12 h’ and then disable it with ‘CSI 2 SP q’. Since the ‘CSI ? 12’ escapes are used in the civis/cnorm/cvvis terminfo entries, applications often ended up disabling the blink state on exit (typically be emitting ‘cnorm’), requiring users to manually re-enable blinking. By splitting the internal state into two separate states, we can improve the situation. The cursor will blink if at least one of the two have been enabled. The setting in foot.ini sets the default state of the ‘CSI Ps SP q’ escape. This means if the user has enabled blinking in the configuration, the cursor will blink regardless of civis/cnorm/cvvis. Which probably is what the user wants. If the user has NOT enabled blinking, civis/cnorm/cvvis act as intended: cvvis blink, civis and cnorm do not. If an application overrides the cursor blink/style with ‘CSI Ps SP q’, that will override the user’s setting in foot.ini. But most likely that too is intended (for example, the user may have configured the application to use a different cursor style). And, a well written application will emit the ‘Se’ terminfo sequence on exit, which in foot is defined to ‘CSI SP q’, which will reset both the style and blink state to the user configured style/state. Closes #218
Owner

Note that this solution would mean the cursor does not stop blinking when the application is started (nor when it exits), unless the application also emits a \e[X q escape to explicitly set the cursor style.

Note that this solution would mean the cursor does **not** stop blinking when the application is started (nor when it exits), _unless_ the application **also** emits a `\e[X q` escape to explicitly set the cursor style.
Poster

Yes, I am aware of this and that's imo how it should be considering most programs that do not disable the cursor use it for normal text input (so there is no reason for it to not blink if blinking is enabled in foot.ini unless the program specifically requests to turn it off).

Yes, I am aware of this and that's imo how it should be considering most programs that do not disable the cursor use it for normal text input (so there is no reason for it to not blink if blinking is enabled in foot.ini unless the program specifically requests to turn it off).
dnkl closed this issue 11 months ago
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.