Consolidate the interfaces for setting VT input modes (#11384)

Instead of having a separate method for setting each mouse and keyboard
mode, this PR consolidates them all into a single method which takes a
mode parameter, and stores the modes in a `til::enumset` rather than
having a separate `bool` for each mode.

This enables us to get rid of a lot of boilerplate code, and makes the
code easier to extend when we want to introduce additional modes in the
future. It'll also makes it easier to read back the state of the various
modes when implementing the `DECRQM` query.

Most of the complication is in the `TerminalInput` class, which had to
be adjusted to work with an `enumset` in place of all the `bool` fields.
For the rest, it was largely a matter of replacing calls to all the old
mode setting methods with the new `SetInputMode` method, and deleting a
bunch of unused code.

One thing worth mentioning is that the `AdaptDispatch` implementation
used to have a `_ShouldPassThroughInputModeChange` method that was
called after every mode change. This code has now been moved up into the
`SetInputMode` implementation in `ConhostInternalGetSet` so it's just
handled in one place. Keeping this out of the dispatch class will also
be beneficial for sharing the implementation with `TerminalDispatch`.

## Validation

The updated interface necessitated some adjustments to the tests in
`AdapterTest` and `MouseInputTest`, but the essential structure of the
tests remains unchanged, and everything still passes.

I've also tested the keyboard and mouse modes in Vttest and confirmed
they still work at least as well as they did before (both conhost and
Windows Terminal), and I tested the alternate scroll mode manually
(conhost only).

Simplifying the `ConGetSet` and `ITerminalApi` is also part of the plan
to de-duplicate the `AdaptDispatch` and `TerminalDispatch`
implementation (#3849).
This commit is contained in:
James Holderness 2021-10-26 22:12:22 +01:00 committed by GitHub
parent a916a5d9de
commit 7b7dea009c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 182 additions and 753 deletions

View file

@ -3,6 +3,7 @@
#pragma once
#include "../../terminal/adapter/DispatchTypes.hpp"
#include "../../terminal/input/terminalInput.hpp"
#include "../../buffer/out/TextAttribute.hpp"
#include "../../types/inc/Viewport.hpp"
@ -47,16 +48,9 @@ namespace Microsoft::Terminal::Core
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0;
virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0;
virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
virtual bool SetScreenMode(const bool reverseMode) noexcept = 0;
virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0;
virtual bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableSGRExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableButtonEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAnyEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAlternateScrollMode(const bool enabled) noexcept = 0;
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;

View file

@ -112,16 +112,9 @@ public:
bool SetDefaultForeground(const COLORREF color) noexcept override;
bool SetDefaultBackground(const COLORREF color) noexcept override;
bool EnableWin32InputMode(const bool win32InputMode) noexcept override;
bool SetCursorKeysMode(const bool applicationMode) noexcept override;
bool SetKeypadMode(const bool applicationMode) noexcept override;
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
bool SetScreenMode(const bool reverseMode) noexcept override;
bool EnableVT200MouseMode(const bool enabled) noexcept override;
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override;
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override;
bool EnableButtonEventMouseMode(const bool enabled) noexcept override;
bool EnableAnyEventMouseMode(const bool enabled) noexcept override;
bool EnableAlternateScrollMode(const bool enabled) noexcept override;
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override;
bool IsXtermBracketedPasteModeEnabled() const noexcept override;

View file

@ -482,23 +482,13 @@ til::color Terminal::GetDefaultBackground() const noexcept
return _defaultBg;
}
bool Terminal::EnableWin32InputMode(const bool win32InputMode) noexcept
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
try
{
_terminalInput->ChangeWin32InputMode(win32InputMode);
return true;
}
bool Terminal::SetCursorKeysMode(const bool applicationMode) noexcept
{
_terminalInput->ChangeCursorKeysMode(applicationMode);
return true;
}
bool Terminal::SetKeypadMode(const bool applicationMode) noexcept
{
_terminalInput->ChangeKeypadMode(applicationMode);
_terminalInput->SetInputMode(mode, enabled);
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::SetScreenMode(const bool reverseMode) noexcept
try
@ -511,42 +501,6 @@ try
}
CATCH_RETURN_FALSE()
bool Terminal::EnableVT200MouseMode(const bool enabled) noexcept
{
_terminalInput->EnableDefaultTracking(enabled);
return true;
}
bool Terminal::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
{
_terminalInput->SetUtf8ExtendedMode(enabled);
return true;
}
bool Terminal::EnableSGRExtendedMouseMode(const bool enabled) noexcept
{
_terminalInput->SetSGRExtendedMode(enabled);
return true;
}
bool Terminal::EnableButtonEventMouseMode(const bool enabled) noexcept
{
_terminalInput->EnableButtonEventTracking(enabled);
return true;
}
bool Terminal::EnableAnyEventMouseMode(const bool enabled) noexcept
{
_terminalInput->EnableAnyEventTracking(enabled);
return true;
}
bool Terminal::EnableAlternateScrollMode(const bool enabled) noexcept
{
_terminalInput->EnableAlternateScroll(enabled);
return true;
}
bool Terminal::EnableXtermBracketedPasteMode(const bool enabled) noexcept
{
_bracketedPasteMode = enabled;

View file

@ -321,9 +321,9 @@ CATCH_LOG_RETURN_FALSE()
// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetKeypadMode(const bool fApplicationMode) noexcept
bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
{
_terminalApi.SetKeypadMode(fApplicationMode);
_terminalApi.SetInputMode(TerminalInput::Mode::Keypad, applicationMode);
return true;
}
@ -334,7 +334,7 @@ bool TerminalDispatch::SetKeypadMode(const bool fApplicationMode) noexcept
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
{
_terminalApi.SetCursorKeysMode(applicationMode);
_terminalApi.SetInputMode(TerminalInput::Mode::CursorKey, applicationMode);
return true;
}
@ -359,7 +359,7 @@ bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
// - True if handled successfully. False otherwise.
bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
{
_terminalApi.EnableWin32InputMode(win32Mode);
_terminalApi.SetInputMode(TerminalInput::Mode::Win32, win32Mode);
return true;
}
@ -371,7 +371,7 @@ bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
{
_terminalApi.EnableVT200MouseMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled);
return true;
}
@ -384,7 +384,7 @@ bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
{
_terminalApi.EnableUTF8ExtendedMouseMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled);
return true;
}
@ -397,7 +397,7 @@ bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
{
_terminalApi.EnableSGRExtendedMouseMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled);
return true;
}
@ -409,7 +409,7 @@ bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
{
_terminalApi.EnableButtonEventMouseMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled);
return true;
}
@ -422,7 +422,7 @@ bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
{
_terminalApi.EnableAnyEventMouseMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled);
return true;
}
@ -435,7 +435,7 @@ bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
{
_terminalApi.EnableAlternateScrollMode(enabled);
_terminalApi.SetInputMode(TerminalInput::Mode::AlternateScroll, enabled);
return true;
}

