Repository: microsoft/terminal
File: src/cascadia/TerminalCore/Terminal.cpp (C++)

Code before:

            // If the new scroll offset is different, then we'll still want to raise a scroll event
            updatedViewport = updatedViewport || (oldScrollOffset != _scrollOffset);
        }

        // If the viewport moved, then send a scrolling notification.
        if (updatedViewport)
        {
            _NotifyScrollEvent();
        }
    }

    if (rowsPushedOffTopOfBuffer != 0)
    {
        if (_scrollMarks.size() > 0)
        {
            for (auto& mark : _scrollMarks)
            {
                // Move the mark up
                mark.start.y -= rowsPushedOffTopOfBuffer;

                // If the mark had sub-regions, then move those pointers too
                if (mark.commandEnd.has_value())
                    (*mark.commandEnd).y -= rowsPushedOffTopOfBuffer;
                if (mark.outputEnd.has_value())
                    (*mark.outputEnd).y -= rowsPushedOffTopOfBuffer;
            }

            _scrollMarks.erase(std::remove_if(_scrollMarks.begin(),
                                              _scrollMarks.end(),
                                              [](const VirtualTerminal::DispatchTypes::ScrollMark& m) { return m.start.y < 0; }),
                               _scrollMarks.end());
        }
        // We have to report the delta here because we might have circled the text buffer.
        // That didn't change the viewport and therefore the TriggerScroll(void)
        // method can't detect the delta on its own.
        til::point delta{ 0, -rowsPushedOffTopOfBuffer };
        _activeBuffer().TriggerScroll(delta);
    }
}

void Terminal::UserScrollViewport(const int viewTop)
{
    if (_inAltBuffer())
    {
        return;
    }

    // we're going to modify state here that the renderer could be reading.
    auto lock = LockForWriting();


Review comment (suggestion):
```suggestion
                // If the mark had sub-regions, then move those pointers too
                if (mark.commandEnd.has_value())
                {
                    (*mark.commandEnd).y -= rowsPushedOffTopOfBuffer;
                }
                if (mark.outputEnd.has_value())
                {
                    (*mark.outputEnd).y -= rowsPushedOffTopOfBuffer;
                }
```

Code after:
                }
            }

            _scrollMarks.erase(std::remove_if(_scrollMarks.begin(),
                                              _scrollMarks.end(),
                                              [](const VirtualTerminal::DispatchTypes::ScrollMark& m) { return m.start.y < 0; }),
                               _scrollMarks.end());
        }
        // We have to report the delta here because we might have circled the text buffer.
        // That didn't change the viewport and therefore the TriggerScroll(void)
        // method can't detect the delta on its own.
        const til::point delta{ 0, -rowsPushedOffTopOfBuffer };
        _activeBuffer().TriggerScroll(delta);
    }
}

void Terminal::UserScrollViewport(const int viewTop)
{
    if (_inAltBuffer())
    {
        return;
    }

    // we're going to modify state here that the renderer could be reading.
    auto lock = LockForWriting();

    const auto clampedNewTop = std::max(0, viewTop);
    const auto realTop = ViewStartIndex();
    const auto newDelta = realTop - clampedNewTop;
    // if viewTop > realTop, we want the offset to be 0.

    _scrollOffset = std::max(0, newDelta);

    // We can use the void variant of TriggerScroll here because
    // we adjusted the viewport so it can detect the difference
    // from the previous frame drawn.
    _activeBuffer().TriggerScroll();
}

int Terminal::GetScrollOffset() noexcept
{
    return _VisibleStartIndex();
}

void Terminal::_NotifyScrollEvent() noexcept
try
{
    if (_pfnScrollPositionChanged)
    {
        const auto visible = _GetVisibleViewport();
        const auto top = visible.Top();