From 7cca19d13f77187bce836b510376b52f6ceb19eb Mon Sep 17 00:00:00 2001 From: khvitaly Date: Fri, 5 Mar 2021 08:23:25 +0200 Subject: [PATCH 1/4] Fix selection not to extend on multi-click --- src/cascadia/TerminalControl/TermControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 041f9393802..b6a81eed64a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1348,7 +1348,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { _HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition)); } - else if (shiftEnabled && _terminal->IsSelectionActive()) + else if (shiftEnabled && mode == ::Terminal::SelectionExpansionMode::Cell && _terminal->IsSelectionActive()) { // Shift+Click: only set expand on the "end" selection point _terminal->SetSelectionEnd(terminalPosition, mode); From 1aa147f181f2c3b20749bbbbe3e6f9edb3925d31 Mon Sep 17 00:00:00 2001 From: khvitaly Date: Sun, 7 Mar 2021 11:11:41 +0200 Subject: [PATCH 2/4] Introduce selection reset on anchor / same position click --- src/cascadia/TerminalControl/TermControl.cpp | 66 +++++++++++++------- src/cascadia/TerminalControl/TermControl.h | 1 + 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b6a81eed64a..14e2e9e4a8d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -79,6 +79,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _blinkTimer{}, _lastMouseClickTimestamp{}, _lastMouseClickPos{}, + _lastMouseClickPosNoSelection{}, _selectionNeedsToBeCopied{ false }, _searchBox{ nullptr } { @@ -1342,35 +1343,58 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation mode = ::Terminal::SelectionExpansionMode::Line; } - // Update the selection appropriately if (ctrlEnabled && multiClickMapper == 1 && !(_terminal->GetHyperlinkAtPosition(terminalPosition).empty())) { _HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition)); } - else if (shiftEnabled && mode == ::Terminal::SelectionExpansionMode::Cell && _terminal->IsSelectionActive()) - { - // Shift+Click: only set expand on the "end" selection point - _terminal->SetSelectionEnd(terminalPosition, mode); - _selectionNeedsToBeCopied = true; - } - else if (mode == ::Terminal::SelectionExpansionMode::Cell && !shiftEnabled) - { - // 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; - } + // Update the selection appropriately - _lastMouseClickTimestamp = point.Timestamp(); - _lastMouseClickPos = cursorPosition; - _renderer->TriggerSelection(); + // Capture the position of the first click when no selection is active + if (mode == ::Terminal::SelectionExpansionMode::Cell && !_terminal->IsSelectionActive()) + { + _singleClickTouchdownPos = cursorPosition; + _lastMouseClickPosNoSelection = cursorPosition; + } + + // We reset the active selection if one of the conditions apply: + // - shift is not held + // - GH#9384: the position is the same as of the first click starting the selection + // (we need to reset selection on double-click or triple-click, so it captures the word or the line, + // rather than extending the selection) + // - the click is the first click on selection anchor: we need to have a way to cancel selection with mouse, + // even when shift is held (crucial for mouse mode, where all interaction with selection is done when shift is held) + const auto isClickOnAnchor = _terminal->IsSelectionActive() && _terminal->GetSelectionAnchor() == terminalPosition && mode == ::Terminal::SelectionExpansionMode::Cell; + if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition || isClickOnAnchor)) + { + // Reset the selection + _terminal->ClearSelection(); + _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update + } + + if (shiftEnabled && !isClickOnAnchor) + { + if (_terminal->IsSelectionActive()) + { + // If there is a selection we extend it using the selection mode + // (expand the "end"selection point) + _terminal->SetSelectionEnd(terminalPosition, mode); + } + else + { + // If there is no selection we establish it using the selected mode + // (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()) { diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 4a85142002b..0cd9b463b67 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -261,6 +261,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation unsigned int _multiClickCounter; Timestamp _lastMouseClickTimestamp; std::optional _lastMouseClickPos; + std::optional _lastMouseClickPosNoSelection; std::optional _singleClickTouchdownPos; // This field tracks whether the selection has changed meaningfully // since it was last copied. It's generally used to prevent copyOnSelect From a11c9c258381475070030ebb45ceaef323854fba Mon Sep 17 00:00:00 2001 From: khvitaly Date: Sun, 7 Mar 2021 11:59:22 +0200 Subject: [PATCH 3/4] Remove clean selection on anchor as mintty lives without it --- src/cascadia/TerminalControl/TermControl.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 14e2e9e4a8d..998456b4cb0 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1364,17 +1364,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - GH#9384: the position is the same as of the first click starting the selection // (we need to reset selection on double-click or triple-click, so it captures the word or the line, // rather than extending the selection) - // - the click is the first click on selection anchor: we need to have a way to cancel selection with mouse, - // even when shift is held (crucial for mouse mode, where all interaction with selection is done when shift is held) - const auto isClickOnAnchor = _terminal->IsSelectionActive() && _terminal->GetSelectionAnchor() == terminalPosition && mode == ::Terminal::SelectionExpansionMode::Cell; - if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition || isClickOnAnchor)) + if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition)) { // Reset the selection _terminal->ClearSelection(); _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update } - if (shiftEnabled && !isClickOnAnchor) + if (shiftEnabled) { if (_terminal->IsSelectionActive()) { From 8d9d71392bebc1edeb2ac23348f19a8a90085c75 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Mon, 8 Mar 2021 10:52:06 -0800 Subject: [PATCH 4/4] Remove extra space --- src/cascadia/TerminalControl/TermControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 998456b4cb0..7aef81f5963 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1362,7 +1362,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // We reset the active selection if one of the conditions apply: // - shift is not held // - GH#9384: the position is the same as of the first click starting the selection - // (we need to reset selection on double-click or triple-click, so it captures the word or the line, + // (we need to reset selection on double-click or triple-click, so it captures the word or the line, // rather than extending the selection) if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition)) {