From ef686238744acfb12236371ffc1d6e865f743a4e Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Tue, 2 Jun 2020 16:40:14 -0700 Subject: [PATCH 1/8] Add Proper Shift+MultiClick Selection Expansion --- src/cascadia/TerminalControl/TermControl.cpp | 18 +++++++++++-- src/cascadia/TerminalCore/Terminal.hpp | 2 +- .../TerminalCore/TerminalSelection.cpp | 26 ++++++++++++++++--- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 653a2cdf55f..699f8c32d6f 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1001,12 +1001,26 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (multiClickMapper == 3) { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + if (shiftEnabled && _terminal->IsSelectionActive()) + { + _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + } + else + { + _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + } _selectionNeedsToBeCopied = true; } else if (multiClickMapper == 2) { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word); + if (shiftEnabled && _terminal->IsSelectionActive()) + { + _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Word); + } + else + { + _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word); + } _selectionNeedsToBeCopied = true; } else diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 6f502e37740..c3d90e656ab 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -292,7 +292,7 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region TextSelection // These methods are defined in TerminalSelection.cpp std::vector _GetSelectionRects() const noexcept; - std::pair _PivotSelection(const COORD targetPos) const; + std::pair _PivotSelection(const COORD targetPos, bool& targetStart) const; std::pair _ExpandSelectionAnchors(std::pair anchors) const; COORD _ConvertToBufferCell(const COORD viewportPos) const; #pragma endregion diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index eda1088791f..19dde0729f3 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -151,8 +151,25 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optionalstart, _selection->end) = _ExpandSelectionAnchors(anchors); + bool targetStart = false; + const auto anchors = _PivotSelection(textBufferPos, targetStart); + const auto expandedAnchors = _ExpandSelectionAnchors(anchors); + + if (newExpansionMode.has_value()) + { + // shift-click operations only expand the target side + auto &anchorToExpand = targetStart ? _selection->start : _selection->end; + anchorToExpand = targetStart ? expandedAnchors.first : expandedAnchors.second; + + // the other anchor should then become the pivot (we don't expand it) + auto& anchorToPivot = targetStart ? _selection->end : _selection->start; + anchorToPivot = _selection->pivot; + } + else + { + // expand both anchors + std::tie(_selection->start, _selection->end) = expandedAnchors; + } } // Method Description: @@ -160,11 +177,12 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional Terminal::_PivotSelection(const COORD targetPos) const +std::pair Terminal::_PivotSelection(const COORD targetPos, bool& targetStart) const { - if (_buffer->GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0) + if (targetStart = _buffer->GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0) { // target is before pivot // treat target as start From 71602235e0b17154ba327f6d2886757c135c185a Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Tue, 2 Jun 2020 17:05:44 -0700 Subject: [PATCH 2/8] add tests for shift clicks and pivots --- .../UnitTests_TerminalCore/SelectionTest.cpp | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index 5e117dc8db6..c479e817fee 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -672,5 +672,121 @@ namespace TerminalCoreUnitTests selection = term.GetViewport().ConvertToOrigin(selectionRects.at(1)).ToInclusive(); VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 0, 11, 99, 11 })); } + + TEST_METHOD(ShiftClick) + { + Terminal term; + DummyRenderTarget emptyRT; + term.Create({ 100, 100 }, 0, emptyRT); + + // set word delimiters for terminal + auto settings = winrt::make(0, 100, 100); + term.UpdateSettings(settings); + + // Insert text at position (4,10) + const std::wstring_view text = L"doubleClickMe dragThroughHere"; + term.SetCursorPosition(4, 10); + term.Write(text); + + // Step 1: Create a selection on "doubleClickMe" + { + // Simulate double click at (x,y) = (5,10) + term.MultiClickSelection({ 5, 10 }, Terminal::SelectionExpansionMode::Word); + + // Validate selection area: "doubleClickMe" selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 16, 10 })); + } + + // Step 2: Shift+Click to "dragThroughHere" + { + // Simulate Shift+Click at (x,y) = (21,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ + // start finish + term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Cell); + + // Validate selection area: "doubleClickMe drag" selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 21, 10 })); + } + + // Step 3: Shift+Double-Click to "dragThroughHere" + { + // Simulate Shift+DoubleClick at (x,y) = (21,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ + // start finish + term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Word); + + // Validate selection area: "doubleClickMe dragThroughHere" selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 32, 10 })); + } + + // Step 4: Shift+Double-Click to "dragThroughHere" + { + // Simulate Shift+TripleClick at (x,y) = (21,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ + // start finish + term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Line); + + // Validate selection area: "doubleClickMe dragThroughHere..." selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 99, 10 })); + } + } + + TEST_METHOD(Pivot) + { + Terminal term; + DummyRenderTarget emptyRT; + term.Create({ 100, 100 }, 0, emptyRT); + + // Step 1: Create a selection + { + // (10,10) to (20, 10) + term.SelectNewRegion({ 10, 10 }, { 20, 10 }); + + // Validate selection area + ValidateSingleRowSelection(term, SMALL_RECT({ 10, 10, 20, 10 })); + } + + // Step 2: Pivot to (5,10) + { + term.SetSelectionEnd({ 5, 10 }); + + // Validate selection area + // NOTE: Pivot should be (10, 10) + ValidateSingleRowSelection(term, SMALL_RECT({ 5, 10, 10, 10 })); + } + + // Step 3: Pivot back to (20,10) + { + term.SetSelectionEnd({ 20, 10 }); + + // Validate selection area + // NOTE: Pivot should still be (10, 10) + ValidateSingleRowSelection(term, SMALL_RECT({ 10, 10, 20, 10 })); + } + + // Step 4: Pivot back to (5,10) with Shift+Click + { + term.SetSelectionEnd({ 5, 10 }, ::Terminal::SelectionExpansionMode::Cell); + + // Validate selection area + // NOTE: Pivot should still be (10, 10) + ValidateSingleRowSelection(term, SMALL_RECT({ 5, 10, 10, 10 })); + } + + // Step 5: Pivot back to (20,10) wtih Shift+Click + { + term.SetSelectionEnd({ 20, 10 }, ::Terminal::SelectionExpansionMode::Cell); + + // Validate selection area + // NOTE: Pivot should still be (10, 10) + ValidateSingleRowSelection(term, SMALL_RECT({ 10, 10, 20, 10 })); + } + } }; } From 186d0f965d3a69e3c98111778dc2835a5a96708f Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Tue, 2 Jun 2020 17:15:39 -0700 Subject: [PATCH 3/8] make my code look good --- src/cascadia/TerminalCore/TerminalSelection.cpp | 2 +- src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index 19dde0729f3..7d383702775 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -158,7 +158,7 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optionalstart : _selection->end; + auto& anchorToExpand = targetStart ? _selection->start : _selection->end; anchorToExpand = targetStart ? expandedAnchors.first : expandedAnchors.second; // the other anchor should then become the pivot (we don't expand it) diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index c479e817fee..003f0263a95 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -779,7 +779,7 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 5, 10, 10, 10 })); } - // Step 5: Pivot back to (20,10) wtih Shift+Click + // Step 5: Pivot back to (20,10) with Shift+Click { term.SetSelectionEnd({ 20, 10 }, ::Terminal::SelectionExpansionMode::Cell); From 4f44d5d08c477a683f21775aa3101b311feb62a4 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 3 Jun 2020 11:20:03 -0700 Subject: [PATCH 4/8] add a lambda for multi-click selections --- src/cascadia/TerminalControl/TermControl.cpp | 33 +++++++++----------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 699f8c32d6f..53ad7e7e3e7 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -994,34 +994,31 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); - // This formula enables the number of clicks to cycle properly between single-, double-, and triple-click. - // To increase the number of acceptable click states, simply increment MAX_CLICK_COUNT and add another if-statement - const unsigned int MAX_CLICK_COUNT = 3; - const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - - if (multiClickMapper == 3) - { + // performs a double/triple click selection + auto multiClickSelection = [this, terminalPosition, shiftEnabled](::Terminal::SelectionExpansionMode mode) { if (shiftEnabled && _terminal->IsSelectionActive()) { - _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + _terminal->SetSelectionEnd(terminalPosition, mode); } else { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + _terminal->MultiClickSelection(terminalPosition, mode); } _selectionNeedsToBeCopied = true; + }; + + // This formula enables the number of clicks to cycle properly between single-, double-, and triple-click. + // To increase the number of acceptable click states, simply increment MAX_CLICK_COUNT and add another if-statement + const unsigned int MAX_CLICK_COUNT = 3; + const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; + + if (multiClickMapper == 3) + { + multiClickSelection(::Terminal::SelectionExpansionMode::Line); } else if (multiClickMapper == 2) { - if (shiftEnabled && _terminal->IsSelectionActive()) - { - _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Word); - } - else - { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word); - } - _selectionNeedsToBeCopied = true; + multiClickSelection(::Terminal::SelectionExpansionMode::Word); } else { From 519fb279f6735ead3c24fcd30a158f98c873f8c5 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 3 Jun 2020 11:50:32 -0700 Subject: [PATCH 5/8] Revert "add a lambda for multi-click selections" This reverts commit 39c944d01bda52af4488b72cd71fe98162418e7f. --- src/cascadia/TerminalControl/TermControl.cpp | 33 +++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 53ad7e7e3e7..699f8c32d6f 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -994,19 +994,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); - // performs a double/triple click selection - auto multiClickSelection = [this, terminalPosition, shiftEnabled](::Terminal::SelectionExpansionMode mode) { - if (shiftEnabled && _terminal->IsSelectionActive()) - { - _terminal->SetSelectionEnd(terminalPosition, mode); - } - else - { - _terminal->MultiClickSelection(terminalPosition, mode); - } - _selectionNeedsToBeCopied = true; - }; - // This formula enables the number of clicks to cycle properly between single-, double-, and triple-click. // To increase the number of acceptable click states, simply increment MAX_CLICK_COUNT and add another if-statement const unsigned int MAX_CLICK_COUNT = 3; @@ -1014,11 +1001,27 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (multiClickMapper == 3) { - multiClickSelection(::Terminal::SelectionExpansionMode::Line); + if (shiftEnabled && _terminal->IsSelectionActive()) + { + _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + } + else + { + _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line); + } + _selectionNeedsToBeCopied = true; } else if (multiClickMapper == 2) { - multiClickSelection(::Terminal::SelectionExpansionMode::Word); + if (shiftEnabled && _terminal->IsSelectionActive()) + { + _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Word); + } + else + { + _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word); + } + _selectionNeedsToBeCopied = true; } else { From 0b8e5608b0ab56237258fef3f868dd464c1095d6 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 3 Jun 2020 12:48:38 -0700 Subject: [PATCH 6/8] a better refactor --- src/cascadia/TerminalControl/TermControl.cpp | 66 ++++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 699f8c32d6f..a1f7bcb81b1 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -999,49 +999,49 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const unsigned int MAX_CLICK_COUNT = 3; const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - if (multiClickMapper == 3) + ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell; + if (multiClickMapper == 1) { - if (shiftEnabled && _terminal->IsSelectionActive()) - { - _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Line); - } - else - { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line); - } - _selectionNeedsToBeCopied = true; + mode = ::Terminal::SelectionExpansionMode::Cell; } else if (multiClickMapper == 2) { - if (shiftEnabled && _terminal->IsSelectionActive()) - { - _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Word); - } - else - { - _terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word); - } - _selectionNeedsToBeCopied = true; + mode = ::Terminal::SelectionExpansionMode::Word; + } + else if (multiClickMapper == 3) + { + mode = ::Terminal::SelectionExpansionMode::Line; } else { - if (shiftEnabled && _terminal->IsSelectionActive()) - { - _terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Cell); - _selectionNeedsToBeCopied = true; - } - else - { - // A single click down resets the selection and begins a new one. - _terminal->ClearSelection(); - _singleClickTouchdownPos = cursorPosition; - _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update - } + // This should never happen because the multiClickMapper should be limited to the other values. + // Perhaps you forgot to update MAX_CLICK_COUNT + FAIL_FAST(); + } - _lastMouseClickTimestamp = point.Timestamp(); - _lastMouseClickPos = cursorPosition; + // Update the selection appropriately + if (shiftEnabled && _terminal->IsSelectionActive()) + { + // Shift+Click: only set expand on the "end" selection point + _terminal->SetSelectionEnd(terminalPosition, mode); + _selectionNeedsToBeCopied = true; + } + else if (multiClickMapper == 1) + { + // Single Click: reset the selection and begin a new one + _terminal->ClearSelection(); + _singleClickTouchdownPos = cursorPosition; + _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update + } + else + { + // Multi-Click Selection: expand both "start" and "end" selection points + _terminal->MultiClickSelection(terminalPosition, mode); + _selectionNeedsToBeCopied = true; } + _lastMouseClickTimestamp = point.Timestamp(); + _lastMouseClickPos = cursorPosition; _renderer->TriggerSelection(); } else if (point.Properties().IsRightButtonPressed()) From 3fdbbdaabef0b72b9e9b8e6d41cc487342bed8a2 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Fri, 5 Jun 2020 10:29:23 -0700 Subject: [PATCH 7/8] make this a bit cleaner --- src/cascadia/TerminalControl/TermControl.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index a1f7bcb81b1..a9975ce6007 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1003,6 +1003,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (multiClickMapper == 1) { mode = ::Terminal::SelectionExpansionMode::Cell; + _singleClickTouchdownPos = cursorPosition; } else if (multiClickMapper == 2) { @@ -1012,12 +1013,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { mode = ::Terminal::SelectionExpansionMode::Line; } - else - { - // This should never happen because the multiClickMapper should be limited to the other values. - // Perhaps you forgot to update MAX_CLICK_COUNT - FAIL_FAST(); - } // Update the selection appropriately if (shiftEnabled && _terminal->IsSelectionActive()) @@ -1026,11 +1021,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _terminal->SetSelectionEnd(terminalPosition, mode); _selectionNeedsToBeCopied = true; } - else if (multiClickMapper == 1) + else if (mode == ::Terminal::SelectionExpansionMode::Cell) { // Single Click: reset the selection and begin a new one _terminal->ClearSelection(); - _singleClickTouchdownPos = cursorPosition; _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update } else From 8dc5a1dda61525b6d7c389fb38ddafb6faf7db8d Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 24 Jun 2020 15:42:06 -0700 Subject: [PATCH 8/8] fix shift+click+drag bug. Add more tests --- src/cascadia/TerminalControl/TermControl.cpp | 2 +- .../UnitTests_TerminalCore/SelectionTest.cpp | 75 ++++++++++++++++--- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 37f71ac55cf..0d8fa29e2b4 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1082,7 +1082,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (multiClickMapper == 1) { mode = ::Terminal::SelectionExpansionMode::Cell; - _singleClickTouchdownPos = cursorPosition; } else if (multiClickMapper == 2) { @@ -1104,6 +1103,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { // Single Click: reset the selection and begin a new one _terminal->ClearSelection(); + _singleClickTouchdownPos = cursorPosition; _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update } else diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index 003f0263a95..39f78b0b41c 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -710,31 +710,84 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 21, 10 })); } - // Step 3: Shift+Double-Click to "dragThroughHere" + // Step 3: Shift+Double-Click at "dragThroughHere" { // Simulate Shift+DoubleClick at (x,y) = (21,10) // // buffer: doubleClickMe dragThroughHere - // ^ ^ - // start finish + // ^ ^ ^ + // start click finish term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Word); // Validate selection area: "doubleClickMe dragThroughHere" selected ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 32, 10 })); } - // Step 4: Shift+Double-Click to "dragThroughHere" + // Step 4: Shift+Triple-Click at "dragThroughHere" { // Simulate Shift+TripleClick at (x,y) = (21,10) // - // buffer: doubleClickMe dragThroughHere - // ^ ^ - // start finish + // buffer: doubleClickMe dragThroughHere | + // ^ ^ ^ + // start click finish (boundary) term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Line); // Validate selection area: "doubleClickMe dragThroughHere..." selected ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 99, 10 })); } + + // Step 5: Shift+Double-Click at "dragThroughHere" + { + // Simulate Shift+DoubleClick at (x,y) = (21,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ ^ + // start click finish + term.SetSelectionEnd({ 21, 10 }, ::Terminal::SelectionExpansionMode::Word); + + // Validate selection area: "doubleClickMe dragThroughHere" selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 32, 10 })); + } + + // Step 6: Drag past "dragThroughHere" + { + // Simulate drag to (x,y) = (35,10) + // Since we were preceded by a double-click, we're in "word" expansion mode + // + // buffer: doubleClickMe dragThroughHere | + // ^ ^ + // start finish (boundary) + term.SetSelectionEnd({ 35, 10 }); + + // Validate selection area: "doubleClickMe dragThroughHere..." selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 99, 10 })); + } + + // Step 6: Drag back to "dragThroughHere" + { + // Simulate drag to (x,y) = (21,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ ^ + // start drag finish + term.SetSelectionEnd({ 21, 10 }); + + // Validate selection area: "doubleClickMe dragThroughHere" selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 32, 10 })); + } + + // Step 7: Drag within "dragThroughHere" + { + // Simulate drag to (x,y) = (25,10) + // + // buffer: doubleClickMe dragThroughHere + // ^ ^ ^ + // start drag finish + term.SetSelectionEnd({ 25, 10 }); + + // Validate selection area: "doubleClickMe dragThroughHere" still selected + ValidateSingleRowSelection(term, SMALL_RECT({ 4, 10, 32, 10 })); + } } TEST_METHOD(Pivot) @@ -752,7 +805,7 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 10, 10, 20, 10 })); } - // Step 2: Pivot to (5,10) + // Step 2: Drag to (5,10) { term.SetSelectionEnd({ 5, 10 }); @@ -761,7 +814,7 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 5, 10, 10, 10 })); } - // Step 3: Pivot back to (20,10) + // Step 3: Drag back to (20,10) { term.SetSelectionEnd({ 20, 10 }); @@ -770,7 +823,7 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 10, 10, 20, 10 })); } - // Step 4: Pivot back to (5,10) with Shift+Click + // Step 4: Shift+Click at (5,10) { term.SetSelectionEnd({ 5, 10 }, ::Terminal::SelectionExpansionMode::Cell); @@ -779,7 +832,7 @@ namespace TerminalCoreUnitTests ValidateSingleRowSelection(term, SMALL_RECT({ 5, 10, 10, 10 })); } - // Step 5: Pivot back to (20,10) with Shift+Click + // Step 5: Shift+Click back at (20,10) { term.SetSelectionEnd({ 20, 10 }, ::Terminal::SelectionExpansionMode::Cell);