ConPTY: pass through requests for the alt buffer #577

Closed
opened 2026-01-30 21:55:54 +00:00 by claunia · 28 comments
Owner

Originally created by @davidhewitt on GitHub (Mar 4, 2019).

Originally assigned to: @zadjii-msft on GitHub.

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.

Originally created by @davidhewitt on GitHub (Mar 4, 2019). Originally assigned to: @zadjii-msft on GitHub. When running cmd.exe inside a pseudoconsole, trying to enter the [alternate screen buffer](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#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.
Author
Owner

@miniksa commented on GitHub (Mar 4, 2019):

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.

@miniksa commented on GitHub (Mar 4, 2019): 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.
Author
Owner

@davidhewitt commented on GitHub (Mar 4, 2019):

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

@davidhewitt commented on GitHub (Mar 4, 2019): 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?)
Author
Owner

@zadjii-msft commented on GitHub (Mar 5, 2019):

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.

@zadjii-msft commented on GitHub (Mar 5, 2019): 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.
Author
Owner

@davidhewitt commented on GitHub (Mar 5, 2019):

Sounds great, thanks!

@davidhewitt commented on GitHub (Mar 5, 2019): Sounds great, thanks!
Author
Owner

@ihor-sviziev commented on GitHub (May 7, 2020):

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 commented on GitHub (May 7, 2020): 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
Author
Owner

@DHowett-MSFT commented on GitHub (May 7, 2020):

@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 commented on GitHub (May 7, 2020): @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!)
Author
Owner

@ihor-sviziev commented on GitHub (May 7, 2020):

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

@ihor-sviziev commented on GitHub (May 7, 2020): @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?
Author
Owner

@DHowett-MSFT commented on GitHub (May 7, 2020):

It’s something we could consider, but if the solution to making it work for WSL wouldn’t be something we could build on for Win32, I’d rather not ask my team to do the throwaway work. Once the pressure from 1.0 lets up, we’ll be able to evaluate things like this 😄

@DHowett-MSFT commented on GitHub (May 7, 2020): It’s something we could consider, but if the solution to making it work for WSL wouldn’t be something we could build on for Win32, I’d rather not ask my team to do the throwaway work. Once the pressure from 1.0 lets up, we’ll be able to evaluate things like this 😄
Author
Owner

@davidchisnall commented on GitHub (May 27, 2020):

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.

@davidchisnall commented on GitHub (May 27, 2020): 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.
Author
Owner

@jamescassell commented on GitHub (May 27, 2020):

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!

@jamescassell commented on GitHub (May 27, 2020): > 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!
Author
Owner

@davidchisnall commented on GitHub (May 27, 2020):

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.

@davidchisnall commented on GitHub (May 27, 2020): 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.
Author
Owner

@jamescassell commented on GitHub (May 27, 2020):

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

@jamescassell commented on GitHub (May 27, 2020): > 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
Author
Owner

@zadjii-msft commented on GitHub (Aug 19, 2020):

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?

@zadjii-msft commented on GitHub (Aug 19, 2020): 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: ```c++ 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?
Author
Owner

@j4james commented on GitHub (Aug 19, 2020):

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.

@j4james commented on GitHub (Aug 19, 2020): 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.
Author
Owner

@zadjii-msft commented on GitHub (Aug 19, 2020):

Well that certainly makes my life easier!

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

it is then 😝

@zadjii-msft commented on GitHub (Aug 19, 2020): Well that certainly makes my life easier! ```c++ std::unique_ptr<TextBuffer> _mainBuffer; std::unique_ptr<TextBuffer> _altBuffer; ``` it is then 😝
Author
Owner

@DHowett commented on GitHub (Aug 19, 2020):

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"

@DHowett commented on GitHub (Aug 19, 2020): 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"
Author
Owner

@zadjii-msft commented on GitHub (Aug 19, 2020):

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

@zadjii-msft commented on GitHub (Aug 19, 2020): 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`
Author
Owner

@j4james commented on GitHub (Aug 19, 2020):

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.

@j4james commented on GitHub (Aug 19, 2020): 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.
Author
Owner

@j4james commented on GitHub (Aug 19, 2020):

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.

@j4james commented on GitHub (Aug 19, 2020): 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.
Author
Owner

@chenzhiwei commented on GitHub (Jul 28, 2021):

Any new update on this issue?

This is very annoying, my history command output is replaced by the vim, less or man text.

