Compare commits

...

11 commits

Author SHA1 Message Date
Carlos Zamora 23ae33cb8f SelectionMode --> TripleClickSelectionMode
Terminal: save winrt version of enum
Added doc comments
2019-06-28 10:15:19 -07:00
Carlos Zamora 9db18ab1e0 Triple Click Settings 2019-06-28 09:52:27 -07:00
Carlos Zamora d2e1be1bf0 Viewport selection is now an option
TODO: connect to setting
2019-06-28 09:52:27 -07:00
Carlos Zamora 6cef7ce9c7 Merge branch 'master' into dev/cazamor/multi-click-selection 2019-06-28 08:59:48 -07:00
Carlos Zamora a12f7275df PR changes 2019-06-13 15:53:24 -07:00
Carlos Zamora c244e5da26 PR changes + format 2019-06-12 13:50:52 -07:00
Carlos Zamora f210bef378 code formatting 2019-06-12 13:21:07 -07:00
Carlos Zamora df0f1a27be Merge remote-tracking branch 'origin/master' into dev/cazamor/multi-click-selection 2019-06-12 13:19:19 -07:00
Carlos Zamora b70157b75b merge to before clang format 2019-06-12 13:18:47 -07:00
Carlos Zamora 27dab77701 PR Changes
Bugfix (double click after scrolling would go out of bounds)
2019-06-11 13:31:20 -07:00
Carlos Zamora aea8dc8c53 Double and Triple Click Selection 2019-06-10 15:11:42 -07:00
10 changed files with 342 additions and 9 deletions

View file

@ -40,6 +40,7 @@ static constexpr std::string_view IconKey{ "icon" };
static constexpr std::string_view BackgroundImageKey{ "backgroundImage" };
static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" };
static constexpr std::string_view BackgroundimageStretchModeKey{ "backgroundImageStretchMode" };
static constexpr std::string_view TripleClickSelectionModeKey{ "tripleClickSelectionMode" };
// Possible values for Scrollbar state
static constexpr std::wstring_view AlwaysVisible{ L"visible" };
@ -58,6 +59,11 @@ static constexpr std::string_view ImageStretchModeFill{ "fill" };
static constexpr std::string_view ImageStretchModeUniform{ "uniform" };
static constexpr std::string_view ImageStretchModeUniformTofill{ "uniformToFill" };
// Possible values for Triple Click Selection Mode
static constexpr std::wstring_view TripleClickSelectionModeDisabled{ L"disabled" };
static constexpr std::wstring_view TripleClickSelectionModeLine{ L"line" };
static constexpr std::wstring_view TripleClickSelectionModeViewport{ L"viewport" };
Profile::Profile() :
Profile(Utils::CreateGuid())
{
@ -76,6 +82,7 @@ Profile::Profile(const winrt::guid& guid) :
_cursorColor{ DEFAULT_CURSOR_COLOR },
_cursorShape{ CursorStyle::Bar },
_cursorHeight{ DEFAULT_CURSOR_HEIGHT },
_tripleClickSelectionMode{ TripleClickSelectionMode::Line },
_commandline{ L"cmd.exe" },
_startingDirectory{},
@ -144,6 +151,7 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>&
terminalSettings.CursorColor(_cursorColor);
terminalSettings.CursorHeight(_cursorHeight);
terminalSettings.CursorShape(_cursorShape);
terminalSettings.TripleClickSelectionMode(_tripleClickSelectionMode);
// Fill in the remaining properties from the profile
terminalSettings.UseAcrylic(_useAcrylic);
@ -249,6 +257,7 @@ Json::Value Profile::ToJson() const
root[JsonKey(CursorHeightKey)] = _cursorHeight;
}
root[JsonKey(CursorShapeKey)] = winrt::to_string(_SerializeCursorStyle(_cursorShape));
root[JsonKey(TripleClickSelectionModeKey)] = winrt::to_string(_SerializeTripleClickSelectionMode(_tripleClickSelectionMode));
///// Control Settings /////
root[JsonKey(CommandlineKey)] = winrt::to_string(_commandline);
@ -369,6 +378,10 @@ Profile Profile::FromJson(const Json::Value& json)
{
result._cursorShape = _ParseCursorShape(GetWstringFromJson(cursorShape));
}
if (auto tripleClickSelectionMode{ json[JsonKey(TripleClickSelectionModeKey)] })
{
result._tripleClickSelectionMode = _ParseTripleClickSelectionMode(GetWstringFromJson(tripleClickSelectionMode));
}
// Control Settings
if (auto commandline{ json[JsonKey(CommandlineKey)] })
@ -673,3 +686,44 @@ std::wstring_view Profile::_SerializeCursorStyle(const CursorStyle cursorShape)
return CursorShapeBar;
}
}
// Method Description:
// - Helper function for converting a user-specified triple click selection mode to the corresponding
// TripleClickSelectionMode enum value
// Arguments:
// - selectionModeString: The string value from the settings file to parse
// Return Value:
// - The corresponding enum value which maps to the string provided by the user
winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode Profile::_ParseTripleClickSelectionMode(const std::wstring& selectionModeString)
{
if (selectionModeString == TripleClickSelectionModeDisabled)
{
return winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::Disabled;
}
else if (selectionModeString == TripleClickSelectionModeViewport)
{
return winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::VisibleViewport;
}
return winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::Line;
}
// Method Description:
// - Helper function for converting a TripleClickSelectionMode to its corresponding string
// value.
// Arguments:
// - selectionMode: The enum value to convert to a string.
// Return Value:
// - The string value for the given TripleClickSelectionMode
std::wstring_view Profile::_SerializeTripleClickSelectionMode(const winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode selectionMode)
{
switch (selectionMode)
{
case winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::Disabled:
return TripleClickSelectionModeDisabled;
case winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::VisibleViewport:
return TripleClickSelectionModeViewport;
case winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode::Line:
default:
return TripleClickSelectionModeLine;
}
}

