Repository navigation
Description
Windows Terminal version
1.25.2733.0 (binary ProductVersion 1.25.260930003). Code inspection suggests v1.26.2734.0 and main are also affected; not tested at runtime.
Windows build number
10.0.26100.7462
Other Software
Found with oh-my-pi v18.6.0, a TUI that runs on the main screen with CSI > 1 u and switches to the alternate screen temporarily for fullscreen overlays. The repro below needs only PowerShell 7.
Steps to reproduce
Run this in a Windows Terminal PowerShell 7 tab (pwsh -NoProfile -File repro.ps1). It pushes Kitty flags on the main screen, enters and leaves the alternate screen without touching the Kitty stack, and queries the current flags (CSI ? u) after each step:
Add-Type -Namespace W -Name K -MemberDefinition @'
[DllImport("kernel32.dll")] public static extern IntPtr GetStdHandle(int h);
[DllImport("kernel32.dll")] public static extern bool GetConsoleMode(IntPtr h, out uint m);
[DllImport("kernel32.dll")] public static extern bool SetConsoleMode(IntPtr h, uint m);
'@
$h = [W.K]::GetStdHandle(-10); $mode = 0; [void][W.K]::GetConsoleMode($h, [ref]$mode)
[void][W.K]::SetConsoleMode($h, ($mode -bor 0x200) -band -bnot 0x7) # VT input on; line/echo/processed off
$e = [char]27
function Query-Flags {
[Console]::Write("$e[?u")
$s = ''; while (-not $s.EndsWith('u')) { $s += [Console]::ReadKey($true).KeyChar }
$s.Substring(1)
}
try {
$r = [ordered]@{}
[Console]::Write("$e[>1u"); $r['1. push 1 on main screen '] = Query-Flags
[Console]::Write("$e[?1049h"); $r['2. enter alternate screen '] = Query-Flags
[Console]::Write("$e[?1049l"); $r['3. leave alternate screen '] = Query-Flags
} finally {
[Console]::Write("$e[<u"); [void][W.K]::SetConsoleMode($h, $mode)
}
$r.GetEnumerator() | ForEach-Object { "$($_.Key) -> ESC$($_.Value)" }The same thing happens with the sequence a well-behaved app sends: CSI > 1 u on main, then CSI ? 1049 h, CSI > 1 u, CSI < u, CSI ? 1049 l.
Expected Behavior
1. push 1 on main screen -> ESC[?1u
2. enter alternate screen -> ESC[?0u
3. leave alternate screen -> ESC[?1u
Leaving the alternate screen should bring back the flags that were active on the main screen. The spec says:
The main and alternate screens in the terminal emulator must maintain their own, independent, keyboard mode stacks. This is so that a program that uses the alternate screen such as an editor, can change the keyboard mode in the alternate screen only, without affecting the mode in the main screen or even knowing what that mode is.
Actual Behavior
1. push 1 on main screen -> ESC[?1u
2. enter alternate screen -> ESC[?0u
3. leave alternate screen -> ESC[?0u
After step 3 the main screen is back to legacy encoding, but the main-screen app still assumes the flags it pushed are active. In practice, Shift+Enter starts arriving as a plain \r (so it submits instead of inserting a newline) and Ctrl+Enter as \n. Nothing tells the app that its mode was dropped.
Probable cause, in terminalInput.cpp:
// PushKittyFlags
stack.push_back(_kittyFlags); // saves the flags in effect *before* the push
_kittyFlags = flags; // flags that are now active live only here
// UseAlternateScreenBuffer
_kittyFlags = 0; // main screen's active flags are not saved anywhere
// UseMainScreenBuffer
_kittyFlags = _kittyMainStack.empty() ? 0 : _kittyMainStack.back(); // restores the *pre-push* valueThe stack holds the values to restore on pop, not the flags currently in effect. So _kittyMainStack.back() is the main screen's state from before its last push, which is 0 in the repro. One way to fix this is to save the main screen's _kittyFlags in UseAlternateScreenBuffer and restore that value in UseMainScreenBuffer, for example with separate _kittyMainFlags / _kittyAltFlags.
Activity
Restore KKP flags when disabling ASB (microsoft#20768)
chore(deps): update dependency can1357/oh-my-pi to v18.11.1 (#1350)
Restore KKP flags when disabling ASB (#20768)
Restore KKP flags when disabling ASB (#20768)