Conversation
| if (const auto v = appearance.Foreground()) | ||
| { | ||
| _DefaultForeground = til::color{ appearance.Foreground().Value() }; | ||
| _DefaultForeground = til::color{ v.Value() }; | ||
| } | ||
| if (appearance.Background()) | ||
| if (const auto v = appearance.Background()) | ||
| { | ||
| _DefaultBackground = til::color{ appearance.Background().Value() }; | ||
| _DefaultBackground = til::color{ v.Value() }; | ||
| } | ||
| if (appearance.SelectionBackground()) | ||
| if (const auto v = appearance.SelectionBackground()) | ||
| { | ||
| _SelectionBackground = til::color{ appearance.SelectionBackground().Value() }; | ||
| _SelectionBackground = til::color{ v.Value() }; | ||
| } | ||
| if (appearance.CursorColor()) | ||
| if (const auto v = appearance.CursorColor()) | ||
| { | ||
| _CursorColor = til::color{ appearance.CursorColor().Value() }; | ||
| _CursorColor = til::color{ v.Value() }; | ||
| } |
9a6e2ac to
a865c8d
Compare
| X(IMediaResource, BackgroundImagePath, "backgroundImage", implementation::MediaResource::Empty()) \ | ||
| X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \ | ||
| X(Core::AdjustTextMode, AdjustIndistinguishableColors, "adjustIndistinguishableColors", Core::AdjustTextMode::Automatic) \ | ||
| X(bool, GeneratePalette, "generatePalette", true) \ |
There was a problem hiding this comment.
Should the default indeed be true?
There was a problem hiding this comment.
In my opinion, yes. For the vast majority of users, I expect the downside to be low.
More importantly, I have thought about ways to make this setting more discoverable. We could put it onto the compatibility page as well, given that it affects standard color rendering.
There was a problem hiding this comment.
I think there is a fair chance that this is going to break some applications. These colors were always intended to be absolute values, and now we're replacing them with colors that could be completely different, potentially resulting in color combinations that are unreadable. If that happens you're going to have some very angry users.
There was a problem hiding this comment.
I do like, however, that this "fixes" the behavior when using a light theme. It also improves the stylistic look when using themes that aren't traditional (e.g. with a non-black background color).
While I believe that this would be most useful if enabled by default, it would certainly still be fine if we disable it instead.
There was a problem hiding this comment.
I do like, however, that this "fixes" the behavior when using a light theme.
I would have thought the most common problem with light themes came from apps that are just using the 8 basic ANSI colors (when it's assumed that white is going to be visible on the default background color, and the default foreground color will be visible on black), and this mode doesn't help with that.
That said, I'm assuming there must be some apps that would benefit from it, and I'm sure some people will love it, but I'd be very wary of forcing it on everyone and expecting them to opt out if they don't like it.
There was a problem hiding this comment.
@j4james The default palette interpolates from black to white. As a result, using color 231 (white) on a white background is unreadable. The generated palette instead interpolates from background to foreground. So for a light theme, color 231 is dark and readable against the background.
Whether to set this as default is a difficult choice. I believe that quicker and wider adoption would lead program maintainers to consider the palette a viable choice and actually use it, making all the benefits a reality.
Though breaking changes are a big deal so I understand either way.
There was a problem hiding this comment.
As a result, using color 231 (white) on a white background is unreadable. The generated palette instead interpolates from background to foreground. So for a light theme, color 231 is dark and readable against the background.
I was talking about apps using the basic ANSI colors though. ANSI white 7 (or the bright white 15) is still going to be unreadable on a light background.
And apps that try to detect light color schemes, and then compensate by using dark colors from the 256-color palette, could actually end up being worse off with this mode (they might decide to use 16 or 17 in place of 231 when the color scheme is light, which would assumedly now have the opposite effect than what was intended).
There was a problem hiding this comment.
I was talking about apps using the basic ANSI colors though. ANSI white 7 (or the bright white 15) is still going to be unreadable on a light background.
Oh. I think ansi 7 for light themes should be dark. Like 15 should not mean bright white but instead intense/high contrast.
I understand this may not be the case for some base16 themes and will result in problems trying to use them for programs created with dark themes in mind. Though this will be an issue regardless.
There was a problem hiding this comment.
I think ansi 7 for light themes should be dark.
Just looking at the color schemes here, that's not typical for a light color scheme. Regardless of whether the scheme is light or dark, ANSI black is typically black (or at least a dark color), and ANSI white is typically white/gray (or at least a lighter color).
There are obviously a lot of weird color schemes that do there own thing, but I thought it was generally expected that ANSI colors match their names, at least to some extent.
| { | ||
| if (_colorTableDirty) | ||
| { | ||
| _generate256ColorTable(); |
There was a problem hiding this comment.
I probably would have just thrown a mutable on and called it a day lmao
There was a problem hiding this comment.
We could consider silencing the const rule and just not use const anymore. It's rarely useful in my opinion.
| void RenderSettings::SetColorTableEntry(const size_t tableIndex, const COLORREF color) | ||
| { | ||
| _colorTable.at(tableIndex) = color; | ||
| _flagColorTableDirty(); | ||
| } |
There was a problem hiding this comment.
If you flag the color table as dirty, does that not mean it's going to be regenerated as soon as someone tries to use it? Because then it looks like an application attempting to change one palette entry is going to immediately cause all other entries to be reset. In fact, wouldn't that even reset the entry that has just been changed? That surely can't be right. Am I misunderstanding how this works?
Same thing applies to most of the other calls to _flagColorTableDirty below. Other than maybe RestoreDefaultIndexed256ColorTable, it doesn't seem like any of those operations should be triggering a reset of the palette.
There was a problem hiding this comment.
Hmm, I have only considered what happens if you change the color aliases and base colors, not what happens if you change the 240 other entries. I wonder what the best way to fix this is... Obviously, we could hold a "has this slot been overriden" array, but maybe I should simply not regenerate the table outside of the initial setup.
Now that I mention this, the 2nd array may actually be useful, because we already have this ambiguity around INVALID_COLOR...
There was a problem hiding this comment.
@lhecker I used the "has this slot been overridden" approach for my PRs.
There was a problem hiding this comment.
I should simply not regenerate the table outside of the initial setup.
Personally I think that would be preferable. Even if it wasn't potentially corrupting the color table, I wouldn't want it changing colors at runtime because of the performance implications. I have a number of games that use palette animation, which I suspect would be triggering this color table regeneration almost non-stop.
|
There is active discussion at the Ghostty repo about approaching this slightly differently. The idea is that light themes should not invert the palette so that ansi 16 remains black. This is with the intention of removing the breaking change of generating by default. Then, an opt-in option for "harmonious" colors which inverts the colors for light themes since there are advantages for doing so. |
Unlike the proposal this PR implements it using Oklab, which
we already had and previously found to be superior to CIELAB.
Lots of changes due to const-correctness (giga-meh)
and several to plumb settings through the model and UI.
The core is in the
TerminalSettingsclass, as you'd expect.The way this is implemented the dynamically generated palette
will react to changes in the palette via VT sequences.
Closes #19881
Validation Steps Performed