Terminal: ConPTY: pass through requests for the alt buffer

Created on 4 Mar 2019  路  19Comments  路  Source: microsoft/terminal

When running cmd.exe inside a pseudoconsole, trying to enter the alternate screen buffer escape sequences via echo [?1049h and echo [?1049l does not result in them being sent to the ConPTY output pipe. It appears to me they are being processed inside cmd.exe and swallowed.

Does it make sense / is it possible for these sequences be output by ConPTY? This would allow terminal emulators to do things like support scrolling inside programs such as less which make use of the alternate screen buffer.

Area-Interop Issue-Feature Product-Conpty Work-Item

All 19 comments

They're processed inside the console host window (which is hosting cmd.exe and powering your ConPTY session) to establish and remove an alternate screen buffer at that level. The effects of the operation will be visible on the output pipe (that is, it should "clear the screen" and then draw the contents of the alternate one onto the final terminal attached to the ConPTY end). But the final terminal isn't responsible for the maintenence of that state right now.

I believe that tools like less that use an alternate screen buffer currently work just fine with this arrangement. If you have evidence to the contrary, we'd be interested in pursuing that as an issue itself.

Internally we have the potential future work item to make it so there is a ConPTY "pass-through" mode. MSFT: 20190846.

Indeed tools such as less do work acceptably at the moment. I can see the console host window is processing the alternate buffer, thanks. However, comparing the experience of using less on Windows to Centos linux (gnome):

  • Centos: scrolling with the mousewheel scrolls less's alternate buffer, keeping the document in less correctly ordered
  • Windows / WSL: scrolling with the mousewheel scrolls the console window history, potentially creating garbled lines of output as the history gets mixed with the contents of the document in the alternate buffer.

It would be really nice if the console window behaved like Centos in this case, as I find it much more intuitive and a convenient way to read documents. Furthermore, terminal emulators with their own scrollback function are unable to provide the Centos-like behavior if they are not aware that the alternate buffer has been opened.

The pass-through mode sounds like it'd make it possible for terminal emulators to handle this themselves, thanks!

(Happy to provide some gifs if I've done a poor job explaining the behavior?)

Unfortunately conpty doesn't support mouse input quite yet, though that's something fairly high on our backlog.

Pass-throughing the alt buffer switching is something that we'll likely do earlier than adding mouse support, and definitely before enabling a true passthrough mode.

Sounds great, thanks!

Hi @DHowett-MSFT,
I see that last comment there was added more than 1 year ago. Is there any plans for fixing it?
This is follow up on https://github.com/microsoft/terminal/issues/5762

@ihor-sviziev every bug that we keep open is something we are hoping to fix :) we have been prioritizing other things because we wanted to make sure the basic experience worked properly. This one is more complicated because it needs to work for classic Win32 applications at the same time as modern VT applications (like the ones running inside WSL!)

@DHowett-MSFT maybe there is a way to support it only for WSL as first part and later on add support for for win32 applications?

It鈥檚 something we could consider, but if the solution to making it work for WSL wouldn鈥檛 be something we could build on for Win32, I鈥檇 rather not ask my team to do the throwaway work. Once the pressure from 1.0 lets up, we鈥檒l be able to evaluate things like this 馃槃

I believe that this either is, or is related do, the issue that prevents tmux from using the scrollback. The following line in .tmux.conf should instruct tmux to write into the scrollback as well as the alternate screen:

set -g terminal-overrides 'xterm*:smcup@:rmcup@'

I am using tmux for persistence, but don't want it managing my scrollback when I have a perfectly good terminal emulator for this. I can ssh to a machine with Konsole (WSL + VcXsrv) that has this setting, run commands that generate a lot of log output, and then scroll back and see it (and, importantly, select multiple screens' worth to copy and paste). If I ssh to the same machine from the same machine, this time using the Windows Terminal and do the same thing, I have nothing in my scrollback from tmux.

I am using tmux for persistence, but don't want it managing my scrollback when I have a perfectly good terminal emulator for this. I can ssh to a machine with Konsole (WSL + VcXsrv) that has this setting, run commands that generate a lot of log output, and then scroll back and see it (and, importantly, select multiple screens' worth to copy and paste). If I ssh to the same machine from the same machine, this time using the Windows Terminal and do the same thing, I have nothing in my scrollback from tmux.

