Windows Terminal not properly resetting default colors altered within WSL #17853

Closed
opened 2026-01-31 05:56:21 +00:00 by claunia · 11 comments
Owner

Originally created by @RoiEXLab on GitHub (Jul 3, 2022).

Windows Terminal version

1.14.145 (the latest Windows Store preview)

Windows build number

10.0.19044.1766

Other Software

ncurses (probably not necessary, but used for the reproducer)
WSL using Ubuntu 20.04

Steps to reproduce

You need to have a working C++ compiler and ncurses installed (sudo apt install libncurses-dev), also I'm using colortest (sudo apt install colortest) to illustrate the before and after differences.

Run colortest-256 in the terminal. This should produce an output similar to this:
Color Example before

Then you create this file called "MinimalExample.cpp"

#include <algorithm>
#include <iostream>
#include <ncurses.h>
#include <unistd.h>


int main() {
  initscr();
  start_color();

  for (int color = 0; color < std::min(16, COLORS); color++) {
    init_color(color, 1000, 0, 0);
  }
  refresh();
  usleep(500000);
  // separates initialization from tear down in stdout
  std::cout << std::endl << std::endl;
  endwin();
}

And compile it using g++ (clang should work too in theory, haven't tested it) using g++ ./MinimalExample.cpp -lncurses.
Then run it using ./a.out.

Expected Behavior

Using a regular bash shell inside a Ubuntu 20.04 VM colortest-256 has the same output regardless if the example code has been run. (This is also the case when using the VS Code Terminal with the WSL integration.) Within the application the colors 0-15 are correctly changing, it should just reset properly when ending the application.

Actual Behavior

Using the standard terminal (conhost.exe) and within Windows Terminal this causes the 16 standard colors to be replaced with #F00. This makes colortest-256 output this result:
Colortest output after

When looking at stdout the example code creates something along those lines (the output is escaped to be readable):

ESC[?1049hESC[22;0;0tESC[1;71rESC(BESC[mESC[4lESC[?7hESC[39;49mESC]4;0;rgb:FF/00/00ESC\ESC]4;1;rgb:FF/00/00ESC\ESC]4;2;rgb:FF/00/00ESC\ESC]4;3;rgb:FF/00/00ESC\ESC]4;4;rgb:FF/00/00ESC\ESC]4;5;rgb:FF/00/00ESC\ESC]4;6;rgb:FF/00/00ESC\ESC]4;7;rgb:FF/00/00ESC\ESC]4;8;rgb:FF/00/00ESC\
ESC]4;9;rgb:FF/00/00ESC\ESC]4;10;rgb:FF/00/00ESC\ESC]4;11;rgb:FF/00/00ESC\ESC]4;12;rgb:FF/00/00ESC\ESC]4;13;rgb:FF/00/00ESC\ESC]4;14;rgb:FF/00/00ESC\ESC]4;15;rgb:FF/00/00ESC\ESC[39;49mESC[37mESC[40mESC[HESC[2J

ESC[39;49mESC[71dESC[KESC[39;49mESC]104^GESC[71;1HESC[?1049lESC[23;0;0t^MESC[?1lESC>

So on a regular Ubuntu Terminal the last line seems to properly reset the colors, for Windows Terminal and conhost.exe this does not seem to be the case. Someone familiar with those Escape sequences can probably understand the output, but for me it's just a lot of gibberish. (Also there's probably a way to transform this output into a bash script to skip the whole compilation step in the reproducer, no idea on how to do that though, also this makes it dependent on the os/terminal capabilities probably).
The reset command in bash does not help either

If there's some more info you need me to provide I'd be happy to help here.

Originally created by @RoiEXLab on GitHub (Jul 3, 2022). ### Windows Terminal version 1.14.145 (the latest Windows Store preview) ### Windows build number 10.0.19044.1766 ### Other Software ncurses (probably not necessary, but used for the reproducer) WSL using Ubuntu 20.04 ### Steps to reproduce You need to have a working C++ compiler and ncurses installed (`sudo apt install libncurses-dev`), also I'm using colortest (`sudo apt install colortest`) to illustrate the before and after differences. Run `colortest-256` in the terminal. This should produce an output similar to this: ![Color Example before](https://user-images.githubusercontent.com/8350879/177055326-9f0d2566-31b0-4bf0-89b3-de439bdb2319.png) Then you create this file called "MinimalExample.cpp" ```c++ #include <algorithm> #include <iostream> #include <ncurses.h> #include <unistd.h> int main() { initscr(); start_color(); for (int color = 0; color < std::min(16, COLORS); color++) { init_color(color, 1000, 0, 0); } refresh(); usleep(500000); // separates initialization from tear down in stdout std::cout << std::endl << std::endl; endwin(); } ``` And compile it using g++ (clang should work too in theory, haven't tested it) using `g++ ./MinimalExample.cpp -lncurses`. Then run it using `./a.out`. ### Expected Behavior Using a regular bash shell inside a Ubuntu 20.04 VM `colortest-256` has the same output regardless if the example code has been run. (This is also the case when using the VS Code Terminal with the WSL integration.) Within the application the colors 0-15 are correctly changing, it should just reset properly when ending the application. ### Actual Behavior Using the standard terminal (conhost.exe) and within Windows Terminal this causes the 16 standard colors to be replaced with `#F00`. This makes `colortest-256` output this result: ![Colortest output after](https://user-images.githubusercontent.com/8350879/177055431-308ec71a-96c2-41a8-af6d-c54c4cbc2623.png) When looking at stdout the example code creates something along those lines (the output is escaped to be readable): ``` ESC[?1049hESC[22;0;0tESC[1;71rESC(BESC[mESC[4lESC[?7hESC[39;49mESC]4;0;rgb:FF/00/00ESC\ESC]4;1;rgb:FF/00/00ESC\ESC]4;2;rgb:FF/00/00ESC\ESC]4;3;rgb:FF/00/00ESC\ESC]4;4;rgb:FF/00/00ESC\ESC]4;5;rgb:FF/00/00ESC\ESC]4;6;rgb:FF/00/00ESC\ESC]4;7;rgb:FF/00/00ESC\ESC]4;8;rgb:FF/00/00ESC\ ESC]4;9;rgb:FF/00/00ESC\ESC]4;10;rgb:FF/00/00ESC\ESC]4;11;rgb:FF/00/00ESC\ESC]4;12;rgb:FF/00/00ESC\ESC]4;13;rgb:FF/00/00ESC\ESC]4;14;rgb:FF/00/00ESC\ESC]4;15;rgb:FF/00/00ESC\ESC[39;49mESC[37mESC[40mESC[HESC[2J ESC[39;49mESC[71dESC[KESC[39;49mESC]104^GESC[71;1HESC[?1049lESC[23;0;0t^MESC[?1lESC> ``` So on a regular Ubuntu Terminal the last line seems to properly reset the colors, for Windows Terminal and conhost.exe this does not seem to be the case. Someone familiar with those Escape sequences can probably understand the output, but for me it's just a lot of gibberish. (Also there's probably a way to transform this output into a bash script to skip the whole compilation step in the reproducer, no idea on how to do that though, also this makes it dependent on the os/terminal capabilities probably). The `reset` command in bash does not help either If there's some more info you need me to provide I'd be happy to help here.
claunia added the Issue-BugResolution-Duplicate labels 2026-01-31 05:56:22 +00:00
Author
Owner

@j4james commented on GitHub (Jul 5, 2022):

The sequence that resets the palette in that last line is OSC 104. We don't yet support that, but it's being tracked in issue #3719.

@j4james commented on GitHub (Jul 5, 2022): The sequence that resets the palette in that last line is `OSC 104`. We don't yet support that, but it's being tracked in issue #3719.
Author
Owner

@RoiEXLab commented on GitHub (Jul 5, 2022):

@j4james Thank you for your reply. Good to know what the reason for the issue is. The workaround for me was not to alter the first 16 colors (even though it would be legal for regular xterm compliant terminals), which is a bummer because this way the limited 256 colors are limited even further to 240, but is fine for my use-case.
What's not fine is that the default conhost.exe literally becomes unusable when using the reproducer because it makes the text a red font on a red background more or less permanently. Windows Terminal is still usable with a reduced color palette (red) but the background and text color seem to be controlled by the user settings, so it's not that bad.

I have some questions about this though:
Has there been some progress in the past 2 years? What are the hurdles that need to be overcome?
The issue you linked makes it sound like there is no supported way to reset the color scheme at all, right? Otherwise it would be possible to create a custom entry in the capability database and replace OSC 104 with an alternative control code. Is that correct?

Thanks in advance.

@RoiEXLab commented on GitHub (Jul 5, 2022): @j4james Thank you for your reply. Good to know what the reason for the issue is. The workaround for me was not to alter the first 16 colors (even though it would be legal for regular xterm compliant terminals), which is a bummer because this way the limited 256 colors are limited even further to 240, but is fine for my use-case. What's not fine is that the default `conhost.exe` literally becomes unusable when using the reproducer because it makes the text a red font on a red background more or less permanently. Windows Terminal is still usable with a reduced color palette (red) but the background and text color seem to be controlled by the user settings, so it's not that bad. I have some questions about this though: Has there been some progress in the past 2 years? What are the hurdles that need to be overcome? The issue you linked makes it sound like there is no supported way to reset the color scheme at all, right? Otherwise it would be possible to create a custom entry in the capability database and replace `OSC 104` with an alternative control code. Is that correct? Thanks in advance.
Author
Owner

@j4james commented on GitHub (Jul 5, 2022):

Windows Terminal is still usable with a reduced color palette (red) but the background and text color seem to be controlled by the user settings, so it's not that bad.

FWIW, you can actually setup conhost to work that way too. In the Properties dialog, on the Terminal tab, check the Use Separate Foreground and Use Separate Background options.

Has there been some progress in the past 2 years?

Not on this issue specifically, but there was a lot of refactoring work done that should make it easier to implement now than it would have been 2 years ago.

What are the hurdles that need to be overcome?

As mentioned in #3719, conhost doesn't really have the concept of a "default palette" that we can reset to, so we need to figure out a plan for that. And then someone needs to actually write the code.

The issue you linked makes it sound like there is no supported way to reset the color scheme at all, right?

That's correct.

@j4james commented on GitHub (Jul 5, 2022): > Windows Terminal is still usable with a reduced color palette (red) but the background and text color seem to be controlled by the user settings, so it's not that bad. FWIW, you can actually setup conhost to work that way too. In the _Properties_ dialog, on the _Terminal_ tab, check the _Use Separate Foreground_ and _Use Separate Background_ options. > Has there been some progress in the past 2 years? Not on this issue specifically, but there was a lot of refactoring work done that should make it easier to implement now than it would have been 2 years ago. > What are the hurdles that need to be overcome? As mentioned in #3719, conhost doesn't really have the concept of a "default palette" that we can reset to, so we need to figure out a plan for that. And then someone needs to actually write the code. > The issue you linked makes it sound like there is no supported way to reset the color scheme at all, right? That's correct.
Author
Owner

@DHowett commented on GitHub (Jul 5, 2022):

Thanks for the report @RoiEXLab, and for finding the root cause @j4james. I'm going to close this as a /duplicate of #3719.

I do have to ask, however: Why is there an application that is setting the entire 16-color palette to one color? That can't be readable while the application is running, OSC 104 support notwithstanding. Is there a purpose we're missing, and would it be better handled with better VT support somewhere else?

In addition... can that application break the 256 (240)-color limit by using direct 24-bit color?

@DHowett commented on GitHub (Jul 5, 2022): Thanks for the report @RoiEXLab, and for finding the root cause @j4james. I'm going to close this as a /duplicate of #3719. I do have to ask, however: Why is there an application that is setting the entire 16-color palette to one color? That can't be readable _while the application is running_, `OSC 104` support notwithstanding. Is there a purpose we're missing, and would it be better handled with better VT support somewhere else? In addition... can that application break the 256 (240)-color limit by using direct 24-bit color?
Author
Owner

@ghost commented on GitHub (Jul 5, 2022):

Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!

@ghost commented on GitHub (Jul 5, 2022): Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!
Author
Owner

@RoiEXLab commented on GitHub (Jul 5, 2022):

Why is there an application that is setting the entire 16-color palette to one color?

Technically it was various shades of red in the actual code to be able to visualize a very basic heat map in the console, so color 0-15 were set to colors #000000 to #0F0000 (up to 255) but conhost.exe uses colors 10-13 (I think) for the part where it says username@hostname:~$ which is pretty much indistinguishable for the human eye

In addition... can that application break the 256 (240)-color limit by using direct 24-bit color?

I have no idea. What exactly do you mean by breaking the limit?

@RoiEXLab commented on GitHub (Jul 5, 2022): > Why is there an application that is setting the entire 16-color palette to one color? Technically it was various shades of red in the actual code to be able to visualize a very basic heat map in the console, so color 0-15 were set to colors `#000000` to `#0F0000` (up to 255) but conhost.exe uses colors 10-13 (I think) for the part where it says `username@hostname:~$` which is pretty much indistinguishable for the human eye > In addition... can that application break the 256 (240)-color limit by using direct 24-bit color? I have no idea. What exactly do you mean by breaking the limit?
Author
Owner

@RoiEXLab commented on GitHub (Jul 5, 2022):

@j4james I had a quick look at the codebase for Window Terminal (ignoring conhost) and implementing a handler for code 104 seemed relatively straightforward. So I gave it a quick shot aaand nothing happened.
Would you mind having a look at my branch? https://github.com/microsoft/terminal/compare/main...RoiEXLab:terminal:osc-104 it seems like the only problem (maybe I'm naive to believe that, feel free to correct me :D ) is that OutputStateMachineEngine is not called for OSC 104? OSC 4 triggered a breakpoint for me, but not 104. Am I missing something important?

@RoiEXLab commented on GitHub (Jul 5, 2022): @j4james I had a quick look at the codebase for Window Terminal (ignoring conhost) and implementing a handler for code 104 seemed relatively straightforward. So I gave it a quick shot aaand nothing happened. Would you mind having a look at my branch? https://github.com/microsoft/terminal/compare/main...RoiEXLab:terminal:osc-104 it seems like the only problem (maybe I'm naive to believe that, feel free to correct me :D ) is that `OutputStateMachineEngine` is not called for `OSC 104`? `OSC 4` triggered a breakpoint for me, but not 104. Am I missing something important?
Author
Owner

@DHowett commented on GitHub (Jul 5, 2022):

I have no idea. What exactly do you mean by breaking the limit?

Many modern terminals support 24-bit color--xterm included--through the specification of individual red, green and blue components from 0-255. One of the chief benefits of using 24-bit color is that the hardcopy in scrollback, if you commit to scrollback, will retain the colors as-emitted rather than switching back to the original definitons for each indexed color after you issue OSC 104.

image
@DHowett commented on GitHub (Jul 5, 2022): > I have no idea. What exactly do you mean by breaking the limit? Many modern terminals [support 24-bit color](https://github.com/termstandard/colors)--xterm included--through the specification of individual red, green and blue components from 0-255. One of the chief benefits of using 24-bit color is that the hardcopy in scrollback, if you commit to scrollback, will retain the colors as-emitted rather than switching back to the original definitons for each indexed color after you issue `OSC 104`. <img width="617" alt="image" src="https://user-images.githubusercontent.com/189190/177405644-6a7ecdde-478e-40cc-9f3d-89e59032471d.png">
Author
Owner

@j4james commented on GitHub (Jul 5, 2022):

it seems like the only problem (maybe I'm naive to believe that, feel free to correct me :D ) is that OutputStateMachineEngine is not called for OSC 104?

It looks to me like it's a limitation of the existing OSC parser. It expects the OSC number to be followed by a semicolon, otherwise it's just ignored. So that will need to be fixed, but you can at least get a little further with testing your code by doing something like printf "\e]104;\e\\".

However, the real problem is that RenderSettings::ResetColorTable doesn't actually do what we need here. It just sets the first 16 palette entries to the "default" Campbell color scheme. We need to reset those values to the user's chosen color scheme.

Also, by default OSC 104 should reset the full 256 color table, but if there were any parameter values following the 104, then it should only reset the given color table entries corresponding to those values.

@j4james commented on GitHub (Jul 5, 2022): > it seems like the only problem (maybe I'm naive to believe that, feel free to correct me :D ) is that `OutputStateMachineEngine` is not called for `OSC 104`? It looks to me like it's a limitation of the existing `OSC` parser. It expects the `OSC` number to be followed by a semicolon, otherwise it's just ignored. So that will need to be fixed, but you can at least get a little further with testing your code by doing something like `printf "\e]104;\e\\"`. However, the real problem is that `RenderSettings::ResetColorTable` doesn't actually do what we need here. It just sets the first 16 palette entries to the "default" Campbell color scheme. We need to reset those values to the user's chosen color scheme. Also, by default `OSC 104` should reset the full 256 color table, but if there were any parameter values following the 104, then it should only reset the given color table entries corresponding to those values.
Author
Owner

@RoiEXLab commented on GitHub (Jul 6, 2022):

@j4james

So that will need to be fixed, but you can at least get a little further with testing your code by doing something like printf "\e]104;\e\\".

However, the real problem is that RenderSettings::ResetColorTable doesn't actually do what we need here. It just sets the first 16 palette entries to the "default" Campbell color scheme. We need to reset those values to the user's chosen color scheme.

Good idea using the printf. It definitely works for the default color scheme, just verified this. colortest-256 shows the original colors.

@DHowett
I did some research (even though I haven't completely figured it out) and it looks like the most recent version of ncurses supports direct color with 24 bits. The ncurses repository even provides a "demo", but I haven't been able to build it with the direct color extension enabled so far: https://github.com/ThomasDickey/ncurses-snapshots/blob/master/test/picsmap.c
So the documentation says there's a way, but I haven't been able to reproduce it myself.

@RoiEXLab commented on GitHub (Jul 6, 2022): @j4james > So that will need to be fixed, but you can at least get a little further with testing your code by doing something like `printf "\e]104;\e\\"`. > > However, the real problem is that `RenderSettings::ResetColorTable` doesn't actually do what we need here. It just sets the first 16 palette entries to the "default" Campbell color scheme. We need to reset those values to the user's chosen color scheme. Good idea using the printf. It definitely works for the default color scheme, just verified this. `colortest-256` shows the original colors. @DHowett I did some research (even though I haven't completely figured it out) and it looks like the most recent version of ncurses supports direct color with 24 bits. The ncurses repository even provides a "demo", but I haven't been able to build it with the direct color extension enabled so far: https://github.com/ThomasDickey/ncurses-snapshots/blob/master/test/picsmap.c So the documentation says there's a way, but I haven't been able to reproduce it myself.
Author
Owner

@ClaireCJS commented on GitHub (Dec 9, 2024):

So they recently added \027c as a way to reset the colors.

It works, but it also clears the screen and shouldn’t...

@ClaireCJS commented on GitHub (Dec 9, 2024): So they recently added \027c as a way to reset the colors. It works, but it also clears the screen and shouldn’t...
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#17853