Terminal: WINDOW_BUFFER_SIZE_EVENT generated during window scrolling

Created on 11 Oct 2018  路  15Comments  路  Source: microsoft/terminal

Windows Version 10.0.17763.1

SetConsoleWindowInfo can be used to scroll the contents of the console screen buffer by shifting the position of the window rectangle without changing its size.

Starting from Windows 10 1709 (FCU) such scrolling generates a WINDOW_BUFFER_SIZE_EVENT even though the console buffer size remains unchanged.

This breaks our application behaviour and does not make sense for the following reasons:

  • The documentation explicitly says that WINDOW_BUFFER_SIZE_RECORD "describes a change in the size of the console screen buffer", but there's no change in this case.
  • The event is generated only if the contents of the console screen buffer is scrolled via SetConsoleWindowInfo API, but it's useless - the application already knows that the console is being scrolled because the scrolling is initiated by the application itself.
  • event is not generated when the user moves the scrollbar manually, so the application does not know that the console it being scrolled in that case.
  • It does not happen in Legacy mode and never happened before for 20+ years.

A minimal project to reproduce the issue attached.
BufferSizeEventBug.zip

Area-Server Issue-Feature Product-Conhost Work-Item

All 15 comments

Thank you for the report. I've copied this into my internal bug queue as MSFT: 19275577.

Another (possibly related) observation: v2 console sends WINDOW_BUFFER_SIZE_EVENT even if ENABLE_WINDOW_INPUT flag is not set:

ENABLE_WINDOW_INPUT 0x0008 | User interactions that change the size of the console screen buffer are reported in the console's input buffer.

It looks like this was an intentional change to fix https://github.com/Maximus5/ConEmu/issues/1123.

We don't really have any other notification mechanism for the viewport or buffer changing, so it looks like we're triggering that event whenever the view changes even when the buffer size does not to try to keep things in sync.

It looks like at the time we thought that applications receiving an additional message with no actual change wouldn't really be harmed by that information as whatever they were doing would probably be able to detect nothing really happened with GetConsoleScreenBufferInfoEx before performing a further action after the event.

In theory, we could revert the change and come up with a new message type or notification type for the viewport change behavior and then change other downstream components that are now relying on it for synchrony, but I'm a bit hesitant to do that because this is the first report I've seen of it causing issues after being in the wild for over a year. I'm also afraid changing it to fix your issue will then cause me to have to completely revisit the ConEmu one and potentially cause other bugs as a result.

Is it an extremely onerous change in your software to realize that nothing has actually changed when this message comes through with the same buffer size as before? If so, can you further describe your scenario and estimated usage market? It would be useful to weigh your report versus the installed market of ConEmu and WSL users to see whether it's worth the risk of changing this further at this time or if I need to defer a more complete solution to a future milestone.

Thanks for looking into this.

Indeed, there was no way for applications to receive notifications about window changing. And now there is one (sort of).

Sadly this looks like a quick hack rather than a long-term solution - the only information provided is basically "something's happened, go figure it out yourself":

  • Has the buffer size changed? You can't say for sure any more without storing the previous size somewhere
  • Has the window size/position changed? Maybe, but you need to call another API to find it out and yes, also compare with the previous value, stored somewhere.

Also, what about this (see above):

  • The event is generated only if the contents of the console screen buffer is scrolled via SetConsoleWindowInfo API ...
  • event is not generated when the user moves the scrollbar manually ...

- Shouldn't the event be generated in both cases if you're triggering that event "whenever the view changes"?

Our scenario:

  1. On WINDOW_BUFFER_SIZE_EVENT the app recalculates it's interface, redraws everything and resets the viewport position
  2. The app provides several hotkeys to scroll the viewport using SetConsoleWindowInfo (very similar to the example in the first post)
  3. The user presses the hotkey to, say, scroll up, the app receives WINDOW_BUFFER_SIZE_EVENT and... see point 1. The viewport flickers and remains in the same position, the user is unhappy and files a bug report.

Detecting that nothing has actually changed is not extremely onerous, and that's what I already did a month ago (a commit reference is just above your comment), so it's not a blocker for us at least.
I can't say anything about other apps in the wild which might be also affected (or not) of course.

I'd say reverting this and introducing a new notification type for the window changes is a Good Thing To Do in general:

  • it won't break any code that existed before this change
  • this change is not documented, so, technically, any code that relies on it since last year relies on undocumented behaviour and should stop doing that anyway
  • any new code that needs to monitor window changes can be more straightforward and more efficient with the new notification type.

