diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp index 1bcd31a3b71d..c71accc8f3dc 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp @@ -38,6 +38,9 @@ LRESULT CALLBACK HwndTerminal::HwndTerminalWndProc( case WM_LBUTTONDOWN: LOG_IF_FAILED(terminal->_StartSelection(lParam)); return 0; + case WM_LBUTTONUP: + terminal->_singleClickTouchdownPos = std::nullopt; + break; case WM_MOUSEMOVE: if (WI_IsFlagSet(wParam, MK_LBUTTON)) { @@ -351,23 +354,17 @@ void _stdcall TerminalUserScroll(void* terminal, int viewTop) HRESULT HwndTerminal::_StartSelection(LPARAM lParam) noexcept try { - const bool altPressed = GetKeyState(VK_MENU) < 0; - COORD cursorPosition{ + const til::point cursorPosition{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), }; - const auto fontSize = this->_actualFont.GetSize(); - - RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.X == 0); - RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.Y == 0); - - cursorPosition.X /= fontSize.X; - cursorPosition.Y /= fontSize.Y; - - this->_terminal->SetSelectionAnchor(cursorPosition); + auto lock = _terminal->LockForWriting(); + const bool altPressed = GetKeyState(VK_MENU) < 0; this->_terminal->SetBlockSelection(altPressed); + this->_terminal->ClearSelection(); + _singleClickTouchdownPos = cursorPosition; this->_renderer->TriggerSelection(); return S_OK; @@ -377,20 +374,29 @@ CATCH_RETURN(); HRESULT HwndTerminal::_MoveSelection(LPARAM lParam) noexcept try { - COORD cursorPosition{ + const til::point cursorPosition{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), }; - const auto fontSize = this->_actualFont.GetSize(); + auto lock = _terminal->LockForWriting(); + const til::size fontSize{ this->_actualFont.GetSize() }; - RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.X == 0); - RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.Y == 0); + RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.area() == 0); // either dimension = 0, area == 0 - cursorPosition.X /= fontSize.X; - cursorPosition.Y /= fontSize.Y; + if (this->_singleClickTouchdownPos) + { + const auto& touchdownPoint{ *this->_singleClickTouchdownPos }; + auto distance{ std::sqrtf(std::powf(cursorPosition.x() - touchdownPoint.x(), 2) + std::powf(cursorPosition.y() - touchdownPoint.y(), 2)) }; + if (distance >= (std::min(fontSize.width(), fontSize.height()) / 4.f)) + { + _terminal->SetSelectionAnchor(touchdownPoint / fontSize); + // stop tracking the touchdown point + _singleClickTouchdownPos = std::nullopt; + } + } - this->_terminal->SetSelectionEnd(cursorPosition); + this->_terminal->SetSelectionEnd(cursorPosition / fontSize); this->_renderer->TriggerSelection(); return S_OK; diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.hpp b/src/cascadia/PublicTerminalCore/HwndTerminal.hpp index 3e03cf94b1a0..bc2ea0a8e3a3 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.hpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.hpp @@ -75,6 +75,8 @@ struct HwndTerminal : ::Microsoft::Console::Types::IControlAccessibilityInfo std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; + std::optional _singleClickTouchdownPos; + friend HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal); friend HRESULT _stdcall TerminalResize(void* terminal, COORD dimensions); friend void _stdcall TerminalDpiChanged(void* terminal, int newDpi);