Avoid dropping Esc characters from VT responses (#17833)

`GetChar` checks if the vkey is VK_ESCAPE. `CharToKeyEvents` however
tries really hard to figure out the vkeys of all characters.
To avoid these issues all we need to do is to simply use the existing
`WriteString` function we already use for all other VT responses.
If it's good for conhost responses, it's good for ConPTY responses.

Additionally, this removes another `IsVtInputEnabled` which was
redundant with `WriteString` which worked exactly the same internally.

Closes #17813
Closes #17851
Probably also related to #17823

## Validation Steps Performed
* Wrote a small app to send and receive a DA1 request. It works 
* WSL already worked to begin with (and still works now) 
* No double-encoding of mouse input events 
This commit is contained in:
Leonard Hecker 2024-09-04 15:47:01 +02:00 committed by GitHub
parent 6e5827add5
commit 7b50f12a78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 29 additions and 24 deletions

View File

@ -33,6 +33,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual void WriteInput(const std::span<const INPUT_RECORD>& inputEvents) = 0; virtual void WriteInput(const std::span<const INPUT_RECORD>& inputEvents) = 0;
virtual void WriteCtrlKey(const INPUT_RECORD& event) = 0; virtual void WriteCtrlKey(const INPUT_RECORD& event) = 0;
virtual void WriteString(std::wstring_view string) = 0; virtual void WriteString(std::wstring_view string) = 0;
virtual void WriteStringRaw(std::wstring_view string) = 0;
virtual void WindowManipulation(DispatchTypes::WindowManipulationType function, VTParameter parameter1, VTParameter parameter2) = 0; virtual void WindowManipulation(DispatchTypes::WindowManipulationType function, VTParameter parameter1, VTParameter parameter2) = 0;
virtual void MoveCursor(VTInt row, VTInt col) = 0; virtual void MoveCursor(VTInt row, VTInt col) = 0;
virtual void FocusChanged(bool focused) = 0; virtual void FocusChanged(bool focused) = 0;

View File

@ -53,10 +53,11 @@ void InteractDispatch::WriteCtrlKey(const INPUT_RECORD& event)
HandleGenericKeyEvent(event, false); HandleGenericKeyEvent(event, false);
} }
// Method Description: // Call this method to write some plain text to the InputBuffer.
// - Writes a string of input to the host. //
// Arguments: // Since the hosting terminal for ConPTY may not support win32-input-mode,
// - string : a string to write to the console. // it may send an "A" key as an "A", for which we need to generate up/down events.
// Because of this, we cannot simply call InputBuffer::WriteString directly.
void InteractDispatch::WriteString(const std::wstring_view string) void InteractDispatch::WriteString(const std::wstring_view string)
{ {
if (!string.empty()) if (!string.empty())
@ -73,6 +74,12 @@ void InteractDispatch::WriteString(const std::wstring_view string)
} }
} }
void InteractDispatch::WriteStringRaw(std::wstring_view string)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->WriteString(string);
}
//Method Description: //Method Description:
// Window Manipulation - Performs a variety of actions relating to the window, // Window Manipulation - Performs a variety of actions relating to the window,
// such as moving the window position, resizing the window, querying // such as moving the window position, resizing the window, querying

View File

@ -30,6 +30,7 @@ namespace Microsoft::Console::VirtualTerminal
void WriteInput(const std::span<const INPUT_RECORD>& inputEvents) override; void WriteInput(const std::span<const INPUT_RECORD>& inputEvents) override;
void WriteCtrlKey(const INPUT_RECORD& event) override; void WriteCtrlKey(const INPUT_RECORD& event) override;
void WriteString(std::wstring_view string) override; void WriteString(std::wstring_view string) override;
void WriteStringRaw(std::wstring_view string) override;
void WindowManipulation(DispatchTypes::WindowManipulationType function, VTParameter parameter1, VTParameter parameter2) override; void WindowManipulation(DispatchTypes::WindowManipulationType function, VTParameter parameter1, VTParameter parameter2) override;
void MoveCursor(VTInt row, VTInt col) override; void MoveCursor(VTInt row, VTInt col) override;
void FocusChanged(bool focused) override; void FocusChanged(bool focused) override;

View File

@ -293,27 +293,10 @@ bool InputStateMachineEngine::ActionPrintString(const std::wstring_view string)
// - true iff we successfully dispatched the sequence. // - true iff we successfully dispatched the sequence.
bool InputStateMachineEngine::ActionPassThroughString(const std::wstring_view string) bool InputStateMachineEngine::ActionPassThroughString(const std::wstring_view string)
{ {
if (string.empty()) if (!string.empty())
{ {
return true; _pDispatch->WriteStringRaw(string);
} }
if (_pDispatch->IsVtInputEnabled())
{
// Synthesize string into key events that we'll write to the buffer
// similar to TerminalInput::_SendInputSequence
InputEventQueue inputEvents;
for (const auto& wch : string)
{
inputEvents.push_back(SynthesizeKeyEvent(true, 1, 0, 0, wch, 0));
}
_pDispatch->WriteInput(inputEvents);
}
else
{
_pDispatch->WriteString(string);
}
return true; return true;
} }

View File

@ -322,6 +322,7 @@ public:
const VTParameter parameter1, const VTParameter parameter1,
const VTParameter parameter2) override; // DTTERM_WindowManipulation const VTParameter parameter2) override; // DTTERM_WindowManipulation
virtual void WriteString(const std::wstring_view string) override; virtual void WriteString(const std::wstring_view string) override;
virtual void WriteStringRaw(const std::wstring_view string) override;
virtual void MoveCursor(const VTInt row, virtual void MoveCursor(const VTInt row,
const VTInt col) override; const VTInt col) override;
@ -377,6 +378,18 @@ void TestInteractDispatch::WriteString(const std::wstring_view string)
WriteInput(keyEvents); WriteInput(keyEvents);
} }
void TestInteractDispatch::WriteStringRaw(const std::wstring_view string)
{
InputEventQueue keyEvents;
for (const auto& wch : string)
{
keyEvents.push_back(SynthesizeKeyEvent(true, 1, 0, 0, wch, 0));
}
WriteInput(keyEvents);
}
void TestInteractDispatch::MoveCursor(const VTInt row, const VTInt col) void TestInteractDispatch::MoveCursor(const VTInt row, const VTInt col)
{ {
VERIFY_IS_TRUE(_testState->_expectCursorPosition); VERIFY_IS_TRUE(_testState->_expectCursorPosition);

View File

@ -184,7 +184,7 @@ static int run(int argc, const wchar_t* argv[])
if (write != 0) if (write != 0)
{ {
DWORD written; DWORD written;
if (!WriteFile(pipe.server.get(), &inputConptyBuffer[0], write, &written, nullptr) || written != read) if (!WriteFile(pipe.server.get(), &inputConptyBuffer[0], write, &written, nullptr) || written != write)
{ {
return 0; return 0;
} }