terminal/src/terminal/input/terminalInput.hpp
Leonard Hecker f2386de422
Improve performance and binary size of til::enumset (#11493)
This commit approximately doubles the performance of til::enumset
and reduces it's binary footprint by approximately 1kB.
Most of the binary size can be attributed to exception handling.

Unfortunately this commit removes assertions that the given values are less than
the number of bits in the `underlying_type`. However I believe this to be a good
trade-off as the tests previously only happened at runtime, while tests at
compile time would be highly preferable. Such tests are technically possible,
however MSVC fails to compile (valid) `static_assert`s containing
`static_cast`s over a parameter pack at the time of writing.
With future MSVC versions such checks can be added to this class.

This change was initially discussed in #10492, but was forgotten to
be considered before it was merged. Since the work was already done,
this commit re-introduces the optimization. It's free!

## PR Checklist
* [x] I work here.
* [x] Tests added/passed

## Validation Steps Performed
* Run `printf '\e]8;;http://example.com\e\\This is a link\e]8;;\e\\\n'` in WSL
* A wild dotted line appears ✔️
2021-11-23 18:44:58 +00:00

137 lines
4.9 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- terminalInput.hpp
Abstract:
- This serves as an adapter between virtual key input from a user and the virtual terminal sequences that are
typically emitted by an xterm-compatible console.
Author(s):
- Michael Niksa (MiNiksa) 30-Oct-2015
--*/
#include <functional>
#include "../../types/inc/IInputEvent.hpp"
#pragma once
namespace Microsoft::Console::VirtualTerminal
{
class TerminalInput final
{
public:
TerminalInput(_In_ std::function<void(std::deque<std::unique_ptr<IInputEvent>>&)> pfn);
TerminalInput() = delete;
TerminalInput(const TerminalInput& old) = default;
TerminalInput(TerminalInput&& moved) = default;
TerminalInput& operator=(const TerminalInput& old) = default;
TerminalInput& operator=(TerminalInput&& moved) = default;
~TerminalInput() = default;
bool HandleKey(const IInputEvent* const pInEvent);
enum class Mode : size_t
{
Ansi,
Keypad,
CursorKey,
Win32,
Utf8MouseEncoding,
SgrMouseEncoding,
DefaultMouseTracking,
ButtonEventMouseTracking,
AnyEventMouseTracking,
AlternateScroll
};
void SetInputMode(const Mode mode, const bool enabled) noexcept;
bool GetInputMode(const Mode mode) const noexcept;
void ForceDisableWin32InputMode(const bool win32InputMode) noexcept;
#pragma region MouseInput
// These methods are defined in mouseInput.cpp
struct MouseButtonState
{
bool isLeftButtonDown;
bool isMiddleButtonDown;
bool isRightButtonDown;
};
bool HandleMouse(const COORD position,
const unsigned int button,
const short modifierKeyState,
const short delta,
const MouseButtonState state);
bool IsTrackingMouseInput() const noexcept;
#pragma endregion
#pragma region MouseInputState Management
// These methods are defined in mouseInputState.cpp
void UseAlternateScreenBuffer() noexcept;
void UseMainScreenBuffer() noexcept;
#pragma endregion
private:
std::function<void(std::deque<std::unique_ptr<IInputEvent>>&)> _pfnWriteEvents;
// storage location for the leading surrogate of a utf-16 surrogate pair
std::optional<wchar_t> _leadingSurrogate;
til::enumset<Mode> _inputMode{ Mode::Ansi };
bool _forceDisableWin32InputMode{ false };
void _SendChar(const wchar_t ch);
void _SendNullInputSequence(const DWORD dwControlKeyState) const;
void _SendInputSequence(const std::wstring_view sequence) const noexcept;
void _SendEscapedInputSequence(const wchar_t wch) const;
static std::wstring _GenerateWin32KeySequence(const KeyEvent& key);
#pragma region MouseInputState Management
// These methods are defined in mouseInputState.cpp
struct MouseInputState
{
bool inAlternateBuffer{ false };
COORD lastPos{ -1, -1 };
unsigned int lastButton{ 0 };
int accumulatedDelta{ 0 };
};
MouseInputState _mouseInputState;
#pragma endregion
#pragma region MouseInput
static std::wstring _GenerateDefaultSequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta);
static std::wstring _GenerateUtf8Sequence(const COORD position,
const unsigned int button,
const bool isHover,
const short modifierKeyState,
const short delta);
static std::wstring _GenerateSGRSequence(const COORD position,
const unsigned int button,
const bool isDown,
const bool isHover,
const short modifierKeyState,
const short delta);
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept;
bool _SendAlternateScroll(const short delta) const noexcept;
static constexpr unsigned int s_GetPressedButton(const MouseButtonState state) noexcept;
#pragma endregion
};
}