Background colour sometimes ignored in Windows Terminal #12116

Closed
opened 2026-01-31 03:06:39 +00:00 by claunia · 5 comments
Owner

Originally created by @clinton-r on GitHub (Jan 19, 2021).

Environment

Microsoft Windows [Version 10.0.19041.746]
Windows Terminal Version: 1.4.3243.0
Microsoft Visual Studio Community 2019 Version 16.8.4

Steps to reproduce

Compile the test program below.
Open Windows Terminal cmd or Powershell tab. Run the program. (Might have to run it several times to see the problem.)

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

static HANDLE hStdin = NULL;
static HANDLE hStdout = NULL;

typedef struct
{
    int fgCode;
    int bgCode;
    char* colourName;

} VT_COLOUR_INFO;

void writeString(char* str)
{
#if 1
    WriteConsoleA(hStdout, str, strlen(str), NULL, NULL);
#else
    printf(str);
#endif
}

int main(void)
{
    char buf[1000];
    DWORD mode;

    // Get handles for stdin and stdout
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE || hStdin == NULL)
        return 1;
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdout == INVALID_HANDLE_VALUE || hStdout == NULL)
        return 1;

    // Enable escape sequences
    if (!GetConsoleMode(hStdout, &mode))
        return 1;
    if (!SetConsoleMode(hStdout, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
        return 1;

    if (!GetConsoleMode(hStdin, &mode))
        return 1;
    if (!SetConsoleMode(hStdin, mode | ENABLE_VIRTUAL_TERMINAL_INPUT))
        return 1;

    // TEST OUTPUT

    // SGR colour codes
    VT_COLOUR_INFO colourLookup[] =
    {
        { 30, 40, "black" },
        { 31, 41, "red" },
        { 32, 42, "green" },
        { 33, 43, "yellow" },
        { 34, 44, "blue" },
        { 35, 45, "magenta" },
        { 36, 46, "cyan" },
        { 37, 47, "white" },

        { 90, 100, "bright black" },
        { 91, 101, "bright red" },
        { 92, 102, "bright green" },
        { 93, 103, "bright yellow" },
        { 94, 104, "bright blue" },
        { 95, 105, "bright magenta" },
        { 96, 106, "bright cyan" },
        { 97, 107, "bright white" },
    };

    writeString("normal text\r\n");

    for (int bg = 0; bg < (sizeof(colourLookup) / sizeof(colourLookup[0])); bg += 1)
    {
        sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[bg].bgCode); // set background colour
        writeString(buf);
        for (int fg = 0; fg < (sizeof(colourLookup) / sizeof(colourLookup[0])); fg += 1)
        {
            writeString("\x1b[2K"); // erase line (set line to background colour)
            sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[fg].fgCode); // set foreground colour
            writeString(buf);
            sprintf_s(buf, sizeof(buf), "%16s on %16s ",
                colourLookup[fg].colourName, colourLookup[bg].colourName);
            writeString(buf);
            writeString("\x1b[7mnegative ");    // SGR negative on
            writeString("\x1b[27m");            // SGR negative off
            writeString("\x1b[4munderline ");   // SGR underline on
            writeString("\x1b[24m\r\n");        // SGR underline off
        }
    }

    writeString("\x1b[0m"); // SGR defaults
    writeString("\x1b[2K"); // erase line
    writeString("\r\nnormal text\r\n");

    if (!SetConsoleMode(hStdin, mode))
        return 1;

    return 0;
}

Expected behavior

The test program uses SGR VT sequences to show all the different foreground and background colours, as well as negative and underlined text.

Actual behavior

For each line, the program first erases the line before printing text on it, to set the entire line to the background colour. It appears that sometimes black is used instead of the background colour. Also, spaces are sometimes printed as black instead of the background colour as well. Here is an example with both line and a space:
bgcolour

Notes

Doesn't happen in conhost.

Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.)

Thanks

