From b0b0a6ce4d1c9cdefab88cfd5f395d0496a50754 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 22 Jun 2022 13:59:24 -0700 Subject: [PATCH 1/3] [1.14] Fix keyboard selection and copyOnSelect interaction --- src/cascadia/TerminalControl/ControlCore.cpp | 12 ++++++-- src/cascadia/TerminalControl/ControlCore.h | 3 +- .../TerminalControl/ControlInteractivity.cpp | 30 ++++++++++++++----- .../TerminalControl/ControlInteractivity.h | 3 +- src/cascadia/TerminalCore/Terminal.cpp | 1 + src/cascadia/TerminalCore/Terminal.hpp | 2 ++ .../TerminalCore/TerminalSelection.cpp | 9 +++++- 7 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index f91bae43034..d40a9207623 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -933,13 +933,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - 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: // - singleLine: collapse all of the text to one line // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr // if we should defer which formats are copied to the global setting + // - clearSelection: if true, clear the selection. Used for CopyOnSelect. bool ControlCore::CopySelectionToClipboard(bool singleLine, - const Windows::Foundation::IReference& formats) + const Windows::Foundation::IReference& formats, + bool clearSelection) { // no selection --> nothing to copy if (!_terminal->IsSelectionActive()) @@ -979,7 +980,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bgColor) : ""; - if (!_settings->CopyOnSelect()) + if (clearSelection) { _terminal->ClearSelection(); _renderer->TriggerSelection(); @@ -1001,6 +1002,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderer->TriggerSelection(); } + const bool ControlCore::IsInQuickEditMode() const noexcept + { + return _terminal->IsInQuickEditMode(); + } + // Method Description: // - Pre-process text pasted (presumably from the clipboard) // before sending it over the terminal's connection. diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 1a8b744cb7f..dfa3d445a95 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -79,8 +79,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void SendInput(const winrt::hstring& wstr); void PasteText(const winrt::hstring& hstr); - bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); + bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats, bool clearSelection = true); void SelectAll(); + const bool IsInQuickEditMode() const noexcept; void GotFocus(); void LostFocus(); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index f84c834fac4..2757e8f4d08 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -142,13 +142,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - 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: // - singleLine: collapse all of the text to one line // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr // if we should defer which formats are copied to the global setting + // - clearSelection: if true, clear the selection after copying it. Used for CopyOnSelect. bool ControlInteractivity::CopySelectionToClipboard(bool singleLine, - const Windows::Foundation::IReference& formats) + const Windows::Foundation::IReference& formats, + bool clearSelection) { if (_core) { @@ -164,7 +165,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Mark the current selection as copied _selectionNeedsToBeCopied = false; - return _core->CopySelectionToClipboard(singleLine, formats); + return _core->CopySelectionToClipboard(singleLine, formats, clearSelection); } return false; @@ -257,15 +258,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation } else if (WI_IsFlagSet(buttonState, MouseButtonState::IsRightButtonDown)) { - // CopyOnSelect right click always pastes - if (_core->CopyOnSelect() || !_core->HasSelection()) + if (_core->CopyOnSelect()) { + // CopyOnSelect: + // 1. keyboard selection? --> copy the new content first + // 2. right click always pastes! + if (_core->IsInQuickEditMode()) + { + CopySelectionToClipboard(shiftEnabled, nullptr); + } RequestPasteTextFromClipboard(); } - else + else if (_core->HasSelection()) { + // copy selected text CopySelectionToClipboard(shiftEnabled, nullptr); } + else + { + // no selection --> paste + RequestPasteTextFromClipboard(); + } } } @@ -383,7 +396,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation isLeftMouseRelease && _selectionNeedsToBeCopied) { - CopySelectionToClipboard(false, nullptr); + // IMPORTANT! + // Set clearSelection to false here! + // Otherwise, the selection will be cleared immediately after you make it. + CopySelectionToClipboard(false, nullptr, /*clearSelection*/ false); } _singleClickTouchdownPos = std::nullopt; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 200498a37ab..1ff0b5de12c 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -80,7 +80,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation #pragma endregion bool CopySelectionToClipboard(bool singleLine, - const Windows::Foundation::IReference& formats); + const Windows::Foundation::IReference& formats, + bool clearSelection = true); void RequestPasteTextFromClipboard(); void SetEndSelectionPoint(const Core::Point pixelPosition); bool ManglePathsForWsl(); diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 648d7fff902..4e20e94e00a 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -45,6 +45,7 @@ Terminal::Terminal() : _snapOnInput{ true }, _altGrAliasing{ true }, _blockSelection{ false }, + _quickEditMode{ false }, _selection{ std::nullopt }, _taskbarState{ 0 }, _taskbarProgress{ 0 }, diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index e89e9167b47..4c2b3425a25 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -241,6 +241,7 @@ class Microsoft::Terminal::Core::Terminal final : void SetBlockSelection(const bool isEnabled) noexcept; void UpdateSelection(SelectionDirection direction, SelectionExpansion mode); void SelectAll(); + const bool IsInQuickEditMode() const noexcept; using UpdateSelectionParams = std::optional>; static UpdateSelectionParams ConvertKeyEventToUpdateSelectionParams(const ControlKeyStates mods, const WORD vkey); @@ -313,6 +314,7 @@ class Microsoft::Terminal::Core::Terminal final : bool _blockSelection; std::wstring _wordDelimiters; SelectionExpansion _multiClickSelectionMode; + bool _quickEditMode; #pragma endregion std::unique_ptr _mainBuffer; diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index ad33e3f0b54..a510f711af8 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -96,6 +96,11 @@ const bool Terminal::IsBlockSelection() const noexcept return _blockSelection; } +const bool Terminal::IsInQuickEditMode() const noexcept +{ + return _quickEditMode; +} + // Method Description: // - Perform a multi-click selection at viewportPos expanding according to the expansionMode // Arguments: @@ -314,9 +319,10 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion targetPos = bottomRightInclusive; } - // 3. Actually modify the selection + // 3. Actually modify the selection state // NOTE: targetStart doesn't matter here auto targetStart = false; + _quickEditMode = true; std::tie(_selection->start, _selection->end) = _PivotSelection(targetPos, targetStart); // 4. Scroll (if necessary) @@ -482,6 +488,7 @@ void Terminal::_MoveByBuffer(SelectionDirection direction, COORD& pos) void Terminal::ClearSelection() { _selection = std::nullopt; + _quickEditMode = false; } // Method Description: From c4f37fc1d1a03506e920f10b770ce10f5fa698eb Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 23 Jun 2022 16:04:35 -0700 Subject: [PATCH 2/3] remove const --- src/cascadia/TerminalCore/Terminal.hpp | 2 +- src/cascadia/TerminalCore/TerminalSelection.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 4c2b3425a25..b88f79b653c 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -241,7 +241,7 @@ class Microsoft::Terminal::Core::Terminal final : void SetBlockSelection(const bool isEnabled) noexcept; void UpdateSelection(SelectionDirection direction, SelectionExpansion mode); void SelectAll(); - const bool IsInQuickEditMode() const noexcept; + bool IsInQuickEditMode() const noexcept; using UpdateSelectionParams = std::optional>; static UpdateSelectionParams ConvertKeyEventToUpdateSelectionParams(const ControlKeyStates mods, const WORD vkey); diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index a510f711af8..cea7f6a3820 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -96,7 +96,7 @@ const bool Terminal::IsBlockSelection() const noexcept return _blockSelection; } -const bool Terminal::IsInQuickEditMode() const noexcept +bool Terminal::IsInQuickEditMode() const noexcept { return _quickEditMode; } From 9dc99a91c1d94cb30e64cbbfa75fdf3c4d544bd2 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Thu, 30 Jun 2022 18:02:45 -0500 Subject: [PATCH 3/3] Update src/cascadia/TerminalCore/TerminalSelection.cpp --- src/cascadia/TerminalCore/TerminalSelection.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index 1ec8160eb13..132af1c771b 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -310,16 +310,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion break; } - // 2.B) Clamp the movement to the mutable viewport - const auto bufferSize = _activeBuffer().GetSize(); - const auto mutableViewport = _GetMutableViewport(); - const COORD bottomRightInclusive{ mutableViewport.RightInclusive(), mutableViewport.BottomInclusive() }; - if (bufferSize.CompareInBounds(targetPos, bottomRightInclusive) > 0) - { - targetPos = bottomRightInclusive; - } - - // 3. Actually modify the selection state + // 3. Actually modify the selection // NOTE: targetStart doesn't matter here auto targetStart = false; _quickEditMode = true;