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

Terminal: add support for Window Manipulation (CSI t, resize), or reject it explicitly (and force a client resize) #5094

Open
Tracked by #6999 ...
DHowett-MSFT opened this issue Mar 24, 2020 · 36 comments
Labels
Area-VT Virtual Terminal sequence support In-PR This issue has a related PR Issue-Task It's a feature request, but it doesn't really need a major design. Priority-2 A description (P2) Product-Terminal The new Windows Terminal.
Milestone

Comments

@DHowett-MSFT
Copy link
Contributor

DHowett-MSFT commented Mar 24, 2020

Notes from @j4james:

Note that this is a problem for all the VT resizing sequences too. For example, you'll get the same problem resizing the screen from within a bash shell like this:

    printf "\e[8;10;10t"

And if you want to make mode work, then you'll probably want to start with the VT sequences first, because ultimately that's how you're going to have to communicate this information to the Terminal.

The real issue, though, is deciding how the Terminal should deal with a resize request. When you've got multiple tabs, each potentially requesting a different size, you can't satisfy all of them at once. I've been thinking about this for a while, and there were three approaches that I considered:

  1. Ignore the size request, as we are doing now. But for this to work, it's vital that the Terminal communicate back to the host that the request has failed. If you don't do that, the Terminal and conhost get out of sync, and the renderer goes barmy..

  2. Accept the requested size as a kind of virtual window, similar to the way conhost works when the buffer width and window width are different. If the virtual window is larger than the actual window, you'll need to be able to scroll across the viewport, both horizontally and vertically (the latter being kind of tricky to differentiate from the scrollback).

  3. Accept the requested size and actually resize the whole Terminal window to fit, but only if the tab making the request is currently focused. A background tab shouldn't be able to change the size. And as with option 1, it's vital that the resulting sizes are communicated back to the different hosts for each tab.

Personally I'm in favor of option 3, but I suspect others will disagree, and it may need to be a configurable preference. It's also possible there are other better approaches that I haven't thought of.

Notes from @egmontkob:

On a more important note, I believe that this escape sequence with a fixed size is borderline problematic/harmful, whereas this one with the "maximized" value, and other nearby escape sequences, are straight harmful (just like when webpages that are allowed to move/resize the browser window – everyone hates that, right?) and terminals should deliberately refuse to implement.

Notes from @DHowett-MSFT:
We should choose one of the above options and stick to our guns.


More notes:

  • option 4: Only allow a resize like this if there's a single pane. If there's two panes, we'll do the thing from option 1, and ignore it.
  • We're probably gonna just go with option 4
  • We'll add a compatibility.allowWindowResizing defaulted to true to let people fully disable this
  • If there's multiple tabs, then inactive tabs won't notice the current tabs new size till they get focused (and the control is re-added to the UI tree).
    • theoretically, one app could ask for 30x80 and another tab 45x120 and switching back and forth would keep resizing the window
  • if a inactive tab gets a resize request... then we need to somehow mark that tab asked for a new size, and allow the resize, and resize the Terminal & buffer, but only resize the window when it gets activated.
  • This probably needs to be handled as a core->control->app request, so the app can allow/reject
@DHowett-MSFT DHowett-MSFT added Area-VT Virtual Terminal sequence support Product-Terminal The new Windows Terminal. Issue-Task It's a feature request, but it doesn't really need a major design. Priority-2 A description (P2) labels Mar 24, 2020
@DHowett-MSFT DHowett-MSFT added this to the Terminal Backlog milestone Mar 24, 2020
@ghost ghost added the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Mar 24, 2020
@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Mar 24, 2020
@DHowett-MSFT DHowett-MSFT changed the title Terminal: add support for Window Manipulation (CSI t, resize) Terminal: add support for Window Manipulation (CSI t, resize), or reject it explicitly (and force a client resize) Mar 24, 2020
@jdebp
Copy link

jdebp commented Mar 24, 2020

It's worth noting that the problems don't arise with just 1 tab. With just 1 tab, you can resize the terminal GUI window willy-nilly as the resize events come down the pipe, and behave exactly as the prior console server's GUI windows did in response to size changes. It's what to do when there are 2 or more tabs, each wanting a different terminal size, that is the problem.