View file

@ -61,6 +61,8 @@ private:
static std::string_view SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode);
static winrt::Microsoft::Terminal::Settings::CursorStyle _ParseCursorShape(const std::wstring& cursorShapeString);
static std::wstring_view _SerializeCursorStyle(const winrt::Microsoft::Terminal::Settings::CursorStyle cursorShape);
static winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode _ParseTripleClickSelectionMode(const std::wstring& selectionModeString);
static std::wstring_view _SerializeTripleClickSelectionMode(const winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode selectionMode);
GUID _guid;
std::wstring _name;
@ -76,6 +78,7 @@ private:
uint32_t _cursorColor;
uint32_t _cursorHeight;
winrt::Microsoft::Terminal::Settings::CursorStyle _cursorShape;
winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode _tripleClickSelectionMode;
std::wstring _commandline;
std::wstring _fontFace;

View file

@ -39,7 +39,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_actualFont{ DEFAULT_FONT_FACE.c_str(), 0, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false },
_touchAnchor{ std::nullopt },
_leadingSurrogate{},
_cursorTimer{}
_cursorTimer{},
_lastMouseClick{},
_lastMouseClickPos{},
_doubleClickOccurred{ false }
{
_Create();
}
@ -703,13 +706,31 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
// save location before rendering
_terminal->SetSelectionAnchor(terminalPosition);
// handle ALT key
_terminal->SetBoxSelection(altEnabled);
_renderer->TriggerSelection();
if (_IsTripleClick(cursorPosition, point.Timestamp()))
{
_terminal->TripleClickSelection(terminalPosition);
_renderer->TriggerSelection();
_doubleClickOccurred = true;
}
else if (_IsDoubleClick(cursorPosition, point.Timestamp()))
{
_terminal->DoubleClickSelection(terminalPosition);
_renderer->TriggerSelection();
_doubleClickOccurred = true;
}
else
{
// save location before rendering
_terminal->SetSelectionAnchor(terminalPosition);
_renderer->TriggerSelection();
_lastMouseClick = point.Timestamp();
_lastMouseClickPos = cursorPosition;
_doubleClickOccurred = false;
}
}
else if (point.Properties().IsRightButtonPressed())
{
@ -1501,13 +1522,56 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return terminalPosition;
}
// clang-format off
// Method Description:
// - Checks if a double click occurred
// Arguments:
// - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor).
// NOTE: origin (0,0) is top-left.
// - clickTime: the timestamp that the click occurred
// Return Value:
// - true if the new click was at the same location within the time delta
const bool TermControl::_IsDoubleClick(winrt::Windows::Foundation::Point clickPos, TimeStamp clickTime) const
{
if (clickPos == _lastMouseClickPos)
{
TimeStamp delta;
UInt64Sub(clickTime, _lastMouseClick, &delta);
if (delta < multiClickTimer)
{
return true;
}
}
return false;
}
// Method Description:
// - Checks if a triple click occurred
// Arguments:
// - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor).
// NOTE: origin (0,0) is top-left.
// - clickTime: the timestamp that the click occurred
// Return Value:
// - true if the new click was at the same location within the time delta after a double click having occurred
const bool TermControl::_IsTripleClick(winrt::Windows::Foundation::Point clickPos, TimeStamp clickTime) const
{
if (_doubleClickOccurred && clickPos == _lastMouseClickPos)
{
TimeStamp delta;
UInt64Sub(clickTime, _lastMouseClick, &delta);
if (delta < multiClickTimer)
{
return true;
}
}
return false;
}
// -------------------------------- WinRT Events ---------------------------------
// Winrt events need a method for adding a callback to the event and removing the callback.
// These macros will define them both for you.
DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs);
DEFINE_EVENT(TermControl, ConnectionClosed, _connectionClosedHandlers, TerminalControl::ConnectionClosedEventArgs);
DEFINE_EVENT(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::CopyToClipboardEventArgs);
DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs);
DEFINE_EVENT(TermControl, ConnectionClosed, _connectionClosedHandlers, TerminalControl::ConnectionClosedEventArgs);
DEFINE_EVENT(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::CopyToClipboardEventArgs);
DEFINE_EVENT(TermControl, ScrollPositionChanged, _scrollPositionChangedHandlers, TerminalControl::ScrollPositionChangedEventArgs);
// clang-format on

