terminal: GetConsoleScreenBufferInfoEx doesn't return the actual palette
Windows Terminal version (or Windows build number)
1.9.1523.0
Other Software
No response
Steps to reproduce
- Compile the following code:
#include <iomanip>
#include <iostream>
#include <windows.h>
int main()
{
CONSOLE_SCREEN_BUFFER_INFOEX Info{ sizeof(Info) };
if (!GetConsoleScreenBufferInfoEx(GetStdHandle(STD_OUTPUT_HANDLE), &Info))
return 1;
for (const auto& i: Info.ColorTable)
{
std::cout << std::hex << std::setw(8) << std::setfill('0') << i << '\n';
}
std::cout.flush();
}
- Set WT palette to “Vintage” in settings
- Run the compiled code
Expected Behavior
The same colour codes as in the corresponding section of C:\Program Files\WindowsApps\Microsoft.WindowsTerminalPreview_1.9.1523.0_x64__8wekyb3d8bbwe\defaults.json
:
000000
800000
008000
808000
000080
800080
008080
C0C0C0
808080
FF0000
00FF00
FFFF00
0000FF
FF00FF
00FFFF
FFFFFF
Actual Behavior
It looks like the default Windows 10 palette is returned instead:
000c0c0c
00da3700
000ea113
00dd963a
001f0fc5
00981788
00009cc1
00cccccc
00767676
00ff783b
000cc616
00d6d661
005648e7
009e00b4
00a5f1f9
00f2f2f2
About this issue
- Original URL
- State: open
- Created 3 years ago
- Comments: 17 (7 by maintainers)
Commits related to this issue
- Add undoc Lua API to get the color table. Terminal and the new conhost do not support GetConsoleScreenBufferInfoEx returning the actual color table. If/when that issues gets fixed, then Clink will b... — committed to chrisant996/clink by chrisant996 7 months ago
- Detect light/dark theme when using legacy conhost. Can't work in Windows Terminal until Terminal#10639 is fixed. https://github.com/microsoft/terminal/issues/10639 — committed to chrisant996/clink by chrisant996 7 months ago
That was my proposal / patch you came across 😃
Here’s the link for reference: https://gitlab.gnome.org/GNOME/vte/-/issues/2740
(For thread tending purposes, I moved the byte swapping discussion over to #16795)
My understanding is that conpty is designed to work in a similar fashion to the Linux pty system, so a Linux terminal could theoretically be ported to Windows without too much effort. I don’t know all the details, but I think there’s an input stream, an output stream, and a signal stream, and it’s the latter that is responsible for notifying conhost of window size changes, similar to the
SIGWINCH
signal on LinuxThere isn’t an equivalent signal for palette changes (as far as I’m aware), so that would be something we’d have to invent. Whereas conhost querying the palette from the conpty client just relies on standard escape sequences that a lot of terminals should already support out of the box. That’s why I was considering a query as my initial approach to the problem.
But as you’re both proposing, having the conpty client notify conhost of palette changes does seem like a much better idea. And if some don’t support it, they’d be no worse off than they are now. I’m not very familiar with this part of the code, so there may be technical reasons why this isn’t feasible, but if the core devs don’t raise any objections, I’d be willing to give it a try some time.
@j4james @zadjii-msft Here are some brainstorming thoughts. Maybe some of them will be viable, or maybe some of them with spark further ideas.
What if conhost didn’t need to wait?
Yes, GCSBIE can get called a ton. What if the work weren’t done every time?
Do you mean that there is a single two-way channel of communication, i.e. all data communication must be through input and output streams, so the two sides can only communicate by passing escape codes to each other? And so if one side doesn’t support responding to a query sequence then the other side can hang?
I agree that supporting palette changes at runtime should be considered a requirement for any solution. Making runtime palette changes instantly be noticed is not necessarily a requirement, though.
I’m not suggesting it would be trivial to implement, nor that it should be perfect with no caveats. But this is currently a pretty significant regression from the perspective of console mode programs.
Why? I have a very basic idea of how all this is organised, but this sounds unnecessarily inverted. Why can’t conhost return its internal local array, exactly as it does currently, but update that array whenever the connected conpty client updates its palette? There should be some notification mechanism. After all, you somehow do know client’s window and buffer dimensions, and I don’t think they are queried every time in a blocking way.
Our usage of this API is mostly related to colours mixing, e.g. transparency and shadows. To properly mix index colours we have to know to which exactly RGB values they are mapped.