Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cursor inheritance #17576

Merged
merged 1 commit into from
Jul 17, 2024
Merged
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
13 changes: 8 additions & 5 deletions src/host/VtIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ bool VtIo::IsUsingVt() const
CATCH_RETURN();
}

if (_pVtInputThread)
{
LOG_IF_FAILED(_pVtInputThread->Start());
}

// MSFT: 15813316
// If the terminal application wants us to inherit the cursor position,
// we're going to emit a VT sequence to ask for the cursor position, then
Expand All @@ -193,6 +198,9 @@ bool VtIo::IsUsingVt() const
{
_lookingForCursorPosition = false;
LOG_IF_FAILED(_pVtRenderEngine->RequestCursor());

// Allow the input thread to momentarily gain the console lock.
const auto suspension = g.getConsoleInformation().SuspendLock();
_pVtInputThread->WaitUntilDSR(3000);
}

Expand All @@ -202,11 +210,6 @@ bool VtIo::IsUsingVt() const
// this sequence, it'll just ignore it.
LOG_IF_FAILED(_pVtRenderEngine->RequestWin32Input());

if (_pVtInputThread)
{
LOG_IF_FAILED(_pVtInputThread->Start());
}

if (_pPtySignalInputThread)
{
// Let the signal thread know that the console is connected.
Expand Down
14 changes: 10 additions & 4 deletions src/inc/til/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,29 @@

namespace til
{
// Similar to std::atomic<T>::wait, but slightly faster and with the ability to specify a timeout.
// Returns false on failure, which is pretty much always a timeout. (We prevent invalid arguments by taking references.)
template<typename T>
inline void atomic_wait(const std::atomic<T>& atomic, const T& current, DWORD waitMilliseconds = INFINITE) noexcept
bool atomic_wait(const std::atomic<T>& atomic, const T& current, DWORD waitMilliseconds = INFINITE) noexcept
{
static_assert(sizeof(atomic) == sizeof(current));
#pragma warning(suppress : 26492) // Don't use const_cast to cast away const or volatile
WaitOnAddress(const_cast<std::atomic<T>*>(&atomic), const_cast<T*>(&current), sizeof(current), waitMilliseconds);
return WaitOnAddress(const_cast<std::atomic<T>*>(&atomic), const_cast<T*>(&current), sizeof(current), waitMilliseconds);
}

// Wakes at most one of the threads waiting on the atomic via atomic_wait().
// Don't use this with std::atomic<T>::wait, because it's not guaranteed to work in the future.
template<typename T>
inline void atomic_notify_one(const std::atomic<T>& atomic) noexcept
void atomic_notify_one(const std::atomic<T>& atomic) noexcept
{
#pragma warning(suppress : 26492) // Don't use const_cast to cast away const or volatile
WakeByAddressSingle(const_cast<std::atomic<T>*>(&atomic));
}

// Wakes all threads waiting on the atomic via atomic_wait().
// Don't use this with std::atomic<T>::wait, because it's not guaranteed to work in the future.
template<typename T>
inline void atomic_notify_all(const std::atomic<T>& atomic) noexcept
void atomic_notify_all(const std::atomic<T>& atomic) noexcept
{
#pragma warning(suppress : 26492) // Don't use const_cast to cast away const or volatile
WakeByAddressAll(const_cast<std::atomic<T>*>(&atomic));
Expand Down
4 changes: 2 additions & 2 deletions src/terminal/parser/InputStateMachineEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ InputStateMachineEngine::InputStateMachineEngine(std::unique_ptr<IInteractDispat

void InputStateMachineEngine::WaitUntilDSR(DWORD timeout) const noexcept
{
// atomic_wait() returns false when the timeout expires.
// Technically we should decrement the timeout with each iteration,
// but I suspect infinite spurious wake-ups are a theoretical problem.
while (_lookingForDSR.load(std::memory_order::relaxed))
while (_lookingForDSR.load(std::memory_order::relaxed) && til::atomic_wait(_lookingForDSR, true, timeout))
{
til::atomic_wait(_lookingForDSR, true, timeout);
}
}

Expand Down
Loading