Terminal: Feature Request: Show character under cursor when cursorShape is set to filledBox

Created on 11 Jun 2019  ·  35Comments  ·  Source: microsoft/terminal

Summary of the new feature/enhancement

When cursorShape is set to filledBox, it hides the character under it:
image
(The command is cat /etc/os-release)

This is a bit annoying. It will be helpful if the character can still be visible when the cursor is moved to its position.

Area-Rendering Issue-Task Priority-3 Product-Terminal Resolution-Fix-Committed v1-Scrubbed

Most helpful comment

Can we just reverse the foreground and the background color of the text under cursor like what gVim does?
image
image

All 35 comments

It's a good idea. Naively doing this will break up ligatures under the cursor, _but perhaps that is desirable!_

As a big Vim user this one is annoying me enough that I've had to switch to Hyper. Raised an issue in #3241 but closed it in favour of this one. Otherwise everything worked pretty great!

Adding to this discussion from #3322, since we should probably include all these scenarios:

  • Someone might want the current behavior (for some reason)
  • someone might want the character to appear on top of the cursor, in the character's FG color
  • someone might want the character to appear in the character's BG color, on top of the cursor (which is drawn in cursorColor)

Also relevant: #1356, which tracks a similar request in conhost (not the terminal).

Configuration of this will be great, but the most important and easy fix for now would be to just display the underlying character negative. That will make it at the very least usable, until the added configuration is implemented.

Maybe allowing to change the cursor opacity can be a solution for now?

I'd like something along the lines of cursorForegroundColor, defined in colorschemes/profiles, describing the color of the character under the cursor as a complement to the existing cursorColor.

For those frustrated vim users, changing OPACITY_OPAQUE to 0x7F000000 should somewhat mitigate this issue. Drawing the character on top of the cursor might be a better solution but it doesn't seems trivial.
https://github.com/microsoft/terminal/blob/64ac0d25e04834391598775f3aced6856cb59257/src/renderer/dx/DxRenderer.cpp#L1454

For those frustrated vim users, changing OPACITY_OPAQUE to 0x7F000000 should somewhat mitigate this issue. Drawing the character on top of the cursor might be a better solution but it doesn't seems trivial.
https://github.com/microsoft/terminal/blob/64ac0d25e04834391598775f3aced6856cb59257/src/renderer/dx/DxRenderer.cpp#L1454

image

Notes from @nj-ms:

Description of the new feature/enhancement

Unless I'm mistaken, Windows Terminal configuration supports just the cursorColor setting, which functions as if I've set both the foreground and background colors to the same color.
Other terminal programs (Alacritty, ..., ?) support configuration of the cursor foreground color and the cursor background color, and/or they respect the foreground color setting and the character shows through the cursor.
For example, I'd like to set the background to black (#000000), foreground to white (#ffffff), the cursor background to magenta (#990099) and the cursor foreground to white (#ffffff).
This way, I can still see the character under the cursor.
This is especially annoying, for example, if I'm in a Linux WSL and vim'ing a file.
This modification is also important in relation to #1379.

Proposed technical implementation details

  • Make the current cursorColor setting continue to set both foreground and background colors.
  • Add a cursorBackground setting to set just the background color; should use cursorColor by default.
  • Add a cursorForeground setting to set just the foreground color; should use foreground and/or cursorColor by default. It might also work to just use the foreground color and make the character show through the cursor, with the drawback that it's slightly less configurable.

Can we just reverse the foreground and the background color of the text under cursor like what gVim does?
image
image

@DHowett-MSFT Is there any chance we can get the simple case fix that multiple people have suggest above?

Yes, it would be great if this could be configured and what not, but I think there's a large group of Terminal users who would just be thankful for a basic fix as outlined above https://github.com/microsoft/terminal/issues/1203#issuecomment-598002624.

If it were trivially possible with our renderer set up the way it is, I'd say yes. This close to our signoff date, though, I'm a bit concerned about that. ☹️

@DHowett-MSFT I'm not sure I understand.

