Skip to content

Commit

Permalink
Disable win32 input mode on exit (#16408)
Browse files Browse the repository at this point in the history
When ConPTY exits it should attempt to restore the state as it was
before it started. This is particularly important for the win32
input mode sequences, as Linux shells don't know what to do with it.

Related to #16343

## Validation Steps Performed
* Replace conhost with this
* Launch a Win32 application inside WSL
* Exit that application
* Shell prompt doesn't get filled with win32 input mode sequences ✅

(cherry picked from commit 70e51ae)
Service-Card-Id: 91246943
Service-Version: 1.19
  • Loading branch information
lhecker authored and DHowett committed Dec 5, 2023
1 parent ef32e3e commit 8a9af94
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ void ConptyRoundtripTests::PassthroughHardReset()
// Write a Hard Reset VT sequence to the host, it should come through to the Terminal
// along with a DECSET sequence to re-enable win32 input and focus events.
expectedOutput.push_back("\033c");
expectedOutput.push_back("\033[?9001;1004h");
expectedOutput.push_back("\033[?9001h\033[?1004h");
hostSm.ProcessString(L"\033c");

const auto termSecondView = term->GetViewport();
Expand Down
19 changes: 0 additions & 19 deletions src/renderer/vt/VtSequences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,25 +476,6 @@ using namespace Microsoft::Console::Render;
return _Write(isReversed ? "\x1b[7m" : "\x1b[27m");
}

// Method Description:
// - Send a sequence to the connected terminal to request win32-input-mode from
// them. This will enable the connected terminal to send us full INPUT_RECORDs
// as input. If the terminal doesn't understand this sequence, it'll just
// ignore it.
// Arguments:
// - <none>
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_RequestWin32Input() noexcept
{
return _Write("\x1b[?9001h");
}

[[nodiscard]] HRESULT VtEngine::_RequestFocusEventMode() noexcept
{
return _Write("\x1b[?1004h");
}

// Method Description:
// - Send a sequence to the connected terminal to switch to the alternate or main screen buffer.
// Arguments:
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/vt/invalidate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ CATCH_RETURN();
// - S_OK
[[nodiscard]] HRESULT VtEngine::PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept
{
// This must be kept in sync with RequestWin32Input().
// It ensures that we disable the modes that we requested on startup.
// Linux shells for instance don't understand the win32-input-mode 9001.
//
// This can be here, instead of being appended at the end of this final rendering pass,
// because these two states happen to have no influence on the caller's VT parsing.
std::ignore = _Write("\033[?9001l\033[?1004l");

*pForcePaint = true;
return S_OK;
}
6 changes: 4 additions & 2 deletions src/renderer/vt/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,11 +525,13 @@ void VtEngine::SetTerminalCursorTextPosition(const til::point cursor) noexcept
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
HRESULT VtEngine::RequestWin32Input() noexcept
{
// On startup we request the modes we require for optimal functioning
// (namely win32 input mode and focus event mode).
//
// It's important that any additional modes set here are also mirrored in
// the AdaptDispatch::HardReset method, since that needs to re-enable them
// in the connected terminal after passing through an RIS sequence.
RETURN_IF_FAILED(_RequestWin32Input());
RETURN_IF_FAILED(_RequestFocusEventMode());
RETURN_IF_FAILED(_Write("\033[?9001h\033[?1004h"));
_Flush();
return S_OK;
}
Expand Down
5 changes: 0 additions & 5 deletions src/renderer/vt/vtrenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT WriteTerminalUtf8(const std::string_view str) noexcept;
[[nodiscard]] virtual HRESULT WriteTerminalW(const std::wstring_view str) noexcept = 0;
void SetTerminalOwner(Microsoft::Console::VirtualTerminal::VtIo* const terminalOwner);
void BeginResizeRequest();
void EndResizeRequest();
void SetResizeQuirk(const bool resizeQuirk);
void SetPassthroughMode(const bool passthrough) noexcept;
void SetLookingForDSRCallback(std::function<void(bool)> pfnLooking) noexcept;
Expand Down Expand Up @@ -208,11 +206,8 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT _RequestCursor() noexcept;
[[nodiscard]] HRESULT _ListenForDSR() noexcept;

[[nodiscard]] HRESULT _RequestWin32Input() noexcept;
[[nodiscard]] HRESULT _SwitchScreenBuffer(const bool useAltBuffer) noexcept;

[[nodiscard]] HRESULT _RequestFocusEventMode() noexcept;

[[nodiscard]] virtual HRESULT _MoveCursor(const til::point coord) noexcept = 0;
[[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const TextAttribute& textAttributes) noexcept;
[[nodiscard]] HRESULT _16ColorUpdateDrawingBrushes(const TextAttribute& textAttributes) noexcept;
Expand Down
10 changes: 8 additions & 2 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1917,7 +1917,13 @@ bool AdaptDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, con
return !_api.IsConsolePty();
case DispatchTypes::ModeParams::W32IM_Win32InputMode:
_terminalInput.SetInputMode(TerminalInput::Mode::Win32, enable);
return !_PassThroughInputModes();
// ConPTY requests the Win32InputMode on startup and disables it on shutdown. When nesting ConPTY inside
// ConPTY then this should not bubble up. Otherwise, when the inner ConPTY exits and the outer ConPTY
// passes the disable sequence up to the hosting terminal, we'd stop getting Win32InputMode entirely!
// It also makes more sense to not bubble it up, because this mode is specifically for INPUT_RECORD interop
// and thus entirely between a PTY's input records and its INPUT_RECORD-aware VT-aware console clients.
// Returning true here will mark this as being handled and avoid this.
return true;
default:
// If no functions to call, overall dispatch was a failure.
return false;
Expand Down Expand Up @@ -3097,7 +3103,7 @@ bool AdaptDispatch::HardReset()
if (stateMachine.FlushToTerminal())
{
auto& engine = stateMachine.Engine();
engine.ActionPassThroughString(L"\033[?9001;1004h");
engine.ActionPassThroughString(L"\033[?9001h\033[?1004h");
}
}
return true;
Expand Down

0 comments on commit 8a9af94

Please sign in to comment.