-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Recalculate window size after a screen buffer resize #20647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
leecher1337
wants to merge
3
commits into
microsoft:main
Choose a base branch
from
leecher1337:fix/window-resize-scrollbar
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1411,6 +1411,7 @@ rerasterize | |
| rescap | ||
| RESETCONTENT | ||
| resheader | ||
| resizewindowtest | ||
| resmimetype | ||
| resultmacros | ||
| resw | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,208 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| // Licensed under the MIT license. | ||
|
|
||
| // Reproduces a three-step console resize sequence some clients use to | ||
| // safely resize a console window/buffer pair in either direction (a window | ||
| // can never be made bigger than the current buffer, and a buffer can never | ||
| // be made smaller than the current window, so the safe order is: shrink the | ||
| // window first if needed, resize the buffer, then grow the window back up | ||
| // if the requested size is bigger than what it was shrunk to): | ||
| // | ||
| // 1. SetConsoleWindowInfo() - shrink the window if it's currently | ||
| // bigger than the requested size | ||
| // 2. SetConsoleScreenBufferSize() - resize the buffer to the requested size | ||
| // 3. SetConsoleWindowInfo() - grow the window back up to the | ||
| // requested size, but only if step 1 | ||
| // didn't already get it there | ||
| // | ||
| // Step 3 is skipped whenever the requested size doesn't exceed the window's | ||
| // size from before this sequence started. That's exactly the case that | ||
| // exposes the bug this tool validates: after step 2, the window's outer | ||
| // pixel rect can be left holding pixel space that was reserved for a scroll | ||
| // bar which is no longer needed, and without step 3 nothing else | ||
| // re-evaluates that rect (see ResizeScreenBuffer's PostUpdateWindowSize() | ||
| // call in src/host/screenInfo.cpp). | ||
| // | ||
| // Usage: resizewindowtest.exe [width height] (defaults to 80x25) | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| // | ||
| // After resizing, the whole buffer is filled with a solid color and the | ||
| // resulting buffer/window/max-window sizes (from GetConsoleScreenBufferInfo) | ||
| // are written to the window title and to resizewindowtest.log next to the | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| // executable. Watch the right and bottom edges of the window: any strip of | ||
| // unpainted background left between the filled content and the window | ||
| // frame indicates the bug - even though the log will show the buffer and | ||
| // window character dimensions matching exactly. | ||
|
|
||
| #include <windows.h> | ||
| #include <conio.h> | ||
| #include <cstdio> | ||
| #include <cstdlib> | ||
|
|
||
| namespace | ||
| { | ||
| HANDLE g_hOut; | ||
| FILE* g_log; | ||
|
|
||
| void WindowSize(int w, int h, int top, int left) | ||
| { | ||
| SMALL_RECT rect; | ||
| rect.Top = static_cast<SHORT>(top); | ||
| rect.Left = static_cast<SHORT>(left); | ||
| rect.Bottom = static_cast<SHORT>(top + h - 1); | ||
| rect.Right = static_cast<SHORT>(left + w - 1); | ||
|
|
||
| if (!SetConsoleWindowInfo(g_hOut, TRUE, &rect)) | ||
| { | ||
| fprintf(g_log, "SetConsoleWindowInfo(%d,%d @ %d,%d) FAILED: %lu\n", w, h, top, left, GetLastError()); | ||
| } | ||
| else | ||
| { | ||
| fprintf(g_log, "SetConsoleWindowInfo(%d,%d @ %d,%d) OK\n", w, h, top, left); | ||
| } | ||
| } | ||
|
|
||
| void BufferSize(int w, int h) | ||
| { | ||
| COORD size; | ||
| size.X = static_cast<SHORT>(w); | ||
| size.Y = static_cast<SHORT>(h); | ||
|
|
||
| if (!SetConsoleScreenBufferSize(g_hOut, size)) | ||
| { | ||
| fprintf(g_log, "SetConsoleScreenBufferSize(%d,%d) FAILED: %lu\n", w, h, GetLastError()); | ||
| } | ||
| else | ||
| { | ||
| fprintf(g_log, "SetConsoleScreenBufferSize(%d,%d) OK\n", w, h); | ||
| } | ||
| } | ||
|
|
||
| // The shrink/resize/grow sequence described at the top of this file. | ||
| void ResizeWindow(int w, int h) | ||
| { | ||
| CONSOLE_SCREEN_BUFFER_INFO info; | ||
| if (!GetConsoleScreenBufferInfo(g_hOut, &info)) | ||
| { | ||
| fprintf(g_log, "GetConsoleScreenBufferInfo (1) FAILED: %lu\n", GetLastError()); | ||
| return; | ||
| } | ||
|
|
||
| const auto oldTop = info.srWindow.Top; | ||
| const auto oldLeft = info.srWindow.Left; | ||
| const auto oldWindowWidth = info.srWindow.Right - info.srWindow.Left + 1; | ||
| const auto oldWindowHeight = info.srWindow.Bottom - info.srWindow.Top + 1; | ||
|
|
||
| fprintf(g_log, "ResizeWindow(%d,%d): oldWindow=%dx%d oldBuffer=%dx%d\n", | ||
| w, h, oldWindowWidth, oldWindowHeight, info.dwSize.X, info.dwSize.Y); | ||
|
|
||
| // 1. Shrink the window first if it's bigger than the target in | ||
| // either dimension - a buffer can never be resized smaller than | ||
| // the window currently displaying it. | ||
| if (info.srWindow.Bottom >= h || info.srWindow.Right >= w) | ||
| { | ||
| WindowSize(min(w, oldWindowWidth), min(h, oldWindowHeight), 0, 0); | ||
| } | ||
|
|
||
| // 2. Resize the buffer to the target size. | ||
| BufferSize(w, h); | ||
|
|
||
| if (!GetConsoleScreenBufferInfo(g_hOut, &info)) | ||
| { | ||
| fprintf(g_log, "GetConsoleScreenBufferInfo (2) FAILED: %lu\n", GetLastError()); | ||
| return; | ||
| } | ||
| fprintf(g_log, " dwMaximumWindowSize = %dx%d\n", info.dwMaximumWindowSize.X, info.dwMaximumWindowSize.Y); | ||
|
|
||
| auto newLeft = w - info.dwMaximumWindowSize.X; | ||
| if (newLeft > 0) | ||
| { | ||
| w = info.dwMaximumWindowSize.X; | ||
| } | ||
| else | ||
| { | ||
| newLeft = 0; | ||
| } | ||
|
|
||
| auto newTop = h - info.dwMaximumWindowSize.Y; | ||
| if (newTop > 0) | ||
| { | ||
| h = info.dwMaximumWindowSize.Y; | ||
| } | ||
| else | ||
| { | ||
| newTop = 0; | ||
| } | ||
|
|
||
| // 3. Grow the window back up to the target size, only if step 1 | ||
| // didn't already get it there. This is the step that's skipped | ||
| // when the requested size doesn't exceed the window's original | ||
| // size - the case this tool is meant to exercise. | ||
| if (w > oldWindowWidth || h > oldWindowHeight) | ||
| { | ||
| WindowSize(w, h, min(newTop, oldTop), min(newLeft, oldLeft)); | ||
| } | ||
| } | ||
|
|
||
| void FillAndReport(int requestedWidth, int requestedHeight) | ||
| { | ||
| CONSOLE_SCREEN_BUFFER_INFO info; | ||
| GetConsoleScreenBufferInfo(g_hOut, &info); | ||
|
|
||
| const COORD origin{ 0, 0 }; | ||
| const DWORD cellCount = static_cast<DWORD>(info.dwSize.X) * static_cast<DWORD>(info.dwSize.Y); | ||
| const WORD attr = BACKGROUND_BLUE | BACKGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; | ||
| DWORD written; | ||
|
|
||
| FillConsoleOutputCharacterW(g_hOut, L' ', cellCount, origin, &written); | ||
| FillConsoleOutputAttribute(g_hOut, attr, cellCount, origin, &written); | ||
|
|
||
| char title[256]; | ||
| sprintf_s(title, | ||
| "req=%dx%d buffer=%dx%d window=%dx%d (col %d-%d, row %d-%d) maxWin=%dx%d", | ||
| requestedWidth, requestedHeight, | ||
| info.dwSize.X, info.dwSize.Y, | ||
| info.srWindow.Right - info.srWindow.Left + 1, | ||
| info.srWindow.Bottom - info.srWindow.Top + 1, | ||
| info.srWindow.Left, info.srWindow.Right, | ||
| info.srWindow.Top, info.srWindow.Bottom, | ||
| info.dwMaximumWindowSize.X, info.dwMaximumWindowSize.Y); | ||
| SetConsoleTitleA(title); | ||
| fprintf(g_log, "%s\n", title); | ||
|
|
||
| const char* msg = "resizewindowtest - see title bar / resizewindowtest.log - press any key"; | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| WriteConsoleOutputCharacterA(g_hOut, msg, static_cast<DWORD>(strlen(msg)), origin, &written); | ||
| } | ||
| } | ||
|
|
||
| int __cdecl wmain(int argc, WCHAR* argv[]) | ||
| { | ||
| int width = 80; | ||
| int height = 25; | ||
| if (argc >= 3) | ||
| { | ||
| width = _wtoi(argv[1]); | ||
| height = _wtoi(argv[2]); | ||
| } | ||
|
|
||
| g_log = fopen("resizewindowtest.log", "w"); | ||
| if (!g_log) | ||
| { | ||
| g_log = stderr; | ||
| } | ||
|
|
||
| g_hOut = GetStdHandle(STD_OUTPUT_HANDLE); | ||
| if (g_hOut == INVALID_HANDLE_VALUE || g_hOut == nullptr) | ||
| { | ||
| fprintf(g_log, "GetStdHandle failed: %lu\n", GetLastError()); | ||
| return 1; | ||
| } | ||
|
|
||
| fprintf(g_log, "Resizing to %d x %d...\n", width, height); | ||
| ResizeWindow(width, height); | ||
|
|
||
| FillAndReport(width, height); | ||
| fflush(g_log); | ||
|
|
||
| _getch(); | ||
| return 0; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <PropertyGroup Label="Globals"> | ||
| <ProjectGuid>{A8020AD3-2EF5-48F1-BE5E-91189FEC5351}</ProjectGuid> | ||
| <Keyword>Win32Proj</Keyword> | ||
| <RootNamespace>resizewindowtest</RootNamespace> | ||
| <ProjectName>resizewindowtest</ProjectName> | ||
| <TargetName>resizewindowtest</TargetName> | ||
| <ConfigurationType>Application</ConfigurationType> | ||
| </PropertyGroup> | ||
| <Import Project="..\..\common.build.pre.props" /> | ||
| <ItemGroup> | ||
| <ClCompile Include="main.cpp" /> | ||
| </ItemGroup> | ||
| <ItemDefinitionGroup> | ||
| <ClCompile> | ||
| <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| <PrecompiledHeader>NotUsing</PrecompiledHeader> | ||
| </ClCompile> | ||
| <Link> | ||
| <SubSystem>Console</SubSystem> | ||
| </Link> | ||
| </ItemDefinitionGroup> | ||
| <!-- Careful reordering these. Some default props (contained in these files) are order sensitive. --> | ||
| <Import Project="..\..\common.build.post.props" /> | ||
| <Import Project="..\..\common.build.tests.props" /> | ||
| </Project> | ||
22 changes: 22 additions & 0 deletions
22
src/tools/resizewindowtest/resizewindowtest.vcxproj.filters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ItemGroup> | ||
| <Filter Include="Source Files"> | ||
| <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> | ||
| <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> | ||
| </Filter> | ||
| <Filter Include="Header Files"> | ||
| <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> | ||
| <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> | ||
| </Filter> | ||
| <Filter Include="Resource Files"> | ||
| <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> | ||
| <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> | ||
| </Filter> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ClCompile Include="main.cpp"> | ||
| <Filter>Source Files</Filter> | ||
| </ClCompile> | ||
| </ItemGroup> | ||
| </Project> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.