Fix search not scrolling to result past view (#19571)

## Summary of the Pull Request
Fixes a bug where search would not scroll to results just below the
viewport.

This was caused by code intended to scroll the search result in such a
way that it isn't covered by the search box. The scroll offset is
calculated in `TermControl::_calculateSearchScrollOffset()` then handed
down in the `SearchRequest` when conducting a search. This would get to
`Terminal::ScrollToSearchHighlight()` where the offset is applied to the
search result's position so that we would scroll to the adjusted
position.

The adjustment was overly aggressive in that it would apply it to both
"start" and "end". In reality, we don't need to apply it to "end"
because it wouldn't be covered by the search box (we only scroll to end
if it's past the end of the current view anyways).

The fix applies the adjustment only to "start" and only does so if it's
actually in the first few rows that would be covered by the search box.

That unveiled another bug where `Terminal::_ScrollToPoints()` would also
be too aggressive about scrolling the "end" into view. In some testing,
it would generally end up scrolling to the end of the buffer. To fix
this cascading bug, I just had `_ScrollToPoints()` just call
`Terminal::_ScrollToPoint()` (singular, not plural) which is
consistently used throughout the Terminal code for selection (so it's
battle tested).

`_ScrollToPoints()` was kept since it's still used for accessibility
when selecting a new region to keep the new selection in view. It's also
just a nice wrapper that ensures a range is visible (or at least as much
as it could be).

## References and Relevant Issues
Scroll offset was added in #17516

## Validation Steps Performed
 search results that would be covered by the search box are still
adjusted
 search results that are past the end of the view become visible
 UIA still selects properly and brings the selection into view

## PR Checklist
Duncan reported this bug internally, but there doesn't seem to be one on
the repo.
This commit is contained in:
Carlos Zamora 2025-11-24 09:35:52 -08:00 committed by GitHub
parent 81cdb07646
commit ee6060b3a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 20 deletions

View File

@ -1297,9 +1297,15 @@ void Terminal::ScrollToSearchHighlight(til::CoordType searchScrollOffset)
if (_searchHighlightFocused < _searchHighlights.size()) if (_searchHighlightFocused < _searchHighlights.size())
{ {
const auto focused = til::at(_searchHighlights, _searchHighlightFocused); const auto focused = til::at(_searchHighlights, _searchHighlightFocused);
const auto adjustedStart = til::point{ focused.start.x, std::max(0, focused.start.y - searchScrollOffset) };
const auto adjustedEnd = til::point{ focused.end.x, std::max(0, focused.end.y - searchScrollOffset) }; // Only adjust the y coordinates if "start" is in a row that would be covered by the search box
_ScrollToPoints(adjustedStart, adjustedEnd); auto adjustedStart = focused.start;
const auto firstVisibleRow = _VisibleStartIndex();
if (focused.start.y > firstVisibleRow && focused.start.y < firstVisibleRow + searchScrollOffset)
{
adjustedStart.y = std::max(0, focused.start.y - searchScrollOffset);
}
_ScrollToPoints(adjustedStart, focused.end);
} }
} }

View File

@ -152,29 +152,14 @@ const til::point_span* Terminal::GetSearchHighlightFocused() const noexcept
// - The updated scroll offset // - The updated scroll offset
til::CoordType Terminal::_ScrollToPoints(const til::point coordStart, const til::point coordEnd) til::CoordType Terminal::_ScrollToPoints(const til::point coordStart, const til::point coordEnd)
{ {
auto notifyScrollChange = false;
if (coordStart.y < _VisibleStartIndex()) if (coordStart.y < _VisibleStartIndex())
{ {
// recalculate the scrollOffset _ScrollToPoint(coordStart);
_scrollOffset = ViewStartIndex() - coordStart.y;
notifyScrollChange = true;
} }
else if (coordEnd.y > _VisibleEndIndex()) else if (coordEnd.y > _VisibleEndIndex())
{ {
// recalculate the scrollOffset, note that if the found text is _ScrollToPoint(coordEnd);
// beneath the current visible viewport, it may be within the
// current mutableViewport and the scrollOffset will be smaller
// than 0
_scrollOffset = std::max(0, ViewStartIndex() - coordStart.y);
notifyScrollChange = true;
} }
if (notifyScrollChange)
{
_activeBuffer().TriggerScroll();
_NotifyScrollEvent();
}
return _VisibleStartIndex(); return _VisibleStartIndex();
} }