View file

@ -1248,55 +1248,6 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
CATCH_RETURN();
}
// Routine Description:
// - A private API call for changing the cursor keys input mode between normal and application mode.
// The cursor keys are the arrows, plus Home and End.
// Parameters:
// - fApplicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
// Return value:
// - True if handled successfully. False otherwise.
[[nodiscard]] NTSTATUS DoSrvPrivateSetCursorKeysMode(_In_ bool fApplicationMode)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
if (gci.pInputBuffer == nullptr)
{
return STATUS_UNSUCCESSFUL;
}
gci.pInputBuffer->GetTerminalInput().ChangeCursorKeysMode(fApplicationMode);
return STATUS_SUCCESS;
}
// Routine Description:
// - A private API call for changing the keypad input mode between numeric and application mode.
// This controls what the keys on the numpad translate to.
// Parameters:
// - fApplicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
// Return value:
// - True if handled successfully. False otherwise.
[[nodiscard]] NTSTATUS DoSrvPrivateSetKeypadMode(_In_ bool fApplicationMode)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
if (gci.pInputBuffer == nullptr)
{
return STATUS_UNSUCCESSFUL;
}
gci.pInputBuffer->GetTerminalInput().ChangeKeypadMode(fApplicationMode);
return STATUS_SUCCESS;
}
// Function Description:
// - A private API call which enables/disables sending full input records
// encoded as a string of characters to the client application.
// Parameters:
// - win32InputMode - set to true to enable win32-input-mode, false to disable.
// Return value:
// - <none>
void DoSrvPrivateEnableWin32InputMode(const bool win32InputMode)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.pInputBuffer->GetTerminalInput().ChangeWin32InputMode(win32InputMode);
}
// Routine Description:
// - A private API call for changing the screen mode between normal and reverse.
// When in reverse screen mode, the background and foreground colors are switched.
@ -1525,78 +1476,6 @@ void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo)
screenInfo.GetActiveBuffer().UseMainScreenBuffer();
}
// Routine Description:
// - A private API call for enabling VT200 style mouse mode.
// Parameters:
// - fEnable - true to enable default tracking mode, false to disable mouse mode.
// Return value:
// - None
void DoSrvPrivateEnableVT200MouseMode(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().EnableDefaultTracking(fEnable);
}
// Routine Description:
// - A private API call for enabling utf8 style mouse mode.
// Parameters:
// - fEnable - true to enable, false to disable.
// Return value:
// - None
void DoSrvPrivateEnableUTF8ExtendedMouseMode(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().SetUtf8ExtendedMode(fEnable);
}
// Routine Description:
// - A private API call for enabling SGR style mouse mode.
// Parameters:
// - fEnable - true to enable, false to disable.
// Return value:
// - None
void DoSrvPrivateEnableSGRExtendedMouseMode(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().SetSGRExtendedMode(fEnable);
}
// Routine Description:
// - A private API call for enabling button-event mouse mode.
// Parameters:
// - fEnable - true to enable button-event mode, false to disable mouse mode.
// Return value:
// - None
void DoSrvPrivateEnableButtonEventMouseMode(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().EnableButtonEventTracking(fEnable);
}
// Routine Description:
// - A private API call for enabling any-event mouse mode.
// Parameters:
// - fEnable - true to enable any-event mode, false to disable mouse mode.
// Return value:
// - None
void DoSrvPrivateEnableAnyEventMouseMode(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().EnableAnyEventTracking(fEnable);
}
// Routine Description:
// - A private API call for enabling alternate scroll mode
// Parameters:
// - fEnable - true to enable alternate scroll mode, false to disable.
// Return value:
// None
void DoSrvPrivateEnableAlternateScroll(const bool fEnable)
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.GetActiveInputBuffer()->GetTerminalInput().EnableAlternateScroll(fEnable);
}
// Routine Description:
// - A private API call for performing a VT-style erase all operation on the buffer.
// See SCREEN_INFORMATION::VtEraseAll's description for details.

View file