Originally created by @clinton-r on GitHub (Jan 19, 2021). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> <!-- This bug tracker is monitored by Windows Terminal development team and other technical folks. **Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**. Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue. If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link. Please use this form and describe your issue, concisely but precisely, with as much detail as possible. --> # Environment Microsoft Windows [Version 10.0.19041.746] Windows Terminal Version: 1.4.3243.0 Microsoft Visual Studio Community 2019 Version 16.8.4 # Steps to reproduce <!-- A description of how to trigger this bug. --> Compile the test program below. Open Windows Terminal cmd or Powershell tab. Run the program. (Might have to run it several times to see the problem.) ```C #include <stdio.h> #include <stdlib.h> #include <windows.h> static HANDLE hStdin = NULL; static HANDLE hStdout = NULL; typedef struct { int fgCode; int bgCode; char* colourName; } VT_COLOUR_INFO; void writeString(char* str) { #if 1 WriteConsoleA(hStdout, str, strlen(str), NULL, NULL); #else printf(str); #endif } int main(void) { char buf[1000]; DWORD mode; // Get handles for stdin and stdout hStdin = GetStdHandle(STD_INPUT_HANDLE); if (hStdin == INVALID_HANDLE_VALUE || hStdin == NULL) return 1; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdout == INVALID_HANDLE_VALUE || hStdout == NULL) return 1; // Enable escape sequences if (!GetConsoleMode(hStdout, &mode)) return 1; if (!SetConsoleMode(hStdout, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 1; if (!GetConsoleMode(hStdin, &mode)) return 1; if (!SetConsoleMode(hStdin, mode | ENABLE_VIRTUAL_TERMINAL_INPUT)) return 1; // TEST OUTPUT // SGR colour codes VT_COLOUR_INFO colourLookup[] = { { 30, 40, "black" }, { 31, 41, "red" }, { 32, 42, "green" }, { 33, 43, "yellow" }, { 34, 44, "blue" }, { 35, 45, "magenta" }, { 36, 46, "cyan" }, { 37, 47, "white" }, { 90, 100, "bright black" }, { 91, 101, "bright red" }, { 92, 102, "bright green" }, { 93, 103, "bright yellow" }, { 94, 104, "bright blue" }, { 95, 105, "bright magenta" }, { 96, 106, "bright cyan" }, { 97, 107, "bright white" }, }; writeString("normal text\r\n"); for (int bg = 0; bg < (sizeof(colourLookup) / sizeof(colourLookup[0])); bg += 1) { sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[bg].bgCode); // set background colour writeString(buf); for (int fg = 0; fg < (sizeof(colourLookup) / sizeof(colourLookup[0])); fg += 1) { writeString("\x1b[2K"); // erase line (set line to background colour) sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[fg].fgCode); // set foreground colour writeString(buf); sprintf_s(buf, sizeof(buf), "%16s on %16s ", colourLookup[fg].colourName, colourLookup[bg].colourName); writeString(buf); writeString("\x1b[7mnegative "); // SGR negative on writeString("\x1b[27m"); // SGR negative off writeString("\x1b[4munderline "); // SGR underline on writeString("\x1b[24m\r\n"); // SGR underline off } } writeString("\x1b[0m"); // SGR defaults writeString("\x1b[2K"); // erase line writeString("\r\nnormal text\r\n"); if (!SetConsoleMode(hStdin, mode)) return 1; return 0; } ``` # Expected behavior <!-- A description of what you're expecting, possibly containing screenshots or reference material. --> The test program uses SGR VT sequences to show all the different foreground and background colours, as well as negative and underlined text. # Actual behavior <!-- What's actually happening? --> For each line, the program first erases the line before printing text on it, to set the entire line to the background colour. It appears that sometimes black is used instead of the background colour. Also, spaces are sometimes printed as black instead of the background colour as well. Here is an example with both line and a space: ![bgcolour](https://user-images.githubusercontent.com/50687925/104981429-d44a4a80-59c5-11eb-8f95-4bc92fc34152.png) # Notes Doesn't happen in conhost. Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.) Thanks
Author
Owner

@zadjii-msft commented on GitHub (Jan 19, 2021):

Weird. I don't think this is #3848, though it does seem similar.

@zadjii-msft commented on GitHub (Jan 19, 2021): Weird. I don't think this is #3848, though it does seem similar.
Author
Owner

@j4james commented on GitHub (Jan 19, 2021):

This looks to me like a problem in the conpty space optimization - on some lines it's just not sending through the ESC [ K to clear the line. It's sensitive to timing, so by inserting sleeps in different parts of the test code, you can affect how often the problem shows up (or even prevent it showing up).

Issue #5430 might be related.

@j4james commented on GitHub (Jan 19, 2021): This looks to me like a problem in the conpty space optimization - on some lines it's just not sending through the `ESC [ K` to clear the line. It's sensitive to timing, so by inserting sleeps in different parts of the test code, you can affect how often the problem shows up (or even prevent it showing up). Issue #5430 might be related.
Author
Owner

@zadjii-msft commented on GitHub (Mar 1, 2022):

We believe this was fixed in Terminal v1.13, in #11982. @clinton-r would you mind confirming?

@zadjii-msft commented on GitHub (Mar 1, 2022): We believe this was fixed in Terminal v1.13, in #11982. @clinton-r would you mind confirming?
Author
Owner

@clinton-r commented on GitHub (Mar 2, 2022):

We believe this was fixed in Terminal v1.13, in #11982. @clinton-r would you mind confirming?

Hi @zadjii-msft , I just tried it again with version 1.13.10395.0 and the problem is gone. Thanks!

I had also mentioned this in the Notes section:

Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.)

(Note I meant the first line of the inner for loop.)

That is still the case, but I think it makes sense for it to be behaving like this - I assume it colours the full line when scrolling down, before I set the new colours and write text. Here's what it looks like:

scroll_bg_colour

@clinton-r commented on GitHub (Mar 2, 2022): > We believe this was fixed in Terminal v1.13, in #11982. @clinton-r would you mind confirming? Hi @zadjii-msft , I just tried it again with version 1.13.10395.0 and the problem is gone. Thanks! I had also mentioned this in the Notes section: >Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.) (Note I meant the first line of the _inner_ for loop.) That is still the case, but I think it makes sense for it to be behaving like this - I assume it colours the full line when scrolling down, before I set the new colours and write text. Here's what it looks like: ![scroll_bg_colour](https://user-images.githubusercontent.com/50687925/156442344-375a60f3-f832-4e18-b2cb-42ba9f0afefb.png)
Author
Owner

@zadjii-msft commented on GitHub (Mar 2, 2022):

Yep, that's correct. That's more in line with what other Terminal emulators do. Thanks for confirming!

@zadjii-msft commented on GitHub (Mar 2, 2022): Yep, that's correct. That's more in line with what other Terminal emulators do. Thanks for confirming!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#12116