Looking to existing practice, Konsole has some noteworthy behaviour. The control sequence resizes the terminal exactly as requested. stty shows the requested number of rows and columns, and text wraps at the designated column. Size changes take effect even if this is not the active tab. The GUI window does not change when the active tab's size is changed, however. Things stay that way until the next time that the tab is switched back to from another tab, at which point the pseudo-terminal receives a resize event sizing it back to the size of the GUI window. If there is only 1 tab present this never happens, as the single tab is never switched away from and never switched back to.

This is of course, to discuss resizing in the GUI front-end. The actual console screen buffer should definitely support resizing via control sequences, just as it supports resizing via SetConsoleScreenBufferSize().

How are you supporting sending along to the GUI front-ends changes made by SetConsoleScreenBufferSize() and SetConsoleWindowInfo(), and changes to the window size made by the GUI front end? You've only provided one set of size information in ResizePseudoConsole(), and appear to be treating that as the console screen buffer size. How are GUI terminal emulator applications to pass the other size through so that console I/O applications can see it?

@egmontkob
Copy link

Looking to existing practice, Konsole has some noteworthy behaviour.

If I had to make a guess, my guess would be that this behavior is not by design, just whatever happened to come out of the simplest implementation, using the UI libraries used by Konsole.

Let's take a step back. You don't have to support any kind of app-initiated resize. Let's just take a tabbed UI where whatever is inside the tab can query the dimensions at any time, as it's necessarily the case with terminals. There's already a nontrivial question: When should inactive terminals receive the resize event?

Immediately? That might be a waste of CPU time, both from the terminal and from the hosted apps, since you don't squash multiple resize events into one; and a waste of network traffic, if there's ssh involved. Especially if resizing isn't super fast (e.g. in VTE the time required to rewrap is proportional to the number of scrollback lines), doing it for multiple tabs at once might cause a noticeable lag. It also might trigger some apps to exit, if they don't support one of the intermediate (e.g. extremely small) size, or might cause bad display in cases that don't really like getting resized (shell prompts typically play badly with rewrap-on-resize).

Or when that tab is switched to? In that case switching is a weird experience, you don't immediately get to see the desired contents, but you see a resize dance, even including ssh latency if it's involved.

Or some more complex solution in between, e.g. resize when the mouse dragging the window border is released, or after a timeout?)

The same question goes to some other kinds of apps too, e.g. most notably web browsers. Do they resize the page (e.g. responsive layout) immediately, or when that tab is switched to? I wouldn't be surprised if the answer varied across browsers, or even within the same browser varied across OSes (graphical toolkits).

Now combine it with various resizing strategies across terminals (some force a grid, some don't), various tab switching experiences (some prefer to keep the pixel size, some prefer to keep the character size), various zooming experiences (some might zoom all tabs at once, some zoom each tab separately), and then let's even introduce app-initiated resizes. There are loads of possible behaviors to pick from, and it's really hard to tell which one is better.

@SWB54
Copy link

SWB54 commented Apr 7, 2020

Would I be correct to assume that this issue also encompasses non-VT resizing? For example, the .NET API Console.WindowWidth, which I believe maps (on Windows) to the Win32 APIs SetConsoleScreenBufferSize() and SetConsoleWindowInfo().

If so, I am in favor of either option 2 or 3 (some version of honoring the request), but not 1 (ignoring it). I just ran into this issue today. I have a .NET Core console app that prints formatted tables with relatively long rows. If the console width is too narrow to display the table, I increase it via Console.WindowWidth. This works in a cmd.exe window but not (yet) inside Windows Terminal.

@j4james
Copy link
Collaborator

j4james commented Apr 8, 2020

Would I be correct to assume that this issue also encompasses non-VT resizing?

I think that's the intention, yes (assuming it's decided that we do anything about this at all). The original bug report that prompted this issue was a Windows app using SetConsoleScreenBufferSize (see issue #5079). I was just saying that we needed to fix the VT sequences first, because that's how the resizing information would be communicated to the Windows Terminal.

@luke1961
Copy link

luke1961 commented Apr 14, 2020

Would I be correct to assume that this issue also encompasses non-VT resizing?

I think that's the intention, yes (assuming it's decided that we do anything about this at all). The original bug report that prompted this issue was a Windows app using SetConsoleScreenBufferSize (see issue #5079). I was just saying that we needed to fix the VT sequences first, because that's how the resizing information would be communicated to the Windows Terminal.

100% agreed. Fixing printf("\x1b[8;%d;%dt", nY, nX); is critical to address app-initiated resizing. This is very important to stay compatible with many apps that just count on running with a specific number of rows and columns. Some of these apps are usually configured to be launched from a batch batch file which includes a mode con lines=rrr cols=ccc statement to ensure proper buffer size. Of course the mode statement results in the escape sentence listed above sent to the Terminal.

@alexrp
Copy link

alexrp commented Oct 11, 2020

Has any sort of decision been made on this yet?

For what it's worth, I'm for option 3.

I find the comparison to web browsers rather unconvincing. Running applications in a terminal is not the same thing as the arbitrary JavaScript code we encounter on the (probably) 100s of unique web pages we casually visit every day. We all sort of get that the web is a bit of a wild west kind of deal, but command line ecosystems are rarely (if ever) that. We generally know what we're doing when we run things in a terminal.

@pjfarleyiii
Copy link

pjfarleyiii commented Dec 29, 2020

I am the author of #8673 which was closed as a duplicate of this issue. I understand the discussion here concerning the intricacies of what other tabs in Terminal do / see and when, but my interest is from the POV of a simple text-based application that wants to ensure an appropriate terminal height and width (in characters) depending on startup options specified by the application user.

In the old CMD.EXE console (which is not tabbed) I can just print the "CSI 8; lines; cols t" sequence and have the window resize immediately. If you can provide that support more quickly for only the "single tab open" case my needs would be satisfied.

Can a single-tab-only solution be considered for more rapid update as an intermediate step pending multi-tab design and implementation solution(s)?

Regards,

Peter

P.S. -- Whatever the mechanism, WSL screens (which I was given to understand are using MS Terminal) DO respond to the "CSI 8; lines; cols t" sequence and immediately resize the WSL console window. Tested with Ubuntu 20.04LTS and Debian 10 WSL instances.

darthwalsh added a commit to darthwalsh/ConsoleInvaders that referenced this issue Feb 11, 2021
Resizing doesn't seem to work well accoring to microsoft/terminal#5094
@TheUbMunster
Copy link

I really don't know much about the implementation differences, but is the new slick Terminal app really plagued with a bunch of non-functionality? I've been trying to work around this (even hacky-ish winapi stuff), but have not yet found anything satisfactory.

Is this ever going to be fixed?

@lhecker
Copy link
Member

lhecker commented Jun 19, 2024

I really don't know much about the implementation differences, but is the new slick Terminal app really plagued with a bunch of non-functionality?

Part of it is intentional for the sake of simplicity. The new terminal hosts multiple terminal applications simultaneously in the same window and it's not immediately obvious if one application should be allowed to decide the window size of another in another tab or pane. This isn't impossible to solve (for instance we could make it so that the focused tab gets to decide this, if there aren't any split panes), but I think one can see how ignoring client requested resizes makes this a lot simpler...

Is this ever going to be fixed?

In fairness to everyone we usually prioritize work on the things that receive the most attention from our users (fwiw we're only around 2 devs on this project). While this issue is pretty bad overall, it's unfortunately not among the most important ones.

But regarding your question, I think the answer is generally "yes". Work on this however isn't currently planned. Work around this on the other hand is currently ongoing (specifically the translation of window resizes to CSI t, and how resizes are fed back to the terminal), and I expect that this work should make it easier to address this issue in the future.

@LurkingKiwi
Copy link

The omission of this feature becomes even more critical, because now the users can set Windows Terminal as the default terminal experience. I am supporting an old console app which uses the Win32 API calls SetConsoleScreenBufferSize and SetConsoleWindowInfo. I used to work-around the WT problem using the following algorithm:

  • Option 4. Add an executable manifest option, similar to the supportedOS option. Using it, app developers and advanced users can explicitly request the old conhost, the new terminal, or leave it as a user choice. Also, add a Windows API call which can set this, if possible.

I also support an app which enforces window and buffer sizes using the old console API.
We have had to keep evolving as MS console changes all seem to be controlled by an all-or-nothing switch. It was old conhost/new conhost as a global setting, now its conhost/terminal, and ignoring the window size options destroys the app.
A manifest option to choose the old conhost is an excellent idea, and I was trying to find the (non-existent) option when I found this issue.

@zadjii-msft zadjii-msft removed their assignment Aug 20, 2024
@zadjii-msft zadjii-msft added the In-PR This issue has a related PR label Aug 20, 2024
zadjii-msft pushed a commit that referenced this issue Aug 29, 2024
`ResizeWindow` event in `TerminalApi` is handled and bubbled to
`TerminalApi->ControlCore->TermControl->TerminalPage->AppHost`. Resizing
is accepted only if the window is not in fullscreen or quake mode, and
has 1 tab and pane.

Relevant issues: #5094
@BDisp
Copy link

BDisp commented Nov 1, 2024

In Windows Terminal Preview version 1.22.2912.0 it is no longer possible to resize the buffer. In version 1.21.2911.0 it is working fine with buffer resizing.

@lhecker
Copy link
Member

lhecker commented Nov 4, 2024

@BDisp I don't remember CSI t being supported in either 1.21 or 1.22.
Reading through the linked gui-cs PR I can see that there are various issues with 1.22 being discussed, but I don't fully understand it, as I'm unfamiliar with gui-cs. So, could you please be more specific what's broken and how to reproduce it? I'd be happy to help. 🙂
If it's unrelated with CSI t though, please consider creating a new issue. Just some repro steps and perhaps a screenshot or two should already be sufficient (although it's of course always helpful if you can provide even more information).

Edit: I should mention that the issues you're experiencing are extremely likely due to our new ConPTY implementation (the translation layer between console APIs and VT). That's one of the major new features in 1.22.

@BDisp
Copy link

BDisp commented Nov 4, 2024

Thanks for your attention @lhecker. On Windows 11 using Win32 API, like the SetConsoleScreenBufferInfoEx or even using CSI t I cannot now resize the screen buffer and it remain greater than the terminal window size. Thus allow the user to scroll using the scroll bar which we don't want for not let the user see corrupted buffer. If is there an alternative to change the buffer size to the same window size I would appreciate any information, thanks.

@lhecker
Copy link
Member

lhecker commented Nov 4, 2024

Are you by any chance looking for something like the "alternate screen buffer"? You can enter it by emitting \x1b[?1049h and exit it by emitting \x1b[?1049l. All versions of Windows that are still officially supported support that sequence.

@BDisp
Copy link

BDisp commented Nov 4, 2024

Are you by any chance looking for something like the "alternate screen buffer"? You can enter it by emitting \x1b[?1049h and exit it by emitting \x1b[?1049l. All versions of Windows that are still officially supported support that sequence.

Yes that is done on enter and exit. But during the execution resize the window isn't resizing the buffer size using the Win32 API. I also tried with the escape sequence but also without success.

Here is a screenshot. Maximize the window and restore doesn't not set anymore the buffer size with the same size of the window:

Image

@BDisp
Copy link

BDisp commented Nov 4, 2024

Only to remember that in the WT version 1.21 the resize is working well. Only in the 1.22 (Preview) version this issue is happening.

@lhecker
Copy link
Member

lhecker commented Nov 4, 2024

We should continue this discussion in another issue, since there are over 20 people subscribed to this one. Do you mind filing an issue? It would be great if you could include reproduction steps.

BTW: I'm also confused why you mention the need to resize the buffer. The terminal resizes the buffer for you when the window size changes. There should be no need for you to call anything (nor use CSI t) during a maximize/restore. The alternate screen buffer always has the size of the window.

@ClaireCJS
Copy link

Are you by any chance looking for something like the "alternate screen buffer"? You can enter it by emitting \x1b[?1049h and exit it by emitting \x1b[?1049l. All versions of Windows that are still officially supported support that sequence.

You know.. I read the entire VT100 manual and hand-tried every single feasible one in the manual. I don't think I remember that one but maybe I just didn't understand it at the time.

@Jibun-no-Kage
Copy link

Check the VT220 Manual. There were a lot, literally a lot of changes between VT100 and VT220 standards. I want to say, if memory services, it was in the VT220 standard that buffering options were enhanced.

@ClaireCJS
Copy link

ClaireCJS commented Nov 5, 2024

Check the VT220 Manual. There were a lot, literally a lot of changes between VT100 and VT220 standards. I want to say, if memory services, it was in the VT220 standard that buffering options were enhanced.

I guess every good story has its sequel 🤣 I'll have to do that, thanks for the recommendation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-VT Virtual Terminal sequence support In-PR This issue has a related PR Issue-Task It's a feature request, but it doesn't really need a major design. Priority-2 A description (P2) Product-Terminal The new Windows Terminal.
Projects
None yet
Development

No branches or pull requests