In the comment I linked to a solution is presented that requires changing one flag in an existing call from OPACITY_OPAQUE to 0x7F000000: https://github.com/microsoft/terminal/blob/64ac0d25e04834391598775f3aced6856cb59257/src/renderer/dx/DxRenderer.cpp#L1454

While not perfect, the change seems to involve changing 14 characters, and it seems to at least let the character be seen in most cases. Others have confirmed this above.

Maybe I'm completely misunderstanding, but this seems like the literal definition of a trivial change that has useful impact today? If you want someone to PR it I'm happy to do so.

@DHowett-MSFT Just to clarify - I understand and appreciate what you're saying about being close to 1.0, and I really appreciate all of the work you and the team are doing for Terminal. If it wasn't for you folks and this project I'd still be stuck in the Apple ecosystem.

I think this is a bug, not a feature for console/tty/terminal. Need Make it usable before optimizing.
image
image
image

An illegible filled box is not a feature it's a bug. It's about the one thing I have found problematic with Windows Terminal; in general Terminal has been well behaved and the configuration capability was a delight to discover.

A number of color terminals allow end-applications to set colors independently - vim is an example, when paired with the right terminal. That's probably a feature set too much to ask for, so being able to tune the FG/BG colors would be enough. Some of us can't live without our filled boxes - they make spotting location much easier in a big page of text. Granted the opaque ones fill that need but seeing the character underneath is a must-half. Cheers.

I consider this a bug, all characters on screen should be legible. Also this is not even a problem in the basic cmd terminal. The behavior Windows terminal currently shows for this does not exist in any other Windows, Linux or Mac terminals i have seen.

I would like to start by saying that the overall experience of the terminal from installing in the Microsoft Store to the tabs all are wonderful but this is a serious issue that ruins the entire WSL experience. There is no way for someone to practically use the terminal with editor like vim/neovim/gvim. I am disappointed that this has been open for almost a year now, I do not feel this is getting the response from the maintainers. With great regret, I am going to have to switch to another open-source terminal, hopefully, this will get resolved quickly so I can return to this wonderful terminal.

I am disappointed that this has been open for almost a year now, I do not feel this is getting the response from the maintainers

https://github.com/microsoft/terminal/issues/1203#issuecomment-622045617
DHowett-MSFT 21 days ago

We're pretty actively looking into it. It's _unfortunately_ not trivial to just implement, because the _right_ solution isn't just "paint the cursor at half opacity". I'd rather not stick in the wrong behavior temporarily while we're working on the _right_ behavior.

The real problem here is that the cursor is drawn in our renderer _after_ the text is, so it's always painted on top. @DHowett and I discussed a bunch of options here, but none of them were trivial changes to sneak in right before a major release.

Now that we're past 1.0, we'll be coming back to see which of the options we discussed is the best. Hence why it's on our "v1.x" milestone, the generic "we want to get to this ASAP after 1.0" milestone.

@zadjii-msft Appreciate the thought and effort you and @DHowett and the rest of the team are putting towards this issue.

That said and by way of explanation of why we're being so annoying about this issue, I don't think anyone in this thread proposed the 0x7f hack as the _right_ behaviour, simply that it would be implementing a _working_ fix today over something that is _completely broken_.

Maybe you don't encounter this frustration because y'all are using VSCode as your daily drivers - but for the large contingent of terminal based editor users out there this bug is frustrating on a daily basis, and that's why we'd push for a _working but temporary_ fix today over a _perfect and right_ fix however many more months away.

To add some personal context, now that Apple have fixed their atrocious keyboards this year, I'm considering moving back to OSX because it would remove this daily and constant source of frustration as I try to work everyday. _That's how annoying I find this issue_.

EDIT: And I am particularly galled by this whole thing when I think about the fact I can turn on retro-style CRT effects, which literally no one asked for, but I can't reliably edit text in Vim.

I use filledBox in vim/bash/tmux every day, So I use 0x7f hack build it for myself now. But I don't want build every time when update. I support merge this hack before right solution come.

Okay I'm putting together a more formal spec now, but here's the important bits:

We could try drawing the cursor _first_.

We're going to draw the cursor in two phases - a pre-paint and a post-paint. All the other renderers will just return S_FALSE from the cursor pre-paint phase automatically - we absolutely don't need to implement it for them.