@ -18,10 +18,6 @@ Revision History:
#include "../inc/conattrs.hpp"
class SCREEN_INFORMATION;
[[nodiscard]] NTSTATUS DoSrvPrivateSetCursorKeysMode(_In_ bool fApplicationMode);
[[nodiscard]] NTSTATUS DoSrvPrivateSetKeypadMode(_In_ bool fApplicationMode);
void DoSrvPrivateEnableWin32InputMode(const bool win32InputMode);
[[nodiscard]] NTSTATUS DoSrvPrivateSetScreenMode(const bool reverseMode);
[[nodiscard]] NTSTATUS DoSrvPrivateSetAutoWrapMode(const bool wrapAtEOL);
@ -35,13 +31,6 @@ void DoSrvPrivateAllowCursorBlinking(SCREEN_INFORMATION& screenInfo, const bool
[[nodiscard]] NTSTATUS DoSrvPrivateUseAlternateScreenBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvPrivateEnableVT200MouseMode(const bool fEnable);
void DoSrvPrivateEnableUTF8ExtendedMouseMode(const bool fEnable);
void DoSrvPrivateEnableSGRExtendedMouseMode(const bool fEnable);
void DoSrvPrivateEnableButtonEventMouseMode(const bool fEnable);
void DoSrvPrivateEnableAnyEventMouseMode(const bool fEnable);
void DoSrvPrivateEnableAlternateScroll(const bool fEnable);
[[nodiscard]] HRESULT DoSrvPrivateEraseAll(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateClearBuffer(SCREEN_INFORMATION& screenInfo);

View file

@ -15,6 +15,7 @@
using namespace Microsoft::Console;
using Microsoft::Console::Interactivity::ServiceLocator;
using Microsoft::Console::VirtualTerminal::TerminalInput;
WriteBuffer::WriteBuffer(_In_ Microsoft::Console::IIoProvider& io) :
_io{ io },
@ -237,43 +238,28 @@ bool ConhostInternalGetSet::SetConsoleWindowInfo(const bool absolute, const SMAL
}
// Routine Description:
// - Connects the PrivateSetCursorKeysMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateSetCursorKeysMode is an internal-only "API" call that the vt commands can execute,
// - Sets the various terminal input modes.
// SetInputMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - fApplicationMode - set to true to enable Application Mode Input, false for Normal Mode.
// - mode - the input mode to change.
// - enabled - set to true to enable the mode, false to disable it.
// Return Value:
// - true if successful (see DoSrvPrivateSetCursorKeysMode). false otherwise.
bool ConhostInternalGetSet::PrivateSetCursorKeysMode(const bool fApplicationMode)
// - true if successful. false otherwise.
bool ConhostInternalGetSet::SetInputMode(const TerminalInput::Mode mode, const bool enabled)
{
return NT_SUCCESS(DoSrvPrivateSetCursorKeysMode(fApplicationMode));
}
auto& terminalInput = _io.GetActiveInputBuffer()->GetTerminalInput();
terminalInput.SetInputMode(mode, enabled);
// Routine Description:
// - Connects the PrivateSetKeypadMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateSetKeypadMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - fApplicationMode - set to true to enable Application Mode Input, false for Numeric Mode.
// Return Value:
// - true if successful (see DoSrvPrivateSetKeypadMode). false otherwise.
bool ConhostInternalGetSet::PrivateSetKeypadMode(const bool fApplicationMode)
{
return NT_SUCCESS(DoSrvPrivateSetKeypadMode(fApplicationMode));
}
// Routine Description:
// - Connects the PrivateEnableWin32InputMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableWin32InputMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - win32InputMode - set to true to enable win32-input-mode, false to disable.
// Return Value:
// - true always
bool ConhostInternalGetSet::PrivateEnableWin32InputMode(const bool win32InputMode)
{
DoSrvPrivateEnableWin32InputMode(win32InputMode);
return true;
// If we're a conpty, AND WE'RE IN VT INPUT MODE, always pass input mode requests
// The VT Input mode check is to work around ssh.exe v7.7, which uses VT
// output, but not Input.
// The original comment said, "Once the conpty supports these types of input,
// this check can be removed. See GH#4911". Unfortunately, time has shown
// us that SSH 7.7 _also_ requests mouse input and that can have a user interface
// impact on the actual connected terminal. We can't remove this check,
// because SSH <=7.7 is out in the wild on all versions of Windows <=2004.
return !(IsConsolePty() && PrivateIsVtInputEnabled());
}
// Routine Description:
@ -289,7 +275,7 @@ bool ConhostInternalGetSet::PrivateSetAnsiMode(const bool ansiMode)
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
stateMachine.SetAnsiMode(ansiMode);
auto& terminalInput = _io.GetActiveInputBuffer()->GetTerminalInput();
terminalInput.ChangeAnsiMode(ansiMode);
terminalInput.SetInputMode(TerminalInput::Mode::Ansi, ansiMode);
return true;
}
@ -448,90 +434,6 @@ bool ConhostInternalGetSet::PrivateUseMainScreenBuffer()
return true;
}
// Routine Description:
// - Connects the PrivateEnableVT200MouseMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableVT200MouseMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable vt200 mouse mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableVT200MouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableVT200MouseMode(const bool enabled)
{
DoSrvPrivateEnableVT200MouseMode(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEnableUTF8ExtendedMouseMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableUTF8ExtendedMouseMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable utf8 extended mouse mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableUTF8ExtendedMouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableUTF8ExtendedMouseMode(const bool enabled)
{
DoSrvPrivateEnableUTF8ExtendedMouseMode(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEnableSGRExtendedMouseMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableSGRExtendedMouseMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable SGR extended mouse mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableSGRExtendedMouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableSGRExtendedMouseMode(const bool enabled)
{
DoSrvPrivateEnableSGRExtendedMouseMode(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEnableButtonEventMouseMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableButtonEventMouseMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable button-event mouse mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableButtonEventMouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableButtonEventMouseMode(const bool enabled)
{
DoSrvPrivateEnableButtonEventMouseMode(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEnableAnyEventMouseMode call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableAnyEventMouseMode is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable any-event mouse mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableAnyEventMouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableAnyEventMouseMode(const bool enabled)
{
DoSrvPrivateEnableAnyEventMouseMode(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEnableAlternateScroll call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEnableAlternateScroll is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on out public API surface.
// Arguments:
// - enabled - set to true to enable alternate scroll mode, false to disable
// Return Value:
// - true if successful (see DoSrvPrivateEnableAnyEventMouseMode). false otherwise.
bool ConhostInternalGetSet::PrivateEnableAlternateScroll(const bool enabled)
{
DoSrvPrivateEnableAlternateScroll(enabled);
return true;
}
// Routine Description:
// - Connects the PrivateEraseAll call directly into our Driver Message servicing call inside Conhost.exe
// PrivateEraseAll is an internal-only "API" call that the vt commands can execute,

View file

@ -72,9 +72,7 @@ public:
bool SetConsoleWindowInfo(bool const absolute,
const SMALL_RECT& window) override;
bool PrivateSetCursorKeysMode(const bool applicationMode) override;
bool PrivateSetKeypadMode(const bool applicationMode) override;
bool PrivateEnableWin32InputMode(const bool win32InputMode) override;
bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
bool PrivateSetAnsiMode(const bool ansiMode) override;
bool PrivateSetScreenMode(const bool reverseMode) override;
@ -97,12 +95,6 @@ public:
bool PrivateUseMainScreenBuffer() override;
bool PrivateEnableVT200MouseMode(const bool enabled) override;
bool PrivateEnableUTF8ExtendedMouseMode(const bool enabled) override;
bool PrivateEnableSGRExtendedMouseMode(const bool enabled) override;
bool PrivateEnableButtonEventMouseMode(const bool enabled) override;
bool PrivateEnableAnyEventMouseMode(const bool enabled) override;
bool PrivateEnableAlternateScroll(const bool enabled) override;
bool PrivateEraseAll() override;
bool PrivateClearBuffer() override;

View file

@ -1167,15 +1167,7 @@ bool AdaptDispatch::ResetMode(const DispatchTypes::ModeParams param)
// - True if handled successfully. False otherwise.
bool AdaptDispatch::SetKeypadMode(const bool fApplicationMode)
{
bool success = true;
success = _pConApi->PrivateSetKeypadMode(fApplicationMode);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::Keypad, fApplicationMode);
}
// Method Description:
@ -1187,15 +1179,7 @@ bool AdaptDispatch::SetKeypadMode(const bool fApplicationMode)
// - True if handled successfully. False otherwise.
bool AdaptDispatch::EnableWin32InputMode(const bool win32InputMode)
{
bool success = true;
success = _pConApi->PrivateEnableWin32InputMode(win32InputMode);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::Win32, win32InputMode);
}
// - DECCKM - Sets the cursor keys input mode to either Application mode or Normal mode (true, false respectively)
@ -1205,15 +1189,7 @@ bool AdaptDispatch::EnableWin32InputMode(const bool win32InputMode)
// - True if handled successfully. False otherwise.
bool AdaptDispatch::SetCursorKeysMode(const bool applicationMode)
{
bool success = true;
success = _pConApi->PrivateSetCursorKeysMode(applicationMode);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::CursorKey, applicationMode);
}
// - att610 - Enables or disables the cursor blinking.
@ -2096,15 +2072,7 @@ bool AdaptDispatch::EnableDECCOLMSupport(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableVT200MouseMode(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableVT200MouseMode(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled);
}
//Routine Description:
@ -2116,15 +2084,7 @@ bool AdaptDispatch::EnableVT200MouseMode(const bool enabled)
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableUTF8ExtendedMouseMode(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled);
}
//Routine Description:
@ -2136,15 +2096,7 @@ bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool enabled)
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableSGRExtendedMouseMode(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled);
}
//Routine Description:
@ -2155,15 +2107,7 @@ bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool enabled)
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableButtonEventMouseMode(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableButtonEventMouseMode(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled);
}
//Routine Description:
@ -2175,15 +2119,7 @@ bool AdaptDispatch::EnableButtonEventMouseMode(const bool enabled)
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableAnyEventMouseMode(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableAnyEventMouseMode(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled);
}
//Routine Description:
@ -2195,15 +2131,7 @@ bool AdaptDispatch::EnableAnyEventMouseMode(const bool enabled)
// True if handled successfully. False otherwise.
bool AdaptDispatch::EnableAlternateScroll(const bool enabled)
{
bool success = true;
success = _pConApi->PrivateEnableAlternateScroll(enabled);
if (_ShouldPassThroughInputModeChange())
{
return false;
}
return success;
return _pConApi->SetInputMode(TerminalInput::Mode::AlternateScroll, enabled);
}
//Routine Description:
@ -2672,22 +2600,3 @@ void AdaptDispatch::_ReportDECSTBMSetting() const
response += L"r\033\\";
_WriteResponse(response);
}
// Routine Description:
// - Determines whether we should pass any sequence that manipulates
// TerminalInput's input generator through the PTY. It encapsulates
// a check for whether the PTY is in use.
// Return value:
// True if the request should be passed.
bool AdaptDispatch::_ShouldPassThroughInputModeChange() const
{
// If we're a conpty, AND WE'RE IN VT INPUT MODE, always pass input mode requests
// The VT Input mode check is to work around ssh.exe v7.7, which uses VT
// output, but not Input.
// The original comment said, "Once the conpty supports these types of input,
// this check can be removed. See GH#4911". Unfortunately, time has shown
// us that SSH 7.7 _also_ requests mouse input and that can have a user interface
// impact on the actual connected terminal. We can't remove this check,
// because SSH <=7.7 is out in the wild on all versions of Windows <=2004.
return _pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled();
}

View file

@ -194,8 +194,6 @@ namespace Microsoft::Console::VirtualTerminal
void _ReportSGRSetting() const;
void _ReportDECSTBMSetting() const;
bool _ShouldPassThroughInputModeChange() const;
std::vector<bool> _tabStopColumns;
bool _initDefaultTabStops = true;

View file

@ -15,6 +15,7 @@ Author(s):
#pragma once
#include "../input/terminalInput.hpp"
#include "../../types/inc/IInputEvent.hpp"
#include "../../buffer/out/LineRendition.hpp"
#include "../../buffer/out/TextAttribute.hpp"
@ -46,9 +47,8 @@ namespace Microsoft::Console::VirtualTerminal
size_t& eventsWritten) = 0;
virtual bool SetConsoleWindowInfo(const bool absolute,
const SMALL_RECT& window) = 0;
virtual bool PrivateSetCursorKeysMode(const bool applicationMode) = 0;
virtual bool PrivateSetKeypadMode(const bool applicationMode) = 0;
virtual bool PrivateEnableWin32InputMode(const bool win32InputMode) = 0;
virtual bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) = 0;
virtual bool PrivateSetAnsiMode(const bool ansiMode) = 0;
virtual bool PrivateSetScreenMode(const bool reverseMode) = 0;
@ -66,12 +66,6 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool PrivateUseAlternateScreenBuffer() = 0;
virtual bool PrivateUseMainScreenBuffer() = 0;
virtual bool PrivateEnableVT200MouseMode(const bool enabled) = 0;
virtual bool PrivateEnableUTF8ExtendedMouseMode(const bool enabled) = 0;
virtual bool PrivateEnableSGRExtendedMouseMode(const bool enabled) = 0;
virtual bool PrivateEnableButtonEventMouseMode(const bool enabled) = 0;
virtual bool PrivateEnableAnyEventMouseMode(const bool enabled) = 0;
virtual bool PrivateEnableAlternateScroll(const bool enabled) = 0;
virtual bool PrivateEraseAll() = 0;
virtual bool PrivateClearBuffer() = 0;
virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0;

View file

@ -298,7 +298,7 @@ public:
s_pwszInputExpected = L"\x0";
VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {}));
mouseInput->EnableDefaultTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::DefaultMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
@ -318,7 +318,7 @@ public:
NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y));
}
mouseInput->EnableButtonEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -337,7 +337,7 @@ public:
NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y));
}
mouseInput->EnableAnyEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -381,11 +381,11 @@ public:
s_pwszInputExpected = L"\x0";
VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {}));
mouseInput->SetUtf8ExtendedMode(true);
mouseInput->SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, true);
short MaxCoord = SHORT_MAX - 33;
mouseInput->EnableDefaultTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::DefaultMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -404,7 +404,7 @@ public:
NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y));
}
mouseInput->EnableButtonEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -423,7 +423,7 @@ public:
NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y));
}
mouseInput->EnableAnyEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -467,13 +467,13 @@ public:
s_pwszInputExpected = L"\x0";
VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {}));
mouseInput->SetSGRExtendedMode(true);
mouseInput->SetInputMode(TerminalInput::Mode::SgrMouseEncoding, true);
// SGR Mode should be able to handle any arbitrary coords.
// However, mouse moves are only handled in Any Event mode
fExpectedKeyHandled = uiButton != WM_MOUSEMOVE;
mouseInput->EnableDefaultTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::DefaultMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -487,7 +487,7 @@ public:
NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y));
}
mouseInput->EnableButtonEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -506,7 +506,7 @@ public:
}
fExpectedKeyHandled = true;
mouseInput->EnableAnyEventTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
COORD Coord = s_rgTestCoords[i];
@ -550,7 +550,7 @@ public:
VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {}));
// Default Tracking, Default Encoding
mouseInput->EnableDefaultTracking(true);
mouseInput->SetInputMode(TerminalInput::Mode::DefaultMouseTracking, true);
for (int i = 0; i < s_iTestCoordsLength; i++)
{
@ -571,7 +571,7 @@ public:
}
// Default Tracking, UTF8 Encoding
mouseInput->SetUtf8ExtendedMode(true);
mouseInput->SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, true);
short MaxCoord = SHORT_MAX - 33;
for (int i = 0; i < s_iTestCoordsLength; i++)
{
@ -592,7 +592,7 @@ public:
}
// Default Tracking, SGR Encoding
mouseInput->SetSGRExtendedMode(true);
mouseInput->SetInputMode(TerminalInput::Mode::SgrMouseEncoding, true);
fExpectedKeyHandled = true; // SGR Mode should be able to handle any arbitrary coords.
for (int i = 0; i < s_iTestCoordsLength; i++)
{
@ -620,7 +620,7 @@ public:
Log::Comment(L"Enable alternate scroll mode in the alt screen buffer");
mouseInput->UseAlternateScreenBuffer();
mouseInput->EnableAlternateScroll(true);
mouseInput->SetInputMode(TerminalInput::Mode::AlternateScroll, true);
Log::Comment(L"Test mouse wheel scrolling up");
s_pwszInputExpected = L"\x1B[A";
@ -631,7 +631,7 @@ public:
VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, -WHEEL_DELTA, {}));
Log::Comment(L"Enable cursor keys mode");
mouseInput->ChangeCursorKeysMode(true);
mouseInput->SetInputMode(TerminalInput::Mode::CursorKey, true);
Log::Comment(L"Test mouse wheel scrolling up");
s_pwszInputExpected = L"\x1BOA";
@ -643,12 +643,12 @@ public:
Log::Comment(L"Confirm no effect when scroll mode is disabled");
mouseInput->UseAlternateScreenBuffer();
mouseInput->EnableAlternateScroll(false);
mouseInput->SetInputMode(TerminalInput::Mode::AlternateScroll, false);
VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {}));
Log::Comment(L"Confirm no effect when using the main buffer");
mouseInput->UseMainScreenBuffer();
mouseInput->EnableAlternateScroll(true);
mouseInput->SetInputMode(TerminalInput::Mode::AlternateScroll, true);
VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {}));
}
};

