Compare commits

...

5 Commits

Author SHA1 Message Date
Mike Griese
6a4c324879 remove ITerminalOutputConnection from OutputStateMachineEngine 2019-09-27 16:51:55 -05:00
Mike Griese
30ef50fd9b Merge branch 'master' into dev/migrie/b/2011-reordered-fallthrough-strings
# Conflicts:
#	src/host/VtIo.cpp
2019-09-27 16:37:15 -05:00
Mike Griese
d9953f6fe0 Remove some dead code 2019-09-05 08:03:58 -05:00
Mike Griese
9ca8b98863 Fix build, Add comments 2019-09-04 12:15:43 -05:00
Mike Griese
5a36578ef2 I think this fixes it
The solution here is to have the parser call up to the host to have the host
  paint a frame, before the parser writes the string to the terminal. This way,
  any state from the text before the string we didn't understand will be sent to
  the terminal before the string we didn't understand, which should hopefully
  maintain state like this.

  Unsure if this works with a sequence we didn't understand that's at the end of
  a frame all by itself, something that doesn't trigger another frame.

  This is hard to test unfortunately.
2019-09-04 10:58:16 -05:00
19 changed files with 143 additions and 22 deletions

View File

@@ -30,6 +30,23 @@ void TerminalDispatch::PrintString(const wchar_t* const rgwch, const size_t cch)
_terminalApi.PrintString({ rgwch, cch });
}
// Method Description:
// - Called when the ITermDispatch or output parser was unable to handle a
// particular VT sequence. This string should be forwarded along to the
// terminal, if there is one, so the terminal has a chance to process the
// string.
// - This function is only ever implemented in the console codebase. The
// Terminal doesn't need to pass anything along to anyone.
// Arguments:
// - <unused>
// Return Value:
// - true always.
bool TerminalDispatch::PassThroughString(const wchar_t* const /*rgwch*/, const size_t /*cch*/)
{
// Do nothing.
return true;
}
bool TerminalDispatch::CursorPosition(const unsigned int uiLine,
const unsigned int uiColumn)
{

View File

@@ -12,6 +12,7 @@ public:
virtual void Execute(const wchar_t wchControl) override;
virtual void Print(const wchar_t wchPrintable) override;
virtual void PrintString(const wchar_t* const rgwch, const size_t cch) override;
bool PassThroughString(const wchar_t* const rgwch, const size_t cch) override;
bool SetGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::GraphicsOptions* const rgOptions,
const size_t cOptions) override;

View File

@@ -396,6 +396,27 @@ bool VtIo::IsUsingVt() const
return hr;
}
// Method Description:
// - Used to write a string straight to the terminal, via the attached VT renderer.
// - When used for passing-through VT sequences we didn't understand, the caller
// should make sure to call Renderer::PaintFrame before calling this, to
// ensure the buffered state of the current frame is flushed before we write
// this sequence. If you don't do that, this string will appear out-of-order
// from the buffered state (see microsoft/terminal#2011)
// Arguments:
// - rgwch: The start of the string of characters to write to the terminal
// - cch: The number of characters to write
// Return Value:
// - <none>
void VtIo::PassThroughString(const wchar_t* const rgwch, const size_t cch)
{
if (_pVtRenderEngine)
{
std::wstring wstr{ rgwch, cch };
LOG_IF_FAILED(_pVtRenderEngine->WriteTerminalW(wstr));
}
}
// Method Description:
// - Tell the vt renderer to begin a resize operation. During a resize
// operation, the vt renderer should _not_ request to be repainted during a

View File

@@ -31,6 +31,7 @@ namespace Microsoft::Console::VirtualTerminal
[[nodiscard]] HRESULT SuppressResizeRepaint();
[[nodiscard]] HRESULT SetCursorPosition(const COORD coordCursor);
void PassThroughString(const wchar_t* const rgwch, const size_t cch);
void BeginResize();
void EndResize();

View File

@@ -2219,3 +2219,37 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
}
CATCH_RETURN();
}
// Method Description:
// - Attempts to pass the given string through to the connected terminal.
// - If we're in conpty mode, the string will be written to the terminal,
// _AFTER_ first calling PaintFrame to render our current state. We do this
// because the string we're about to pass through to the terminal might be
// dependent upon state that's currently buffered in this frame. This way, we
// can flush the buffered state to the terminal, before writing the string to
// the terminal.
// - If we're not in conpty mode, we'll eat the string, doing nothing with it.
// - See microsoft/terminal#2011 for more context.
// Arguments:
// - rgwch: The start of the string of characters to write to the terminal
// - cch: The number of characters to write
// Return Value:
// - <none>
void DoSrvPrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) noexcept
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
// If we're in conpty mode, pass this string through to the connected
// terminal. Do this by first painting the frame, then writing the string we
// didn't understand to the terminal. This will ensure that any effects from
// sequences we _did_ understand are sent to the terminal _before_ the
// sequence we didn't understand. See GH#2011.
if (g.pRender && gci.IsInVtIoMode())
{
if (SUCCEEDED(g.pRender->PaintFrame()))
{
gci.GetVtIo()->PassThroughString(rgwch, cch);
}
}
}

View File

@@ -89,3 +89,5 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept;
void DoSrvPrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) noexcept;

View File

@@ -786,3 +786,18 @@ BOOL ConhostInternalGetSet::PrivateSetDefaultBackground(const COLORREF value) co
{
return SUCCEEDED(DoSrvPrivateSetDefaultBackgroundColor(value));
}
// Method Description:
// - Connects the PrivatePassThroughString call directly into our Driver Message servicing
// call inside Conhost.exe. See DoSrvPrivatePassThroughString for details.
// Arguments:
// - rgwch: The start of the string of characters to write to the terminal
// - cch: The number of characters to write
// Return Value:
// - TRUE always.
BOOL ConhostInternalGetSet::PrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) const noexcept
{
// return SUCCEEDED(DoSrvPrivatePassThroughString(rgwch, cch));
DoSrvPrivatePassThroughString(rgwch, cch);
return TRUE;
}

View File

@@ -161,6 +161,8 @@ public:
BOOL PrivateSetDefaultBackground(const COLORREF value) const noexcept override;
BOOL PrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) const noexcept override;
private:
Microsoft::Console::IIoProvider& _io;
};

View File

@@ -2521,13 +2521,11 @@ void SCREEN_INFORMATION::SetTerminalConnection(_In_ ITerminalOutputConnection* c
OutputStateMachineEngine& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
if (pTtyConnection)
{
engine.SetTerminalConnection(pTtyConnection,
std::bind(&StateMachine::FlushToTerminal, _stateMachine.get()));
engine.EnableFlushing(std::bind(&StateMachine::FlushToTerminal, _stateMachine.get()));
}
else
{
engine.SetTerminalConnection(nullptr,
nullptr);
engine.EnableFlushing(nullptr);
}
}

View File

@@ -27,6 +27,8 @@ public:
virtual void Print(const wchar_t wchPrintable) = 0;
virtual void PrintString(const wchar_t* const rgwch, const size_t cch) = 0;
virtual bool PassThroughString(const wchar_t* const rgwch, const size_t cch) = 0;
virtual bool CursorUp(const unsigned int uiDistance) = 0; // CUU
virtual bool CursorDown(const unsigned int uiDistance) = 0; // CUD
virtual bool CursorForward(const unsigned int uiDistance) = 0; // CUF

View File

@@ -79,6 +79,21 @@ void AdaptDispatch::PrintString(const wchar_t* const rgwch, const size_t cch)
CATCH_LOG();
}
// Method Description:
// - Called when the ITermDispatch or output parser was unable to handle a
// particular VT sequence. This string should be forwarded along to the
// terminal, if there is one, so the terminal has a chance to process the
// string.
// Arguments:
// - rgwch: The start of the string of characters to write to the terminal
// - cch: The number of characters to write
// Return Value:
// - true if the console was able to handle (or eat) the provided string
bool AdaptDispatch::PassThroughString(const wchar_t* const rgwch, const size_t cch)
{
return !!_conApi->PrivatePassThroughString(rgwch, cch);
}
// Routine Description:
// - Generalizes cursor movement for up/down/left/right and next/previous line.
// Arguments:

View File

@@ -39,6 +39,9 @@ namespace Microsoft::Console::VirtualTerminal
void PrintString(const wchar_t* const rgwch, const size_t cch) override;
void Print(const wchar_t wchPrintable) override;
// This is used by conpty to pass sequences it doesn't understand through to the terminal
bool PassThroughString(const wchar_t* const rgwch, const size_t cch);
bool CursorUp(_In_ unsigned int const uiDistance) override; // CUU
bool CursorDown(_In_ unsigned int const uiDistance) override; // CUD
bool CursorForward(_In_ unsigned int const uiDistance) override; // CUF

View File

