Skip to content

Support both software and hardware block cursors (v2) - #16163

Open
marcv81 wants to merge 6 commits into
helix-editor:masterfrom
marcv81:hardware-block-cursor-v2
Open

Support both software and hardware block cursors (v2)#16163
marcv81 wants to merge 6 commits into
helix-editor:masterfrom
marcv81:hardware-block-cursor-v2

Conversation

@marcv81

@marcv81 marcv81 commented Aug 9, 2026

Copy link
Copy Markdown

This PR builds upon #16151. Additionally the software block cursor no longer uses any hardware cursor anywhere, which fixes the visual artifacts with Kitty/Ghostty cursor trails.

Side effect: there is no longer any cursor effect when the terminal emulator loses focus. This is the only way to avoid visual artifacts.

marcv81 added 5 commits August 2, 2026 17:46
The default cursor shape now has a single source of truth and cannot
drift from the enum's default in the future.
The code path for the software block cursor remains unchanged.

To implement the hardware block cursor, we simply keep the terminal
cursor visible instead of hiding it.

We draw the hardware block cursor on top of the software cursor, not
instead of it. This means we unconditionally draw the software cursor
without worrying where the hardware cursor will be, which greatly
simplifies the code.

The hardware block cursor is not themed. For best results, users
should select a theme with primary cursor colors matching their
terminal cursor colors.
No need to call show_cursor(). terminal.restore() already resets the
cursor to the terminal default style and visibility.
Moved the cursor position calculation to a cusor_position() helper.
Before this change, we used a software cursor in the editor, and a
hardware cursor in prompts. We now use a software cursor everywhere,
which fixes visual artifacts with Kitty/Ghostty cursor trails.

Since we should no longer draw the BlockSoftware cursor anywhere,
attempting to do so now panics.

Side effect: there is no longer any cursor effect when the terminal
emulator loses focus. This is the only way to avoid visual artifacts.
@marcv81 marcv81 changed the title Hardware block cursor v2 Support both software and hardware block cursors (v2) Aug 9, 2026
@dmyyy dmyyy mentioned this pull request Aug 10, 2026
@senekor

senekor commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Reporting the same bug here as on #16159: The hardware cursor doesn't get the color of the theme. For light themes, that makes the cursor invisible (white on white background). I don't know if there's a way for TUIs to set the color of a hardware cursor.

@senekor

senekor commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Ghostty supports OSC 12, which can be used to set the hardware cursor color. That should fix the problem. It might be worth investigating a little how well OSC 12 is supported in the ecosystem. It might also be fine to mention this in the docs of the configuration. People who use terminal emulators that don't support this should just be aware / not use this config.

@waddie

waddie commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

I don’t think “hardware” cursor is the right terminology here. The existing comments in editor.rs refer to it as the terminal cursor.

@waddie

waddie commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Ghostty supports OSC 12, which can be used to set the hardware cursor color. That should fix the problem.

I don’t think it does, quite: OSC 12 only sets the cursor fill/stroke colour. You would really need to set the cursor text at the same time for that to be reliably legible.

kitty added OSC 21 to solve that, I think Ghostty supports it. iTerm has OSC 1337 / SetColors instead. WezTerm has OSC 1337, but only for SetUserVar, not SetColors. I don’t think you can do it at all in xterm.

OSC 12/21/1337 are all queryable if they exist, so I guess you could do that for capability detection. But based on admittedly <1hr of research, it doesn’t look there’s much in the way of broad/standardised support.

I think theming is a separate issue though. bar/underline cursors already have the same problem.

@marcv81

marcv81 commented Aug 11, 2026

Copy link
Copy Markdown
Author

I am aware that the cursor does not follow the theme. I left a note in one of the commit messages. Thanks for the thorough review in any case 🙏

The hardware block cursor is not themed. For best results, users
should select a theme with primary cursor colors matching their
terminal cursor colors.

