Skip to content

OpenConsole: Cursor visibility prevents programmatic scrolling #19390

@alabuzhev

Description

@alabuzhev

Windows Terminal version

1.25.2509.25001 or the latest source

Windows build number

10.0.19045.6218

Other Software

No response

Steps to reproduce

  1. Get the latest openconsole (compile or from the WT package)

Compile the code:

Code
#include <iostream>

#include <windows.h>

static bool Scroll(int Lines)
{
	const auto Out = GetStdHandle(STD_OUTPUT_HANDLE);

	CONSOLE_SCREEN_BUFFER_INFO Info;
	if (!GetConsoleScreenBufferInfo(Out, &Info))
		return false;

	if (!(Lines < 0 && Info.srWindow.Top) && !(Lines > 0 && Info.srWindow.Bottom != Info.dwSize.Y - 1))
		return false;

	Info.srWindow.Top += Lines;
	Info.srWindow.Bottom += Lines;

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

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

	if (!SetConsoleWindowInfo(Out, true, &Info.srWindow))
		return false;

	return true;
}

int main()
{
	const auto In = GetStdHandle(STD_INPUT_HANDLE);
	const auto Out = GetStdHandle(STD_OUTPUT_HANDLE);

	{
		CONSOLE_SCREEN_BUFFER_INFO Info;
		GetConsoleScreenBufferInfo(Out, &Info);
		if (Info.dwSize.Y < 1000)
		{
			Info.dwSize.Y = 1000;
			SetConsoleScreenBufferSize(Out, { 80, 1000 });
		}
	}

	for (size_t i = 0; i != 1000; ++i)
		std::wcout << i << '\n';

	std::wcout << "\nPress Up or Down to scroll\nPress C to toggle cursor";
	std::wcout.flush();

	for (;;)
	{
		INPUT_RECORD InputRecord;
		DWORD Read;
		if (!ReadConsoleInput(In, &InputRecord, 1, &Read) || !Read)
			return EXIT_FAILURE;

		if (InputRecord.EventType != KEY_EVENT)
			continue;

		const auto& KeyEvent = InputRecord.Event.KeyEvent;

		if (!KeyEvent.bKeyDown)
			continue;


		switch (KeyEvent.wVirtualKeyCode)
		{
		case VK_UP:
		case VK_DOWN:
			Scroll(KeyEvent.wVirtualKeyCode == VK_UP ? -1 : 1);
			break;

		case 'C':
			{
				CONSOLE_CURSOR_INFO Info;
				GetConsoleCursorInfo(Out, &Info);
				Info.bVisible = !Info.bVisible;
				SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info);
			}
			break;

		default:
			break;
		}
	}
}
  1. Run it in openconsole.
  2. Follow the instructions on the screen.
  3. Try to move it far enough, so that the cursor is outside of the viewport.

Expected Behavior

The code is a simple program that moves the viewport up or down as you press the corresponding buttons.

It's basically an isolated/simplified feature of another app (Far) that allows the user to inspect the scrollback without reaching for the mouse.

It worked as expected for years in legacy, conhost, and openconsole until recently.

Actual Behavior

After some relatively recent changes it is only possible to move it while the cursor position stays in the viewport.
As soon as you reach the edge it blinks and reverts.

It is still possible to move it freely if the cursor is not visible (press 'C' to goggle).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-ServerDown in the muck of API call servicing, interprocess communication, eventing, etc.Issue-BugIt either shouldn't be doing this or needs an investigation.Priority-2A description (P2)Product-ConhostFor issues in the Console codebase

    Type

    Projects

    Status

    To Cherry Pick

    Status

    To Cherry Pick

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions