Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3742,7 +3742,13 @@ namespace winrt::TerminalApp::implementation
// for nulls
if (const auto& connection{ _duplicateConnectionForRestart(paneContent) })
{
paneContent.GetTermControl().Connection(connection);
// Reset the terminal's VT state before attaching the new connection.
// The previous client may have left dirty modes (e.g., bracketed
// paste, mouse tracking, alternate buffer, kitty keyboard) that
// would corrupt input/output for the new shell process.
const auto& termControl = paneContent.GetTermControl();
termControl.ResetConnection();
termControl.Connection(connection);
connection.Start();
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}

void ControlCore::ResetConnection()
{
const auto lock = _terminal->LockForWriting();
_terminal->ResetConnection();
}

bool ControlCore::Initialize(const float actualWidth,
const float actualHeight,
const float compositionScale)
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation

TerminalConnection::ITerminalConnection Connection();
void Connection(const TerminalConnection::ITerminalConnection& connection);
void ResetConnection();

void AnchorContextMenu(til::point viewportRelativeCharacterPosition);

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/ControlCore.idl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ namespace Microsoft.Terminal.Control
void ApplyAppearance(Boolean focused);

Microsoft.Terminal.TerminalConnection.ITerminalConnection Connection;
void ResetConnection();

IControlSettings Settings { get; };
IControlAppearance FocusedAppearance { get; };
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.Connection(newConnection);
}

void TermControl::ResetConnection()
{
_core.ResetConnection();
}

void TermControl::_throttledUpdateScrollbar(const ScrollBarUpdate& update)
{
if (!_initializedTerminal)
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation

TerminalConnection::ITerminalConnection Connection();
void Connection(const TerminalConnection::ITerminalConnection& connection);
void ResetConnection();

Control::CursorDisplayState CursorVisibility() const noexcept;
void CursorVisibility(Control::CursorDisplayState cursorVisibility);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace Microsoft.Terminal.Control
void SetOverrideColorScheme(Microsoft.Terminal.Core.ICoreScheme scheme);

Microsoft.Terminal.TerminalConnection.ITerminalConnection Connection;
void ResetConnection();

UInt64 ContentId{ get; };

Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
}

// Method Description:
// - Resets all VT state to defaults without clearing the buffer content.
// Called when a connection is restarted so that any dirty modes left
// behind by a crashed application don't affect the new connection.
void Terminal::ResetConnection()
{
_assertLocked();
_stateMachine->ResetState();
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().HardResetWithoutBufferClear();
}

// Method Description:
// - Initializes the Terminal from the given set of settings.
// Arguments:
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Microsoft::Terminal::Core::Terminal final :
void Create(til::size viewportSize,
til::CoordType scrollbackLines,
Microsoft::Console::Render::Renderer& renderer);
void ResetConnection();

void CreateFromSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings,
Microsoft::Console::Render::Renderer& renderer);
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch

virtual void SoftReset() = 0; // DECSTR
virtual void HardReset() = 0; // RIS
virtual void HardResetWithoutBufferClear() = 0;
virtual void ScreenAlignmentPattern() = 0; // DECALN

virtual void SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) = 0; // DECSCUSR
Expand Down
44 changes: 39 additions & 5 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2994,6 +2994,31 @@ void AdaptDispatch::SoftReset()
//Arguments:
// <none>
void AdaptDispatch::HardReset()
{
_hardResetCore(true);
}

// Routine Description:
// - Performs a hard reset of all VT state without clearing the buffer content
// or scrollback. This is used when a connection is restarted to clean up
// any dirty state left behind by a crashed application (e.g., bracketed
// paste, mouse tracking, alternate buffer, kitty keyboard, etc.).
// Arguments:
// - None
void AdaptDispatch::HardResetWithoutBufferClear()
{
_hardResetCore(false);
}

// Routine Description:
// - Shared implementation for HardReset and HardResetWithoutBufferClear.
// Resets all VT state (parser, input modes, display modes, character sets,
// color table, tab stops, macros, etc.) to initial defaults. When
// clearBuffers is true, the screen and scrollback are also erased (full
// RIS behavior). When false, buffer content is preserved.
// Arguments:
// - clearBuffers: if true, erase the screen and scrollback
void AdaptDispatch::_hardResetCore(const bool clearBuffers)
{
// If in the alt buffer, switch back to main before doing anything else.
if (_usingAltBuffer)
Expand All @@ -3020,9 +3045,12 @@ void AdaptDispatch::HardReset()
// to ensure that it clears with the default background color.
SoftReset();

// Clears the screen - Needs to be done in two operations.
EraseInDisplay(DispatchTypes::EraseType::All);
EraseInDisplay(DispatchTypes::EraseType::Scrollback);
if (clearBuffers)
{
// Clears the screen - Needs to be done in two operations.
EraseInDisplay(DispatchTypes::EraseType::All);
EraseInDisplay(DispatchTypes::EraseType::Scrollback);
}

// Set the color table and render modes back to their initial startup values.
_renderSettings.RestoreDefaultSettings();
Expand All @@ -3033,8 +3061,14 @@ void AdaptDispatch::HardReset()
_renderer->SynchronizedOutputChanged();
}

// Cursor to 1,1 - the Soft Reset guarantees this is absolute
CursorPosition(1, 1);
if (clearBuffers)
{
// Cursor to 1,1 - the Soft Reset guarantees this is absolute.
// Only done when clearing buffers, because when preserving content
// the cursor should stay where the previous shell left it so the
// new shell prompt appears in the right place.
CursorPosition(1, 1);
}

// We only reset the system line feed mode if the input mode is set. If it
// isn't set, that either means they're both reset, and there's nothing for
Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/adaptDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace Microsoft::Console::VirtualTerminal
void AnnounceCodeStructure(const VTInt ansiLevel) override; // ACS
void SoftReset() override; // DECSTR
void HardReset() override; // RIS
void HardResetWithoutBufferClear() override;
void ScreenAlignmentPattern() override; // DECALN
void SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) override; // DECSCUSR

Expand Down Expand Up @@ -195,6 +196,7 @@ namespace Microsoft::Console::VirtualTerminal
void SetOptionalFeatures(const til::enumset<OptionalFeature> features) noexcept override;

private:
void _hardResetCore(const bool clearBuffers);
enum class Mode
{
InsertReplace,
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/termDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons

void SoftReset() override {} // DECSTR
void HardReset() override {} // RIS
void HardResetWithoutBufferClear() override {}
void ScreenAlignmentPattern() override {} // DECALN

void SetCursorStyle(const DispatchTypes::CursorStyle /*cursorStyle*/) override {} // DECSCUSR
Expand Down
Loading