I found that the WSL Ubuntu works perfect on alternate screen, steps to reproduce:

  1. Open the Ubuntu from start menu
  2. Run man ls command, then scroll the man page(either ctrl+f or down arrow)
  3. Quit the man page by press q
  4. Scroll up the terminal, the man page does not show in the terminal

But if you open Ubuntu in Windows Terminal and repeat the same steps, the man page will show in Windows Terminal when you scroll up.

@chenzhiwei commented on GitHub (Jul 28, 2021): Any new update on this issue? This is very annoying, my history command output is replaced by the `vim`, `less` or `man` text. I found that the `WSL Ubuntu` works perfect on alternate screen, steps to reproduce: 1. Open the `Ubuntu` from start menu 2. Run `man ls` command, then scroll the man page(either `ctrl+f` or `down arrow`) 3. Quit the man page by press `q` 4. Scroll up the terminal, the man page does not show in the terminal But if you open `Ubuntu in Windows Terminal` and repeat the same steps, the man page will show in Windows Terminal when you scroll up.
Author
Owner

@zadjii-msft commented on GitHub (Jul 28, 2021):

Nope. We'll make sure to update this thread when there is. In the meantime, might I recommend the Subscribe button?
image
That way you'll be notified of any updates to this thread, without needlessly pinging everyone on this thread ☺️

@zadjii-msft commented on GitHub (Jul 28, 2021): Nope. We'll make sure to update this thread when there is. In the meantime, might I recommend the Subscribe button? ![image](https://user-images.githubusercontent.com/18356694/91237459-5cbb0c80-e700-11ea-9347-b9b1ec2813b1.png) That way you'll be notified of any updates to this thread, without needlessly pinging everyone on this thread ☺️
Author
Owner

@ghost commented on GitHub (Aug 4, 2021):

Adding "experimental.rendering.forceFullRepaint": true, to the JSON file or enabling Redraw entire screen when display updates seems to fix it.

@ghost commented on GitHub (Aug 4, 2021): Adding `"experimental.rendering.forceFullRepaint": true,` to the JSON file or enabling `Redraw entire screen when display updates `seems to fix it.
Author
Owner

@lucy commented on GitHub (Nov 16, 2021):

Adding "experimental.rendering.forceFullRepaint": true, to the JSON file or enabling Redraw entire screen when display updates seems to fix it.

less still seems to overwrite my scrollback with this enabled, but vim doesn't for some reason.

@lucy commented on GitHub (Nov 16, 2021): > > > Adding `"experimental.rendering.forceFullRepaint": true,` to the JSON file or enabling `Redraw entire screen when display updates `seems to fix it. less still seems to overwrite my scrollback with this enabled, but vim doesn't for some reason.
Author
Owner

@DHowett commented on GitHub (Nov 16, 2021):

The rendering settings will neither fix nor break this. If you observed them helping, that was just a stroke of luck. 😄

@DHowett commented on GitHub (Nov 16, 2021): The rendering settings will neither fix nor break this. If you observed them helping, that was just a stroke of luck. :smile:
Author
Owner

@GaroneHuang commented on GitHub (Nov 22, 2021):

Is there any progress in this issue?

@GaroneHuang commented on GitHub (Nov 22, 2021): Is there any progress in this issue?
Author
Owner

@zadjii-msft commented on GitHub (Nov 22, 2021):

Nope. We'll make sure to update this thread when there is. In the meantime, might I recommend the Subscribe button?
image
That way you'll be notified of any updates to this thread, without needlessly pinging everyone on this thread ☺️

@zadjii-msft commented on GitHub (Nov 22, 2021): Nope. We'll make sure to update this thread when there is. In the meantime, might I recommend the Subscribe button? ![image](https://user-images.githubusercontent.com/18356694/91237459-5cbb0c80-e700-11ea-9347-b9b1ec2813b1.png) That way you'll be notified of any updates to this thread, without needlessly pinging everyone on this thread ☺️
Author
Owner

@eugenov commented on GitHub (Dec 8, 2021):

2.5 years of not using MT. It's a pity.

@eugenov commented on GitHub (Dec 8, 2021): 2.5 years of not using MT. It's a pity.
Author
Owner

@ghost commented on GitHub (May 24, 2022):

:tada:This issue was addressed in #12561, which has now been successfully released as Windows Terminal Preview v1.14.143.🎉

Handy links:

@ghost commented on GitHub (May 24, 2022): :tada:This issue was addressed in #12561, which has now been successfully released as `Windows Terminal Preview v1.14.143`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.14.143) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#577