-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Add support for restoring a DECCTR color table report #13139
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I realize now, that making VTInt
a signed integer might've been a mistake... Thankfully it should be easier to change that since it's just a alias now.
If we need these two new color functions to be performant, we could use a LUT for mapping 0-100 to 0-255. That wouldn't just work for ColorFromRGB100
but also for ColorFromHLS
which can be written with integer arithmetic only (without integer division).
Why's that? I actually thought a signed int was the right choice. As an example, if you're working with VT coordinates, a typical calculation would be to add or subtract an offset, and then clamp the result within the active margins or buffer range. If that intermediate offset goes negative on a signed int that's not a problem - it's still going to clamp correctly. But if it's unsigned, it's going to wrap, and you're going to end up with the wrong result.
I like that idea. I am keen to get these functions as fast as possible, mostly for when they're used in sixel. Although HLS colors aren't likely to be used much, so the HLS one is less critical.
I've done some initial experiments with a LUT, and it's a big improvement for I'll play around some more and see if I can improve things, otherwise I'll just do the LUT for |
It's just... It kind of feels wrong to me at times. For instance your code does
Oh nice! I'm glad it works in practice! BTW here's a SO answer with a low-level HLS-RGB routine: https://stackoverflow.com/a/45450486 |
I see your point. My main concern was that we'd find ourselves having to cast to
They're relying on all the inputs being in the range 0-255, which allows them to do a bunch of bit shifting and masking that isn't applicable in our case. And then there's stuff like using a branch in place of So for now I think I'm happy to stick with the current HLS implementation, and just use your LUT idea in the RGB conversion. You're welcome to take a stab at optimising this further after it's merged, although as I said, the HLS routine isn't that critical. |
I agree. There's no need to overcomplicate it if it isn't used much. 🙂 BTW, I'm a bit surprised the |
Oh wow. I've always assumed Could I just use an |
Eh, honestly that's what Yes, creating new tools to work around our old tools being poor tools is the name of the game here. 😁 At least |
🤦♂️ Doh! That's what I thought I was using! And looking now, there are a bunch of other places in the code where I've used |
Oh right, |
OK, I think this is it. I've switched to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOVE IT! Thanks!
@msftbot make sure @DHowett signs off on this |
Hello @carlos-zamora! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request:
If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told you". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lovely, as always. Thank you!
// The color class is expecting components in the range 0 to 255, | ||
// so we need to scale our percentage values by 255/100. We can | ||
// optimise this conversion with a pre-created lookup table. | ||
static constexpr auto scale100To255 = [] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love that this is compiled-in :D
// - s - The saturation component of the color (0-100%). | ||
// Return Value: | ||
// - The color defined by the given components. | ||
til::color Utils::ColorFromHLS(const int h, const int l, const int s) noexcept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eventually, I will file a workitem for moving this stuff into til/color.h itself (not necessarily into the color
class, mind). We have about three copies of the HSL/HLS code, and perhaps we can get it down to 1. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm totally on board with this. I was initially expecting to put it somewhere related to the til::color
class - I only went with Utils
because that's what we were doing for the XTerm color routines. But as you noted below, these conversions are somewhat unique, and would probably need to be named something like ColorFromDecRGB
and ColorFromDecHLS
.
|
||
// Finally we order the components based on the given hue. But note that the | ||
// DEC terminals used a different mapping for hue than is typical for modern | ||
// color models. Blue is at 0°, red is at 120°, and green is at 240°. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, is this function more like ColorFromDecHLS
? Perhaps we should not generalize it... 😄
## Summary of the Pull Request Up to now we haven't supported passing `DCS` sequences over conpty, so any `DCS` operations would just be ignored in Windows Terminal. This PR introduces a mechanism whereby we can selectively pass through operations that could reasonably be handled by the connected terminal without interfering with the regular conpty renderer. For now this is just used to support restoring the `DECCTR` color table report. ## References Support for `DECCTR` was originally added to conhost in PR #13139. ## PR Checklist * [x] Closes #13223 * [x] CLA signed. * [x] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments The way this works is we have a helper method in `AdaptDispatch` that `DCS` operations can use to create a passthrough `StringHandler` for the incoming data instead of their usual handler. To make this passthrough process more efficient, the handler buffers the data before forwarding it to conpty. However, it's important that we aren't holding back data if output is paused before the string terminator, so we need to flush the buffer whenever we reach the end of the current write operation. This is achieved by querying a new method in the `StateMachine` that lets us know if we're currently dealing with the last character. Another issue that came up was with the way the `StateMachine` caches sequences that it might later need to forward to conpty. In the case of string sequences like `DCS`, we don't want the actual string data cached here, because that will just waste memory, and can also result in the data being mistakenly output. So I've now disabled that caching when we're in any of the string processing states. ## Validation Steps Performed I've manually confirmed that the `DECCTR` sequence can now update the color table in Windows Terminal. I've also added a new unit test in `ConptyRoundtripTests` to verify the sequence is being passed through successfully.
🎉 Handy links: |
This PR introduces the framework for the `DECRQTSR` sequence which is used to query terminal state reports. But for now I've just implemented the `DECCTR` color table report, which provides a way for applications to query the terminal's color scheme. ## References and Relevant Issues This is the counterpart to the the `DECRSTS` sequence, which is used to restore a color table report. That was implemented in PR #13139, but it only became practical to report the color table once conpty passthrough was added in PR #17510. ## Detailed Description of the Pull Request / Additional comments This sequence has the option of reporting the colors as either HLS or RGB, but in both cases the resolution is lower than 24 bits, so the colors won't necessarily round-trip exactly when saving and restoring. The HLS model in particular can accumulate rounding errors over time. ## Validation Steps Performed I've added a basic unit test that confirms the colors are reported as expected for both color models. The color values in these tests were obtained from color reports on a real VT525 terminal. ## PR Checklist - [x] Tests added/passed
This PR introduces the framework for the
DECRSTS
sequence which isused to restore terminal state reports. But to start with, I've just
implemented the
DECCTR
color table report, which provides a way forapplications to alter the terminal's color scheme.
PR Checklist
Detailed Description of the Pull Request / Additional comments
I've added the functions for parsing DEC RGB and HLS color formats into
the
Utils
class, where we've got all our other color parsing routines,since this functionality will eventually be needed in other VT protocols
like Sixel and ReGIS.
Since
DECRSTS
is aDCS
sequence, this only works in conhost for now,or when using the experimental passthrough mode in Windows Terminal.
Validation Steps Performed
I've added a number of unit tests to check that the
DECCTR
report isbeing interpreted as expected. This includes various edge cases (e.g.
omitted and out-of-range parameters), which I have confirmed to match
the color parsing on a real VT240 terminal.