I'm in the same boat wrt persistence and not wanting a terminal in my terminal. abduco seems to do this well. The classic dtach also performs just the persistence function. Unfortunately, these are not installed as frequently as tmux... if you find a way to get tmux to do this, I'd be very interested!

Thanks for the abduco hint, it seems to do what I want with WT but, oddly, with Konsole the behaviour is flipped (tmux gives me scrollback, abduco does not, and using the mouse wheel in Konsole sends up/down keys to the shell and doesn't scroll with abduco but scrolls correctly with tmux). At least for the machines I control, this solves it because I can install abduco and have some lines in my .bashrc that selects the between tmux and abduco as the command to pass to autossh depending on whether $WT_SESSION exists.

Thanks for the abduco hint, it seems to do what I want with WT but, oddly, with Konsole the behaviour is flipped (tmux gives me scrollback, abduco does not, and using the mouse wheel in Konsole sends up/down keys to the shell and doesn't scroll with abduco but scrolls correctly with tmux). At least for the machines I control, this solves it because I can install abduco and have some lines in my .bashrc that selects the between tmux and abduco as the command to pass to autossh depending on whether $WT_SESSION exists.

Yeah, this is the annoying bug in abduco: https://github.com/martanne/abduco/issues/35

workaround is to printf '\033[?1049l' as first thing in the session, or when re-connecting

Hey @j4james, I'm thinking about trying to do this in the near future. In order to make my life easier in the future, do you know which of the members of Terminal are supposed to be persisted across the main/alt buffer, and which _aren't_? I'm planning on pulling Terminal into two classes - Terminal with a main and alt TerminalBuffer.

I'm thinking:

    std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
    COLORREF _defaultFg;
    COLORREF _defaultBg;
    bool _screenReversed;
    std::unique_ptr<TextBuffer> _buffer;
    Microsoft::Console::Types::Viewport _mutableViewport;

will all need to get moved to TerminalBuffer (though of course, the alt _mutableViewport will be the same as the alt buffer's size). Am I wrong here? Is the color table shared across buffers?

Technically the alternate buffer has no separate state. Literally everything is shared with the main buffer except for the actual buffer contents. Cursor position, colors, color tables, modes, margins - they're all shared between the two buffers. All that happens is you're writing to and viewing a different buffer.

I suppose the viewport could be considered separate in some sense, but it's more the case that the viewport is locked when you're in the alternate buffer because the screen never scrolls. In XTerm the user can still scroll up manually and see the scroll back from the main buffer, but I'm not sure anyone else supports that.

Note that the current conhost implementation is wrong in this regard. That's tracked by issue #3545.

Well that certainly makes my life easier!

std::unique_ptr<TextBuffer> _mainBuffer;
std::unique_ptr<TextBuffer> _altBuffer;

it is then 馃槤

Would that we could do the same for conhost! Right now we have a stack of SCREEN_INFORMATIONs each of which has .. their own alternate SCREEN_INFORMATION and a bunch of getters that return "whichever one is most active"

oh oh oh

could we just do that to SCREEN_INFORMATION and then have "whichever is the most active" always return this?

Though, I suppose we'd need to internally to SCREEN_INFO use GetWhicheverTextBufferIsTheMostActive() instead of _textBuffer

I'd love for us to get this working correctly in conhost too, but I remember looking at it in the past and thinking it would be quite complicated to sort out. That may just have been my lack of understanding of the code base though.

Also, I should point out that the cursor position might be a bit tricky here, depending on how you're implementing things. The relative position should be the same between buffers, but if it's stored as an absolute position (which I think it might be), and the two buffers don't match in size, then the absolute position will likely need adjusting.

Just FYI, there are also some discussions regarding the alternate buffer in issues #3082 and #3686 which may be worth reading, in case any of those issues influence how you decide to implement this.

Was this page helpful?
0 / 5 - 0 ratings