mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
Compare commits
4 Commits
dev/lhecke
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaf72153e7 | ||
|
|
ca658ba331 | ||
|
|
45b3e8d4f8 | ||
|
|
2ec30ef270 |
@@ -255,10 +255,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsRightButtonDown))
|
||||
{
|
||||
// Try to copy the text and clear the selection
|
||||
const auto successfulCopy = CopySelectionToClipboard(shiftEnabled, nullptr);
|
||||
const auto copyOnSelect{ _core->CopyOnSelect() };
|
||||
bool successfulCopy = false;
|
||||
|
||||
// Don't try to copy if we're in copyOnSelect mode and have already
|
||||
// copied this selection. GH#14464 demonstrates a scenario where the
|
||||
// buffer contents might have changed since the selection was made,
|
||||
// and copying here would cause weirdness.
|
||||
if (_selectionNeedsToBeCopied || !copyOnSelect)
|
||||
{
|
||||
// Try to copy the text and clear the selection
|
||||
successfulCopy = CopySelectionToClipboard(shiftEnabled, nullptr);
|
||||
}
|
||||
_core->ClearSelection();
|
||||
if (_core->CopyOnSelect() || !successfulCopy)
|
||||
|
||||
if (copyOnSelect || !successfulCopy)
|
||||
{
|
||||
// CopyOnSelect: right click always pastes!
|
||||
// Otherwise: no selection --> paste
|
||||
|
||||
@@ -43,6 +43,9 @@ namespace ControlUnitTests
|
||||
TEST_METHOD(GetMouseEventsInTest);
|
||||
TEST_METHOD(AltBufferClampMouse);
|
||||
|
||||
TEST_METHOD(CopyOnSelectSimple);
|
||||
TEST_METHOD(CopyOnSelectAltBuffer);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
@@ -966,4 +969,183 @@ namespace ControlUnitTests
|
||||
cursorPosition1.to_core_point());
|
||||
VERIFY_ARE_EQUAL(0u, expectedOutput.size(), L"Validate we drained all the expected output");
|
||||
}
|
||||
|
||||
void ControlInteractivityTests::CopyOnSelectSimple()
|
||||
{
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
settings->CopyOnSelect(true);
|
||||
auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn);
|
||||
_standardInit(core, interactivity);
|
||||
auto& term{ *core->_terminal };
|
||||
|
||||
// Output some text
|
||||
for (auto i = 0; i < core->ViewHeight() / 2; ++i)
|
||||
{
|
||||
conn->WriteInput(winrt::hstring{ fmt::format(L"line {}\r\n", i) });
|
||||
}
|
||||
|
||||
// A callback for checking Copy events. expectedCopyContents=nullopt
|
||||
// indicates that we're not expecting any copy events.
|
||||
std::optional<std::wstring> expectedCopyContents{ std::nullopt };
|
||||
core->CopyToClipboard([&](auto&&, auto& args) {
|
||||
VERIFY_IS_TRUE(expectedCopyContents.has_value());
|
||||
const std::wstring expected{ expectedCopyContents->c_str() };
|
||||
const std::wstring actual{ args.Text().c_str() };
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
});
|
||||
bool expectedPaste = false;
|
||||
interactivity->PasteFromClipboard([&](auto&&, auto&&) {
|
||||
VERIFY_IS_TRUE(expectedPaste);
|
||||
});
|
||||
|
||||
const auto originalViewport{ term.GetViewport() };
|
||||
VERIFY_ARE_EQUAL(originalViewport.Width(), 30);
|
||||
|
||||
// For this test, don't use any modifiers
|
||||
const auto modifiers = ControlKeyStates();
|
||||
const auto leftMouseDown{ Control::MouseButtonState::IsLeftButtonDown };
|
||||
const auto rightMouseDown{ Control::MouseButtonState::IsRightButtonDown };
|
||||
const Control::MouseButtonState noMouseDown{};
|
||||
const til::size fontSize{ 9, 21 };
|
||||
const til::point terminalPosition0{ 0, 5 };
|
||||
const til::point terminalPosition1{ 5, 5 };
|
||||
const auto cursorPosition0{ terminalPosition0 * fontSize };
|
||||
const auto cursorPosition1{ terminalPosition1 * fontSize };
|
||||
|
||||
Log::Comment(L" --- Click on the terminal at 0,5 ---");
|
||||
|
||||
interactivity->PointerPressed(leftMouseDown,
|
||||
WM_LBUTTONDOWN, //pointerUpdateKind
|
||||
0, // timestamp
|
||||
modifiers,
|
||||
cursorPosition0.to_core_point());
|
||||
VERIFY_IS_FALSE(core->HasSelection());
|
||||
|
||||
Log::Comment(L" --- Drag to 5,5 ---");
|
||||
|
||||
interactivity->PointerMoved(leftMouseDown,
|
||||
WM_LBUTTONDOWN, //pointerUpdateKind
|
||||
modifiers,
|
||||
true, // focused,
|
||||
cursorPosition1.to_core_point(),
|
||||
true); // pointerPressedInBounds
|
||||
VERIFY_IS_TRUE(core->HasSelection());
|
||||
// expectedCopyContents being nullopt here will ensure that we don't send the copy event till the pointer released
|
||||
|
||||
Log::Comment(L" --- Release the mouse --- ");
|
||||
expectedCopyContents = L"line 5";
|
||||
interactivity->PointerReleased(noMouseDown,
|
||||
WM_LBUTTONUP, //pointerUpdateKind
|
||||
modifiers,
|
||||
cursorPosition1.to_core_point());
|
||||
VERIFY_IS_TRUE(core->HasSelection());
|
||||
|
||||
Log::Comment(L" --- Right-click to paste --- ");
|
||||
// Note from GH#14464: we don't want to copy _again_ at this point. The
|
||||
// copy occured when the selection was made, we shouldn't stealth-update
|
||||
// the clipboard again.
|
||||
expectedCopyContents = std::nullopt;
|
||||
expectedPaste = true;
|
||||
interactivity->PointerPressed(rightMouseDown,
|
||||
WM_RBUTTONDOWN, //pointerUpdateKind
|
||||
0, // timestamp
|
||||
modifiers,
|
||||
cursorPosition1.to_core_point());
|
||||
VERIFY_IS_FALSE(core->HasSelection());
|
||||
}
|
||||
|
||||
void ControlInteractivityTests::CopyOnSelectAltBuffer()
|
||||
{
|
||||
// This test was inspired by GH#14464. Ultimately, it's similar to the
|
||||
// CopyOnSelectSimple, just with an alt buffer, and outputting text
|
||||
// after the selection was made.
|
||||
auto [settings, conn] = _createSettingsAndConnection();
|
||||
settings->CopyOnSelect(true);
|
||||
auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn);
|
||||
_standardInit(core, interactivity);
|
||||
auto& term{ *core->_terminal };
|
||||
|
||||
Log::Comment(L" --- Switch to alt buffer ---");
|
||||
term.Write(L"\x1b[?1049h");
|
||||
auto returnToMain = wil::scope_exit([&]() { term.Write(L"\x1b[?1049h"); });
|
||||
|
||||
// Output some text
|
||||
auto i = 0;
|
||||
for (i = 0; i < core->ViewHeight() - 1; ++i)
|
||||
{
|
||||
conn->WriteInput(winrt::hstring{ fmt::format(L"line {}\r\n", i) });
|
||||
}
|
||||
|
||||
// A callback for checking Copy events. expectedCopyContents=nullopt
|
||||
// indicates that we're not expecting any copy events.
|
||||
std::optional<std::wstring> expectedCopyContents{ std::nullopt };
|
||||
core->CopyToClipboard([&](auto&&, auto& args) {
|
||||
VERIFY_IS_TRUE(expectedCopyContents.has_value());
|
||||
const std::wstring expected{ expectedCopyContents->c_str() };
|
||||
const std::wstring actual{ args.Text().c_str() };
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
});
|
||||
bool expectedPaste = false;
|
||||
interactivity->PasteFromClipboard([&](auto&&, auto&&) {
|
||||
VERIFY_IS_TRUE(expectedPaste);
|
||||
});
|
||||
|
||||
const auto originalViewport{ term.GetViewport() };
|
||||
VERIFY_ARE_EQUAL(originalViewport.Width(), 30);
|
||||
|
||||
// For this test, don't use any modifiers
|
||||
const auto modifiers = ControlKeyStates();
|
||||
const auto leftMouseDown{ Control::MouseButtonState::IsLeftButtonDown };
|
||||
const auto rightMouseDown{ Control::MouseButtonState::IsRightButtonDown };
|
||||
const Control::MouseButtonState noMouseDown{};
|
||||
const til::size fontSize{ 9, 21 };
|
||||
const til::point terminalPosition0{ 0, 5 };
|
||||
const til::point terminalPosition1{ 5, 5 };
|
||||
const auto cursorPosition0{ terminalPosition0 * fontSize };
|
||||
const auto cursorPosition1{ terminalPosition1 * fontSize };
|
||||
|
||||
Log::Comment(L" --- Click on the terminal at 0,5 ---");
|
||||
|
||||
interactivity->PointerPressed(leftMouseDown,
|
||||
WM_LBUTTONDOWN, //pointerUpdateKind
|
||||
0, // timestamp
|
||||
modifiers,
|
||||
cursorPosition0.to_core_point());
|
||||
VERIFY_IS_FALSE(core->HasSelection());
|
||||
|
||||
Log::Comment(L" --- Drag to 5,5 ---");
|
||||
|
||||
interactivity->PointerMoved(leftMouseDown,
|
||||
WM_LBUTTONDOWN, //pointerUpdateKind
|
||||
modifiers,
|
||||
true, // focused,
|
||||
cursorPosition1.to_core_point(),
|
||||
true); // pointerPressedInBounds
|
||||
VERIFY_IS_TRUE(core->HasSelection());
|
||||
// expectedCopyContents being nullopt here will ensure that we don't send the copy event till the pointer released
|
||||
|
||||
Log::Comment(L" --- Release the mouse --- ");
|
||||
expectedCopyContents = L"line 5";
|
||||
interactivity->PointerReleased(noMouseDown,
|
||||
WM_LBUTTONUP, //pointerUpdateKind
|
||||
modifiers,
|
||||
cursorPosition1.to_core_point());
|
||||
VERIFY_IS_TRUE(core->HasSelection());
|
||||
|
||||
// Output some text
|
||||
for (; i < 5; ++i)
|
||||
{
|
||||
conn->WriteInput(winrt::hstring{ fmt::format(L"line {}\r\n", i) });
|
||||
}
|
||||
|
||||
Log::Comment(L" --- Right-click to paste --- ");
|
||||
expectedCopyContents = std::nullopt;
|
||||
expectedPaste = true;
|
||||
interactivity->PointerPressed(rightMouseDown,
|
||||
WM_RBUTTONDOWN, //pointerUpdateKind
|
||||
0, // timestamp
|
||||
modifiers,
|
||||
cursorPosition1.to_core_point());
|
||||
VERIFY_IS_FALSE(core->HasSelection());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user