From d636a1de86c68bc19512b1c92bad17116e6dab5e Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Sat, 22 Apr 2017 14:57:35 -0700 Subject: [PATCH] Synthesize a WINDOW_BUFFER_SIZE_EVENT event after winpty is resized Fixes https://github.com/rprichard/winpty/issues/110. --- src/agent/Agent.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/agent/Agent.cc b/src/agent/Agent.cc index 649aecc..8b2b4a1 100644 --- a/src/agent/Agent.cc +++ b/src/agent/Agent.cc @@ -529,11 +529,31 @@ void Agent::resizeWindow(int cols, int rows) Win32Console::FreezeGuard guard(m_console, m_console.frozen()); const Coord newSize(cols, rows); ConsoleScreenBufferInfo info; - m_primaryScraper->resizeWindow(*openPrimaryBuffer(), newSize, info); + auto primaryBuffer = openPrimaryBuffer(); + m_primaryScraper->resizeWindow(*primaryBuffer, newSize, info); m_consoleInput->setMouseWindowRect(info.windowRect()); if (m_errorScraper) { m_errorScraper->resizeWindow(*m_errorBuffer, newSize, info); } + + // Synthesize a WINDOW_BUFFER_SIZE_EVENT event. Normally, Windows + // generates this event only when the buffer size changes, not when the + // window size changes. This behavior is undesirable in two ways: + // - When winpty expands the window horizontally, it must expand the + // buffer first, then the window. At least some programs (e.g. the WSL + // bash.exe wrapper) use the window width rather than the buffer width, + // so there is a short timespan during which they can read the wrong + // value. + // - If the window's vertical size is changed, no event is generated, + // even though a typical well-behaved console program cares about the + // *window* height, not the *buffer* height. + // This synthesization works around a design flaw in the console. It's probably + // harmless. See https://github.com/rprichard/winpty/issues/110. + INPUT_RECORD sizeEvent {}; + sizeEvent.EventType = WINDOW_BUFFER_SIZE_EVENT; + sizeEvent.Event.WindowBufferSizeEvent.dwSize = primaryBuffer->bufferSize(); + DWORD actual {}; + WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &sizeEvent, 1, &actual); } void Agent::scrapeBuffers()