Conhost window is not refreshed after software scroll #20445

Open
opened 2026-01-31 07:14:02 +00:00 by claunia · 0 comments
Owner

Originally created by @alabuzhev on GitHub (Sep 5, 2023).

Originally assigned to: @lhecker on GitHub.

Windows Terminal version

1.18.1462.0

Windows build number

10.0.19045.3324

Other Software

No response

Steps to reproduce

  1. Compile the code:
#include <iostream>
#include <stdexcept>
#include <string>

#include <windows.h>

void scroll(bool page, bool up)
{
	const auto out = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	if (!GetConsoleScreenBufferInfo(out, &csbi))
		throw std::runtime_error("GetConsoleScreenBufferInfo");

	if (up && !csbi.srWindow.Top)
		return;

	if (!up && csbi.srWindow.Bottom == csbi.dwSize.Y - 1)
		return;

	auto lines = page?
		csbi.srWindow.Bottom - csbi.srWindow.Top + 1:
		1;

	if (up)
		lines = -lines;

	csbi.srWindow.Top += lines;
	csbi.srWindow.Bottom += lines;

	if (csbi.srWindow.Top < 0)
	{
		csbi.srWindow.Bottom -= csbi.srWindow.Top;
		csbi.srWindow.Top = 0;
	}

	if (csbi.srWindow.Bottom >= csbi.dwSize.Y)
	{
		csbi.srWindow.Top -= (csbi.srWindow.Bottom - (csbi.dwSize.Y - 1));
		csbi.srWindow.Bottom = csbi.dwSize.Y - 1;
	}

	if (!SetConsoleWindowInfo(out, true, &csbi.srWindow))
		throw std::runtime_error("SetConsoleWindowInfo");
}

void run()
{
	const auto width = 80, height = 25;
	const auto screens = 5;
	const auto out = GetStdHandle(STD_OUTPUT_HANDLE);
	const SMALL_RECT Window{ 0, 0, width - 1, height - 1 };
	SetConsoleWindowInfo(out, true, &Window);
	SetConsoleScreenBufferSize(out, { width, height * screens });

	for (size_t i = 0; i != height * screens - 1; ++i)
	{
		const auto data = L"Line " + std::to_wstring(i) + L"\n";
		DWORD n;
		WriteConsole(out, data.data(), static_cast<DWORD>(data.size()), &n, {});
	}

	const auto in = GetStdHandle(STD_INPUT_HANDLE);
	for (;;)
	{
		INPUT_RECORD r;
		DWORD n;
		if (!ReadConsoleInput(in, &r, 1, &n))
			break;

		if (r.EventType != KEY_EVENT || !r.Event.KeyEvent.bKeyDown)
			continue;

		switch (const auto key = r.Event.KeyEvent.wVirtualKeyCode)
		{
		case VK_UP:
		case VK_DOWN:
		case VK_NEXT:
		case VK_PRIOR:
			scroll(key == VK_NEXT || key == VK_PRIOR, key == VK_UP || key == VK_PRIOR);
		}
	}
}

int main()
{
	try
	{
		run();
	}
	catch(const std::exception& e)
	{
		std::cerr << e.what();
	}
}

  1. Run it with the latest published OpenConsole, e.g. from WT 1.18.1462.
  2. Press Up and Down a few times.
  3. Press PgUp and PgDn a few times.

Expected Behavior

The viewport moves up or down, line by line or page by page.

Actual Behavior

Pressing Up or Down works as expected.
Pressing PgUp or PgDown doesn't.

When PgUp/PgDown are pressed, the scrollbar on the right moves appropriately, indicating that the viewport has moved, but the window is not refreshed and shows the very same content.

The issue occurs only if the number of lines to scroll is >= window height.

The original issue is described here:
https://github.com/FarGroup/FarManager/issues/727
According to the comments, the default conhost in Windows 11 is also affected to some extent.

Originally created by @alabuzhev on GitHub (Sep 5, 2023). Originally assigned to: @lhecker on GitHub. ### Windows Terminal version 1.18.1462.0 ### Windows build number 10.0.19045.3324 ### Other Software _No response_ ### Steps to reproduce 1. Compile the code: <details> ```C++ #include <iostream> #include <stdexcept> #include <string> #include <windows.h> void scroll(bool page, bool up) { const auto out = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; if (!GetConsoleScreenBufferInfo(out, &csbi)) throw std::runtime_error("GetConsoleScreenBufferInfo"); if (up && !csbi.srWindow.Top) return; if (!up && csbi.srWindow.Bottom == csbi.dwSize.Y - 1) return; auto lines = page? csbi.srWindow.Bottom - csbi.srWindow.Top + 1: 1; if (up) lines = -lines; csbi.srWindow.Top += lines; csbi.srWindow.Bottom += lines; if (csbi.srWindow.Top < 0) { csbi.srWindow.Bottom -= csbi.srWindow.Top; csbi.srWindow.Top = 0; } if (csbi.srWindow.Bottom >= csbi.dwSize.Y) { csbi.srWindow.Top -= (csbi.srWindow.Bottom - (csbi.dwSize.Y - 1)); csbi.srWindow.Bottom = csbi.dwSize.Y - 1; } if (!SetConsoleWindowInfo(out, true, &csbi.srWindow)) throw std::runtime_error("SetConsoleWindowInfo"); } void run() { const auto width = 80, height = 25; const auto screens = 5; const auto out = GetStdHandle(STD_OUTPUT_HANDLE); const SMALL_RECT Window{ 0, 0, width - 1, height - 1 }; SetConsoleWindowInfo(out, true, &Window); SetConsoleScreenBufferSize(out, { width, height * screens }); for (size_t i = 0; i != height * screens - 1; ++i) { const auto data = L"Line " + std::to_wstring(i) + L"\n"; DWORD n; WriteConsole(out, data.data(), static_cast<DWORD>(data.size()), &n, {}); } const auto in = GetStdHandle(STD_INPUT_HANDLE); for (;;) { INPUT_RECORD r; DWORD n; if (!ReadConsoleInput(in, &r, 1, &n)) break; if (r.EventType != KEY_EVENT || !r.Event.KeyEvent.bKeyDown) continue; switch (const auto key = r.Event.KeyEvent.wVirtualKeyCode) { case VK_UP: case VK_DOWN: case VK_NEXT: case VK_PRIOR: scroll(key == VK_NEXT || key == VK_PRIOR, key == VK_UP || key == VK_PRIOR); } } } int main() { try { run(); } catch(const std::exception& e) { std::cerr << e.what(); } } ``` </details> 2. Run it with the latest published OpenConsole, e.g. from WT 1.18.1462. 3. Press Up and Down a few times. 4. Press PgUp and PgDn a few times. ### Expected Behavior The viewport moves up or down, line by line or page by page. ### Actual Behavior Pressing Up or Down works as expected. Pressing PgUp or PgDown doesn't. When PgUp/PgDown are pressed, the scrollbar on the right moves appropriately, indicating that the viewport has moved, but the window is not refreshed and shows the very same content. The issue occurs only if the number of lines to scroll is >= window height. The original issue is described here: https://github.com/FarGroup/FarManager/issues/727 According to the comments, the default conhost in Windows 11 is also affected to some extent.
claunia added the Product-ConhostArea-OutputIssue-BugIn-PRNeeds-Tag-Fix labels 2026-01-31 07:14:02 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#20445