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

Add support for the DECSCNM Screen Mode #3773

Closed
j4james opened this issue Nov 28, 2019 · 5 comments · Fixed by #3817
Closed

Add support for the DECSCNM Screen Mode #3773

j4james opened this issue Nov 28, 2019 · 5 comments · Fixed by #3817
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.

Comments

@j4james
Copy link
Collaborator

j4james commented Nov 28, 2019

Description of the new feature/enhancement

The DECSCNM (screen mode) escape sequence is a DEC private mode for switching the display between normal and reverse - often referred to as dark and light backgrounds on monochrome terminals. I doubt it's widely used in practice, but it's needed to pass some of the tests in the Vttest suite.

In the DEC STD 070 manual, the behaviour of the DECSCNM mode is described as follows:

Changing between normal and reverse screen mode will affect which attribute bits from display memory are used to render the text foreground and background color. It does not affect the current rendition, or how the current rendition is applied to the character attribute bits associated with each character in display memory.

I take that to mean that the background attributes of a cell will be used to render the text foreground and the foreground attributes will be used for the background. This seems to be how it's implemented in Konsole and the Linux virtual terminal, but there is quite a lot of variation in how other terminals interpret it. Without a clear consensus, though, I'd be inclined to follow the standard. As long as it passes Vttest, I don't think it really matters.

Proposed technical implementation details

Looking at the conhost side of things, I think this can be achieved with a new flag in the Settings class, and then updates to the LookupForegroundColor and LookupBackgroundColor methods, to switch the returned foreground and background colors when the flag is set. This seems to be enough to make the renderer draw everything with the correct colors, including underlines.

We'll also need a new private API in the ConGetSet interface, which can be called from the AdaptDispatch class to actually toggle the mode, and trigger a redraw of the display. And the HardReset implementation should probably be updated to reset the mode back to normal.

As for the Windows Terminal, my preliminary tests suggest it doesn't require anything special. Whatever is rendered on the conhost side seems to be passed through correctly via conpty as well.

@j4james j4james added the Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. label Nov 28, 2019
@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Nov 28, 2019
@egmontkob
Copy link

egmontkob commented Nov 28, 2019

I doubt it's widely used in practice

I think it's used by some apps to achieve a visual bell. Terminfo describes flash=\E[?5h$<100/>\E[?5l, the middle segment apparently encoding a delay. Accordingly, tput flash switches to global reverse mode for 0.1 seconds. I haven't seen any app (except for vttest) enabling this mode for a longer time, and they really shouldn't.

Probably the same question applies as for the per-character reverse mode (SGR 7): if combined with the "bright" attribute is it the foreground or the background to be brightened? I don't think it really matters. Probably the simplest is just to XOR the per-character "reverse" bit with this global flag, and have whatever comes out of that.

In my opinion emitting this sequence, even for the purpose of a visual bell, is a terrible practice. The timing is unreliable across a remote connection. The sudden switch between such different colors, especially if repeated a couple of times, could perhaps even trigger epileptic seizure in some people. I think apps should emit the regular BEL, and it should be a user setting of the terminal whether they want audible or visual bell (or both or none), whereas the visual can be implemented in more sophisticated ways, e.g. a smooth transition back and forth between normal and reverse video, or a(n animated) bell icon symbol showing up in the tab bar, etc.

I've also seen apps toggling this global reverse mode back and forth without a delay in between, expecting to achieve a visual bell effect – like, what?

You might also want to look at this bug in "screen": https://savannah.gnu.org/bugs/?52545, just to give you an idea how broken sometimes it is implemented in practice.

That being said, of course it's okay to support this feature in the terminal and blame the apps that actually use it. :)

@j4james
Copy link
Collaborator Author

j4james commented Nov 29, 2019

I think it's used by some apps to achieve a visual bell.

