Skip to content

Conversation

@MunsMan
Copy link

@MunsMan MunsMan commented Dec 11, 2025

Summary

This PR changes the cursor rendering behavior to use the terminal's native cursor APIs instead of a software-rendered block for the primary cursor.

Rationale

Previously, Helix rendered the block cursor by manually inverting the cell colors. While consistent, this prevents the terminal emulator from applying its own cursor effects, such as:

  • Cursor trails (e.g., in Kitty, Ghostty, or WezTerm).
  • Accessibility features that rely on tracking the native cursor.
  • IME composition windows positioning correctly.

Implementation

  • The native terminal cursor is now used whenever there is exactly one active cursor.
  • Multiple cursors continue to be software-rendered to maintain visual consistency (as terminals generally support only one hardware cursor).
  • This is enabled by default and does not require configuration.

Fixes #12642

This replaces the manually rendered block cursor with the native
terminal cursor. This change allows users to leverage terminal
capabilities such as cursor blinking, distinct shapes, and visual
effects (e.g., cursor trails).

Note: This behavior is applied only when a single cursor is active;
multiple cursors are still rendered via cell inversion.

Fixes helix-editor#12642
@MunsMan
Copy link
Author

MunsMan commented Dec 11, 2025

I have been using this feature for the last two weeks and haven't found any problems—it works like a charm! I'm currently using Ghostty with shaders enabled, and having the native cursor support makes working in Helix so much more enjoyable.

@gj1118
Copy link
Contributor

gj1118 commented Dec 11, 2025

How is it different to #13821 ?

@MunsMan
Copy link
Author

MunsMan commented Dec 11, 2025

On my initial search I didn't find this pull request due to the different description. After checking the applied changes, I'm not sure if we're achieving the same result. In particular, #13821 adds more complexity with its prompt option. That complexity may be required, but up to this point I haven't found a reason for it in my testing.

@CalebLarsen
Copy link
Contributor

See #13821 (comment)
How does this solution interact with theming the cursor via helix? It seems that one of the major blockers from the other PR was that by using native cursor rendering, helix couldn't style the cursor.

@MunsMan
Copy link
Author

MunsMan commented Dec 12, 2025

I just updated the code, to allow the user to control the behavior via the config.

[editor.cursor-shape]
insert = "bar"
normal = "native"
select = "underline"

@iamvoidcoder
Copy link

Some terminals support multiple native cursors for a while now. E.g. Kitty and probably some others as well. Which basically means soon every terminal will follow the suit, same as with image support protocols. Can the more-than-one-cursor fake cursor logic check the term capabilities and use multiple native cursors when available?

@MunsMan
Copy link
Author

MunsMan commented Dec 17, 2025

While native multi-cursor support is definitely the future, I think we still need the manual rendering logic for now. Helix aims to support all terminals, and I'm skeptical that the wider ecosystem will adopt the Kitty protocol anytime soon.

Also, regarding the implementation—I'm not exactly sure how to check for that capability here. It feels like something that should be abstracted away by helix terminal backend/dependency.

@iamvoidcoder
Copy link

iamvoidcoder commented Dec 17, 2025

Also, regarding the implementation—I'm not exactly sure how to check for that capability here. It feels like something that should be abstracted away by helix terminal backend/dependency.

Here:

Querying for support
A terminal program can query the terminal emulator for support of this protocol by sending the escape code:

CSI > TRAILER
In this case a supporting terminal must reply with:

CSI > 1;2;3;29;30;40;100;101 TRAILER

Kitty specifically proposed that as an open multi cursor standard, not a Kitty only protocol. Which is why I think many other terminals will pick it up too. There is just no standards body deciding on these terminal protocols so it is pretty much whoever comes first. It was the case with inline images and I bet built-in multiplexing is the next in line. Both Kitty and WezTerm already support built-in multiplexing so I think the days of tmux are numbered...

Interestingly Ghostty appears to support multi-cursors too. That's two popular terminals already.

Also I have just discovered this helix multi-cursor support PR here: 14757

@NSPC911
Copy link

NSPC911 commented Dec 19, 2025

This PR made me realise how terrible my cursor color is :feelsgood:

Also about the PR description, as far as I know, Wezterm lets you customise the cursor, but for now, there is no support for cursor trails, aside from a recent pull request wezterm/wezterm#7420

@NSPC911
Copy link

NSPC911 commented Dec 19, 2025

I just updated the code, to allow the user to control the behavior via the config.

[editor.cursor-shape]
insert = "bar"
normal = "native"
select = "underline"

I'm not sure if this is an issue related to my fork, but if this editor.cursor-shape.normal is not set to native, the cursor doesn't have anything
image
and this is worse in insert mode
image
the only way this works is by setting normal to native, which looks awkward given my wezterm config
image

@MunsMan
Copy link
Author

MunsMan commented Jan 5, 2026

I'm sorry for the late response, I was pretty busy. I just verified your described bug and fixed it.

@NSPC911 Could you please verify, if it is working for you know?

@gaborkulik
Copy link

I'm sorry for the late response, I was pretty busy. I just verified your described bug and fixed it.

@NSPC911 Could you please verify, if it is working for you know?

I had the same issue. For me your fix is working. Thank you!

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.

Helix overrides Kitty Terminal's cursor_trail configuration

6 participants