@@ -108,5 +108,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual BOOL PrivateSetColorTableEntry(const short index, const COLORREF value) const = 0;
virtual BOOL PrivateSetDefaultForeground(const COLORREF value) const = 0;
virtual BOOL PrivateSetDefaultBackground(const COLORREF value) const = 0;
virtual BOOL PrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) const = 0;
};
}

View File

@@ -699,6 +699,12 @@ public:
return _fPrivateSetDefaultBackgroundResult;
}
BOOL PrivatePassThroughString(const wchar_t* const /*rgwch*/, const size_t /*cch*/) const noexcept override
{
Log::Comment(L"PrivatePassThroughString MOCK called...");
return TRUE;
}
void _IncrementCoordPos(_Inout_ COORD* pcoord)
{
pcoord->X++;

View File

@@ -14,7 +14,6 @@ using namespace Microsoft::Console::VirtualTerminal;
OutputStateMachineEngine::OutputStateMachineEngine(ITermDispatch* const pDispatch) :
_dispatch(pDispatch),
_pfnFlushToTerminal(nullptr),
_pTtyConnection(nullptr),
_lastPrintedChar(AsciiChars::NUL)
{
}
@@ -124,17 +123,7 @@ bool OutputStateMachineEngine::ActionPrintString(const wchar_t* const rgwch, con
bool OutputStateMachineEngine::ActionPassThroughString(const wchar_t* const rgwch,
_In_ size_t const cch)
{
bool fSuccess = true;
if (_pTtyConnection != nullptr)
{
std::wstring wstr = std::wstring(rgwch, cch);
auto hr = _pTtyConnection->WriteTerminalW(wstr);
LOG_IF_FAILED(hr);
fSuccess = SUCCEEDED(hr);
}
// If there's not a TTY connection, our previous behavior was to eat the string.
return fSuccess;
return _dispatch->PassThroughString(rgwch, cch);
}
// Routine Description:
@@ -1687,10 +1676,8 @@ _Success_(return ) bool OutputStateMachineEngine::_GetCursorStyle(_In_reads_(cPa
// currently processing.
// Return Value:
// - <none>
void OutputStateMachineEngine::SetTerminalConnection(ITerminalOutputConnection* const pTtyConnection,
std::function<bool()> pfnFlushToTerminal)
void OutputStateMachineEngine::EnableFlushing(std::function<bool()> pfnFlushToTerminal)
{
this->_pTtyConnection = pTtyConnection;
this->_pfnFlushToTerminal = pfnFlushToTerminal;
}

View File

@@ -62,15 +62,13 @@ namespace Microsoft::Console::VirtualTerminal
bool DispatchControlCharsFromEscape() const override;
bool DispatchIntermediatesFromEscape() const override;
void SetTerminalConnection(Microsoft::Console::ITerminalOutputConnection* const pTtyConnection,
std::function<bool()> pfnFlushToTerminal);
void EnableFlushing(std::function<bool()> pfnFlushToTerminal);
const ITermDispatch& Dispatch() const noexcept;
ITermDispatch& Dispatch() noexcept;
private:
std::unique_ptr<ITermDispatch> _dispatch;
Microsoft::Console::ITerminalOutputConnection* _pTtyConnection;
std::function<bool()> _pfnFlushToTerminal;
wchar_t _lastPrintedChar;

View File

@@ -21,3 +21,9 @@ void EchoDispatch::Execute(const wchar_t wchControl)
{
wprintf(L"Execute: 0x%x\r\n", wchControl);
}
bool EchoDispatch::PassThroughString(const wchar_t* const rgwch, const size_t cch)
{
wprintf(L"PassThroughString: \"%s\" (%zd chars)\r\n", rgwch, cch);
return true;
}

View File

@@ -15,6 +15,7 @@ namespace Microsoft
void Print(const wchar_t wchPrintable) override;
void PrintString(const wchar_t* const rgwch, const size_t cch) override;
void Execute(const wchar_t wchControl) override;
bool PassThroughString(const wchar_t* const rgwch, const size_t cch) override;
};
}
}

View File

@@ -47,6 +47,11 @@ public:
virtual void PrintString(const wchar_t* const /*rgwch*/, const size_t /*cch*/) override
{
}
bool PassThroughString(const wchar_t* const /*rgwch*/, const size_t /*cch*/) override
{
return false;
}
};
class Microsoft::Console::VirtualTerminal::OutputEngineTest final
@@ -612,6 +617,11 @@ public:
{
}
virtual bool PassThroughString(const wchar_t* const /*rgwch*/, const size_t /*cch*/) override
{
return false;
}
StatefulDispatch() :
_uiCursorDistance{ 0 },
_uiLine{ 0 },