Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for resizing panes with mouse #16895

Open
wants to merge 125 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
f353323
I wanted to do this in one shot but _zelda_
zadjii-msft May 12, 2023
4e14442
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Jul 17, 2023
ef6bb8a
hey look, it builds now
zadjii-msft Jul 17, 2023
5b3aa54
move GetNewTerminalArgs into IPaneContent
zadjii-msft Jul 17, 2023
84df819
close event
zadjii-msft Jul 17, 2023
7c9ffb0
snapping now uses an interface, so that it's not TermControl-specific
zadjii-msft Jul 18, 2023
a1da6c1
huge shuffling so that pane content can raise events instead of relyi…
zadjii-msft Jul 18, 2023
049c043
some last cleanups
zadjii-msft Jul 18, 2023
2dd8f40
[TO PARENT] dead code
zadjii-msft Jul 18, 2023
1b39db7
Single commit that adds the whole scratchpad and action
zadjii-msft Jul 18, 2023
63ba8e1
[PARENT] You know what, I just went for it.
zadjii-msft Jul 18, 2023
262d95a
[PARENT] try to use GetActiveTerminalControl less in TerminalTab
zadjii-msft Jul 18, 2023
2d40306
Let's just make it experimental
zadjii-msft Jul 18, 2023
e6dc314
Merge commit 'b4042ea' into dev/migrie/fhl/non-terminal-panes-2023
zadjii-msft Jul 19, 2023
e31202b
Merge commit '6a10ea5' into dev/migrie/fhl/non-terminal-panes-2023
zadjii-msft Jul 20, 2023
11126f9
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Jul 20, 2023
5f9add4
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Jul 20, 2023
a23c1a2
keybindings too
zadjii-msft Jul 20, 2023
5582e1b
[PARENT] You know what, I just went for it.
zadjii-msft Jul 18, 2023
f89368c
[PARENT] try to use GetActiveTerminalControl less in TerminalTab
zadjii-msft Jul 18, 2023
e0b003a
Merge branch 'main' into dev/migrie/fhl/non-terminal-panes-2023
zadjii-msft Jul 24, 2023
86914bd
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Jul 25, 2023
1cc9835
feature flags too
zadjii-msft Jul 27, 2023
cbd61b0
POC: yea, this works
zadjii-msft Jul 27, 2023
29d0d57
this works better than it has any right to
zadjii-msft Jul 27, 2023
fb7c809
derp
zadjii-msft Aug 1, 2023
842326d
icons for non-terminal pane content
zadjii-msft Aug 3, 2023
521e301
update settings should work now
zadjii-msft Aug 3, 2023
9531069
background brush, done
zadjii-msft Aug 7, 2023
c869b47
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Sep 11, 2023
46469aa
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Sep 11, 2023
6107c3e
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Sep 11, 2023
2086e0f
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Oct 13, 2023
b49997b
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Oct 13, 2023
57e1f26
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Oct 13, 2023
d726165
terrible, but it works
zadjii-msft Oct 13, 2023
e82c627
dead code removal
zadjii-msft Oct 13, 2023
81889a6
derp
zadjii-msft Oct 13, 2023
5f4087f
finish exorcising SettingsTab
zadjii-msft Oct 13, 2023
fb74fc8
dead code
zadjii-msft Oct 13, 2023
fd06409
annoying build break
zadjii-msft Oct 13, 2023
8df9523
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Oct 25, 2023
58e8f3c
mostly nits
zadjii-msft Oct 25, 2023
e9e04d4
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Oct 25, 2023
7bc1457
nits and such
zadjii-msft Oct 25, 2023
dd8606f
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Oct 25, 2023
389ba20
spel
zadjii-msft Oct 25, 2023
cf920e7
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Nov 2, 2023
4cec7e9
try to remove a few of these but ultimately, eh
zadjii-msft Nov 6, 2023
f622d80
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Nov 8, 2023
6bc711d
maybe I'm not that good at coding
zadjii-msft Nov 8, 2023
0d528f8
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Jan 19, 2024
3982358
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Feb 8, 2024
c244633
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Feb 8, 2024
092b355
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Feb 8, 2024
de5f7af
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Feb 28, 2024
25a8851
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Feb 28, 2024
17075d6
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Feb 28, 2024
0a11643
sanely pass around a cache instead of... whatever that was.
zadjii-msft Mar 4, 2024
4d47cd5
cleanup
zadjii-msft Mar 4, 2024
254f3ee
this does resize panes but as noted, DPI is wack
zadjii-msft Mar 5, 2024
38f30c3
horizontal <---> resizing works great
zadjii-msft Mar 5, 2024
04870c9
this totally works, except for the parent pane
zadjii-msft Mar 5, 2024
7a27354
this double-notifies the parent again, but again, not the end of the …
zadjii-msft Mar 5, 2024
112cdf5
this seems to work, but only on the right/bottom edges of a pane. Nev…
zadjii-msft Mar 5, 2024
67c1128
commenting out a lot of failed ideas
zadjii-msft Mar 5, 2024
93a789c
This almost works right
zadjii-msft Mar 5, 2024
18bd6a8
OMG this is so close. the _Resize instead of ResizePane is LOAD-BEARING
zadjii-msft Mar 7, 2024
91a0d0e
GREAT-GRANDPARENT: This fixes a crash in parent pane selection
zadjii-msft Mar 7, 2024
47b06e0
GAH this is SO close.
zadjii-msft Mar 7, 2024
8f89dd4
Again, even closer, but now the middle bottom left pane doesn't resiz…
zadjii-msft Mar 7, 2024
921c94b
cleanup before I blow it all up
zadjii-msft Mar 7, 2024
63ad45a
endless joy. This is so much more elegant
zadjii-msft Mar 7, 2024
ba5fab4
beautiful elegance
zadjii-msft Mar 7, 2024
5e5e13e
VERY IMPORTANT
zadjii-msft Mar 7, 2024
032d15f
Trying to figure out why the drag starting in the control continues i…
zadjii-msft Mar 7, 2024
6ba704d
a thought
zadjii-msft Mar 7, 2024
b6254f8
GREAT-GRANDPARENT: This fixes a crash in parent pane selection
zadjii-msft Mar 7, 2024
a3fbc64
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Mar 8, 2024
35651bc
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 8, 2024
978fd6e
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 8, 2024
ef775a8
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Mar 18, 2024
524d658
GREAT-GREAT-GRANDPARENT: Hey when a pane wants to get closed, we shou…
zadjii-msft Mar 15, 2024
1951f30
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 18, 2024
863840e
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 18, 2024
dde4d0d
AHAHAHA IT WORKS
zadjii-msft Mar 18, 2024
36cefec
comments, comments, comments
zadjii-msft Mar 18, 2024
77d56e0
dead code
zadjii-msft Mar 18, 2024
6bf09df
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Mar 19, 2024
6789ec0
some of the easier nits
zadjii-msft Mar 19, 2024
fd8b083
get rid of this file
zadjii-msft Mar 19, 2024
052dc78
more nits
zadjii-msft Mar 19, 2024
a7533fa
eh these events are from pane content anyways!
zadjii-msft Mar 19, 2024
826fc08
hey there buddy, did you get lost?
zadjii-msft Mar 19, 2024
52970ef
RegisterBigTimeEncapsulationViolatingTerminalPaneContentEvents
zadjii-msft Mar 19, 2024
2357653
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 20, 2024
c8d0c0a
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 20, 2024
0946a43
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Mar 20, 2024
e0bb840
Fix scratch pane for merge
zadjii-msft Mar 20, 2024
352e0a2
fix settings pane for merge
zadjii-msft Mar 20, 2024
bcceb85
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 20, 2024
7300b5b
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Mar 20, 2024
2083b2f
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Mar 21, 2024
f1ab16e
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 21, 2024
77022e9
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 21, 2024
4f77204
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Mar 21, 2024
df73d75
derp
zadjii-msft Mar 21, 2024
d417934
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 21, 2024
216cc3f
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 21, 2024
a0d62ab
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Mar 21, 2024
61e952c
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/non-te…
zadjii-msft Mar 26, 2024
0979cd6
Merge branch 'dev/migrie/fhl/non-terminal-panes-2023' into dev/migrie…
zadjii-msft Mar 26, 2024
b6e4b62
Doesn't really need to be projected
zadjii-msft Mar 26, 2024
1d20599
un fix this file
zadjii-msft Mar 26, 2024
ddc88c8
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 26, 2024
10e1e46
ALSO doesn't really need to be projected
zadjii-msft Mar 26, 2024
7243d22
Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/scratc…
zadjii-msft Mar 26, 2024
ef560bf
Merge branch 'dev/migrie/fhl/scratchpad-pane' into dev/migrie/f/sui-p…
zadjii-msft Mar 26, 2024
e05b2bb
Merge branch 'main' into dev/migrie/f/sui-panes
zadjii-msft Mar 29, 2024
a0e014f
Merge remote-tracking branch 'origin/main' into dev/migrie/f/sui-panes
zadjii-msft Apr 3, 2024
7c4dfff
Merge remote-tracking branch 'origin/main' into dev/migrie/f/sui-panes
zadjii-msft Apr 3, 2024
96c6a44
Merge branch 'dev/migrie/f/sui-panes' into dev/migrie/f/992-redux-redux
zadjii-msft Apr 3, 2024
194f37e
well, definitely this
zadjii-msft Apr 3, 2024
aa6f9bc
derp;
zadjii-msft Apr 4, 2024
26a1ed5
Merge branch 'main' into dev/migrie/f/992-redux-redux
zadjii-msft Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
219 changes: 213 additions & 6 deletions src/cascadia/TerminalApp/Pane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ Pane::Pane(const IPaneContent& content, const bool lastFocused) :
_lostFocusRevoker = control.LostFocus(winrt::auto_revoke, { this, &Pane::_ContentLostFocusHandler });
}

_manipulationDeltaRevoker = _root.ManipulationDelta(winrt::auto_revoke, { this, &Pane::_ManipulationDeltaHandler });
_manipulationStartedRevoker = _root.ManipulationStarted(winrt::auto_revoke, { this, &Pane::_ManipulationStartedHandler });

// When our border is tapped, make sure to transfer focus to our control.
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
// Colors::Transparent! The border won't get Tapped events, and they'll fall
Expand Down Expand Up @@ -73,6 +76,8 @@ Pane::Pane(std::shared_ptr<Pane> first,
_root.Children().Append(_borderFirst);
_root.Children().Append(_borderSecond);

_manipulationDeltaRevoker = _root.ManipulationDelta(winrt::auto_revoke, { this, &Pane::_ManipulationDeltaHandler });

_ApplySplitDefinitions();

// Register event handlers on our children to handle their Close events
Expand Down Expand Up @@ -243,14 +248,13 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t n
// decreasing the size of our first child.
// Return Value:
// - false if we couldn't resize this pane in the given direction, else true.
bool Pane::_Resize(const ResizeDirection& direction)
bool Pane::_Resize(const ResizeDirection& direction, float amount)
{
if (!DirectionMatchesSplit(direction, _splitState))
{
return false;
}

auto amount = .05f;
if (direction == ResizeDirection::Right || direction == ResizeDirection::Down)
{
amount = -amount;
Expand Down Expand Up @@ -284,7 +288,7 @@ bool Pane::_Resize(const ResizeDirection& direction)
// - direction: The direction to move the separator in.
// Return Value:
// - true if we or a child handled this resize request.
bool Pane::ResizePane(const ResizeDirection& direction)
bool Pane::ResizePane(const ResizeDirection& direction, float amount)
{
// If we're a leaf, do nothing. We can't possibly have a descendant with a
// separator the correct direction.
Expand All @@ -301,7 +305,7 @@ bool Pane::ResizePane(const ResizeDirection& direction)
const auto secondIsFocused = _secondChild->_lastActive;
if (firstIsFocused || secondIsFocused)
{
return _Resize(direction);
return _Resize(direction, amount);
}

// If neither of our children were the focused pane, then recurse into
Expand All @@ -315,17 +319,200 @@ bool Pane::ResizePane(const ResizeDirection& direction)
// either.
if ((!_firstChild->_IsLeaf()) && _firstChild->_HasFocusedChild())
{
return _firstChild->ResizePane(direction) || _Resize(direction);
return _firstChild->ResizePane(direction, amount) || _Resize(direction, amount);
}

if ((!_secondChild->_IsLeaf()) && _secondChild->_HasFocusedChild())
{
return _secondChild->ResizePane(direction) || _Resize(direction);
return _secondChild->ResizePane(direction, amount) || _Resize(direction, amount);
}

return false;
}

// Handler for the _root's ManipulationStarted event. We use this to check if a
// manipulation (read: drag) started inside our content. If it did, we _don't_
// want to do our normal pane dragging.
//
// Consider the case that the TermControl might be selecting text, and the user
// drags the mouse over the pane border. We don't want that to start moving the
// border!
void Pane::_ManipulationStartedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::UI::Xaml::Input::ManipulationStartedRoutedEventArgs& args)
{
// This is added to each _root. But it also bubbles, so only leaves should actually try to handle this.
if (args.Handled())
{
return;
}
args.Handled(true);

assert(_IsLeaf());

const auto contentSize = _content.GetRoot().ActualSize();
auto transformCurrentPos = args.Position();
auto transformOrigin = transformCurrentPos;

const auto transform_contentFromOurRoot = _root.TransformToVisual(_content.GetRoot());
const auto transformInControlSpace = transform_contentFromOurRoot.TransformPoint(transformOrigin);

// If we clicked on the control. bail, and don't allow any manipulations
// for this series of events.
_shouldManipulate = !((transformInControlSpace.X >= 0 && transformInControlSpace.X < contentSize.x) &&
(transformInControlSpace.Y >= 0 && transformInControlSpace.Y < contentSize.y));
}

// Handler for the _root's ManipulationDelta event. This is the event raised
// when a user clicks and drags somewhere inside the pane. We're going to use
// this to determine if the user clicked on one of our borders. If they did,
// we're going to need to ask our parent pane (or other ancestors) to resize
// their split.
//
// Recall that a leaf itself is responsible for having the right borders, but it
// is the parent of the leaf that actually controls how big a split is.
//
// When we do want to be resized, we'll pass the delta from this event upwards
// via ManipulationRequested, which will be handled in
// Pane::_handleOrBubbleManipulation.
void Pane::_ManipulationDeltaHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs& args)
{
// sender is ORIGINALLY the root Grid of a leaf, and the leaf may or may not
// have a border.
if (args.Handled())
{
return;
}
if (!_shouldManipulate)
{
// Using our stored _shouldManipulate set up in
// _ManipulationStartedHandler, bail if the manipulation didn't start
// _on the border_.
return;
}

assert(_IsLeaf());

const auto delta = args.Delta().Translation;
const auto transformOrigin = args.Position();

const auto contentSize = _content.GetRoot().ActualSize();

const auto transform_contentFromOurRoot = _root.TransformToVisual(_content.GetRoot());
// This is the position of the drag relative to the bounds of our content.
const auto transformInControlSpace = transform_contentFromOurRoot.TransformPoint(transformOrigin);

// Did we click somewhere in the bounds of our content?
if ((transformInControlSpace.X >= 0 && transformInControlSpace.X < contentSize.x) &&
(transformInControlSpace.Y >= 0 && transformInControlSpace.Y < contentSize.y))
{
// We did! Bail.
return;
}

// Now, we know we clicked somewhere outside the bounds of our content. Set
// border flags based on the side that was clicked on.
Borders clicked = Borders::None;
clicked |= (transformInControlSpace.X < 0) ? Borders::Left : Borders::None;
clicked |= (transformInControlSpace.Y < 0) ? Borders::Top : Borders::None;
clicked |= (transformInControlSpace.X > contentSize.x) ? Borders::Right : Borders::None;
clicked |= (transformInControlSpace.Y > contentSize.y) ? Borders::Bottom : Borders::None;

// Ask our parent to resize their split.
ManipulationRequested.raise(shared_from_this(), delta, clicked);
}

// Handler for our child's own ManipulationRequested event. They will pass to us
// (their immediate parent) the delta and the side that was clicked on.
// * If we control that border, then we'll handle the resize ourself in _handleManipulation.
// * If not, then we'll ask our own parent to try and resize that same border.
void Pane::_handleOrBubbleManipulation(std::shared_ptr<Pane> sender,
const winrt::Windows::Foundation::Point delta,
Borders side)
{
if (side == Borders::None || _splitState == SplitState::None)
{
return;
}

const bool isFirstChild = sender == _firstChild;
// We want to handle this drag in the following cases
// * In a vertical split: if we're dragging the right of the first pane or the left of the second
// * In a horizontal split: if we're dragging the bottom of the first pane or the top of the second
const auto sideMatched = (_splitState == SplitState::Vertical) ? (isFirstChild && WI_IsFlagSet(side, Borders::Right)) || (!isFirstChild && WI_IsFlagSet(side, Borders::Left)) :
(_splitState == SplitState::Horizontal) ? (isFirstChild && WI_IsFlagSet(side, Borders::Bottom)) || (!isFirstChild && WI_IsFlagSet(side, Borders::Top)) :
false;

if (sideMatched)
{
_handleManipulation(delta);
}
else
{
// Bubble, with us as the new sender.
ManipulationRequested.raise(shared_from_this(), delta, side);
}
}

// Actually handle resizing our split in response to a drag event. If we're
// being called, then we know that the delta that's passed to us should be
// applied to our own split. The delta that's passed in here is in PIXELS, not
// DIPs.
void Pane::_handleManipulation(const winrt::Windows::Foundation::Point delta)
{
const auto scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();

const auto weAreVertical = _splitState == SplitState::Vertical;
const winrt::Windows::Foundation::Point translationForUs = (weAreVertical) ? Point{ delta.X, 0 } : Point{ 0, delta.Y };

// Decide on direction based on delta
ResizeDirection dir = ResizeDirection::None;
if (_splitState == SplitState::Vertical)
{
if (translationForUs.X < 0)
{
dir = ResizeDirection::Left;
}
else if (translationForUs.X > 0)
{
dir = ResizeDirection::Right;
}
}
else if (_splitState == SplitState::Horizontal)
{
if (translationForUs.Y < 0)
{
dir = ResizeDirection::Up;
}
else if (translationForUs.Y > 0)
{
dir = ResizeDirection::Down;
}
}

// Resize in the given direction
if (dir != ResizeDirection::None)
{
// turn delta into a percentage
base::ClampedNumeric<float> amount;
base::ClampedNumeric<float> actualDimension;
if (dir == ResizeDirection::Left || dir == ResizeDirection::Right)
{
amount = translationForUs.X;
actualDimension = base::ClampedNumeric<float>(_root.ActualWidth());
}
else if (dir == ResizeDirection::Up || dir == ResizeDirection::Down)
{
amount = translationForUs.Y;
actualDimension = base::ClampedNumeric<float>(_root.ActualHeight());
}
const auto scaledAmount = amount * scaleFactor;
lhecker marked this conversation as resolved.
Show resolved Hide resolved
const auto percentDelta = scaledAmount / actualDimension;

_Resize(dir, percentDelta.Abs());
}
}

// Method Description:
// - Attempt to navigate from the sourcePane according to direction.
// - If the direction is NextInOrder or PreviousInOrder, the next or previous
Expand Down Expand Up @@ -1847,6 +2034,9 @@ Borders Pane::_GetCommonBorders()
// - <none>
void Pane::_ApplySplitDefinitions()
{
// Remove our old handler, if we had one.
_manipulationDeltaRevoker.revoke();

if (_splitState == SplitState::Vertical)
{
Controls::Grid::SetColumn(_borderFirst, 0);
Expand All @@ -1871,6 +2061,17 @@ void Pane::_ApplySplitDefinitions()
_firstChild->_ApplySplitDefinitions();
_secondChild->_ApplySplitDefinitions();
}
else
{
assert(_IsLeaf());
// If we're a leaf, then add a ManipulationDelta handler.
_manipulationDeltaRevoker = _root.ManipulationDelta(winrt::auto_revoke, { this, &Pane::_ManipulationDeltaHandler });
}

_root.ManipulationMode(Xaml::Input::ManipulationModes::TranslateX |
Xaml::Input::ManipulationModes::TranslateRailsX |
Xaml::Input::ManipulationModes::TranslateY |
Xaml::Input::ManipulationModes::TranslateRailsY);
_UpdateBorders();
}

Expand Down Expand Up @@ -2254,6 +2455,9 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
// Create a new pane from ourself
if (!_IsLeaf())
{
_firstChild->ManipulationRequested(_firstManipulatedToken);
_secondChild->ManipulationRequested(_secondManipulatedToken);

// Since we are a parent we don't have borders normally,
// so set them temporarily for when we update our split definition.
_borders = _GetCommonBorders();
Expand Down Expand Up @@ -2292,6 +2496,9 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect

_ApplySplitDefinitions();

_firstManipulatedToken = _firstChild->ManipulationRequested({ this, &Pane::_handleOrBubbleManipulation });
_secondManipulatedToken = _secondChild->ManipulationRequested({ this, &Pane::_handleOrBubbleManipulation });

// Register event handlers on our children to handle their Close events
_SetupChildCloseHandlers();

Expand Down
19 changes: 17 additions & 2 deletions src/cascadia/TerminalApp/Pane.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ class Pane : public std::enable_shared_from_this<Pane>
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const;

void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction, float amount = .05f);

std::shared_ptr<Pane> NavigateDirection(const std::shared_ptr<Pane> sourcePane,
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,
const std::vector<uint32_t>& mruPanes);
Expand Down Expand Up @@ -223,6 +224,7 @@ class Pane : public std::enable_shared_from_this<Pane>
til::event<gotFocusArgs> GotFocus;
til::event<winrt::delegate<std::shared_ptr<Pane>>> LostFocus;
til::event<winrt::delegate<std::shared_ptr<Pane>>> Detached;
til::event<winrt::delegate<std::shared_ptr<Pane>, winrt::Windows::Foundation::Point, Borders>> ManipulationRequested;

private:
struct PanePoint;
Expand Down Expand Up @@ -253,8 +255,14 @@ class Pane : public std::enable_shared_from_this<Pane>
winrt::event_token _firstClosedToken{ 0 };
winrt::event_token _secondClosedToken{ 0 };

winrt::event_token _firstManipulatedToken{ 0 };
winrt::event_token _secondManipulatedToken{ 0 };

winrt::Windows::UI::Xaml::UIElement::GotFocus_revoker _gotFocusRevoker;
winrt::Windows::UI::Xaml::UIElement::LostFocus_revoker _lostFocusRevoker;
winrt::Windows::UI::Xaml::UIElement::ManipulationDelta_revoker _manipulationDeltaRevoker;
winrt::Windows::UI::Xaml::UIElement::ManipulationStarted_revoker _manipulationStartedRevoker;
bool _shouldManipulate{ false };

Borders _borders{ Borders::None };

Expand All @@ -281,7 +289,9 @@ class Pane : public std::enable_shared_from_this<Pane>
Borders _GetCommonBorders();
winrt::Windows::UI::Xaml::Media::SolidColorBrush _ComputeBorderColor();

bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
void _handleOrBubbleManipulation(std::shared_ptr<Pane> sender, const winrt::Windows::Foundation::Point delta, Borders side);
void _handleManipulation(const winrt::Windows::Foundation::Point delta);
bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction, float amount);

std::shared_ptr<Pane> _FindParentOfPane(const std::shared_ptr<Pane> pane);
std::pair<PanePoint, PanePoint> _GetOffsetsForPane(const PanePoint parentOffset) const;
Expand All @@ -304,6 +314,11 @@ class Pane : public std::enable_shared_from_this<Pane>
void _ContentLostFocusHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::UI::Xaml::RoutedEventArgs& e);

void _ManipulationStartedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::UI::Xaml::Input::ManipulationStartedRoutedEventArgs& e);
void _ManipulationDeltaHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs& e);

std::pair<float, float> _CalcChildrenSizes(const float fullSize) const;
SnapChildrenSizeResult _CalcSnappedChildrenSizes(const bool widthOrHeight, const float fullSize) const;
SnapSizeResult _CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
Expand Down