View file

@ -32,6 +32,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
struct TermControl : TermControlT<TermControl>
{
using TimeStamp = uint64_t;
// represents 0.5 seconds (or 5000 ms)
const TimeStamp multiClickTimer = 500000;
TermControl();
TermControl(Settings::IControlSettings settings);
@ -98,6 +103,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// viewport via touch input.
std::optional<winrt::Windows::Foundation::Point> _touchAnchor;
TimeStamp _lastMouseClick;
bool _doubleClickOccurred;
std::optional<winrt::Windows::Foundation::Point> _lastMouseClickPos;
// Event revokers -- we need to deregister ourselves before we die,
// lest we get callbacks afterwards.
winrt::Windows::UI::Xaml::Controls::Control::SizeChanged_revoker _sizeChangedRevoker;
@ -144,6 +153,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
DWORD _GetPressedModifierKeys() const;
const COORD _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition);
const bool _IsDoubleClick(winrt::Windows::Foundation::Point clickPos, TimeStamp clickTime) const;
const bool _IsTripleClick(winrt::Windows::Foundation::Point clickPos, TimeStamp clickTime) const;
};
}

View file

@ -133,6 +133,8 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting
_snapOnInput = settings.SnapOnInput();
_tripleClickMode = settings.TripleClickSelectionMode();
// TODO:MSFT:21327402 - if HistorySize has changed, resize the buffer so we
// have a smaller scrollback. We should do this carefully - if the new buffer
// size is smaller than where the mutable viewport currently is, we'll want
@ -491,3 +493,168 @@ bool Terminal::IsCursorBlinkingAllowed() const noexcept
const auto& cursor = _buffer->GetCursor();
return cursor.IsBlinkingAllowed();
}
// Method Description:
// - Select the sequence between delimiters defined in Settings
// Arguments:
// - position: the (x,y) coordinate on the visible viewport
void Terminal::DoubleClickSelection(const COORD position)
{
// if you double click a delimiter, just select that one cell
COORD positionWithOffsets = _ConvertToBufferCell(position);
auto cellChar = _buffer->GetCellDataAt(positionWithOffsets)->Chars();
if (_DoubleClickDelimiterCheck(cellChar))
{
SetSelectionAnchor(position);
return;
}
// scan leftwards until delimiter is found and
// set selection anchor to one right of that spot
_ExpandDoubleClickSelectionLeft(position);
// scan rightwards until delimiter is found and
// set endSelectionPosition to one left of that spot
_ExpandDoubleClickSelectionRight(position);
}
// Method Description:
// - Performs a triple click selection based on the setting
// Arguments:
// - position: the (x,y) coordinate on the visible viewport
void Terminal::TripleClickSelection(const COORD position)
{
switch (_tripleClickMode)
{
case TripleClickSelectionMode::VisibleViewport:
_SelectViewport();
break;
case TripleClickSelectionMode::Line:
_SelectRow(position);
break;
case TripleClickSelectionMode::Disabled:
default:
SetSelectionAnchor(position);
break;
}
}
// Method Description:
// - Create a selection of the entire row of the position clicked
// Arguments:
// - position: the (x,y) coordinate on the visible viewport
void Terminal::_SelectRow(const COORD position)
{
SetSelectionAnchor({ 0, position.Y });
SetEndSelectionPosition({ _buffer->GetSize().RightInclusive(), position.Y });
}
// Method Description:
// - Create a selection of the entire visible viewport present
void Terminal::_SelectViewport()
{
SetSelectionAnchor({ 0, 0 });
SetEndSelectionPosition(_mutableViewport.Dimensions());
}
// Method Description:
// - expand the double click selection to the left (stopped by delimiter)
// Arguments:
// - position: viewport coordinate for selection
// Return Value:
// - update _selectionAnchor to new expanded location
void Terminal::_ExpandDoubleClickSelectionLeft(const COORD position)
{
// don't change the value if at/outside the boundary
if (position.X <= 0 || position.X >= _buffer->GetSize().RightInclusive())
{
return;
}
COORD positionWithOffsets = _ConvertToBufferCell(position);
const auto bufferViewport = _buffer->GetSize();
auto cellChar = _buffer->GetCellDataAt(positionWithOffsets)->Chars();
while (positionWithOffsets.X != 0 && !_DoubleClickDelimiterCheck(cellChar))
{
bufferViewport.DecrementInBounds(positionWithOffsets);
cellChar = _buffer->GetCellDataAt(positionWithOffsets)->Chars();
}
if (positionWithOffsets.X != 0 || _DoubleClickDelimiterCheck(cellChar))
{
// move off of delimiter to highlight properly
bufferViewport.IncrementInBounds(positionWithOffsets);
}
THROW_IF_FAILED(ShortSub(positionWithOffsets.Y, gsl::narrow<SHORT>(_ViewStartIndex()), &positionWithOffsets.Y));
_selectionAnchor = positionWithOffsets;
_selectionAnchor_YOffset = gsl::narrow<SHORT>(_ViewStartIndex());
_selectionActive = true;
}
// Method Description:
// - expand the double click selection to the right (stopped by delimiter)
// Arguments:
// - position: viewport coordinate for selection
// Return Value:
// - update _endSelectionPosition to new expanded location
void Terminal::_ExpandDoubleClickSelectionRight(const COORD position)
{
// don't change the value if at/outside the boundary
if (position.X <= 0 || position.X >= _buffer->GetSize().RightInclusive())
{
return;
}
COORD positionWithOffsets = _ConvertToBufferCell(position);
const auto bufferViewport = _buffer->GetSize();
auto cellChar = _buffer->GetCellDataAt(positionWithOffsets)->Chars();
while (positionWithOffsets.X != _buffer->GetSize().RightInclusive() && !_DoubleClickDelimiterCheck(cellChar))
{
bufferViewport.IncrementInBounds(positionWithOffsets);
cellChar = _buffer->GetCellDataAt(positionWithOffsets)->Chars();
}
THROW_IF_FAILED(ShortSub(positionWithOffsets.Y, gsl::narrow<SHORT>(_ViewStartIndex()), &positionWithOffsets.Y));
_endSelectionPosition = positionWithOffsets;
_endSelectionPosition_YOffset = gsl::narrow<SHORT>(_ViewStartIndex());
}
// Method Description:
// - check if buffer cell data contains delimiter for double click selection
// Arguments:
// - cellChar: the char saved to the buffer cell under observation
// Return Value:
// - true if cell data contains the delimiter.
const bool Terminal::_DoubleClickDelimiterCheck(std::wstring_view cellChar) const
{
// TODO GitHub #988: hook up delimiters to Settings
std::wstring_view delimiters[] = {
L" ",
L"/",
L"\\"
};
for (auto delimiter : delimiters)
{
if (cellChar == delimiter)
{
return true;
}
}
return false;
}
// Method Description:
// - convert viewport position to the corresponding location on the buffer
// Arguments:
// - viewportPos: a coordinate on the viewport
// Return Value:
// - the corresponding location on the buffer
const COORD Terminal::_ConvertToBufferCell(const COORD viewportPos) const
{
COORD positionWithOffsets = viewportPos;
THROW_IF_FAILED(ShortSub(viewportPos.Y, gsl::narrow<SHORT>(_scrollOffset), &positionWithOffsets.Y));
THROW_IF_FAILED(ShortAdd(positionWithOffsets.Y, gsl::narrow<SHORT>(_ViewStartIndex()), &positionWithOffsets.Y));
return positionWithOffsets;
}