I have a proof-of-concept to improve the situation. It relies on OSC 12. It does not work perfectly, there are corner cases for dimmed code sections (e.g. unreachable code). It was legible with all the themes I tried it with. It is not ready for submission yet, and I was thinking about sharing it as a separate PR.

I don’t think “hardware” cursor is the right terminology here.

@waddie, I read both "hardware" and "terminal" in external sources. I am happy to change this, but could you please confirm this is what we want? Do we call it BlockTerminal / block-terminal, or TerminalBlock / terminal-block? I just want to avoid going back and forth 🙏

@waddie

waddie commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

I don’t think “hardware” cursor is the right terminology here.

@waddie, I read both "hardware" and "terminal" in external sources. I am happy to change this, but could you please confirm this is what we want? Do we call it BlockTerminal / block-terminal, or TerminalBlock / terminal-block? I just want to avoid going back and forth 🙏

I’m just some guy, in no position to confirm anything, so feel free to ignore me. 🙂

But for what it’s worth, I don’t think the Helix code ever uses the phrase “hardware cursor”, and it does use the phrase “terminal cursor” at least 3-4 times. I think terminal cursor is more accurate for most if not all terminal emulators. Unless you’re interfacing directly with something like VGA text mode, there’s nothing really “hardware” about the cursor on a modern OS/machine.

And I think two ways of referring to a single concept is generally to be avoided, so I’d go with the one that was already in the code.

I’m kind of conflicted about which way round to name it. There isn’t a huge sample of options like this to crib from, but looking at things like the statusline options, maybe terminal-block is actually more in line with the existing code. e.g. we have line-numbers and total-line-numbers, not line-numbers-total. block-terminal would have been my first instinct too, but reading like regular English seems to be the preference over sorting related/similar options together. Bike-shedding a bit at this point though, it probably doesn’t matter either way.

This commit attempts to match the hardware cursor colors to the Helix
theme. While this works in many cases, it relies on non-standard
terminal behaviour and is not guaranteed to work in all cases.

Users should configure their terminal emulator to invert the colors of
the cell under the hardware cursor.

Sample Ghostty configuration

```
cursor-text = cell-background
cursor-color = cell-foreground
```

Alternatively, users who rarely switch Helix themes can configure their
terminal emulator with cursor colors that match their Helix theme.

Sample Ghostty configuration

```
cursor-text = #000000
cursor-color = #ffffff
```

The code handles themes with static cursor colors separately from those
with reversed cursor colors. This distinction is not strictly necessary,
but it should minimise the changes between consecutive frames and
provide a negligible performance improvement.
@marcv81

marcv81 commented Aug 12, 2026

Copy link
Copy Markdown
Author

I added a commit to match the hardware cursor colors to the Helix theme. Please try it and let me know what you think!

While this works in many cases, it relies on non-standard terminal behaviour and is not guaranteed to work in all cases.

Users should configure their terminal emulator to invert the colors of the cell under the hardware cursor.

Sample Ghostty configuration

cursor-text = cell-background
cursor-color = cell-foreground

Alternatively, users who rarely switch Helix themes can configure their terminal emulator with cursor colors that match their Helix theme.

Sample Ghostty configuration

cursor-text = #000000
cursor-color = #ffffff

I use Ghostty, and I do not believe it supports Kitty's OSC 21 enough to support Helix themes with 100% accuracy. I was able to change the cursor background color, but not the cursor text color. I do not believe we can change the hardware cursor text color dynamically in Ghostty, but please prove me wrong 🙏

@senekor

senekor commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Users should configure their terminal emulator to invert the colors of the cell under the hardware cursor.

Tried it, and works as expected (also using Ghostty). Being able to switch between dark and light themes and still see the cursor is great. The terminal cursor config obviously applies outside helix, which some users might not like. But I think that shouldn't be Helix' concern. Users can script their terminal config, or just use the traditional software cursor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants