Compare commits

...

4 Commits

Author SHA1 Message Date
Mike Griese
eaf72153e7 Merge remote-tracking branch 'origin/main' into dev/migrie/b/14464-copyOnSelect-moving-text 2023-01-13 15:07:28 -06:00
Mike Griese
ca658ba331 Fix the bug 2023-01-05 14:19:28 -06:00
Mike Griese
45b3e8d4f8 some tests that fail, intentionally 2023-01-05 13:51:26 -06:00
Mike Griese
2ec30ef270 this is a basic copyOnSelect test, for reference, for starting more tests 2023-01-05 12:01:12 -06:00
2 changed files with 196 additions and 3 deletions

View File

@@ -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

View File

@@ -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());
}
}