Avoid encoding VT via win32 input mode (#16407)
This changeset avoids re-encoding output from `AdaptDispatch` via the win32-input-mode mechanism when VT input is enabled. That is, an `AdaptDispatch` output like `\x1b[C` would otherwise result in dozens of characters of input. Related to #16343 ## Validation Steps Performed * Replace conhost with this * Launch a Win32 application inside WSL * ASCII keyboard inputs are represented as single `INPUT_RECORD`s ✅
This commit is contained in:
parent
91fd7d0101
commit
0da37a134a
|
@ -602,6 +602,27 @@ size_t InputBuffer::Write(const std::span<const INPUT_RECORD>& inEvents)
|
|||
}
|
||||
}
|
||||
|
||||
void InputBuffer::WriteString(const std::wstring_view& text)
|
||||
try
|
||||
{
|
||||
if (text.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto initiallyEmptyQueue = _storage.empty();
|
||||
|
||||
_writeString(text);
|
||||
|
||||
if (initiallyEmptyQueue && !_storage.empty())
|
||||
{
|
||||
ServiceLocator::LocateGlobals().hInputEvent.SetEvent();
|
||||
}
|
||||
|
||||
WakeUpReadersWaitingForData();
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
// This can be considered a "privileged" variant of Write() which allows FOCUS_EVENTs to generate focus VT sequences.
|
||||
// If we didn't do this, someone could write a FOCUS_EVENT_RECORD with WriteConsoleInput, exit without flushing the
|
||||
// input buffer and the next application will suddenly get a "\x1b[I" sequence in their input. See GH#13238.
|
||||
|
@ -828,6 +849,22 @@ void InputBuffer::_HandleTerminalInputCallback(const TerminalInput::StringType&
|
|||
return;
|
||||
}
|
||||
|
||||
_writeString(text);
|
||||
|
||||
if (!_vtInputShouldSuppress)
|
||||
{
|
||||
ServiceLocator::LocateGlobals().hInputEvent.SetEvent();
|
||||
WakeUpReadersWaitingForData();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_HR(wil::ResultFromCaughtException());
|
||||
}
|
||||
}
|
||||
|
||||
void InputBuffer::_writeString(const std::wstring_view& text)
|
||||
{
|
||||
for (const auto& wch : text)
|
||||
{
|
||||
if (wch == UNICODE_NULL)
|
||||
|
@ -843,17 +880,6 @@ void InputBuffer::_HandleTerminalInputCallback(const TerminalInput::StringType&
|
|||
}
|
||||
_storage.push_back(SynthesizeKeyEvent(true, 1, 0, 0, wch, 0));
|
||||
}
|
||||
|
||||
if (!_vtInputShouldSuppress)
|
||||
{
|
||||
ServiceLocator::LocateGlobals().hInputEvent.SetEvent();
|
||||
WakeUpReadersWaitingForData();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_HR(wil::ResultFromCaughtException());
|
||||
}
|
||||
}
|
||||
|
||||
TerminalInput& InputBuffer::GetTerminalInput()
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
size_t Prepend(const std::span<const INPUT_RECORD>& inEvents);
|
||||
size_t Write(const INPUT_RECORD& inEvent);
|
||||
size_t Write(const std::span<const INPUT_RECORD>& inEvents);
|
||||
void WriteString(const std::wstring_view& text);
|
||||
void WriteFocusEvent(bool focused) noexcept;
|
||||
bool WriteMouseEvent(til::point position, unsigned int button, short keyState, short wheelDelta);
|
||||
|
||||
|
@ -96,6 +97,7 @@ private:
|
|||
void _WriteBuffer(const std::span<const INPUT_RECORD>& inRecords, _Out_ size_t& eventsWritten, _Out_ bool& setWaitEvent);
|
||||
bool _CoalesceEvent(const INPUT_RECORD& inEvent) noexcept;
|
||||
void _HandleTerminalInputCallback(const Microsoft::Console::VirtualTerminal::TerminalInput::StringType& text);
|
||||
void _writeString(const std::wstring_view& text);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class InputBufferTests;
|
||||
|
|
|
@ -33,24 +33,11 @@ ConhostInternalGetSet::ConhostInternalGetSet(_In_ IIoProvider& io) :
|
|||
// - <none>
|
||||
void ConhostInternalGetSet::ReturnResponse(const std::wstring_view response)
|
||||
{
|
||||
InputEventQueue inEvents;
|
||||
|
||||
// generate a paired key down and key up event for every
|
||||
// character to be sent into the console's input buffer
|
||||
for (const auto& wch : response)
|
||||
{
|
||||
// This wasn't from a real keyboard, so we're leaving key/scan codes blank.
|
||||
auto keyEvent = SynthesizeKeyEvent(true, 1, 0, 0, wch, 0);
|
||||
inEvents.push_back(keyEvent);
|
||||
keyEvent.Event.KeyEvent.bKeyDown = false;
|
||||
inEvents.push_back(keyEvent);
|
||||
}
|
||||
|
||||
// TODO GH#4954 During the input refactor we may want to add a "priority" input list
|
||||
// to make sure that "response" input is spooled directly into the application.
|
||||
// We switched this to an append (vs. a prepend) to fix GH#1637, a bug where two CPR
|
||||
// could collide with each other.
|
||||
_io.GetActiveInputBuffer()->Write(inEvents);
|
||||
_io.GetActiveInputBuffer()->WriteString(response);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
|
Loading…
Reference in New Issue