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

[RFC] Proposal: handling of global transparency #2471

Open
fredizzimo opened this issue Apr 6, 2024 · 3 comments
Open

[RFC] Proposal: handling of global transparency #2471

fredizzimo opened this issue Apr 6, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@fredizzimo
Copy link
Member

fredizzimo commented Apr 6, 2024

We currently have several transparency issues, here are a few:

This is unrelated to this proposal, but should be fixed nevertheless.

The main issue is that neovide transparency applies to all background colors as they are defined in Neovide, so some elements that should not be transparent, like the visual mode selections becomes transparent. The other equally important issue is that some elements should be transparent even if they are rendered as foreground, like the statusline elements.

The third issue is that the default blend mode for floating windows is not always the desirable one.

In order to fix all these issues, we need more customization than what's currently possible. We have one open proposal on the Neovim side.

But after some thinking, I think it's perhaps too complex, and I don't think we can get it into the upcoming 0.10 release either. There are also numerous design decisions that need to be correctly taken and can't easily be fixed if it does not work in practice. So, after some thinking I came up with an alternative solution.

First, let's fix the obvious naming problem, neovide_transparency, should really be neovide_opacity, since 1 means fully opaque, while 0 means fully transparent. So, let's alias these parameters to each other, and deprecate the old one, so that it still works, but all documentation only refers to neovide_opacity.

Neovim always sends both the GUI and terminal colors, so we can (ab)use the terminal color index to control the transparency. Which is done with a new function.

neovide_set_transparent_color(color_index, opts)

The color_index is the terminal ansi color number, and opts is table with all optional fields as described below

The following fields describes how the opacity is calculated for all non-floating window colors:

  • base_opacity - The base opacity, defaults to 0.
  • opacity_multiplier - The multipler specified here is multiplied by the global neovide_opacity, defaults to 1.0
  • global_disable - When set to true, the color is always fully opaque when neovide_opacity is set to 1.0. Defaults to false
  • applies_to_foreground - Applies the transparency also to Neovim foreground colors, defaults to true

The final opacity is defined as base_opacity + opacity_multiplier * neovide_opacity, clamped between 0 and 1. This means that you can create colors that are completely dependent on the neovide_opacity, by setting base_opacity to 0, Or colors that are always transparent by setting opacity_multiplier to 0. And of course, anything in between if you prefer that.

The transparency for floating windows is defined in a similar way, and the meaning is the same ss for now-floating window colors, unless specified otherwise:

  • float_base_opacity - Defaults to 1.0
  • float_multiplier - Defaults to 0
  • blend_multiplier - For floating windows the window blend is also taken into account. Defaults to 1
  • float_global_disable - Defaults to false
  • float_applies_to_foreground - Defaults to true

The final opacity for floating windows is defined as (float_base_opacity + float_opacity_multiplier * neovide_opacity) * blend_multiplier This means that the blend value is the only value controlling the opacity of floating windows, so they don't become more transparent, with respect to the background when changing the neovide_opacity . float_global_disable only affects this part of the expression (float_base_opacity + float_opacity_multiplier * neovide_opacity), so neovim blend values will always have an effect. But note that Neovim itself defines them to not have any effect unless winblend or pumblend is set.

NOTE: Any color that has not been set using neovide_set_transparency is always fully opaque.

We should also have neovide_transparency_reset(no_default), which resets everything to the default.

The default, which also applies at startup or after changing the Normal highlight group, unless no_default is set in the above call is the following.
neovide_set_transparent_color(normal_color, {}), which closely emulates most terminals, and just renders the default background color as transparent.

If you want more colors to be transparent, just use the ColorScheme autocommand, and add them as you want. And since Neovide otherwise does not care about the terminal colors, advanced control can be achieved by creating new highlight groups with different terminal colors than Gui colors. This will break the color schemes for terminals that don't support true colors, but those are rare, and if you need that you can always check if Neovide is active or not.

Once we have determined that this works, we can perhaps try to propose a more standardized way that to Neovim, that does not abuse the cterm colors.

What do you think, do you see anything that does not work or otherwise could be defined better?

As for the implementation, I probably won't have time to do this anytime soon, so volunteers are highly appreciated.

Addendum:
I forgot to specify how to address the issues in:

Some people don't like how the transparency of the floating windows combine, and would prefer a more direct approach, where the transparency is not multiplied together and becomes darker when more windows are created on top of each other.

So, we could add an option:
neovide_alpha_composition, which defaults to true. And setting it to 0 disables that standard alpha composition, and always use floating window alpha when the pixel below it is transparent.

@fredizzimo fredizzimo added the enhancement New feature or request label Apr 6, 2024
@fredizzimo
Copy link
Member Author

I added an addendum about alpha composition.

@fredizzimo
Copy link
Member Author

Note that the api is quite lowlevel, but we can easily create a more highlevel one on top of that, that takes highlight groups as input, with preset configurations.

@MultisampledNight MultisampledNight changed the title [RFC] Propsal: handling of global transparency [RFC] Proposal: handling of global transparency Apr 6, 2024
@Mange
Copy link

Mange commented Apr 11, 2024

I really like the suggestions made here. Being able to have different transparencies for different colors is also very useful in that one could have, for example, a "sidebar"-like split with a different background color and have it be more or less transparent than the "main" bar. This also applies to winbar and statusbar, of course.


RE neovide_set_transparent_color(color_index, opts)

What if a theme uses a lot of truecolor values but only a few legacy color indices? How could this API be extended in the future to support those cases?


My terminal (Wezterminal) has an option to make things where no background is set, and the window_background shines through, transparent. I then run my Neovim theme to not explicitly set background color.

This makes things shine through, and then I can explicitly set background color somewhere and that part stops being transparent, even when setting to the same color as the window_background.

Here's a screenshot to show this effect:
image

The cursorline is barely visible here, but placed against a white background it becomes more obvious. I did this with :hi CursorLine guibg=#1e1e2e, which is the same background color as my terminal has.

Is this perhaps another way to deal with it? Having the windows "default color" be transparent, and any other background color drawn on top of it having its own blending.

Note that Wezterm has two transparency options, one for the window_background and one for text_background, which is the explicit background set. If I were to set text_background_opacity to something else, then that line would also shine through more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants