Skip to content

Commit

Permalink
Fix click-drag selection on an unfocused Terminal (#4506)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request
This PR tries to address some of the weird interactions with pointer pressed events when the Terminal isn't in focus. Here's the four things that have changed as part of this PR;

1. This PR will allow the user to be able to make a selection with a click-drag without having to first perform a single click on a tab/pane to bring it to focus. 
2. Another weird bug that's fixed in this PR is where trying to make a selection on an unfocused tab when it already has a selection active will simply extend the existing selection instead of making a new one.
3. Not related to the issue that his PR closes: a right click will now focus the tab/pane.

I've made sure that we still have the existing functionality where a single click on an unfocused tab/pane does not make a single-cell selection and just focuses the tab/pane.

## PR Checklist
* [x] Closes #4282
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed

## Validation Steps Performed
Played around with all sorts of selection when in-focus and out of focus with multiple panes and tabs.
Unit tests still pass as well.
  • Loading branch information
leonMSFT authored Feb 13, 2020
1 parent c05ad5d commit 7836da0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
42 changes: 33 additions & 9 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,17 +886,20 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
const auto ptr = args.Pointer();
const auto point = args.GetCurrentPoint(_root);

if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
if (!_focused)
{
// Ignore mouse events while the terminal does not have focus.
// This prevents the user from selecting and copying text if they
// click inside the current tab to refocus the terminal window.
if (!_focused)
{
args.Handled(true);
return;
}
Focus(FocusState::Pointer);

// Save the click position here when the terminal does not have focus
// because they might be performing a click-drag selection. Since we
// only want to start the selection when the user moves the pointer with
// the left mouse button held down, the PointerMovedHandler will use
// this saved position to set the SelectionAnchor.
_clickDragStartPos = point.Position();
}

if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
{
const auto modifiers = static_cast<uint32_t>(args.KeyModifiers());
// static_cast to a uint32_t because we can't use the WI_IsFlagSet
// macro directly with a VirtualKeyModifiers
Expand All @@ -905,6 +908,16 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

if (point.Properties().IsLeftButtonPressed())
{
// _clickDragStartPos having a value signifies to us that
// the user clicked on an unfocused terminal. We don't want
// a single left click from out of focus to start a selection,
// so we return fast here.
if (_clickDragStartPos)
{
args.Handled(true);
return;
}

const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);

Expand Down Expand Up @@ -981,6 +994,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
if (point.Properties().IsLeftButtonPressed())
{
// If this does not have a value, it means that PointerPressedHandler already
// set the SelectionAnchor. If it does have a value, that means the user is
// performing a click-drag selection on an unfocused terminal, so
// a SelectionAnchor isn't set yet. We'll have to set it here.
if (_clickDragStartPos)
{
_terminal->SetSelectionAnchor(_GetTerminalPosition(*_clickDragStartPos));
}

const auto cursorPosition = point.Position();
_SetEndSelectionPointAtCursor(cursorPosition);

Expand Down Expand Up @@ -1053,6 +1075,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

const auto ptr = args.Pointer();

_clickDragStartPos = std::nullopt;

if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
{
const auto modifiers = static_cast<uint32_t>(args.KeyModifiers());
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
Timestamp _lastMouseClick;
unsigned int _multiClickCounter;
std::optional<winrt::Windows::Foundation::Point> _lastMouseClickPos;
std::optional<winrt::Windows::Foundation::Point> _clickDragStartPos{ std::nullopt };

// Event revokers -- we need to deregister ourselves before we die,
// lest we get callbacks afterwards.
Expand Down

0 comments on commit 7836da0

Please sign in to comment.