Skip to content
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

Equivalent of SIGWINCH? #305

Closed
HouQiming opened this issue Nov 10, 2018 · 8 comments
Closed

Equivalent of SIGWINCH? #305

HouQiming opened this issue Nov 10, 2018 · 8 comments
Labels
Issue-Question For questions or discussion Resolution-Duplicate There's another issue on the tracker that's pretty much the same thing.

Comments

@HouQiming
Copy link

After reading through the blog post and relevant MSDN pages, I didn't find a way for a modern Windows console app to detect when its output console gets resized. On Unix we have SIGWINCH, but on Windows we only have ReadConsoleInput and WINDOW_BUFFER_SIZE_EVENT, which seems awkward when used alongside simple stdin reading (will they fight for normal input events?).

Can someone share some light on this situation?

Thanks.

@oising
Copy link
Collaborator

oising commented Nov 10, 2018

There's also GetConsoleScreenBufferInfo which will tell you dimensions, but it's obviously done by polling. You could also poll with an ANSI sequence - there are some half-baked tricks like moving the cursor way off screen - beyond any reasonable window size, then reading the actual position of the cursor afterwards. Example with WSL:

oisin@laptop$ echo -e "\e[999;999H"; echo -e "\e[6n"; echo ""
^[[47;1R;oisin@laptop$

The CR killed the horizontal position reporting interactively, but at least you can see my window is 47 rows high. Again, this would need to be polled but at least it's somewhat cross platform. Other techniques I've seen on other platforms (osx,linux) is either shelling out to stty to get info, or more commonly, with an ioctl call to TIOCGWINSZ.

@zadjii-msft
Copy link
Member

Unfortunately, the only SIGWINCH equivalent on Windows is, as you've noted, using ReadConsoleInput for reading the input from the console and looking for WINDOW_BUFFER_SIZE_EVENTs. It's really not great, but if your app is dependent upon the size of the viewport, then that's the only way to do it :/

@zadjii-msft zadjii-msft added the Issue-Question For questions or discussion label Nov 12, 2018
@HouQiming
Copy link
Author

Well, thanks for the clarification. The situation feels kind of disappointing, though. It's hard to qualify a console system as "VT-speaking" when it can't get SIGWINCH right without making clients "un-speak" VT. Polling is not really a solution if one needs to forward SIGWINCH or port something that relies on it.

If all other console input types are converted anyway, maybe we can just do a simple hack and PostMessageW something somewhere for WINDOW_BUFFER_SIZE_EVENT? Then we'll be able to listen to that in a separate thread and simulate SIGWINCH without disturbing stdin.

@oising
Copy link
Collaborator

oising commented Nov 22, 2018

Unfortunately, the only SIGWINCH equivalent on Windows is, as you've noted, using ReadConsoleInput for reading the input from the console and looking for WINDOW_BUFFER_SIZE_EVENTs. It's really not great, but if your app is dependent upon the size of the viewport, then that's the only way to do it :/

@zadjii-msft Mike, I've been playing with this the last few days and noticed that using WINDOWS_BUFFER_SIZE_EVENT doesn't concern itself with the viewport at all; it only deals with the underlying buffer. Additionally, the buffer only ever gets increased in size, so when you resize the console window larger than the buffer, you get a resize event - which is actually defective in itself since it currently only seems to be reporting the vertical size/number of lines, and returning 1 for columns each time. - and you never get a resize event when you reduce the viewport. (running 18282)

@zadjii-msft
Copy link
Member

I'm gonna go ahead and link in #281 here - that thread has WAY more information on basically the same topic.

In fact, we shout probably just commit to that thread being the master thread for all window WINDOW_BUFFER_SIZE_EVENT / SIGWINCH discussion.

@awsdert
Copy link

awsdert commented Jul 17, 2023

Found this thread while I was looking for inspiration, eventually realised WM_ERASEBKGND was better suited since you just need to have a static global by your hook and compare against that, here's a snippet from my code for how I'm planning to implement it:

pawttyxy _pawsig_ttysize = {0};
pawld _pawsig_catch_PAWSIG_TTYSIZE( pawsig *sig, UINT msg, WPARAM wp, LPARAM lp )
{
	pawttyxy xy = {0};
	CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}};
	if ( msg == WM_ERASEBKGND )
		return 0;
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
	xy.x = csbi.dwSize.X;
	xy.y = csbi.dwSize.Y;
	/* Only trigger the event if at least one of limits have changed */
	if ( xy.x && _pawsig_ttysize.x && xy.y == _pawsig_ttysize.y )
		return 0;
	sig->signal = PAWSIG_TTYSIZE;
	sig->extinf.size = xy;
	return 1;
}

I might need to tweak it a little for non-console apps but that's the jist of it. Events like WM_ERASEBKGND are guaranteed to be triggered upon the row & col count changing since the console would need to re-align any visible text.

@zadjii-msft
Copy link
Member

FWIW I fully suspect that won't work in the Windows Terminal, since the HWND returned by GetConsoleWindow is not the actual HWND of the visible Terminal window.

Also, it probably won't work if the console/Terminal is minimized, hidden, etc.

@awsdert
Copy link

awsdert commented Jul 17, 2023

Well given the snippet ...this function returns a window handle for message queue purposes only from GetConsoleWindow I expect it in all cases the HWND should work fine for this, I'll test it anyways once I've completed enough of my library to actually do the tests I wanted to do (this is a byproduct of development rather than the intended product).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question For questions or discussion Resolution-Duplicate There's another issue on the tracker that's pretty much the same thing.
Projects
None yet
Development

No branches or pull requests

4 participants