diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 7b59babd2e..f18851c2fb 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -329,7 +329,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _touchAnchor = contactPoint; } - void ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState, + bool ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, @@ -337,11 +337,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool pointerPressedInBounds) { const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }); + // Returning true from this function indicates that the caller should do no further processing of this movement. + bool handledCompletely = false; // Short-circuit isReadOnly check to avoid warning dialog if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { _sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState); + handledCompletely = true; } // GH#4603 - don't modify the selection if the pointer press didn't // actually start _in_ the control bounds. Case in point - someone drags @@ -378,6 +381,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } _core->SetHoveredCell(terminalPosition.to_core_point()); + return handledCompletely; } void ControlInteractivity::TouchMoved(const Core::Point newTouchPoint, @@ -682,13 +686,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const SHORT wheelDelta, Control::MouseButtonState buttonState) { - const auto adjustment = _core->ScrollOffset() > 0 ? _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight() : 0; - // If the click happened outside the active region, just don't send any mouse event - if (const auto adjustedY = terminalPosition.y - adjustment; adjustedY >= 0) - { - return _core->SendMouseEvent({ terminalPosition.x, adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState)); - } - return false; + const auto adjustment = _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight(); + // If the click happened outside the active region, core should get a chance to filter it out or clamp it. + const auto adjustedY = terminalPosition.y - adjustment; + return _core->SendMouseEvent({ terminalPosition.x, adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState)); } // Method Description: diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 38789827ec..22eaa95c39 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -58,7 +58,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const Core::Point pixelPosition); void TouchPressed(const Core::Point contactPoint); - void PointerMoved(Control::MouseButtonState buttonState, + bool PointerMoved(Control::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, diff --git a/src/cascadia/TerminalControl/ControlInteractivity.idl b/src/cascadia/TerminalControl/ControlInteractivity.idl index d1ca9720dc..926c1e3b0a 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.idl +++ b/src/cascadia/TerminalControl/ControlInteractivity.idl @@ -43,12 +43,12 @@ namespace Microsoft.Terminal.Control Microsoft.Terminal.Core.Point pixelPosition); void TouchPressed(Microsoft.Terminal.Core.Point contactPoint); - void PointerMoved(MouseButtonState buttonState, - UInt32 pointerUpdateKind, - Microsoft.Terminal.Core.ControlKeyStates modifiers, - Boolean focused, - Microsoft.Terminal.Core.Point pixelPosition, - Boolean pointerPressedInBounds); + Boolean PointerMoved(MouseButtonState buttonState, + UInt32 pointerUpdateKind, + Microsoft.Terminal.Core.ControlKeyStates modifiers, + Boolean focused, + Microsoft.Terminal.Core.Point pixelPosition, + Boolean pointerPressedInBounds); void TouchMoved(Microsoft.Terminal.Core.Point newTouchPoint, Boolean focused); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 3e447d5784..8c2a37e7d2 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1936,18 +1936,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (type == Windows::Devices::Input::PointerDeviceType::Mouse || type == Windows::Devices::Input::PointerDeviceType::Pen) { - _interactivity.PointerMoved(TermControl::GetPressedMouseButtons(point), - TermControl::GetPointerUpdateKind(point), - ControlKeyStates(args.KeyModifiers()), - _focused, - pixelPosition.to_core_point(), - _pointerPressedInBounds); + auto suppressFurtherHandling = _interactivity.PointerMoved(TermControl::GetPressedMouseButtons(point), + TermControl::GetPointerUpdateKind(point), + ControlKeyStates(args.KeyModifiers()), + _focused, + pixelPosition.to_core_point(), + _pointerPressedInBounds); // GH#9109 - Only start an auto-scroll when the drag actually // started within our bounds. Otherwise, someone could start a drag // outside the terminal control, drag into the padding, and trick us // into starting to scroll. - if (_focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed()) + if (!suppressFurtherHandling && _focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed()) { // We want to find the distance relative to the bounds of the // SwapChainPanel, not the entire control. If they drag out of diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index a5d443b915..49fcd6d21e 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -998,16 +998,15 @@ namespace ControlUnitTests VERIFY_IS_GREATER_THAN(core->ScrollOffset(), 0); // Viewport is now above the mutable viewport, so the mouse event - // straight up won't be sent to the terminal. + // will be clamped to the top line. - expectedOutput.push_back(L"sentinel"); // Clearly, it won't be this string + expectedOutput.push_back(L"\x1b[M &!"); // 5, 1 interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind 0, // timestamp modifiers, cursorPosition0.to_core_point()); // Flush it out. - conn->WriteInput(winrt_wstring_to_array_view(L"sentinel")); VERIFY_ARE_EQUAL(0u, expectedOutput.size(), L"Validate we drained all the expected output"); // This is the part as mentioned in GH#12719