We'll introduce cursorTextColor as a setting that accepts the following values:

  • "#rrggbb" (a color): paint the character the cursor is on in the given color
  • "textForeground": paint the character the cursor is on _on top of the cursor_ in the text foreground color.
  • "textBackground": paint the character the cursor is on _on top of the cursor_ in the text _background_ color. (This is like what gVim does, see this comment).
  • null: Paint the cursor _on top of the character_ always.

null is effectively the behavior we have now. I'm proposing we move the default _for all profiles_ to textForeground.

So, for this new setting, we get the following scenarios:

cursorShape | cursorTextColor | cursorColor | Break Ligatures? | Pre-draw cursor | character color | post-draw cursor | Result | Notes
-- | -- | -- | -- | -- | -- | -- | -- | --
FilledBox | | #rrggbb | | | | | |
FilledBox | null | #rrggbb | FALSE | N/A | cell FG | #rrggbb | Solid box of #rrggbb | Current behavior
FilledBox | #r2g2b2 | #rrggbb | TRUE | #rrggbb | #r2g2b2 | N/A | Box of #rrggbb with character in #r2g2b2 on top |
FilledBox | textForeground | #rrggbb | FALSE | #rrggbb | cell FG | N/A | Box of #rrggbb with character in (text FG) on top | Proposed Default
FilledBox | textBackground | #rrggbb | TRUE | #rrggbb | cell BG | N/A | Box of #rrggbb with character in (text BG) on top |
Vintage | | | | | | | |
Vintage | null | #rrggbb | FALSE | N/A | cell FG | #rrggbb | ▃ of #rrggbb on top of char in (text FG) | Current behavior
Vintage | #r2g2b2 | #rrggbb | TRUE | #rrggbb | #r2g2b2 | N/A | ▃ of #rrggbb with character in #r2g2b2 on top of ▃ |
Vintage | textForeground | #rrggbb | FALSE | #rrggbb | cell FG | N/A | ▃ of #rrggbb with character in (text FG) on top of ▃ | Proposed Default
Vintage | textBackground | #rrggbb | TRUE | #rrggbb | cell BG | N/A | ▃ of #rrggbb with character in (text BG) on top of ▃ |
Vertical Bar | | | | | | | |
Vertical Bar | null | #rrggbb | FALSE | N/A | cell FG | #rrggbb | ┃ of #rrggbb on top of char in (text FG) | Current behavior
Vertical Bar | #r2g2b2 | #rrggbb | TRUE | #rrggbb | #r2g2b2 | N/A | ┃ of #rrggbb with character in #r2g2b2 on top of ┃ |
Vertical Bar | textForeground | #rrggbb | FALSE | #rrggbb | cell FG | N/A | ┃ of #rrggbb with character in (text FG) on top of ┃ | Proposed Default
Vertical Bar | textBackground | #rrggbb | TRUE | #rrggbb | cell BG | N/A | ┃ of #rrggbb with character in (text BG) on top of ┃ |

I omitted underscore, emptyBox because they're just the same as Vertical Bar

I think I can break this into 3 PRs:

  1. The first would simply move the Terminal to use "cursorTextColor": "textForeground" by default. This won't introduce the setting or anything - merely change the default behavior silently so the character appears on top of the cursor.
  2. The second would actually introduce the cursorTextColor setting, accepting only null or textForeground. This will let users opt-in to the old behavior.
  3. the third would introduce the #rrggbb and textBackground settings to the cursorTextColor property. This is left as a separate PR because these involve manually breaking runs of characters on the cell where the cursor is, which will require some extra plumbing.

I'd want to get both 1&2 done in the course of a single release. Ideally all 3 would be done in the course of a single release, but if only the first two are done, then at least users can opt-out of the new behavior.

I'm cleaning this up for a formal review. The code for 1 is _trivial_, and already written. The biggest delay now is there's a _long_ weekend before the team will be in the office to review 😄

@zadjii-msft Looks awesome, thanks for getting this together and moving us all closer to a rockin' terminal!

For anyone who want a quick fix right away, use this until this feature gets deployed.

