Skip to content
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

Fix block cursor obscuring placeholder text and editor text in some cases #18114

Merged

Conversation

thataboy
Copy link
Contributor

@thataboy thataboy commented Sep 20, 2024

This PR tries to fix a couple of problems with the block cursor (and only the block cursor) not encountered before #17572 allowed user to change the cursor shape outside of vim mode and the terminal.

  1. When the editor has placeholder text, the placeholder character is not shown because block_text does not look at placeholder text, only the display chars at the cursor.
Screenshot 2024-09-19 at 9 24 14 PM
  1. block_text is displayed using EditorElement.style.background. This value is transparent black in some editors, causing regular text to be invisible. This happens with the filter text for the outline panel, for example
Screenshot 2024-09-19 at 9 24 55 PM

My fix for #2 is to use the theme's editor background instead. For the various built-in dark and light themes I tried, this seems to be a decent solution. I tried to use the inverse of the cursor color instead, namely h -> (h + 0.5) % 1., l -> 1. - l and other variations, but the result aren't great. Most themes favor a soft blue for the cursor and the inverse just ends up being soft brown and doesn't provide very good contrast. (Caveat: I have poor eyesight and this may be a me problem, but I think accessibility considerations apply.)

Here's how the fix using theme's editor background looks with gruvbox dark and Atelier Cave light

Screenshot 2024-09-19 at 10 01 28 PM Screenshot 2024-09-19 at 10 01 56 PM

Release Notes:

  • N/A

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Sep 20, 2024
@iamnbutler
Copy link
Member

iamnbutler commented Sep 30, 2024

This looks good to me, essentially we are just inverting the text color when using the block cursor in these cases?

I did just realize though–some themes set transparent background colors.

@thataboy Can we add a check to ensure that we only use editor_background if it isn't transparent? Otherwise we should use some value we know is not transparent (like pure black in a dark theme, pure white in a light theme.)

You can use something like cx.appearance() == Appearance::Dark or match on appearance to do that.

That is just a top of mind solution, there might be a better one though.

@@ -1035,15 +1047,14 @@ impl EditorElement {
&[TextRun {
len,
font,
color: self.style.background,
color: cx.theme().colors().editor_background,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here editor_background may give you a value like hsla(0.,0.,0.,0.) in some themes. I assume this will make the text vanish, so we should have some sort of check to ensure this is a color that is at least partially opaque.

Copy link
Member

@iamnbutler iamnbutler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some sort of check to ensure the text color is at least partially opaque.

@thataboy
Copy link
Contributor Author

thataboy commented Oct 1, 2024

This looks good to me, essentially we are just inverting the text color when using the block cursor in these cases?

I did just realize though–some themes set transparent background colors.

@thataboy Can we add a check to ensure that we only use editor_background if it isn't transparent? Otherwise we should use some value we know is not transparent (like pure black in a dark theme, pure white in a light theme.)

You can use something like cx.appearance() == Appearance::Dark or match on appearance to do that.

That is just a top of mind solution, there might be a better one though.

Ah thank you. I was wondering how to check if theme is light or dark.

Now set color according to Light or Dark appearance

@iamnbutler
Copy link
Member

Let's try something like this?

// Invert the text color for the block cursor. Ensure that the text
// color is opaque enough to be visible against the background color.
//
// 0.75 is an arbitrary threshold to determine if the background color is
// opaque enough to use as a text color.
//
// TODO: In the future we should ensure themes have a `text_inverse` color.
let color = if cx.theme().colors().editor_background.a < 0.75 {
    match cx.theme().appearance {
        Appearance::Dark => Hsla::black(),
        Appearance::Light => Hsla::white(),
    }
} else {
    cx.theme().colors().editor_background
};

This fallback ensures a transparent background doesn't make it so the text disappears.

Without fallback:
CleanShot 2024-10-15 at 09 44 41@2x

With fallback:
CleanShot 2024-10-15 at 09 41 16@2x

@iamnbutler
Copy link
Member

Thanks! Great change :)

@iamnbutler iamnbutler merged commit 8924b3f into zed-industries:main Oct 15, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed The user has signed the Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants