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 · 25 comments
Assignees
Labels
Area-VT Virtual Terminal sequence support 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
@JoezCodes101

This comment was marked as spam.

@zadjii-msft

This comment was marked as off-topic.

@doverton12
Copy link

I am surprised that after 2 years this is still open without a resolution, but more importantly, no view on the choice to be implemented (1,2 or 3). However I am at best a hobbiest programmer, so I struggled to find a place to fix the code and I am very greatful for the progress made in Terminal over the years and therefore the people who dev this.

So what about workarounds? Is there a way an application can launch and not use the default console as a work around? I use Terminal for everything, but this bug is killing me on 2 apps. Both relating to resizing the window and then commands like clear not working correctly (in Powershell of all things). My alternative would be for those apps to launch into their own personal console that use the old Windows console and performs as desired.?

@BlueOnBLack
Copy link

BlueOnBLack commented Dec 3, 2022

Optional solution
https://pastebin.com/8UERXCJr

and use this script, to get Terminal PID
https://pastebin.com/z796Nwak

@BlueOnBLack
Copy link

BlueOnBLack commented Dec 3, 2022

let's assume you are using this
mode con cols=88 lines=23

to use the new api ...
make function that does this

set /a colss=%1*9
set /a lines=%2*22
set PROC_ID=Terminal_Process_ID
PS -nop -file .........

another good option is to use cmdow
https://ritchielawrence.github.io/cmdow/
for that you need to use MainWindowHandle value
@(Get-process | Where Id -EQ !ProcessId!).MainWindowHandle
and convert it into hex with Hex2Dec utility or try this article
https://shellgeek.com/powershell-convert-decimal-to-hex
and try something like this
"%cmdow%" !output:~0,2!0!output:~2! /SIZ !colss! !lines!

BTW
Cmdow will accept only this regex 0x0+HEX_VALUE

@BDisp
Copy link

BDisp commented Jan 3, 2023

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

This escape sequence is for resize the visible window. I would like to know what is the escape sequence for resize the screen buffer, please. Thanks.

@BDisp
Copy link

BDisp commented Jan 22, 2023

@j4james commented in #14568 (comment):

I think the only issue here is that we don't support screen size changes in Windows Terminal. If I remember correctly, the SetConsoleScreenBufferInfoEx call will change the size on the conhost side of the conpty connection, but that change isn't passed on to the conpty client. As a result, the two get out of sync and things can get weird. This problem is tracked in issue #5094.

As I mention in #14568 the lack in the possibility of support screen size changes in Windows Terminal, prevents some feature with scrolling and this is very limited. I think if a app want to handle the buffer size then must provide code for that, otherwise its output will be handled by the terminal default behavior. Only the current tab can handle the windows size manipulation, to avoid windows been resized all the time if another tab is also change its size.

@adithya-s-sekhar
Copy link

It's been 3 years.

I use batch scripts regularly and my current workaround is to change the "Default terminal application" in Windows Terminal settings to "Windows Console Host". It's by default on "Let Windows decide".
This should force all batch scripts at least to start in old console host. Window resizing works.

@2lag
Copy link

2lag commented Apr 21, 2023

It's been 3 years.

I use batch scripts regularly and my current workaround is to change the "Default terminal application" in Windows Terminal settings to "Windows Console Host". It's by default on "Let Windows decide". This should force all batch scripts at least to start in old console host. Window resizing works.

This is awesome as far as a workaround for just the local user, but if I'm trying to design something for both Windows 10 and Windows 11 users that is cross compatible, I can't really expect them to resize the window or change their default settings just to get the full functionality.

I hope sometime soon there can be a solution for this as like you said, it has been 3 years.

@adithya-s-sekhar
Copy link

@2lag I do have users outside, I just put that as part of installation instructions. Had to use big scary "READ THIS, DO THIS FIRST" headers. I don't know how many people reads them and does do it. There is no way to detect if the script is running inside terminal and throw an error afaik, if there was such a thing this could've been better.

@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.

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 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