Skip to content

Commit 1db2606

Browse files
committed
Windows: preserve the current window size on exit
1 parent 82fe19d commit 1db2606

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

source/platform/stdioctl.cpp

+43-2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ namespace stdioctl
172172
return GetConsoleMode(h, &mode);
173173
}
174174

175+
static COORD windowSize(SMALL_RECT srWindow)
176+
{
177+
return {
178+
srWindow.Right - srWindow.Left + 1,
179+
srWindow.Bottom - srWindow.Top + 1,
180+
};
181+
}
182+
175183
} // namespace stdioctl
176184

177185
StdioCtl::StdioCtl() noexcept
@@ -271,8 +279,7 @@ StdioCtl::StdioCtl() noexcept
271279
// Force the screen buffer size to match the window size.
272280
// The Console API guarantees this, but some implementations
273281
// are not compliant (e.g. Wine).
274-
sbInfo.dwSize.X = sbInfo.srWindow.Right - sbInfo.srWindow.Left + 1;
275-
sbInfo.dwSize.Y = sbInfo.srWindow.Bottom - sbInfo.srWindow.Top + 1;
282+
sbInfo.dwSize = windowSize(sbInfo.srWindow);
276283
SetConsoleScreenBufferSize(cn[activeOutput].handle, sbInfo.dwSize);
277284
}
278285
SetConsoleActiveScreenBuffer(cn[activeOutput].handle);
@@ -286,6 +293,40 @@ StdioCtl::StdioCtl() noexcept
286293

287294
StdioCtl::~StdioCtl()
288295
{
296+
using namespace stdioctl;
297+
CONSOLE_SCREEN_BUFFER_INFO activeSbInfo {};
298+
GetConsoleScreenBufferInfo(cn[activeOutput].handle, &activeSbInfo);
299+
CONSOLE_SCREEN_BUFFER_INFO startupSbInfo {};
300+
GetConsoleScreenBufferInfo(cn[startupOutput].handle, &startupSbInfo);
301+
302+
COORD activeWindowSize = windowSize(activeSbInfo.srWindow);
303+
COORD startupWindowSize = windowSize(startupSbInfo.srWindow);
304+
305+
// Preserve the current window size.
306+
if ( activeWindowSize.X != startupWindowSize.X ||
307+
activeWindowSize.Y != startupWindowSize.Y )
308+
{
309+
// The buffer is not allowed to be smaller than the window, so enlarge
310+
// it if necessary. But do not shrink it in the opposite case, to avoid
311+
// loss of data.
312+
COORD dwSize = startupSbInfo.dwSize;
313+
if (dwSize.X < activeWindowSize.X)
314+
dwSize.X = activeWindowSize.X;
315+
if (dwSize.Y < activeWindowSize.Y)
316+
dwSize.Y = activeWindowSize.Y;
317+
SetConsoleScreenBufferSize(cn[startupOutput].handle, dwSize);
318+
// Get the updated cursor position, in case it changed after the resize.
319+
GetConsoleScreenBufferInfo(cn[startupOutput].handle, &startupSbInfo);
320+
// Make sure the cursor is visible. If possible, show it in the bottom row.
321+
SMALL_RECT srWindow = startupSbInfo.srWindow;
322+
COORD dwCursorPosition = startupSbInfo.dwCursorPosition;
323+
srWindow.Right = max(dwCursorPosition.X, activeWindowSize.X - 1);
324+
srWindow.Left = srWindow.Right - (activeWindowSize.X - 1);
325+
srWindow.Bottom = max(dwCursorPosition.Y, activeWindowSize.Y - 1);
326+
srWindow.Top = srWindow.Bottom - (activeWindowSize.Y - 1);
327+
SetConsoleWindowInfo(cn[startupOutput].handle, TRUE, &srWindow);
328+
}
329+
289330
SetConsoleActiveScreenBuffer(cn[startupOutput].handle);
290331
for (auto &c : cn)
291332
if (c.owning)

0 commit comments

Comments
 (0)