-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make certain that the cursor can invert/not-occlude/display the character under it #9610
Comments
Is this blocked by #6193 or other issues? Or we can just implement the algorithm for calculating the contrasted color and call it a day |
I KNEW THERE WAS AN EXISTING ISSUE! Part of the trick here is that when the Presumably, if there's a way of doing it without doing all the work in #6193, that'd be cool. I had all these ideas before in #6151 for different ways of specifying how the text at the cursor should look. Something like |
The thing I was toying with--which initially made me think that this would be easy--was drawing a D2D "fill effect" (that is: a command buffer that produces a flood fill) through the image/effect drawing pipeline with the XOR composition mode. It was promising, but it only worked where we weren't already drawing a background. Everything goes pear-shaped when you are drawing a background color. 😄 |
However, it looks like we can use the 2-pass cursor renderer @zadjii-msft wrote to backplate the color for a destination-inversion cursor. |
Looks like a really good start, nice work. Could this be something that gets backported into the current stable release as a hotfix once you're happy with its performance and stability? It feels like such a huge feature that it transforms the entire experience for anyone who might be using Vim. |
Imo, there are 3 possible solution to this:
Calculated contrast color may not have enough contrast to the cursor's background color (even visible in the post above (purple cursor + inverted color - blue) and it may be distracting for some users. I agree it should be the default behavior but also, there should be a possibility to use a custom cursor foreground color defined by user or system background as default, something like: Cursor color = (contrast color | system background | custom cursor foreground) in profile settings. But I see that the main issue here is the cursor position between renders so thank you for your work @DHowett! |
Well, what needs to happen now is for us to come up with a design that reconciles the current |
This commit introduces support for inverting all types of cursor. To invert the display without re-rendering any text, we draw the cursor into a command list and then compose the command list with the existing renderer using the MASK_XOR composition flag. This wouldn't normally work with our renderer because there is no _background_ color to invert in some cases (such as when acrylic is in use.) To work around that, we're taking advantage of @zadjii-msft's two-pass cursor renderer: First, we draw the cursor region in the background color (to give the later pass something to work with), then after the text is drawn we do the command list MASK_XOR. Example cursor draw (for emptyBox cursor) Therefore, cursor drawing looks like this (`_` is background, `@` is cursor, `A` is glyph) ``` First pass (before text) _____ _ _ _ _ _ _ _____ Text is added __A__ _A A_ _AAA_ _A A_ _A_A_ Second pass (after text) @@A@@ < Drawn with XOR mask; overlaps shown as [a] @A A@ @aaa@ @A A@ @A@a@ ``` The box, underline, etc. cursors are treated the same way, give or take some pixels. Fixes #9610
This commit introduces support for inverting all types of cursor. To invert the display without re-rendering any text, we draw the cursor into a command list and then compose the command list with the existing renderer using the MASK_XOR composition flag. This wouldn't normally work with our renderer because there is no _background_ color to invert in some cases (such as when acrylic is in use.) To work around that, we're taking advantage of @zadjii-msft's two-pass cursor renderer: First, we draw the cursor region in the background color (to give the later pass something to work with), then after the text is drawn we do the command list MASK_XOR. Example cursor draw (for emptyBox cursor) Therefore, cursor drawing looks like this (`_` is background, `@` is cursor, `A` is glyph) ``` First pass (before text) _____ _ _ _ _ _ _ _____ Text is added __A__ _A A_ _AAA_ _A A_ _A_A_ Second pass (after text) @@A@@ < Drawn with XOR mask; overlaps shown as [a] @A A@ @aaa@ @A A@ @A@a@ ``` The box, underline, etc. cursors are treated the same way, give or take some pixels. Fixes #9610
For those of you who appreciate long commentary,
|
This commit introduces support for inverting all types of cursor. To invert the display without re-rendering any text, we draw the cursor into a command list and then compose the command list with the existing renderer using the MASK_XOR composition flag. This wouldn't normally work with our renderer because there is no _background_ color to invert in some cases (such as when acrylic is in use.) To work around that, we're taking advantage of @zadjii-msft's two-pass cursor renderer. To properly invert the cursor over a transparent background: (Examples are given below for two cursor types, but this applies to all of them.) First, we'll draw a "backplate" in the user's requested background color (with the alpha channel set to 0xFF). (`firstPass` == true) EMPTY BOX FILLED BOX ===== ===== = = ===== = = ===== = = ===== ===== ===== Second, the glyph is drawn (outside of the cursor renderer). EMPTY BOX FILLED BOX ==A== ==A== =A A= =A=A= AAAAA AAAAA A A A===A A===A A===A Last, we'll draw the cursor again in all white and use that as the *mask* for XORing the already-drawn pixels. (`firstPass` == false) (# = mask, a = inverted A) EMPTY BOX FILLED BOX ##a## ##a## #A A# #a#a# aAAAa aaaaa a a a###a a###a a###a Fixes #9610
Just wanted to pipe up here for a second, specifically replying to @DHowett's last message. I always considered ligatures being drawn as their individual characters when the cursor is over them as a feature, not a bug. It's nice to be able to see what characters comprise the ligature if you need to, and have it display as a ligature otherwise. That said, I can see it the other way too, but I'm just saying that if it was up to me I wouldn't jump through too many hoops to make ligatures display "correctly". |
Thanks for the input! Yeah... I waffled back and forth on this. Right now, given the architecture of our renderer, it's actually harder for us to split the ligature and re-strike the character 😄 We condense full runs of text into as few rendering calls as possible, and we don't have support for splitting a run where we think the cursor is ... which is 100% something we need to fix later. |
#6337 made an assumption that foreground color is sufficiently different from the block cursor's background, which doesn't hold true. I still need a feature to change the TEXT color when the block cursor is over it. Inverting is too smart for me; I will set it to white in a light theme to distinguish the dark text from my dark block cursor if possible. |
In the preview version with the new AtlasEngine renderer enabled: BeforeAfterAlmost fixed, but the cursor is much darker for some reason (even though If only there was an option to set the cursor text color to black, as was suggested in the original issue 3 years ago... |
This did not look the same for me, the cursor was white and the text was slightly not white - not inverted - so was very hard to see the text behind the cursor. |
what do i do to fix this issue? |
Thank you! @lhecker. I hope to soon use block cursor like god intended (I'm currently using vintage shape because of this indistinguishable-character issue).
This really seems like a no-brainer. Since it's easier to address, as you say, why not implement that before the automated inversion solutions? I am repeating @avih here, I know, but this easy-to-address feature could help me use Vim with proper |
The "automated" mode is ~4 lines of code and took me <5min to write and test, whereas the other issues/feature-requests require a lot more work. Given that I'm technically already 110% booked out with work for months on end, I think you can see why I've picked the easy option for now. 🥲
You could try god's intended cursors right now, if you're curious. 😏 |
Awesome! Been using for a few hours. Works great! Thanks a bunch. |
IMHO, if you insist on choosing the FG color yourself and not letting the user specify it, then just pick either black or white - whichever has the better contrast to the chosen cursor BG color. IMO it would pretty much gurante to look better than any attempt to preserve the underlaying FG color but still modifying it so that it has some contrast to the BG. Just see how many failed atempts there were at that, to realise that it's not as simple as you think to do what the user prefer automatically. |
I think if we stick with setting it manually then we're not going to address the root issue where characters are invisible based on syntax highlighting in terminal based editors such as Vim. You're going to have a wide range of dark and light text based on any variant of color themes. |
ms-terminal has a bug (microsoft/terminal#9610) where cursor hides the character underneath. To circumvent, I used vintage cursor shape (basically thicker version of underscore), so it didn't cover the character. guicursor changed the cursor shape to block in normal mode, so I had to disable it. There has been development in the ms-terminal repo (microsoft/terminal/#15283). The cursor now inverts the character color underneath so the character is now visible. No need to disable guicursor on ms-terminal anymore.
Oklab by Björn Ottosson is a color space that has less irregularities than the CIELAB color space used for ΔE2000. The distance metric for Oklab (ΔEOK) is defined by CSS4 as the simple euclidian distance. This allows us to drastically simplify the code needed to determine a color that has enough contrast. The new implementation still lacks proper gamut mapping, but that's another and less important issue. I also made it so that text with the dim attribute gets adjusted just like regular text, since this is an accessibility feature after all. The new code is so much faster than the old code (12-125x) that I dropped any caching code we had. While this increases the CPU overhead when printing lots of indexed colors, the code is way less complex now. "Increases" in this case however means something in the order of 15-60ns per color change (as measured on my CPU). It's possible to further improve the performance using explicit SIMD instructions, but I've left that as a future improvement, since that will make the code quite a bit more verbose and I didn't want to hinder the initial review. Finally, these new routines are also used for ensuring that the AtlasEngine cursors remains visible at all times. Closes #9610 ## Validation Steps Performed * When `adjustIndistinguishableColors` is enabled colors are distinguishable ✅ * An inverted cursor on top of a `#7f7f7f` foreground & background is still visible ✅ * A colored cursor on top of a background with identical color is still visible ✅ * Cursors on a transparent background are visible ✅
I have used vim for a long time in different terminals that allow setting But anyway, if that new implementation would let us distinguish what is under cursor, I am all for it. |
@habamax This issue has multiple screenshots showing how it would be an issue with a statically configured cursor color. Here's a screenshot you posted a while back:
Your screenshot is also a near-best case scenario because you have pretty bright colors and there's only a few colors shown at once. |
@nickjj it is about other terminals that allow setup of cursor background AND FOREGROUND colors. Like gnome-terminal, for example: |
Oklab by Björn Ottosson is a color space that has less irregularities than the CIELAB color space used for ΔE2000. The distance metric for Oklab (ΔEOK) is defined by CSS4 as the simple euclidian distance. This allows us to drastically simplify the code needed to determine a color that has enough contrast. The new implementation still lacks proper gamut mapping, but that's another and less important issue. I also made it so that text with the dim attribute gets adjusted just like regular text, since this is an accessibility feature after all. The new code is so much faster than the old code (12-125x) that I dropped any caching code we had. While this increases the CPU overhead when printing lots of indexed colors, the code is way less complex now. "Increases" in this case however means something in the order of 15-60ns per color change (as measured on my CPU). It's possible to further improve the performance using explicit SIMD instructions, but I've left that as a future improvement, since that will make the code quite a bit more verbose and I didn't want to hinder the initial review. Finally, these new routines are also used for ensuring that the AtlasEngine cursors remains visible at all times. Closes #9610 * When `adjustIndistinguishableColors` is enabled colors are distinguishable ✅ * An inverted cursor on top of a `#7f7f7f` foreground & background is still visible ✅ * A colored cursor on top of a background with identical color is still visible ✅ * Cursors on a transparent background are visible ✅ (cherry picked from commit 4dd9493) Service-Card-Id: 89215984 Service-Version: 1.17
So, what's the solution? Many issues are closed but I still cann't find a solution. |
Did you try Windows Terminal Preview 1.18 yet? If that doesn’t work for you it’d be great if you could open a new issue with a screenshot showing the problem and I‘ll try to fix it ASAP. 🙂 If you’re asking about setting individual foreground and background colors for the cursor, I don’t think we have an issue tracking specifically that yet, but I‘ve already made it my goal to implement that for 1.19 anyways. |
WT Preview 1.18 is much better. Thank you! |
This is now being discusses in #15766. |
Originally posted by @n1ghtmare in #1203 (comment)
Originally posted by @nickjj in #1203 (comment)
Subscribers, thumbs-uppers from that comment: @krage, @saurik, @krage
The text was updated successfully, but these errors were encountered: