806d992a06
Supports #2941 Previous PRs: #3362 #3416
214 lines
7.2 KiB
C++
214 lines
7.2 KiB
C++
/*++
|
|
Copyright (c) Microsoft Corporation
|
|
Licensed under the MIT license.
|
|
|
|
Module Name:
|
|
- InputStateMachineEngine.hpp
|
|
|
|
Abstract:
|
|
- This is the implementation of the client VT input state machine engine.
|
|
This generates InputEvents from a stream of VT sequences emitted by a
|
|
client "terminal" application.
|
|
|
|
Author(s):
|
|
- Mike Griese (migrie) 18 Aug 2017
|
|
--*/
|
|
#pragma once
|
|
|
|
#include "telemetry.hpp"
|
|
#include "IStateMachineEngine.hpp"
|
|
#include <functional>
|
|
#include "../../types/inc/IInputEvent.hpp"
|
|
#include "../adapter/IInteractDispatch.hpp"
|
|
|
|
namespace Microsoft::Console::VirtualTerminal
|
|
{
|
|
// The values used by VkKeyScan to encode modifiers in the high order byte
|
|
constexpr short KEYSCAN_SHIFT = 1;
|
|
constexpr short KEYSCAN_CTRL = 2;
|
|
constexpr short KEYSCAN_ALT = 4;
|
|
|
|
// The values with which VT encodes modifier values.
|
|
constexpr short VT_SHIFT = 1;
|
|
constexpr short VT_ALT = 2;
|
|
constexpr short VT_CTRL = 4;
|
|
|
|
// The assumed values for SGR Mouse Scroll Wheel deltas
|
|
constexpr DWORD SCROLL_DELTA_BACKWARD = 0xFF800000;
|
|
constexpr DWORD SCROLL_DELTA_FORWARD = 0x00800000;
|
|
|
|
constexpr size_t WRAPPED_SEQUENCE_MAX_LENGTH = 8;
|
|
|
|
// For reference, the equivalent INPUT_RECORD values are:
|
|
// RIGHT_ALT_PRESSED 0x0001
|
|
// LEFT_ALT_PRESSED 0x0002
|
|
// RIGHT_CTRL_PRESSED 0x0004
|
|
// LEFT_CTRL_PRESSED 0x0008
|
|
// SHIFT_PRESSED 0x0010
|
|
// NUMLOCK_ON 0x0020
|
|
// SCROLLLOCK_ON 0x0040
|
|
// CAPSLOCK_ON 0x0080
|
|
// ENHANCED_KEY 0x0100
|
|
|
|
enum CsiActionCodes : uint64_t
|
|
{
|
|
ArrowUp = VTID("A"),
|
|
ArrowDown = VTID("B"),
|
|
ArrowRight = VTID("C"),
|
|
ArrowLeft = VTID("D"),
|
|
Home = VTID("H"),
|
|
End = VTID("F"),
|
|
MouseDown = VTID("<M"),
|
|
MouseUp = VTID("<m"),
|
|
Generic = VTID("~"), // Used for a whole bunch of possible keys
|
|
CSI_F1 = VTID("P"),
|
|
CSI_F2 = VTID("Q"),
|
|
CSI_F3 = VTID("R"), // Both F3 and DSR are on R.
|
|
// DSR_DeviceStatusReportResponse = VTID("R"),
|
|
CSI_F4 = VTID("S"),
|
|
DTTERM_WindowManipulation = VTID("t"),
|
|
CursorBackTab = VTID("Z"),
|
|
Win32KeyboardInput = VTID("_")
|
|
};
|
|
|
|
enum CsiMouseButtonCodes : unsigned short
|
|
{
|
|
Left = 0,
|
|
Middle = 1,
|
|
Right = 2,
|
|
Released = 3,
|
|
ScrollForward = 4,
|
|
ScrollBack = 5,
|
|
};
|
|
|
|
constexpr unsigned short CsiMouseModifierCode_Drag = 32;
|
|
|
|
enum CsiMouseModifierCodes : unsigned short
|
|
{
|
|
Shift = 4,
|
|
Meta = 8,
|
|
Ctrl = 16,
|
|
Drag = 32,
|
|
};
|
|
|
|
// Sequences ending in '~' use these numbers as identifiers.
|
|
enum class GenericKeyIdentifiers : size_t
|
|
{
|
|
GenericHome = 1,
|
|
Insert = 2,
|
|
Delete = 3,
|
|
GenericEnd = 4,
|
|
Prior = 5, //PgUp
|
|
Next = 6, //PgDn
|
|
F5 = 15,
|
|
F6 = 17,
|
|
F7 = 18,
|
|
F8 = 19,
|
|
F9 = 20,
|
|
F10 = 21,
|
|
F11 = 23,
|
|
F12 = 24,
|
|
};
|
|
|
|
enum class Ss3ActionCodes : wchar_t
|
|
{
|
|
ArrowUp = L'A',
|
|
ArrowDown = L'B',
|
|
ArrowRight = L'C',
|
|
ArrowLeft = L'D',
|
|
Home = L'H',
|
|
End = L'F',
|
|
SS3_F1 = L'P',
|
|
SS3_F2 = L'Q',
|
|
SS3_F3 = L'R',
|
|
SS3_F4 = L'S',
|
|
};
|
|
|
|
class InputStateMachineEngine : public IStateMachineEngine
|
|
{
|
|
public:
|
|
InputStateMachineEngine(std::unique_ptr<IInteractDispatch> pDispatch);
|
|
InputStateMachineEngine(std::unique_ptr<IInteractDispatch> pDispatch,
|
|
const bool lookingForDSR);
|
|
|
|
bool ActionExecute(const wchar_t wch) override;
|
|
bool ActionExecuteFromEscape(const wchar_t wch) override;
|
|
|
|
bool ActionPrint(const wchar_t wch) override;
|
|
|
|
bool ActionPrintString(const std::wstring_view string) override;
|
|
|
|
bool ActionPassThroughString(const std::wstring_view string) override;
|
|
|
|
bool ActionEscDispatch(const VTID id) override;
|
|
|
|
bool ActionVt52EscDispatch(const VTID id, const VTParameters parameters) noexcept override;
|
|
|
|
bool ActionCsiDispatch(const VTID id, const VTParameters parameters) override;
|
|
|
|
bool ActionClear() noexcept override;
|
|
|
|
bool ActionIgnore() noexcept override;
|
|
|
|
bool ActionOscDispatch(const wchar_t wch,
|
|
const size_t parameter,
|
|
const std::wstring_view string) noexcept override;
|
|
|
|
bool ActionSs3Dispatch(const wchar_t wch, const VTParameters parameters) override;
|
|
|
|
bool ParseControlSequenceAfterSs3() const noexcept override;
|
|
bool FlushAtEndOfString() const noexcept override;
|
|
bool DispatchControlCharsFromEscape() const noexcept override;
|
|
bool DispatchIntermediatesFromEscape() const noexcept override;
|
|
|
|
void SetFlushToInputQueueCallback(std::function<bool()> pfnFlushToInputQueue);
|
|
|
|
private:
|
|
const std::unique_ptr<IInteractDispatch> _pDispatch;
|
|
std::function<bool()> _pfnFlushToInputQueue;
|
|
bool _lookingForDSR;
|
|
DWORD _mouseButtonState = 0;
|
|
|
|
DWORD _GetCursorKeysModifierState(const VTParameters parameters, const VTID id) noexcept;
|
|
DWORD _GetGenericKeysModifierState(const VTParameters parameters) noexcept;
|
|
DWORD _GetSGRMouseModifierState(const size_t modifierParam) noexcept;
|
|
bool _GenerateKeyFromChar(const wchar_t wch, short& vkey, DWORD& modifierState) noexcept;
|
|
|
|
DWORD _GetModifier(const size_t parameter) noexcept;
|
|
|
|
bool _UpdateSGRMouseButtonState(const VTID id,
|
|
const size_t sgrEncoding,
|
|
DWORD& buttonState,
|
|
DWORD& eventFlags) noexcept;
|
|
bool _GetGenericVkey(const GenericKeyIdentifiers identifier, short& vkey) const;
|
|
bool _GetCursorKeysVkey(const VTID id, short& vkey) const;
|
|
bool _GetSs3KeysVkey(const wchar_t wch, short& vkey) const;
|
|
|
|
bool _WriteSingleKey(const short vkey, const DWORD modifierState);
|
|
bool _WriteSingleKey(const wchar_t wch, const short vkey, const DWORD modifierState);
|
|
|
|
bool _WriteMouseEvent(const size_t column, const size_t line, const DWORD buttonState, const DWORD controlKeyState, const DWORD eventFlags);
|
|
|
|
void _GenerateWrappedSequence(const wchar_t wch,
|
|
const short vkey,
|
|
const DWORD modifierState,
|
|
std::vector<INPUT_RECORD>& input);
|
|
|
|
void _GetSingleKeypress(const wchar_t wch,
|
|
const short vkey,
|
|
const DWORD modifierState,
|
|
std::vector<INPUT_RECORD>& input);
|
|
|
|
bool _GetWindowManipulationType(const gsl::span<const size_t> parameters,
|
|
unsigned int& function) const noexcept;
|
|
|
|
KeyEvent _GenerateWin32Key(const VTParameters parameters);
|
|
|
|
bool _DoControlCharacter(const wchar_t wch, const bool writeAlt);
|
|
|
|
#ifdef UNIT_TESTING
|
|
friend class InputEngineTest;
|
|
#endif
|
|
};
|
|
}
|