Obviously, the final decision is yours. But, in any case:

  • the inconsistency with the manual scrolling (see above) should probably be fixed?
  • the absence of ENABLE_WINDOW_INPUT console mode (see above) should probably be respected?
  • any changes should probably be reflected in the documentation?

You're right, the event should probably be generated in both of those cases if it should be generated in either one.

You're also right that the documentation should probably be reflecting what happens.

And you're right that we would have to look into the ENABLE_WINDOW_INPUT console mode.

You're also right that the solution of sending this event in hindsight is a dirtier quick hack than we thought it was at the time.

So I think what I'm going to do is promote the work item type here from a simple bug into a deliverable. It's obvious to me by how many nuances there are to this particular scenario that it needs a more concerted effort to resolve this than a simple bug fix. I do think The Right Thing To Do is for it to have its own event notification and try to resolve the ConEmu/WSL thing through that mechanism instead.

It looks like you are unblocked for now through your own workaround (sorry, I didn't see the link attached at first). That takes a bit of the pressure off and means that taking longer to craft the right solution (Deliverable style) is easier to justify than making another hack on top of this hack (Bug style).

Deliverable ID: 19275577 - Craft comprehensive solution to buffer/window overload on Input event
Task ID: 19686586 - Ensure that docs.microsoft.com reflects actual behavior of buffer/window overloads
Task ID: 19686595 - Create new/different eventing mechanism for window sizing concerns that isn't overloaded with buffer sizing
Task ID: 19686633 - Ensure that events for window buffer sizing and viewport sizing respect ENABLE_WINDOW_INPUT flag
Task ID: 19686624 - Fix WSL listener to receive new event type
Task ID: 19686633 - Verify ConEmu hosting WSL is proper after adjustments (see Maximus5/ConEmu#1123)
Task ID: 19686646 - Check consistency on event generation between SetConsoleWindowInfo API and manual scrollbar adjustment

@miniksa I noticed (unless I'm doing something wrong) that ENABLE_VIRTUAL_TERMINAL_INPUT and ENABLE_WINDOWS_INPUT seem to be mutually exclusive. This is a real pain in the ass since there's no other way to get console host resize events. Is this a bug you're also tracking? If not, I'll open a new issue. I'm on latest insider build, 18282.

@oising The answer to that depends on how you're reading the console. I think that ENABLE_VIRTUAL_TERMINAL_INPUT | ENABLE_WINDOW_INPUT requires you to ReadConsoleInput. You'll get different types of INPUT_RECORD: key events containing the VT data, and window events containing the window data. You'll also be able to learn about focus events, mouse events and menu events.

@DHowett-MSFT -- that's exactly what I'm doing, except I'm not seeing any events in the buffer. I'm testing by resizing the console window (dragging the corner) and also by adjusting from the control box (top left). Nothing in the input buffer.

Do you have a minimal repro sample code I could debug? What @DHowett-MSFT describes is how WSL does it, so I'm 99% sure that should be working for you.

@zadjii-msft I think the problem is that I had never really taken a good look at WINDOW_BUFFER_SIZE_EVENT before. I was expecting it to be emitted any time the console window was resized. It's only emitted when the console window is sized beyond the current buffer. It's never emitted when the window size is reduced (as the buffer won't shrink to match.) What I really wanted is a way to reliably monitor the _viewport_ not the buffer.

@oising Yea, that's what I would have expected as well, but apparently whoever wrote that API originally hadn't considered that.

So for the record, sometime between RS2 and RS5, we changed the behavior of the console with respect to WINDOW_BUFFER_SIZE_EVENTs. We made the console send the events anytime the viewport size changed, not only the buffer size. However, we didn't change the actual values of the message, it still had the buffer size as the payload, not the viewport size. A client app can now use that message as a notification that the window might have changed size, and they could query the actual window size using GetConsoleScreenBufferInfo.

We haven't added more messages yet, nor have we changed the content of any messages, only increased the frequency of the messages.

I believe there were earlier builds where this change was scoped only to apps using VT input, but IIRC we changed it later to just send the events for all viewport changes regardless. This was probably a year ago, so I'm definitely hazy on the specifics.

Thanks @zadjii-msft for the update. I'd still rather see a new event WINDOWS_VIEWPORT_SIZE_EVENT introduced rather than overload the buffer one, but I understand to ship is to choose. This will unblock a lot of people, but it would be nice to formalize it before it becomes a backcompat issue.

So how do you sync UI update due to console resize and a subsequent resize? As far as I know there's no way to ask Windows to wait or postpone resizing the console.

Was this page helpful?
0 / 5 - 0 ratings