"cursorShape": "emptyBox"

When I go into insert mode, my cursor goes to bar. While in normal mode, I just let it be emptyBox for now.

@rohitkrishna094 yeah that's a odd one, for regular vim, that works but neovim seems to have some way to change the cursor. Though find it makes it confusing for me doing empty box, since on my other machine with iterm2 it uses the empty box for when its not in focus

@zadjii-msft FYI, I had a look at how other terminals handled cursor colors a while back, and I think your proposed solution might not cover some of the common approaches I've seen used.

  1. When no color has been specified, one of the most common defaults is to render a box cursor with the text foreground color, and the character on top of it using the text background color. For an underline cursor (any non-box cursor really), both the cursor and character would be rendered with the same text foreground color, These defaults are essentially the equivalent of the reverse video attribute and the underline attribute, which is actually how the early terminals rendered a cursor.

  2. When a cursorColor has been set, there's a fair bit of variation in what is used for the character color of the box cursor. Personally I think the text background color makes the most sense, but as long as we have all the options I think we're good. My only concern is that the cursorTextColor should only apply to the box cursor - the underline cursor never changes the character color as far as I've seen (the one exception to this would be a per-pixel color inversion cursor, but that's an entirely different concept).

So what I think we might be missing from this proposal is a way to set the cursorColor to textForeground rather than a specific rgb value. And also the ability to set the cursorTextColor, but only have it apply for the box cursor (possibly also the vintage cursor depending on the size, but that's a more complicated issue).

@zadjii-msft so I gather that this will (hopefully) be part of the v1.1 release. What is the release date for v1.1, or when can I expect this feature/bug fix/whatever it's being called now to be released?

As much as I'd love to, I can't really commit on an official date for 1.1, or if this fix will be able to make it for 1.1. We're tracking the work in this thread, in the spec over in #6151, and also in #6224, which I think we'll need in addition to what I've outlined above. When _this_ issue is closed, you'll know that the fix will be available in the next release.

Thanks guys for looking into this. I'm in the same boat as the other vim-users. I've tried both emptyBox and vintage but it still happens that I lose the cursor. In any case, maybe this helps someone too: https://vim.fandom.com/wiki/Highlight_current_word_to_find_cursor

Okay, some progress here:

textAboveCursor

Or for more contrast:

textAboveCursor002

As Dustin called out in the spec over in #6151, I had forgotten that that text background is drawn in the same step as the text foregrounds. So I think this needs to be 4 PRS now:

  1. Separate FG and BG rendering, so they happen in separate steps.
  2. Default the dx renderer to "cursorTextColor": "textForeground" (step 1 above)
  3. Introduce the cursorTextColor setting, accepting only null or textForeground (step 2 above)
  4. Introduce the #rrggbb and textBackground settings to the cursorTextColor property (step 3 above)

1 is a tricky PR, because I want to make sure I don't do double the work. 2 is trivial, 3 is basically trivial, and 4 is a _pain_ to say the least. Fortunately, I think getting to 3 will solve the 99% use case here.



re:

So what I think we might be missing from this proposal is a way to set the cursorColor to textForeground rather than a specific rgb value.

We could probably make cursorColor: null mean this. That seems like a sensible default.

:tada:This issue was addressed in #6337, which has now been successfully released as Windows Terminal Preview v1.1.1671.0.:tada:

Handy links:

:tada:This issue was addressed in #6337, which has now been successfully released as Windows Terminal v1.0.1811.0.:tada:

Handy links:

Thank you! I have just run vim and suddenly I can see under the cursor:

image

There’s still a couple limitations; we’re just drawing the character on top of the cursor in whatever color it would have otherwise been rendered in. We’re tracking a spec and eventual implementation of “better cursors” in #6151

@DHowett yeah, I probably won't be using Microsoft Terminal until this feature is fully implemented in the way you are describing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DieselMeister picture DieselMeister  ·  3Comments

miniksa picture miniksa  ·  3Comments

mdtauk picture mdtauk  ·  3Comments

TayYuanGeng picture TayYuanGeng  ·  3Comments

waf picture waf  ·  3Comments