Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/ControlCore.idl
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ namespace Microsoft.Terminal.Control
void ToggleMarkMode();
Boolean SwitchSelectionEndpoint();
Boolean ExpandSelectionToWord();
Boolean IsVtMouseModeEnabled();
void ClearBuffer(ClearBufferType clearType);

void SetHoveredCell(Microsoft.Terminal.Core.Point terminalPosition);
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalControl/ControlInteractivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
}
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsMiddleButtonDown))
{
const auto action = _core->Settings().MiddleClickAction();
if (action == Control::MiddleClickAction::Paste)
{
RequestPasteTextFromClipboard();
}
}
}

void ControlInteractivity::TouchPressed(const Core::Point contactPoint)
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalControl/IControlSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ namespace Microsoft.Terminal.Control
MinGW,
};

enum MiddleClickAction
{
Pan = 0,
Paste,
None,
};

// Class Description:
// TerminalSettings encapsulates all settings that control the
// TermControl's behavior. In these settings there is both the entirety
Expand Down Expand Up @@ -77,6 +84,7 @@ namespace Microsoft.Terminal.Control

PathTranslationStyle PathTranslationStyle { get; };
String DragDropDelimiter { get; };
Microsoft.Terminal.Control.MiddleClickAction MiddleClickAction { get; };

// NOTE! When adding something here, make sure to update ControlProperties.h too!
};
Expand Down
54 changes: 52 additions & 2 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
else
{
const auto cursorPosition = point.Position();
if (point.Properties().IsMiddleButtonPressed() && !_core.IsVtMouseModeEnabled())
{
const auto action = _core.Settings().MiddleClickAction();
if (action == Control::MiddleClickAction::Pan)
{
_isPanning = true;
_panningAnchorPos = cursorPosition;
}
}
_interactivity.PointerPressed(point.PointerId(),
TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
Expand All @@ -2019,7 +2028,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}

RestorePointerCursor.raise(*this, nullptr);
if (!_isPanning)
{
RestorePointerCursor.raise(*this, nullptr);
}

const auto ptr = args.Pointer();
const auto point = args.GetCurrentPoint(*this);
Expand All @@ -2041,11 +2053,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
ControlKeyStates(args.KeyModifiers()),
pixelPosition);

if (_isPanning && _panningAnchorPos)
{
const auto dy = cursorPosition.Y - _panningAnchorPos->Y;
constexpr auto MinPanDist = 5.0;

if (const auto window = CoreWindow::GetForCurrentThread())
{
if (std::abs(dy) > MinPanDist)
{
window.PointerCursor(CoreCursor(CoreCursorType::SizeNorthSouth, 1));
}
else
{
window.PointerCursor(CoreCursor(CoreCursorType::SizeAll, 1));
}
}

if (std::abs(dy) > MinPanDist)
{
const auto scrollDist = dy > 0 ? (dy - MinPanDist) : (dy + MinPanDist);
const auto newVelocity = _GetAutoScrollSpeed(std::abs(scrollDist)) * (dy > 0 ? 1.0 : -1.0);
_TryStartAutoScroll(point, newVelocity);
}
else
{
_TryStopAutoScroll(ptr.PointerId());
}
}
// 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 (!suppressFurtherHandling && _focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed())
else 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
Expand Down Expand Up @@ -2124,6 +2164,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_interactivity.TouchReleased();
}

if (_isPanning)
{
_isPanning = false;
_panningAnchorPos = std::nullopt;
if (const auto window = CoreWindow::GetForCurrentThread())
{
window.PointerCursor(CoreCursor(CoreCursorType::IBeam, 1));
}
}

_TryStopAutoScroll(ptr.PointerId());

args.Handled(true);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SafeDispatcherTimer _autoScrollTimer;
std::optional<std::chrono::high_resolution_clock::time_point> _lastAutoScrollUpdateTime;
bool _pointerPressedInBounds{ false };
bool _isPanning{ false };
std::optional<Windows::Foundation::Point> _panningAnchorPos;

winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellLightAnimation{ nullptr };
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellDarkAnimation{ nullptr };
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/EnumMappings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::IntenseStyle, IntenseTextStyle);
DEFINE_ENUM_MAP(Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors);
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle);
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::MiddleClickAction, MiddleClickAction);

// Actions
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::ResizeDirection, ResizeDirection);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/EnumMappings.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle> IntenseTextStyle();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Core::AdjustTextMode> AdjustIndistinguishableColors();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::PathTranslationStyle> PathTranslationStyle();
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::MiddleClickAction> MiddleClickAction();

// Actions
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::ResizeDirection> ResizeDirection();
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/EnumMappings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Microsoft.Terminal.Settings.Model
static Windows.Foundation.Collections.IMap<String, UInt16> FontWeight { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.IntenseStyle> IntenseTextStyle { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.PathTranslationStyle> PathTranslationStyle { get; };
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.MiddleClickAction> MiddleClickAction { get; };

// Actions
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.ResizeDirection> ResizeDirection { get; };
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalSettingsModel/MTSMSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ Author(s):
X(bool, AllowOscNotifications, "compatibility.allowOSC777", false) \
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false) \
X(hstring, DragDropDelimiter, "dragDropDelimiter", L" ") \
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None)
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None) \
X(Microsoft::Terminal::Control::MiddleClickAction, MiddleClickAction, "experimental.middleClickAction", Microsoft::Terminal::Control::MiddleClickAction::Pan)

// Intentionally omitted Profile settings:
// * Name
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/Profile.idl
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,6 @@ namespace Microsoft.Terminal.Settings.Model

INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
INHERITABLE_PROFILE_SETTING(String, DragDropDelimiter);
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.MiddleClickAction, MiddleClickAction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,15 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::PathTranslationStyle)
};
};

JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::MiddleClickAction)
{
static constexpr std::array<pair_type, 3> mappings = {
pair_type{ "pan", ValueType::Pan },
pair_type{ "paste", ValueType::Paste },
pair_type{ "none", ValueType::None },
};
};

JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste)
{
JSON_MAPPINGS(3) = {
Expand Down
29 changes: 29 additions & 0 deletions src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace ControlUnitTests

TEST_METHOD(GetMouseEventsInTest);
TEST_METHOD(AltBufferClampMouse);
TEST_METHOD(TestMiddleClick);

TEST_CLASS_SETUP(ClassSetup)
{
Expand Down Expand Up @@ -1070,4 +1071,32 @@ namespace ControlUnitTests
cursorPosition1.to_core_point());
VERIFY_ARE_EQUAL(0u, expectedOutput.size(), L"Validate we drained all the expected output");
}

void ControlInteractivityTests::TestMiddleClick()
{
WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{};

auto [settings, conn] = _createSettingsAndConnection();
auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn);
_standardInit(core, interactivity);

const auto modifiers = ControlKeyStates();
const auto midMouseDown{ Control::MouseButtonState::IsMiddleButtonDown };

bool pasteRequested = false;
interactivity->PasteFromClipboard([&](auto&&, auto&&) {
pasteRequested = true;
});

settings->MiddleClickAction(Control::MiddleClickAction::Paste);

interactivity->PointerPressed(0,
midMouseDown,
WM_MBUTTONDOWN,
0,
modifiers,
Core::Point{ 0, 0 });

VERIFY_IS_TRUE(pasteRequested);
}
}
3 changes: 2 additions & 1 deletion src/cascadia/inc/ControlProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,5 @@
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0) \
X(bool, RightClickContextMenu, false) \
X(winrt::Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle::None) \
X(winrt::hstring, DragDropDelimiter, L" ")
X(winrt::hstring, DragDropDelimiter, L" ") \
X(winrt::Microsoft::Terminal::Control::MiddleClickAction, MiddleClickAction, winrt::Microsoft::Terminal::Control::MiddleClickAction::Pan)
Loading