View file

@ -112,35 +112,17 @@ public:
return _setConsoleWindowInfoResult;
}
bool PrivateSetCursorKeysMode(const bool applicationMode) override
bool SetInputMode(const TerminalInput::Mode mode, const bool enabled) override
{
Log::Comment(L"PrivateSetCursorKeysMode MOCK called...");
Log::Comment(L"SetInputMode MOCK called...");
if (_privateSetCursorKeysModeResult)
if (_setInputModeResult)
{
VERIFY_ARE_EQUAL(_cursorKeysApplicationMode, applicationMode);
VERIFY_ARE_EQUAL(_expectedInputMode, mode);
VERIFY_ARE_EQUAL(_expectedInputModeEnabled, enabled);
}
return _privateSetCursorKeysModeResult;
}
bool PrivateSetKeypadMode(const bool applicationMode) override
{
Log::Comment(L"PrivateSetKeypadMode MOCK called...");
if (_privateSetKeypadModeResult)
{
VERIFY_ARE_EQUAL(_keypadApplicationMode, applicationMode);
}
return _privateSetKeypadModeResult;
}
bool PrivateEnableWin32InputMode(const bool /*win32InputMode*/) override
{
Log::Comment(L"PrivateEnableWin32InputMode MOCK called...");
return true;
return _setInputModeResult;
}
bool PrivateSetAnsiMode(const bool ansiMode) override
@ -352,66 +334,6 @@ public:
return true;
}
bool PrivateEnableVT200MouseMode(const bool enabled) override
{
Log::Comment(L"PrivateEnableVT200MouseMode MOCK called...");
if (_privateEnableVT200MouseModeResult)
{
VERIFY_ARE_EQUAL(_expectedMouseEnabled, enabled);
}
return _privateEnableVT200MouseModeResult;
}
bool PrivateEnableUTF8ExtendedMouseMode(const bool enabled) override
{
Log::Comment(L"PrivateEnableUTF8ExtendedMouseMode MOCK called...");
if (_privateEnableUTF8ExtendedMouseModeResult)
{
VERIFY_ARE_EQUAL(_expectedMouseEnabled, enabled);
}
return _privateEnableUTF8ExtendedMouseModeResult;
}
bool PrivateEnableSGRExtendedMouseMode(const bool enabled) override
{
Log::Comment(L"PrivateEnableSGRExtendedMouseMode MOCK called...");
if (_privateEnableSGRExtendedMouseModeResult)
{
VERIFY_ARE_EQUAL(_expectedMouseEnabled, enabled);
}
return _privateEnableSGRExtendedMouseModeResult;
}
bool PrivateEnableButtonEventMouseMode(const bool enabled) override
{
Log::Comment(L"PrivateEnableButtonEventMouseMode MOCK called...");
if (_privateEnableButtonEventMouseModeResult)
{
VERIFY_ARE_EQUAL(_expectedMouseEnabled, enabled);
}
return _privateEnableButtonEventMouseModeResult;
}
bool PrivateEnableAnyEventMouseMode(const bool enabled) override
{
Log::Comment(L"PrivateEnableAnyEventMouseMode MOCK called...");
if (_privateEnableAnyEventMouseModeResult)
{
VERIFY_ARE_EQUAL(_expectedMouseEnabled, enabled);
}
return _privateEnableAnyEventMouseModeResult;
}
bool PrivateEnableAlternateScroll(const bool enabled) override
{
Log::Comment(L"PrivateEnableAlternateScroll MOCK called...");
if (_privateEnableAlternateScrollResult)
{
VERIFY_ARE_EQUAL(_expectedAlternateScrollEnabled, enabled);
}
return _privateEnableAlternateScrollResult;
}
bool PrivateEraseAll() override
{
Log::Comment(L"PrivateEraseAll MOCK called...");
@ -787,10 +709,9 @@ public:
COORD _expectedScreenBufferSize = { 0, 0 };
SMALL_RECT _expectedScreenBufferViewport{ 0, 0, 0, 0 };
bool _privateSetCursorKeysModeResult = false;
bool _privateSetKeypadModeResult = false;
bool _cursorKeysApplicationMode = false;
bool _keypadApplicationMode = false;
bool _setInputModeResult = false;
TerminalInput::Mode _expectedInputMode;
bool _expectedInputModeEnabled = false;
bool _privateSetAnsiModeResult = false;
bool _expectedAnsiMode = false;
bool _privateAllowCursorBlinkingResult = false;
@ -803,14 +724,6 @@ public:
bool _setConsoleTitleWResult = false;
std::wstring_view _expectedWindowTitle{};
bool _expectedMouseEnabled = false;
bool _expectedAlternateScrollEnabled = false;
bool _privateEnableVT200MouseModeResult = false;
bool _privateEnableUTF8ExtendedMouseModeResult = false;
bool _privateEnableSGRExtendedMouseModeResult = false;
bool _privateEnableButtonEventMouseModeResult = false;
bool _privateEnableAnyEventMouseModeResult = false;
bool _privateEnableAlternateScrollResult = false;
bool _setCursorStyleResult = false;
CursorType _expectedCursorStyle;
bool _setCursorColorResult = false;
@ -2100,15 +2013,17 @@ public:
// success cases
// set numeric mode = true
Log::Comment(L"Test 1: application mode = false");
_testGetSet->_privateSetCursorKeysModeResult = TRUE;
_testGetSet->_cursorKeysApplicationMode = false;
_testGetSet->_setInputModeResult = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::CursorKey;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->SetCursorKeysMode(false));
// set numeric mode = false
Log::Comment(L"Test 2: application mode = true");
_testGetSet->_privateSetCursorKeysModeResult = TRUE;
_testGetSet->_cursorKeysApplicationMode = true;
_testGetSet->_setInputModeResult = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::CursorKey;
_testGetSet->_expectedInputModeEnabled = true;
VERIFY_IS_TRUE(_pDispatch.get()->SetCursorKeysMode(true));
}
@ -2120,15 +2035,17 @@ public:
// success cases
// set numeric mode = true
Log::Comment(L"Test 1: application mode = false");
_testGetSet->_privateSetKeypadModeResult = TRUE;
_testGetSet->_keypadApplicationMode = false;
_testGetSet->_setInputModeResult = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::Keypad;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->SetKeypadMode(false));
// set numeric mode = false
Log::Comment(L"Test 2: application mode = true");
_testGetSet->_privateSetKeypadModeResult = TRUE;
_testGetSet->_keypadApplicationMode = true;
_testGetSet->_setInputModeResult = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::Keypad;
_testGetSet->_expectedInputModeEnabled = true;
VERIFY_IS_TRUE(_pDispatch.get()->SetKeypadMode(true));
}
@ -2316,45 +2233,51 @@ public:
Log::Comment(L"Starting test...");
Log::Comment(L"Test 1: Test Default Mouse Mode");
_testGetSet->_expectedMouseEnabled = true;
_testGetSet->_privateEnableVT200MouseModeResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::DefaultMouseTracking;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableVT200MouseMode(true));
_testGetSet->_expectedMouseEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableVT200MouseMode(false));
Log::Comment(L"Test 2: Test UTF-8 Extended Mouse Mode");
_testGetSet->_expectedMouseEnabled = true;
_testGetSet->_privateEnableUTF8ExtendedMouseModeResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::Utf8MouseEncoding;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableUTF8ExtendedMouseMode(true));
_testGetSet->_expectedMouseEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableUTF8ExtendedMouseMode(false));
Log::Comment(L"Test 3: Test SGR Extended Mouse Mode");
_testGetSet->_expectedMouseEnabled = true;
_testGetSet->_privateEnableSGRExtendedMouseModeResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::SgrMouseEncoding;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableSGRExtendedMouseMode(true));
_testGetSet->_expectedMouseEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableSGRExtendedMouseMode(false));
Log::Comment(L"Test 4: Test Button-Event Mouse Mode");
_testGetSet->_expectedMouseEnabled = true;
_testGetSet->_privateEnableButtonEventMouseModeResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::ButtonEventMouseTracking;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableButtonEventMouseMode(true));
_testGetSet->_expectedMouseEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableButtonEventMouseMode(false));
Log::Comment(L"Test 5: Test Any-Event Mouse Mode");
_testGetSet->_expectedMouseEnabled = true;
_testGetSet->_privateEnableAnyEventMouseModeResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::AnyEventMouseTracking;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableAnyEventMouseMode(true));
_testGetSet->_expectedMouseEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableAnyEventMouseMode(false));
Log::Comment(L"Test 6: Test Alt Scroll Mouse Mode");
_testGetSet->_expectedAlternateScrollEnabled = true;
_testGetSet->_privateEnableAlternateScrollResult = TRUE;
_testGetSet->_expectedInputModeEnabled = true;
_testGetSet->_expectedInputMode = TerminalInput::Mode::AlternateScroll;
_testGetSet->_setInputModeResult = true;
VERIFY_IS_TRUE(_pDispatch.get()->EnableAlternateScroll(true));
_testGetSet->_expectedAlternateScrollEnabled = false;
_testGetSet->_expectedInputModeEnabled = false;
VERIFY_IS_TRUE(_pDispatch.get()->EnableAlternateScroll(false));
}

View file

@ -285,13 +285,13 @@ static constexpr short _encodeDefaultCoordinate(const short sCoordinateValue) no
// - true, if we are tracking mouse input. False, otherwise
bool TerminalInput::IsTrackingMouseInput() const noexcept
{
return (_mouseInputState.trackingMode != TrackingMode::None);
return _inputMode.any(Mode::DefaultMouseTracking, Mode::ButtonEventMouseTracking, Mode::AnyEventMouseTracking);
}
// Routine Description:
// - Attempt to handle the given mouse coordinates and windows button as a VT-style mouse event.
// If the event should be transmitted in the selected mouse mode, then we'll try and
// encode the event according to the rules of the selected ExtendedMode, and insert those characters into the input buffer.
// encode the event according to the rules of the encoding mode, and insert those characters into the input buffer.
// Parameters:
// - position - The windows coordinates (top,left = 0,0) of the mouse event
// - button - the message to decode.
@ -339,7 +339,7 @@ bool TerminalInput::HandleMouse(const COORD position,
}
else
{
success = (_mouseInputState.trackingMode != TrackingMode::None);
success = IsTrackingMouseInput();
if (success)
{
// isHover is only true for WM_MOUSEMOVE events
@ -363,30 +363,23 @@ bool TerminalInput::HandleMouse(const COORD position,
// In AnyEvent, all coord change hovers are sent
const bool physicalButtonPressed = realButton != WM_LBUTTONUP;
success = (isButton && _mouseInputState.trackingMode != TrackingMode::None) ||
(isHover && _mouseInputState.trackingMode == TrackingMode::ButtonEvent && ((!sameCoord) && (physicalButtonPressed))) ||
(isHover && _mouseInputState.trackingMode == TrackingMode::AnyEvent && !sameCoord);
success = (isButton && IsTrackingMouseInput()) ||
(isHover && _inputMode.test(Mode::ButtonEventMouseTracking) && ((!sameCoord) && (physicalButtonPressed))) ||
(isHover && _inputMode.test(Mode::AnyEventMouseTracking) && !sameCoord);
if (success)
{
std::wstring sequence;
switch (_mouseInputState.extendedMode)
if (_inputMode.test(Mode::Utf8MouseEncoding))
{
case ExtendedMode::None:
sequence = _GenerateDefaultSequence(position,
realButton,
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Utf8:
sequence = _GenerateUtf8Sequence(position,
realButton,
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Sgr:
}
else if (_inputMode.test(Mode::SgrMouseEncoding))
{
// For SGR encoding, if no physical buttons were pressed,
// then we want to handle hovers with WM_MOUSEMOVE.
// However, if we're dragging (WM_MOUSEMOVE with a button pressed),
@ -397,13 +390,15 @@ bool TerminalInput::HandleMouse(const COORD position,
isHover,
modifierKeyState,
delta);
break;
case ExtendedMode::Urxvt:
default:
success = false;
break;
}
else
{
sequence = _GenerateDefaultSequence(position,
realButton,
isHover,
modifierKeyState,
delta);
}
success = !sequence.empty();
if (success)
@ -411,7 +406,7 @@ bool TerminalInput::HandleMouse(const COORD position,
_SendInputSequence(sequence);
success = true;
}
if (_mouseInputState.trackingMode == TrackingMode::ButtonEvent || _mouseInputState.trackingMode == TrackingMode::AnyEvent)
if (_inputMode.any(Mode::ButtonEventMouseTracking, Mode::AnyEventMouseTracking))
{
_mouseInputState.lastPos.X = position.X;
_mouseInputState.lastPos.Y = position.Y;
@ -547,10 +542,10 @@ std::wstring TerminalInput::_GenerateSGRSequence(const COORD position,
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the alternate buffer is active and alternate scroll mode is enabled and the event is a mouse wheel event.
bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept
bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const short delta) const
{
return _mouseInputState.inAlternateBuffer &&
_mouseInputState.alternateScroll &&
_inputMode.test(Mode::AlternateScroll) &&
(button == WM_MOUSEWHEEL || button == WM_MOUSEHWHEEL) && delta != 0;
}
@ -560,15 +555,15 @@ bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the input sequence was sent successfully.
bool TerminalInput::_SendAlternateScroll(const short delta) const noexcept
bool TerminalInput::_SendAlternateScroll(const short delta) const
{
if (delta > 0)
{
_SendInputSequence(_cursorApplicationMode ? ApplicationUpSequence : CursorUpSequence);
_SendInputSequence(_inputMode.test(Mode::CursorKey) ? ApplicationUpSequence : CursorUpSequence);
}
else
{
_SendInputSequence(_cursorApplicationMode ? ApplicationDownSequence : CursorDownSequence);
_SendInputSequence(_inputMode.test(Mode::CursorKey) ? ApplicationDownSequence : CursorDownSequence);
}
return true;
}

View file

@ -7,91 +7,6 @@
using namespace Microsoft::Console::VirtualTerminal;
// Routine Description:
// - Either enables or disables UTF-8 extended mode encoding. This *should* cause
// the coordinates of a mouse event to be encoded as a UTF-8 byte stream, however, because windows' input is
// typically UTF-16 encoded, it emits a UTF-16 stream.
// Does NOT enable or disable mouse mode by itself. This matches the behavior I found in Ubuntu terminals.
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::SetUtf8ExtendedMode(const bool enable) noexcept
{
_mouseInputState.extendedMode = enable ? ExtendedMode::Utf8 : ExtendedMode::None;
}
// Routine Description:
// - Either enables or disables SGR extended mode encoding. This causes the
// coordinates of a mouse event to be emitted in a human readable format,
// eg, x,y=203,504 -> "^[[<B;203;504M". This way, applications don't need to worry about character encoding.
// Does NOT enable or disable mouse mode by itself. This matches the behavior I found in Ubuntu terminals.
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::SetSGRExtendedMode(const bool enable) noexcept
{
_mouseInputState.extendedMode = enable ? ExtendedMode::Sgr : ExtendedMode::None;
}
// Routine Description:
// - Either enables or disables mouse mode handling. Leaves the extended mode alone,
// so if we disable then re-enable mouse mode without toggling an extended mode, the mode will persist.
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::EnableDefaultTracking(const bool enable) noexcept
{
_mouseInputState.trackingMode = enable ? TrackingMode::Default : TrackingMode::None;
_mouseInputState.lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_mouseInputState.lastButton = 0;
}
// Routine Description:
// - Either enables or disables ButtonEvent mouse handling. Button Event mode
// sends additional sequences when a button is pressed and the mouse changes character cells.
// Leaves the extended mode alone, so if we disable then re-enable mouse mode
// without toggling an extended mode, the mode will persist.
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::EnableButtonEventTracking(const bool enable) noexcept
{
_mouseInputState.trackingMode = enable ? TrackingMode::ButtonEvent : TrackingMode::None;
_mouseInputState.lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_mouseInputState.lastButton = 0;
}
// Routine Description:
// - Either enables or disables AnyEvent mouse handling. Any Event mode sends sequences
// for any and every mouse event, regardless if a button is pressed or not.
// Leaves the extended mode alone, so if we disable then re-enable mouse mode
// without toggling an extended mode, the mode will persist.
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::EnableAnyEventTracking(const bool enable) noexcept
{
_mouseInputState.trackingMode = enable ? TrackingMode::AnyEvent : TrackingMode::None;
_mouseInputState.lastPos = { -1, -1 }; // Clear out the last saved mouse position & button.
_mouseInputState.lastButton = 0;
}
// Routine Description:
// - Enables alternate scroll mode. This sends Cursor Up/down sequences when in the alternate buffer
// Parameters:
// - enable - either enable or disable.
// Return value:
// <none>
void TerminalInput::EnableAlternateScroll(const bool enable) noexcept
{
_mouseInputState.alternateScroll = enable;
}
// Routine Description:
// - Notify the MouseInput handler that the screen buffer has been swapped to the alternate buffer
// Parameters:

View file

@ -250,25 +250,32 @@ const wchar_t* const CTRL_QUESTIONMARK_SEQUENCE = L"\x7F";
const wchar_t* const CTRL_ALT_SLASH_SEQUENCE = L"\x1b\x1f";
const wchar_t* const CTRL_ALT_QUESTIONMARK_SEQUENCE = L"\x1b\x7F";
void TerminalInput::ChangeAnsiMode(const bool ansiMode) noexcept
void TerminalInput::SetInputMode(const Mode mode, const bool enabled)
{
_ansiMode = ansiMode;
// If we're changing a tracking mode, we always clear other tracking modes first.
// We also clear out the last saved mouse position & button.
if (mode == Mode::DefaultMouseTracking || mode == Mode::ButtonEventMouseTracking || mode == Mode::AnyEventMouseTracking)
{
_inputMode.reset_all(Mode::DefaultMouseTracking, Mode::ButtonEventMouseTracking, Mode::AnyEventMouseTracking);
_mouseInputState.lastPos = { -1, -1 };
_mouseInputState.lastButton = 0;
}
// But if we're changing the encoding, we only clear out the other encoding modes
// when enabling a new encoding - not when disabling.
if ((mode == Mode::Utf8MouseEncoding || mode == Mode::SgrMouseEncoding) && enabled)
{
_inputMode.reset_all(Mode::Utf8MouseEncoding, Mode::SgrMouseEncoding);
}
_inputMode.set(mode, enabled);
}
void TerminalInput::ChangeKeypadMode(const bool applicationMode) noexcept
bool TerminalInput::GetInputMode(const Mode mode) const
{
_keypadApplicationMode = applicationMode;
return _inputMode.test(mode);
}
void TerminalInput::ChangeCursorKeysMode(const bool applicationMode) noexcept
{
_cursorApplicationMode = applicationMode;
}
void TerminalInput::ChangeWin32InputMode(const bool win32InputMode) noexcept
{
_win32InputMode = win32InputMode;
}
void TerminalInput::ForceDisableWin32InputMode(const bool win32InputMode) noexcept
{
_forceDisableWin32InputMode = win32InputMode;
@ -530,7 +537,7 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent)
// GH#4999 - If we're in win32-input mode, skip straight to doing that.
// Since this mode handles all types of key events, do nothing else.
// Only do this if win32-input-mode support isn't manually disabled.
if (_win32InputMode && !_forceDisableWin32InputMode)
if (_inputMode.test(Mode::Win32) && !_forceDisableWin32InputMode)
{
const auto seq = _GenerateWin32KeySequence(keyEvent);
_SendInputSequence(seq);
@ -655,7 +662,7 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent)
// Check any other key mappings (like those for the F1-F12 keys).
// These mappings will kick in no matter which modifiers are pressed and as such
// must be checked last, or otherwise we'd override more complex key combinations.
const auto mapping = _getKeyMapping(keyEvent, _ansiMode, _cursorApplicationMode, _keypadApplicationMode);
const auto mapping = _getKeyMapping(keyEvent, _inputMode.test(Mode::Ansi), _inputMode.test(Mode::CursorKey), _inputMode.test(Mode::Keypad));
if (_translateDefaultMapping(keyEvent, mapping, senderFunc))
{
return true;

View file

@ -34,11 +34,26 @@ namespace Microsoft::Console::VirtualTerminal
~TerminalInput() = default;
bool HandleKey(const IInputEvent* const pInEvent);
void ChangeAnsiMode(const bool ansiMode) noexcept;
void ChangeKeypadMode(const bool applicationMode) noexcept;
void ChangeCursorKeysMode(const bool applicationMode) noexcept;
void ChangeWin32InputMode(const bool win32InputMode) noexcept;
enum class Mode : size_t
{
Ansi,
Keypad,
CursorKey,
Win32,
Utf8MouseEncoding,
SgrMouseEncoding,
DefaultMouseTracking,
ButtonEventMouseTracking,
AnyEventMouseTracking,
AlternateScroll
};
void SetInputMode(const Mode mode, const bool enabled);
bool GetInputMode(const Mode mode) const;
void ForceDisableWin32InputMode(const bool win32InputMode) noexcept;
#pragma region MouseInput
@ -62,14 +77,6 @@ namespace Microsoft::Console::VirtualTerminal
#pragma region MouseInputState Management
// These methods are defined in mouseInputState.cpp
void SetUtf8ExtendedMode(const bool enable) noexcept;
void SetSGRExtendedMode(const bool enable) noexcept;
void EnableDefaultTracking(const bool enable) noexcept;
void EnableButtonEventTracking(const bool enable) noexcept;
void EnableAnyEventTracking(const bool enable) noexcept;
void EnableAlternateScroll(const bool enable) noexcept;
void UseAlternateScreenBuffer() noexcept;
void UseMainScreenBuffer() noexcept;
#pragma endregion
@ -80,10 +87,7 @@ namespace Microsoft::Console::VirtualTerminal
// storage location for the leading surrogate of a utf-16 surrogate pair
std::optional<wchar_t> _leadingSurrogate;
bool _ansiMode{ true };
bool _keypadApplicationMode{ false };
bool _cursorApplicationMode{ false };
bool _win32InputMode{ false };
til::enumset<Mode> _inputMode{ Mode::Ansi };
bool _forceDisableWin32InputMode{ false };
void _SendChar(const wchar_t ch);
@ -94,27 +98,8 @@ namespace Microsoft::Console::VirtualTerminal
#pragma region MouseInputState Management
// These methods are defined in mouseInputState.cpp
enum class ExtendedMode : unsigned int
{
None,
Utf8,
Sgr,
Urxvt
};
enum class TrackingMode : unsigned int
{
None,
Default,
ButtonEvent,
AnyEvent
};
struct MouseInputState
{
ExtendedMode extendedMode{ ExtendedMode::None };
TrackingMode trackingMode{ TrackingMode::None };
bool alternateScroll{ false };
bool inAlternateBuffer{ false };
COORD lastPos{ -1, -1 };
unsigned int lastButton{ 0 };
@ -142,8 +127,8 @@ namespace Microsoft::Console::VirtualTerminal
const short modifierKeyState,
const short delta);
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept;
bool _SendAlternateScroll(const short delta) const noexcept;
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const;
bool _SendAlternateScroll(const short delta) const;
static constexpr unsigned int s_GetPressedButton(const MouseButtonState state) noexcept;
#pragma endregion