View file

@ -20,6 +20,7 @@
namespace winrt::Microsoft::Terminal::Settings
{
struct ICoreSettings;
enum class TripleClickSelectionMode;
}
namespace Microsoft::Terminal::Core
@ -117,6 +118,8 @@ public:
#pragma region TextSelection
// These methods are defined in TerminalSelection.cpp
const bool IsSelectionActive() const noexcept;
void DoubleClickSelection(const COORD position);
void TripleClickSelection(const COORD position);
void SetSelectionAnchor(const COORD position);
void SetEndSelectionPosition(const COORD position);
void SetBoxSelection(const bool isEnabled) noexcept;
@ -149,6 +152,13 @@ private:
bool _selectionActive;
SHORT _selectionAnchor_YOffset;
SHORT _endSelectionPosition_YOffset;
winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode _tripleClickMode;
void _ExpandDoubleClickSelectionLeft(const COORD position);
void _ExpandDoubleClickSelectionRight(const COORD position);
const bool _DoubleClickDelimiterCheck(std::wstring_view cellChar) const;
void _SelectRow(const COORD position);
void _SelectViewport();
const COORD _ConvertToBufferCell(const COORD viewportPos) const;
std::shared_mutex _readWriteLock;

View file

@ -12,6 +12,13 @@ namespace Microsoft.Terminal.Settings
EmptyBox
};
enum TripleClickSelectionMode
{
Disabled,
Line,
VisibleViewport
};
interface ICoreSettings
{
UInt32 DefaultForeground;
@ -27,6 +34,7 @@ namespace Microsoft.Terminal.Settings
UInt32 CursorColor;
CursorStyle CursorShape;
UInt32 CursorHeight;
TripleClickSelectionMode TripleClickSelectionMode;
};
}

