Skip to content

Recalculate window size after a screen buffer resize - #20647

Open
leecher1337 wants to merge 3 commits into
microsoft:mainfrom
leecher1337:fix/window-resize-scrollbar
Open

Recalculate window size after a screen buffer resize#20647
leecher1337 wants to merge 3 commits into
microsoft:mainfrom
leecher1337:fix/window-resize-scrollbar

Conversation

@leecher1337

@leecher1337 leecher1337 commented Sep 6, 2026

Copy link
Copy Markdown

Summary of the Pull Request

Fixes a stale-window-space bug: after SetConsoleScreenBufferSize/SetConsoleScreenBufferInfoEx resizes the screen buffer, the
console window's outer pixel size was never re-evaluated against the new buffer dimensions. If the window had previously
reserved extra pixel space for a scroll bar (based on the buffer size at that time), and the buffer later shrinks so the scroll
bar is no longer needed, that reserved space is never reclaimed — leaving a permanent strip of unpainted background between the
actual content and the window's edge.

References and Relevant Issues

No existing tracked issue. Found while validating an unrelated console-buffer resize sequence that happened to exercise this
path.

Detailed Description of the Pull Request / Additional comments

Window::s_CalculateWindowRect (src/interactivity/win32/window.cpp) compares the window's character size against the buffer's
character size to decide whether to reserve extra pixel space for a scroll bar. SCREEN_INFORMATION::ResizeScreenBuffer
(src/host/screenInfo.cpp) calls UpdateScrollBars() after resizing the buffer, but that only shows/hides the scroll bar control —
it doesn't touch the window's outer rect. So if the reservation was computed against a stale, larger buffer size, it's only
cleaned up if a subsequent SetConsoleWindowInfo call happens to run afterward and re-triggers the rect calculation.

This is easy to hit with the standard safe console-resize sequence recommended for shrinking or growing a console (shrink window
→ resize buffer → grow window back only if the target exceeds the window's pre-resize size): whenever the final "grow" step is
skipped because it isn't needed, the sequence ends right after the buffer resize with the stale reservation never cleaned up.

Fix: ResizeScreenBuffer now also calls PostUpdateWindowSize() right after UpdateScrollBars(), gated on the same
fDoScrollBarUpdate flag the existing scroll bar update already uses — callers that pass false already trigger their own window
resize immediately afterward, so this avoids posting it twice there.

Validation Steps Performed

A reproduction tool is included in this PR (src/tools/resizewindowtest). It performs the shrink-window / resize-buffer /
grow-window-if-needed sequence described above, then fills the whole buffer with a solid color.

To reproduce:
resizewindowtest.exe (defaults to 80x25)

  • Before this fix: a strip of unpainted background remains along the right and bottom edges of the window, even though
    GetConsoleScreenBufferInfo reports the buffer and window character dimensions as identical.
  • After this fix: the window fits the filled buffer exactly.
  • resizewindowtest.exe 80 31 exercises the "grow window back" branch of the sequence (already worked correctly before this
    change) to confirm no regression there.

PR Checklist

  • Closes #xxx
  • Tests added/passed
  • Documentation updated
  • Schema updated (if necessary)

SetConsoleScreenBufferSize/SetConsoleScreenBufferInfoEx only called
UpdateScrollBars() after resizing the buffer, which hides or shows the
scroll bar control but doesn't touch the window's outer pixel rect.
Window::s_CalculateWindowRect reserves extra space for a scroll bar
based on comparing the window's character size against the buffer's -
if that comparison was true at some earlier point (e.g. mid-resize,
while the buffer was still its old, larger size) but becomes false
once the buffer catches up, the previously-reserved margin is never
reclaimed, leaving a stretch of unpainted background where a scroll
bar used to be needed.

This is most visible with the classic safe console-resize sequence
(shrink the window, resize the buffer, grow the window back if
needed): if growing the window back isn't necessary because the
target size doesn't exceed the window's original size, the sequence
ends right after the buffer resize with no further window-size call
to clean up the stale reservation.

Fix: ResizeScreenBuffer also posts a window-size recalculation
alongside the existing scroll bar update, so the window rect is
always re-evaluated against the buffer's current (not previous) size.
Gated on the same fDoScrollBarUpdate flag the scroll bar update itself
already uses - callers that pass false already trigger their own
window resize immediately afterward.
A small standalone console tool (src/tools/resizewindowtest) that
performs the shrink-window / resize-buffer / grow-window-if-needed
sequence described in the previous commit, then fills the buffer with
a solid color so a reviewer can see at a glance whether stale
scroll-bar-reserved space is left behind at the window's right/bottom
edge - even when GetConsoleScreenBufferInfo reports the buffer and
window character dimensions matching exactly.

Usage: resizewindowtest.exe [width height] (defaults to 80x25, which
reliably reproduces the bug without this fix - the "grow window back"
step of the sequence is skipped for any target height at or below the
console's default window height).
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@leecher1337

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Comment thread OpenConsole.slnx Fixed
Comment thread OpenConsole.slnx Fixed
Comment thread src/tools/resizewindowtest/main.cpp Fixed
Comment thread src/tools/resizewindowtest/main.cpp Fixed
Comment thread src/tools/resizewindowtest/main.cpp Fixed
Comment thread src/tools/resizewindowtest/main.cpp Fixed
Comment thread src/tools/resizewindowtest/resizewindowtest.vcxproj Fixed
Comment thread src/tools/resizewindowtest/resizewindowtest.vcxproj Fixed
@github-actions

This comment has been minimized.

check-spelling flagged resizewindowtest as an unrecognized word - both
in the new tool's source and, per docs.check-spelling.dev's
check-file-path check, in the paths of the three files added under
src/tools/resizewindowtest/.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants