Skip to content

Commit

Permalink
This fixes #9955.b
Browse files Browse the repository at this point in the history
  • Loading branch information
zadjii-msft committed Apr 28, 2021
1 parent 4f4df01 commit 33d29fa
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
60 changes: 47 additions & 13 deletions src/cascadia/TerminalControl/ControlInteractivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_selectionNeedsToBeCopied{ false }
{
_core = winrt::make_self<ControlCore>(settings, connection);

_core->ScrollPositionChanged({ this, &ControlInteractivity::_coreScrollPositionChanged });
}

void ControlInteractivity::UpdateSettings()
Expand Down Expand Up @@ -306,8 +308,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// panning down)
const float numRows = -1.0f * (dy / fontSizeInDips.height<float>());

const auto currentOffset = ::base::ClampedNumeric<double>(_core->ScrollOffset());
const auto newValue = numRows + currentOffset;
const double currentOffset = ::base::ClampedNumeric<double>(_core->ScrollOffset());
const double newValue = numRows + currentOffset;

// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
Expand Down Expand Up @@ -436,23 +438,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const til::point pixelPosition,
const bool isLeftButtonPressed)
{
const auto currentOffset = _core->ScrollOffset();
// GH#9955.b: Start scrolling from our internal scrollbar position. This
// lets us accumulate fractional numbers of rows to scroll with each
// event. Especially for precision trackpads, we might be getting scroll
// deltas smaller than a single row, but we still want lots of those to
// accumulate.
const double currentOffset = _internalScrollbarPosition;

// negative = down, positive = up
// However, for us, the signs are flipped.
// With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA),
// but the "smooth scrolling" mode results in non-int values
const auto rowDelta = mouseDelta / (-1.0 * WHEEL_DELTA);
const double rowDelta = mouseDelta / (-1.0 * 120.0);

// WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page
// at a time" setting. If we ignore it, we will scroll a truly absurd number
// of rows.
const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? _core->ViewHeight() : _rowsToScroll };
const double rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? ::base::saturated_cast<double>(_core->ViewHeight()) : _rowsToScroll };
double newValue = (rowsToScroll * rowDelta) + (currentOffset);

// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
_updateScrollbar(::base::saturated_cast<int>(newValue));
_updateScrollbar(newValue);

if (isLeftButtonPressed)
{
Expand All @@ -478,15 +485,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - newValue: The new top of the viewport
// Return Value:
// - <none>
void ControlInteractivity::_updateScrollbar(const int newValue)
void ControlInteractivity::_updateScrollbar(const double newValue)
{
_core->UserScrollViewport(newValue);
// Set this as the new value of our internal scrollbar representation.
// We're doing this so we can accumulate fractional amounts of a row to
// scroll each time the mouse scrolls.
_internalScrollbarPosition = newValue;

// If the new scrollbar position, rounded to an int, is at a different
// row, then actually update the scroll position in the core, and raise
// a ScrollPositionChanged to inform the control.
int viewTop = ::base::saturated_cast<int>(::std::round(_internalScrollbarPosition));
if (viewTop != _core->ScrollOffset())
{
_core->UserScrollViewport(viewTop);

// _core->ScrollOffset() is now set to newValue
_ScrollPositionChangedHandlers(*this,
winrt::make<ScrollPositionChangedArgs>(_core->ScrollOffset(),
_core->ViewHeight(),
_core->BufferHeight()));
}
}

// _core->ScrollOffset() is now set to newValue
_ScrollPositionChangedHandlers(*this,
winrt::make<ScrollPositionChangedArgs>(_core->ScrollOffset(),
_core->ViewHeight(),
_core->BufferHeight()));
// Method Description:
// - Event handler for the core's ScrollPositionChanged event. This is
// called when the core changes its viewport position, due to more text
// being output. We'll use this event to update our own internal scrollbar
// tracker to the position the viewport is at now.
// Arguments:
// - args: args containing infor about the position of the viewport in the buffer.
// Return Value:
// - <none>
void ControlInteractivity::_coreScrollPositionChanged(const IInspectable& /*sender*/,
const Control::ScrollPositionChangedArgs& args)
{
_internalScrollbarPosition = args.ViewTop();
}

void ControlInteractivity::_hyperlinkHandler(const std::wstring_view uri)
Expand Down
5 changes: 4 additions & 1 deletion src/cascadia/TerminalControl/ControlInteractivity.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
private:
winrt::com_ptr<ControlCore> _core{ nullptr };
unsigned int _rowsToScroll;
double _internalScrollbarPosition{ 0.0 };

// If this is set, then we assume we are in the middle of panning the
// viewport via touch input.
Expand Down Expand Up @@ -123,9 +124,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers);

void _sendPastedTextToConnection(std::wstring_view wstr);
void _updateScrollbar(const int newValue);
void _updateScrollbar(const double newValue);
til::point _getTerminalPosition(const til::point& pixelPosition);

void _coreScrollPositionChanged(const IInspectable& /*sender*/, const Control::ScrollPositionChangedArgs& args);

TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs);
Expand Down

1 comment on commit 33d29fa

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misspellings found, please review:

  • draging
  • infor
  • temrinal
To accept these changes, run the following commands from this repository on this branch
pushd $(git rev-parse --show-toplevel)
perl -e '
my @expect_files=qw('".github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt"');
@ARGV=@expect_files;
my @stale=qw('"aef aspnet boostorg BSODs Cac COINIT dahall DEFCON developercommunity fde fea fmtlib hotkeys HPCON isocpp llvm mintty msvcrtd Nc NVDA pinam QOL remoting UNINIT Unk unte vcrt what3words xamarin "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^(?:$re)(?:(?:\r|\n)*$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect/33d29fa30ace884653d797a8f92d69758ffcaae7.txt";
use File::Path qw(make_path);
make_path ".github/actions/spelling/expect";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"cac coinit draging hpcon infor LLVM MSVCRTD nc Remoting temrinal uninit unk "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
popd
✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. You can copy the contents of each perl command excluding the outer ' marks and dropping any '"/"' quotation mark pairs into a file and then run perl file.pl from the root of the repository to run the code. Alternatively, you can manually insert the items...

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/dictionary/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/dictionary/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

🗜️ If you see a bunch of garbage and it relates to a binary-ish string, please add a file path to the .github/actions/spelling/excludes.txt file instead of just accepting the garbage.

File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

Please sign in to comment.