View file

@ -20,6 +20,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_cursorColor{ DEFAULT_CURSOR_COLOR },
_cursorShape{ CursorStyle::Vintage },
_cursorHeight{ DEFAULT_CURSOR_HEIGHT },
_tripleClickSelectionMode{ Settings::TripleClickSelectionMode::Line },
_useAcrylic{ false },
_closeOnExit{ true },
_tintOpacity{ 0.5 },
@ -135,6 +136,16 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_cursorHeight = value;
}
Settings::TripleClickSelectionMode TerminalSettings::TripleClickSelectionMode() const noexcept
{
return _tripleClickSelectionMode;
}
void TerminalSettings::TripleClickSelectionMode(winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode const& value) noexcept
{
_tripleClickSelectionMode = value;
}
bool TerminalSettings::UseAcrylic()
{
return _useAcrylic;

View file

@ -45,6 +45,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
void CursorShape(winrt::Microsoft::Terminal::Settings::CursorStyle const& value) noexcept;
uint32_t CursorHeight();
void CursorHeight(uint32_t value);
Settings::TripleClickSelectionMode TripleClickSelectionMode() const noexcept;
void TripleClickSelectionMode(winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode const& value) noexcept;
// ------------------------ End of Core Settings -----------------------
bool UseAcrylic();
@ -94,6 +96,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
uint32_t _cursorColor;
Settings::CursorStyle _cursorShape;
uint32_t _cursorHeight;
Settings::TripleClickSelectionMode _tripleClickSelectionMode;
bool _useAcrylic;
bool _closeOnExit;

View file

@ -36,6 +36,7 @@ namespace TerminalCoreUnitTests
uint32_t CursorColor() { return COLOR_WHITE; }
CursorStyle CursorShape() const noexcept { return CursorStyle::Vintage; }
uint32_t CursorHeight() { return 42UL; }
TripleClickSelectionMode TripleClickSelectionMode() { return TripleClickSelectionMode::Line; }
// other implemented methods
uint32_t GetColorTableEntry(int32_t) const { return 123; }
@ -50,6 +51,7 @@ namespace TerminalCoreUnitTests
void CursorColor(uint32_t) {}
void CursorShape(CursorStyle const&) noexcept {}
void CursorHeight(uint32_t) {}
void TripleClickSelectionMode(winrt::Microsoft::Terminal::Settings::TripleClickSelectionMode) {}
// other unimplemented methods
void SetColorTableEntry(int32_t /* index */, uint32_t /* value */) {}