I did not know that. Thank you! In fact I see we already have a bug report for visual bell support from way back (#72), which probably means this can be closed as a dup.

Probably the simplest is just to XOR the per-character "reverse" bit with this global flag.

Yep. Based on my reading of the spec that was my conclusion too. The way our code is structured it doesn't work out exactly like that, but the end result is the same.

In my opinion emitting this sequence, even for the purpose of a visual bell, is a terrible practice ... I think apps should emit the regular BEL, and it should be a user setting of the terminal whether they want audible or visual bell (or both or none), whereas the visual can be implemented in more sophisticated ways

Agreed. And I'm convinced we already have an issue with a suggestion along those lines although I can't find it right now.

I've also seen apps toggling this global reverse mode back and forth without a delay in between, expecting to achieve a visual bell effect – like, what?

Yeah, I was just testing the visible bell-style in bash that was mentioned in issue #72, and that's exactly what happened - my DECSCNM implementation had no visible effect. The vim visualbell option does at least work though.

@egmontkob
Copy link

Haha, I totally did not remember that there was this #72 which I even commented on :-D

@DHowett-MSFT DHowett-MSFT added Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. Product-Conhost For issues in the Console codebase labels Nov 30, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Nov 30, 2019
@DHowett-MSFT DHowett-MSFT added Needs-Tag-Fix Doesn't match tag requirements and removed Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Nov 30, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Nov 30, 2019
@DHowett-MSFT DHowett-MSFT added this to the Console Backlog milestone Nov 30, 2019
@zadjii-msft zadjii-msft added Issue-Task It's a feature request, but it doesn't really need a major design. and removed Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. labels Dec 2, 2019
@ghost ghost added the In-PR This issue has a related PR label Dec 3, 2019
@ghost ghost closed this as completed in #3817 Jan 22, 2020
ghost pushed a commit that referenced this issue Jan 22, 2020
## Summary of the Pull Request

This adds support for the [`DECSCNM`](https://vt100.net/docs/vt510-rm/DECSCNM.html) private mode escape sequence, which toggles the display between normal and reverse screen modes. When reversed, the background and foreground colors are switched. Tested manually, with [Vttest](https://invisible-island.net/vttest/), and with some new unit tests.

## References

This also fixes issue #72 for the most part, although if you toggle the mode too fast, there is no discernible flash.

## PR Checklist
* [x] Closes #3773
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Requires documentation to be 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

I've implemented this as a new flag in the `Settings` class, along with updates to the `LookupForegroundColor` and `LookupBackgroundColor` methods, to switch the returned foreground and background colors when that flag is set. 

It also required a new private API in the `ConGetSet` interface to toggle the setting. And that API is then called from the `AdaptDispatch` class when the screen mode escape sequence is received.

The last thing needed was to add a step to the `HardReset` method, to reset the mode back to normal, which is one of the `RIS` requirements.

Note that this does currently work in the Windows Terminal, but once #2661 is implemented that may no longer be the case. It might become necessary to let the mode change sequences pass through conpty, and handle the color reversing on the client side.
 
## Validation Steps Performed

I've added a state machine test to make sure the escape sequence is dispatched correctly, and a screen buffer test to confirm that the mode change does alter the interpretation of colors as expected.

I've also confirmed that the various "light background" tests in Vttest now display correctly, and that the `tput flash` command (in a bash shell) does actually cause the screen to flash.
@ghost ghost added Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Jan 22, 2020
@ghost
Copy link

ghost commented Feb 13, 2020

🎉This issue was addressed in #3817, which has now been successfully released as Windows Terminal Preview v0.9.433.0.:tada:

Handy links:

@jdebp
Copy link

jdebp commented Feb 20, 2020

The original purpose of the screen mode setting is laid out in the user guides, not in the programmers' references. The VT420 user guide, for example, explains that it is for "viewing comfort" and is to "improve readability". It's really a user preference, configurable in SETUP. It is one of the lockable user preferences, meaning that DECSCNM from a host might not do anything at all.

Note that terminal emulators do not do what real terminals did. XTerm has a long tradition of swapping "light" and "dark", and others have copied it, for starters. But then they don't even behave the same as one another when it comes to DECSCNM. Some swap foreground and background; some swap colour indexes 0 and 7; and some only reverse default-coloured text.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants