Skip to content

Commit 741633e

Browse files
authored
ConPTY: Avoid WINDOW_BUFFER_SIZE_EVENT when the viewport moves (#15935)
`SetConsoleWindowInfoImpl` calls `PostUpdateWindowSize`, which emits a `CM_SET_WINDOW_SIZE` event, which causes `_InternalSetWindowSize` to be called, which calls `ScreenBufferSizeChange` which then finally emits a `WINDOW_BUFFER_SIZE_EVENT` event into the client input buffer. This messes up applications like which make use of `WINDOW_BUFFER_SIZE_EVENT` to perform potentially lossy operations. In case of SSH this results in a resize (SIGWINCH) of the server-side screen which similarly may result in a response by the shell, etc. Since that happens over networks and is async, and because our conhost VT viewport implementation appears to have a number of subtle bugs, this results in duplicate output lines (sometimes hundreds). Under Windows Terminal this issue is not as apparent, since ConPTY has no viewport that can be moved and no scrollback. It only appears as an issue if a terminal application reacts poorly to the SIGWINCH event. Closes #15769 ## Validation Steps Performed * Set a breakpoint in `SynthesizeWindowBufferSizeEvent` * Launch WSL and cause the viewport to move down No calls to `SynthesizeWindowBufferSizeEvent` ✅ * Execute `tput reset` Input line moves to row 0 ✅
1 parent 2fa8e76 commit 741633e

File tree

2 files changed

+6
-3
lines changed

2 files changed

+6
-3
lines changed

.github/actions/spelling/expect/expect.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,7 @@ touchpad
19081908
Tpp
19091909
Tpqrst
19101910
tprivapi
1911+
tput
19111912
tracelog
19121913
tracelogging
19131914
traceloggingprovider

src/host/outputStream.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ til::rect ConhostInternalGetSet::GetViewport() const
9595
void ConhostInternalGetSet::SetViewportPosition(const til::point position)
9696
{
9797
auto& info = _io.GetActiveOutputBuffer();
98-
const auto dimensions = info.GetViewport().Dimensions();
99-
const auto windowRect = til::rect{ position, dimensions }.to_inclusive_rect();
100-
THROW_IF_FAILED(ServiceLocator::LocateGlobals().api->SetConsoleWindowInfoImpl(info, true, windowRect));
98+
THROW_IF_FAILED(info.SetViewportOrigin(true, position, false));
99+
// SetViewportOrigin() only updates the virtual bottom (the bottom coordinate of the area
100+
// in the text buffer a VT client writes its output into) when it's moving downwards.
101+
// But this function is meant to truly move the viewport no matter what. Otherwise `tput reset` breaks.
102+
info.UpdateBottom();
101103
}
102104

103105
// Method Description:

0 commit comments

Comments
 (0)