Allow triple-click to select logical line (#18885)

This fixes #18877, by iteratively checking to see if a line is wrapped
and moving up or down accordingly.

**Current behavior:** When a user triple-clicks on a line that’s
visually wrapped by the terminal, only the single physical row that was
clicked gets selected.

**Expected behavior:** A triple-click like in xterm, should select the
entire logical line including all of its wrapped segments, from the true
start through its true end, regardless of where the wrap occurred.

**Why it matters:** Logical line selection is what users expect when
they’re trying to grab one command or output block in full. Limiting the
selection to just the current physical row can lead to copy/paste
mistakes and a confusing experience whenever a long line wraps.

## Validation Steps Performed
I ran the existing tests using `Invoke-OpenConsoleTests` and they were
passing and I was also able to test the build on my machine. I added a
test case as well

## PR Checklist
Closes #18877
This commit is contained in:
ALBIN BABU VARGHESE 2025-05-09 19:00:46 -04:00 committed by GitHub
parent 06f736bebe
commit 976a54d87c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 0 deletions

View File

@ -294,9 +294,21 @@ std::pair<til::point, til::point> Terminal::_ExpandSelectionAnchors(std::pair<ti
const auto& buffer = _activeBuffer();
const auto bufferSize = buffer.GetSize();
const auto height = buffer.GetSize().Height();
switch (_multiClickSelectionMode)
{
case SelectionExpansion::Line:
// climb up to the first row that is wrapped
while (start.y > 0 && buffer.GetRowByOffset(start.y - 1).WasWrapForced())
{
--start.y;
}
// climb down to the last row that is wrapped
while (end.y + 1 < height && buffer.GetRowByOffset(end.y).WasWrapForced())
{
++end.y;
}
start = { bufferSize.Left(), start.y };
end = { bufferSize.RightExclusive(), end.y };
break;

View File

@ -549,6 +549,21 @@ namespace TerminalCoreUnitTests
ValidateLinearSelection(term, { 0, 10 }, { term.GetViewport().RightExclusive(), 10 });
}
TEST_METHOD(TripleClick_WrappedLine)
{
Terminal term{ Terminal::TestDummyMarker{} };
DummyRenderer renderer{ &term };
term.Create({ 10, 5 }, 0, renderer);
term.Write(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
// Simulate click at (x,y) = (3,1)
auto clickPos = til::point{ 3, 1 };
term.MultiClickSelection(clickPos, Terminal::SelectionExpansion::Line);
// Validate selection area
ValidateLinearSelection(term, { 0, 0 }, { term.GetViewport().RightExclusive(), 2 });
}
TEST_METHOD(TripleClickDrag_Horizontal)
{
Terminal term{ Terminal::TestDummyMarker{} };