Added CopyOnSelect as a Global Setting (#2152)
* Added CopyOnSelect as a ControlSetting * Updated doc * Updated doc * CopyOnSelect feature changes (like, overall) * Made CopyOnSelect a CoreSetting CopyOnSelect value accessible through Terminal's IsCopyOnSelectActive * Refactor a bit. * CopyOnSelect Tests * PR nits
This commit is contained in:
parent
98f77818ff
commit
ff87190823
|
@ -6,6 +6,7 @@ Properties listed below affect the entire window, regardless of the profile sett
|
|||
| Property | Necessity | Type | Default | Description |
|
||||
| -------- | --------- | ---- | ------- | ----------- |
|
||||
| `alwaysShowTabs` | _Required_ | Boolean | `true` | When set to `true`, tabs are always displayed. When set to `false` and `showTabsInTitlebar` is set to `false`, tabs only appear after typing <kbd>Ctrl</kbd> + <kbd>T</kbd>. |
|
||||
| `copyOnSelect` | Optional | Boolean | `false` | When set to `true`, a selection is immediately copied to your clipboard upon creation. When set to `false`, the selection persists and awaits further action. |
|
||||
| `defaultProfile` | _Required_ | String | PowerShell guid | Sets the default profile. Opens by typing <kbd>Ctrl</kbd> + <kbd>T</kbd> or by clicking the '+' icon. The guid of the desired default profile is used as the value. |
|
||||
| `initialCols` | _Required_ | Integer | `120` | The number of columns displayed in the window upon first load. |
|
||||
| `initialRows` | _Required_ | Integer | `30` | The number of rows displayed in the window upon first load. |
|
||||
|
|
|
@ -24,6 +24,7 @@ static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTi
|
|||
static constexpr std::string_view RequestedThemeKey{ "requestedTheme" };
|
||||
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
|
||||
static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" };
|
||||
static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" };
|
||||
|
||||
static constexpr std::wstring_view LightThemeValue{ L"light" };
|
||||
static constexpr std::wstring_view DarkThemeValue{ L"dark" };
|
||||
|
@ -39,7 +40,8 @@ GlobalAppSettings::GlobalAppSettings() :
|
|||
_showTitleInTitlebar{ true },
|
||||
_showTabsInTitlebar{ true },
|
||||
_requestedTheme{ ElementTheme::Default },
|
||||
_wordDelimiters{ DEFAULT_WORD_DELIMITERS }
|
||||
_wordDelimiters{ DEFAULT_WORD_DELIMITERS },
|
||||
_copyOnSelect{ false }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -117,6 +119,16 @@ void GlobalAppSettings::SetWordDelimiters(const std::wstring wordDelimiters) noe
|
|||
_wordDelimiters = wordDelimiters;
|
||||
}
|
||||
|
||||
bool GlobalAppSettings::GetCopyOnSelect() const noexcept
|
||||
{
|
||||
return _copyOnSelect;
|
||||
}
|
||||
|
||||
void GlobalAppSettings::SetCopyOnSelect(const bool copyOnSelect) noexcept
|
||||
{
|
||||
_copyOnSelect = copyOnSelect;
|
||||
}
|
||||
|
||||
#pragma region ExperimentalSettings
|
||||
bool GlobalAppSettings::GetShowTabsInTitlebar() const noexcept
|
||||
{
|
||||
|
@ -141,6 +153,7 @@ void GlobalAppSettings::ApplyToSettings(TerminalSettings& settings) const noexce
|
|||
settings.InitialRows(_initialRows);
|
||||
settings.InitialCols(_initialCols);
|
||||
settings.WordDelimiters(_wordDelimiters);
|
||||
settings.CopyOnSelect(_copyOnSelect);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -160,6 +173,7 @@ Json::Value GlobalAppSettings::ToJson() const
|
|||
jsonObject[JsonKey(ShowTitleInTitlebarKey)] = _showTitleInTitlebar;
|
||||
jsonObject[JsonKey(ShowTabsInTitlebarKey)] = _showTabsInTitlebar;
|
||||
jsonObject[JsonKey(WordDelimitersKey)] = winrt::to_string(_wordDelimiters);
|
||||
jsonObject[JsonKey(CopyOnSelectKey)] = _copyOnSelect;
|
||||
jsonObject[JsonKey(RequestedThemeKey)] = winrt::to_string(_SerializeTheme(_requestedTheme));
|
||||
jsonObject[JsonKey(KeybindingsKey)] = AppKeyBindingsSerialization::ToJson(_keybindings);
|
||||
|
||||
|
@ -210,6 +224,11 @@ GlobalAppSettings GlobalAppSettings::FromJson(const Json::Value& json)
|
|||
result._wordDelimiters = GetWstringFromJson(wordDelimiters);
|
||||
}
|
||||
|
||||
if (auto copyOnSelect{ json[JsonKey(CopyOnSelectKey)] })
|
||||
{
|
||||
result._copyOnSelect = copyOnSelect.asBool();
|
||||
}
|
||||
|
||||
if (auto requestedTheme{ json[JsonKey(RequestedThemeKey)] })
|
||||
{
|
||||
result._requestedTheme = _ParseTheme(GetWstringFromJson(requestedTheme));
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
std::wstring GetWordDelimiters() const noexcept;
|
||||
void SetWordDelimiters(const std::wstring wordDelimiters) noexcept;
|
||||
|
||||
bool GetCopyOnSelect() const noexcept;
|
||||
void SetCopyOnSelect(const bool copyOnSelect) noexcept;
|
||||
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme() const noexcept;
|
||||
|
||||
Json::Value ToJson() const;
|
||||
|
@ -72,6 +75,7 @@ private:
|
|||
|
||||
bool _showTabsInTitlebar;
|
||||
std::wstring _wordDelimiters;
|
||||
bool _copyOnSelect;
|
||||
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
|
||||
|
||||
static winrt::Windows::UI::Xaml::ElementTheme _ParseTheme(const std::wstring& themeString) noexcept;
|
||||
|
|
|
@ -773,16 +773,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||
}
|
||||
else if (point.Properties().IsRightButtonPressed())
|
||||
{
|
||||
// copy selection, if one exists
|
||||
if (_terminal->IsSelectionActive())
|
||||
{
|
||||
CopySelectionToClipboard(!shiftEnabled);
|
||||
}
|
||||
// paste selection, otherwise
|
||||
else
|
||||
// copyOnSelect causes right-click to always paste
|
||||
if (_terminal->IsCopyOnSelectActive() || !_terminal->IsSelectionActive())
|
||||
{
|
||||
PasteTextFromClipboard();
|
||||
}
|
||||
else
|
||||
{
|
||||
CopySelectionToClipboard(!shiftEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
|
@ -808,7 +807,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||
|
||||
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse)
|
||||
{
|
||||
if (_terminal->IsSelectionActive() && point.Properties().IsLeftButtonPressed())
|
||||
if (point.Properties().IsLeftButtonPressed())
|
||||
{
|
||||
const auto cursorPosition = point.Position();
|
||||
_SetEndSelectionPointAtCursor(cursorPosition);
|
||||
|
@ -885,7 +884,19 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||
|
||||
const auto ptr = args.Pointer();
|
||||
|
||||
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse)
|
||||
{
|
||||
const auto modifiers = static_cast<uint32_t>(args.KeyModifiers());
|
||||
// static_cast to a uint32_t because we can't use the WI_IsFlagSet
|
||||
// macro directly with a VirtualKeyModifiers
|
||||
const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast<uint32_t>(VirtualKeyModifiers::Shift));
|
||||
|
||||
if (_terminal->IsCopyOnSelectActive())
|
||||
{
|
||||
CopySelectionToClipboard(!shiftEnabled);
|
||||
}
|
||||
}
|
||||
else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
{
|
||||
_touchAnchor = std::nullopt;
|
||||
}
|
||||
|
@ -1387,35 +1398,41 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - get text from buffer and send it to the Windows Clipboard (CascadiaWin32:main.cpp). Also removes rendering of selection.
|
||||
// - Given a copy-able selection, get the selected text from the buffer and send it to the
|
||||
// Windows Clipboard (CascadiaWin32:main.cpp).
|
||||
// - CopyOnSelect does NOT clear the selection
|
||||
// Arguments:
|
||||
// - trimTrailingWhitespace: enable removing any whitespace from copied selection
|
||||
// and get text to appear on separate lines.
|
||||
bool TermControl::CopySelectionToClipboard(bool trimTrailingWhitespace)
|
||||
{
|
||||
if (_terminal != nullptr && _terminal->IsSelectionActive())
|
||||
// no selection --> nothing to copy
|
||||
if (_terminal == nullptr || !_terminal->IsSelectionActive())
|
||||
{
|
||||
// extract text from buffer
|
||||
const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace);
|
||||
|
||||
// convert text: vector<string> --> string
|
||||
std::wstring textData;
|
||||
for (const auto& text : bufferData.text)
|
||||
{
|
||||
textData += text;
|
||||
}
|
||||
|
||||
// convert text to HTML format
|
||||
const auto htmlData = TextBuffer::GenHTML(bufferData, _actualFont.GetUnscaledSize().Y, _actualFont.GetFaceName(), "Windows Terminal");
|
||||
|
||||
_terminal->ClearSelection();
|
||||
|
||||
// send data up for clipboard
|
||||
auto copyArgs = winrt::make_self<CopyToClipboardEventArgs>(winrt::hstring(textData.data(), textData.size()), winrt::to_hstring(htmlData));
|
||||
_clipboardCopyHandlers(*this, *copyArgs);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
// extract text from buffer
|
||||
const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace);
|
||||
|
||||
// convert text: vector<string> --> string
|
||||
std::wstring textData;
|
||||
for (const auto& text : bufferData.text)
|
||||
{
|
||||
textData += text;
|
||||
}
|
||||
|
||||
// convert text to HTML format
|
||||
const auto htmlData = TextBuffer::GenHTML(bufferData, _actualFont.GetUnscaledSize().Y, _actualFont.GetFaceName(), "Windows Terminal");
|
||||
|
||||
if (!_terminal->IsCopyOnSelectActive())
|
||||
{
|
||||
_terminal->ClearSelection();
|
||||
}
|
||||
|
||||
// send data up for clipboard
|
||||
auto copyArgs = winrt::make_self<CopyToClipboardEventArgs>(winrt::hstring(textData.data(), textData.size()), winrt::to_hstring(htmlData));
|
||||
_clipboardCopyHandlers(*this, *copyArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -45,6 +45,8 @@ Terminal::Terminal() :
|
|||
_snapOnInput{ true },
|
||||
_boxSelection{ false },
|
||||
_selectionActive{ false },
|
||||
_allowSingleCharSelection{ false },
|
||||
_copyOnSelect{ false },
|
||||
_selectionAnchor{ 0, 0 },
|
||||
_endSelectionPosition{ 0, 0 }
|
||||
{
|
||||
|
@ -135,6 +137,8 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting
|
|||
|
||||
_wordDelimiters = settings.WordDelimiters();
|
||||
|
||||
_copyOnSelect = settings.CopyOnSelect();
|
||||
|
||||
// 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
|
||||
|
|
|
@ -146,6 +146,7 @@ public:
|
|||
|
||||
#pragma region TextSelection
|
||||
// These methods are defined in TerminalSelection.cpp
|
||||
const bool IsCopyOnSelectActive() const noexcept;
|
||||
void DoubleClickSelection(const COORD position);
|
||||
void TripleClickSelection(const COORD position);
|
||||
void SetSelectionAnchor(const COORD position);
|
||||
|
@ -183,6 +184,8 @@ private:
|
|||
COORD _endSelectionPosition;
|
||||
bool _boxSelection;
|
||||
bool _selectionActive;
|
||||
bool _allowSingleCharSelection;
|
||||
bool _copyOnSelect;
|
||||
SHORT _selectionAnchor_YOffset;
|
||||
SHORT _endSelectionPosition_YOffset;
|
||||
std::wstring _wordDelimiters;
|
||||
|
@ -234,5 +237,6 @@ private:
|
|||
COORD _ExpandDoubleClickSelectionRight(const COORD position) const;
|
||||
const bool _isWordDelimiter(std::wstring_view cellChar) const;
|
||||
const COORD _ConvertToBufferCell(const COORD viewportPos) const;
|
||||
const bool _isSingleCellSelection() const noexcept;
|
||||
#pragma endregion
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ std::vector<SMALL_RECT> Terminal::_GetSelectionRects() const
|
|||
{
|
||||
std::vector<SMALL_RECT> selectionArea;
|
||||
|
||||
if (!_selectionActive)
|
||||
if (!IsSelectionActive())
|
||||
{
|
||||
return selectionArea;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ std::vector<SMALL_RECT> Terminal::_GetSelectionRects() const
|
|||
if (_multiClickSelectionMode == SelectionExpansionMode::Word)
|
||||
{
|
||||
const auto cellChar = _buffer->GetCellDataAt(selectionAnchorWithOffset)->Chars();
|
||||
if (_selectionAnchor == _endSelectionPosition && _isWordDelimiter(cellChar))
|
||||
if (_isSingleCellSelection() && _isWordDelimiter(cellChar))
|
||||
{
|
||||
// only highlight the cell if you double click a delimiter
|
||||
}
|
||||
|
@ -142,15 +142,39 @@ const SHORT Terminal::_ExpandWideGlyphSelectionRight(const SHORT xPos, const SHO
|
|||
return position.X;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if selection is on a single cell
|
||||
// Return Value:
|
||||
// - bool representing if selection is only a single cell. Used for copyOnSelect
|
||||
const bool Terminal::_isSingleCellSelection() const noexcept
|
||||
{
|
||||
return (_selectionAnchor == _endSelectionPosition);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if selection is active
|
||||
// Return Value:
|
||||
// - bool representing if selection is active. Used to decide copy/paste on right click
|
||||
const bool Terminal::IsSelectionActive() const noexcept
|
||||
{
|
||||
// A single cell selection is not considered an active selection,
|
||||
// if it's not allowed
|
||||
if (!_allowSingleCharSelection && _isSingleCellSelection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _selectionActive;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if the CopyOnSelect setting is active
|
||||
// Return Value:
|
||||
// - true if feature is active, false otherwise.
|
||||
const bool Terminal::IsCopyOnSelectActive() const noexcept
|
||||
{
|
||||
return _copyOnSelect;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Select the sequence between delimiters defined in Settings
|
||||
// Arguments:
|
||||
|
@ -211,6 +235,8 @@ void Terminal::SetSelectionAnchor(const COORD position)
|
|||
_selectionAnchor_YOffset = gsl::narrow<SHORT>(_ViewStartIndex());
|
||||
|
||||
_selectionActive = true;
|
||||
_allowSingleCharSelection = (_copyOnSelect) ? false : true;
|
||||
|
||||
SetEndSelectionPosition(position);
|
||||
|
||||
_multiClickSelectionMode = SelectionExpansionMode::Cell;
|
||||
|
@ -230,6 +256,11 @@ void Terminal::SetEndSelectionPosition(const COORD position)
|
|||
// copy value of ViewStartIndex to support scrolling
|
||||
// and update on new buffer output (used in _GetSelectionRects())
|
||||
_endSelectionPosition_YOffset = gsl::narrow<SHORT>(_ViewStartIndex());
|
||||
|
||||
if (_copyOnSelect && !_isSingleCellSelection())
|
||||
{
|
||||
_allowSingleCharSelection = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -246,6 +277,7 @@ void Terminal::SetBoxSelection(const bool isEnabled) noexcept
|
|||
void Terminal::ClearSelection()
|
||||
{
|
||||
_selectionActive = false;
|
||||
_allowSingleCharSelection = false;
|
||||
_selectionAnchor = { 0, 0 };
|
||||
_endSelectionPosition = { 0, 0 };
|
||||
_selectionAnchor_YOffset = 0;
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace Microsoft.Terminal.Settings
|
|||
CursorStyle CursorShape;
|
||||
UInt32 CursorHeight;
|
||||
String WordDelimiters;
|
||||
Boolean CopyOnSelect;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
|
|||
_cursorShape{ CursorStyle::Vintage },
|
||||
_cursorHeight{ DEFAULT_CURSOR_HEIGHT },
|
||||
_wordDelimiters{ DEFAULT_WORD_DELIMITERS },
|
||||
_copyOnSelect{ false },
|
||||
_useAcrylic{ false },
|
||||
_closeOnExit{ true },
|
||||
_tintOpacity{ 0.5 },
|
||||
|
@ -149,6 +150,16 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
|
|||
_wordDelimiters = value;
|
||||
}
|
||||
|
||||
bool TerminalSettings::CopyOnSelect()
|
||||
{
|
||||
return _copyOnSelect;
|
||||
}
|
||||
|
||||
void TerminalSettings::CopyOnSelect(bool value)
|
||||
{
|
||||
_copyOnSelect = value;
|
||||
}
|
||||
|
||||
bool TerminalSettings::UseAcrylic()
|
||||
{
|
||||
return _useAcrylic;
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
|
|||
void CursorHeight(uint32_t value);
|
||||
hstring WordDelimiters();
|
||||
void WordDelimiters(hstring const& value);
|
||||
bool CopyOnSelect();
|
||||
void CopyOnSelect(bool value);
|
||||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
bool UseAcrylic();
|
||||
|
@ -116,6 +118,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
|
|||
winrt::Windows::UI::Xaml::Media::Stretch _backgroundImageStretchMode;
|
||||
winrt::Windows::UI::Xaml::HorizontalAlignment _backgroundImageHorizontalAlignment;
|
||||
winrt::Windows::UI::Xaml::VerticalAlignment _backgroundImageVerticalAlignment;
|
||||
bool _copyOnSelect;
|
||||
hstring _commandline;
|
||||
hstring _startingDir;
|
||||
hstring _startingTitle;
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace TerminalCoreUnitTests
|
|||
CursorStyle CursorShape() const noexcept { return CursorStyle::Vintage; }
|
||||
uint32_t CursorHeight() { return 42UL; }
|
||||
winrt::hstring WordDelimiters() { return winrt::to_hstring(DEFAULT_WORD_DELIMITERS.c_str()); }
|
||||
bool CopyOnSelect() { return _copyOnSelect; }
|
||||
|
||||
// other implemented methods
|
||||
uint32_t GetColorTableEntry(int32_t) const { return 123; }
|
||||
|
@ -47,6 +48,7 @@ namespace TerminalCoreUnitTests
|
|||
void CursorShape(CursorStyle const&) noexcept {}
|
||||
void CursorHeight(uint32_t) {}
|
||||
void WordDelimiters(winrt::hstring) {}
|
||||
void CopyOnSelect(bool copyOnSelect) { _copyOnSelect = copyOnSelect; }
|
||||
|
||||
// other unimplemented methods
|
||||
void SetColorTableEntry(int32_t /* index */, uint32_t /* value */) {}
|
||||
|
@ -55,5 +57,6 @@ namespace TerminalCoreUnitTests
|
|||
int32_t _historySize;
|
||||
int32_t _initialRows;
|
||||
int32_t _initialCols;
|
||||
bool _copyOnSelect{ false };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -504,5 +504,63 @@ namespace TerminalCoreUnitTests
|
|||
selection = term.GetViewport().ConvertToOrigin(selectionRects.at(1)).ToInclusive();
|
||||
VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 0, 11, 99, 11 }));
|
||||
}
|
||||
|
||||
TEST_METHOD(CopyOnSelect)
|
||||
{
|
||||
Terminal term;
|
||||
DummyRenderTarget emptyRT;
|
||||
term.Create({ 100, 100 }, 0, emptyRT);
|
||||
|
||||
// set copyOnSelect for terminal
|
||||
auto settings = winrt::make<MockTermSettings>(0, 100, 100);
|
||||
settings.CopyOnSelect(true);
|
||||
term.UpdateSettings(settings);
|
||||
|
||||
// Simulate click at (x,y) = (5,10)
|
||||
term.SetSelectionAnchor({ 5, 10 });
|
||||
|
||||
// Simulate move to (x,y) = (5,10)
|
||||
// (So, no movement)
|
||||
term.SetEndSelectionPosition({ 5, 10 });
|
||||
|
||||
// Case 1: single cell selection not allowed
|
||||
{
|
||||
// Simulate renderer calling TriggerSelection and acquiring selection area
|
||||
auto selectionRects = term.GetSelectionRects();
|
||||
|
||||
// Validate selection area
|
||||
VERIFY_ARE_EQUAL(selectionRects.size(), static_cast<size_t>(0));
|
||||
|
||||
// single cell selection should not be allowed
|
||||
// thus, selection is NOT active
|
||||
VERIFY_IS_FALSE(term.IsSelectionActive());
|
||||
}
|
||||
|
||||
// Case 2: move off of single cell
|
||||
term.SetEndSelectionPosition({ 6, 10 });
|
||||
{ // Simulate renderer calling TriggerSelection and acquiring selection area
|
||||
auto selectionRects = term.GetSelectionRects();
|
||||
|
||||
// Validate selection area
|
||||
VERIFY_ARE_EQUAL(selectionRects.size(), static_cast<size_t>(1));
|
||||
auto selection = term.GetViewport().ConvertToOrigin(selectionRects.at(0)).ToInclusive();
|
||||
VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 5, 10, 6, 10 }));
|
||||
VERIFY_IS_TRUE(term.IsSelectionActive());
|
||||
}
|
||||
|
||||
// Case 3: move back onto single cell (now allowed)
|
||||
term.SetEndSelectionPosition({ 5, 10 });
|
||||
{ // Simulate renderer calling TriggerSelection and acquiring selection area
|
||||
auto selectionRects = term.GetSelectionRects();
|
||||
|
||||
// Validate selection area
|
||||
VERIFY_ARE_EQUAL(selectionRects.size(), static_cast<size_t>(1));
|
||||
auto selection = term.GetViewport().ConvertToOrigin(selectionRects.at(0)).ToInclusive();
|
||||
VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 5, 10, 5, 10 }));
|
||||
|
||||
// single cell selection should now be allowed
|
||||
VERIFY_IS_TRUE(term.IsSelectionActive());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue