Support both software and hardware block cursors (v2) - #16163
Conversation
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.
|
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. |
|
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. |
|
I don’t think “hardware” cursor is the right terminology here. The existing comments in |
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 / 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. |
|
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 🙏 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.
@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 |
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.
|
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 Alternatively, users who rarely switch Helix themes can configure their terminal emulator with cursor colors that match their Helix theme. Sample Ghostty configuration 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 🙏 |
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. |
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.