Avoid scrolling when the search is open (#19775)

When text scrolls in and out of view, depending on the length
of the scrollback and latency of input, `GetSearchHighlightFocused`
would change which would trigger a `ScrollToSearchHighlight` call.

This PR changes the behavior such that only actively changing the
search mask triggers a search (typing text or pressing enter).

Closes #19754

## Validation Steps Performed
* Brining text in and out of view doesn't scroll 
* Toggling the aA button scrolls results into view 
This commit is contained in:
Leonard Hecker 2026-01-24 01:33:18 +01:00 committed by GitHub
parent 6723ca2239
commit 71409f84f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 26 deletions

View File

@ -1736,7 +1736,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - resetOnly: If true, only Reset() will be called, if anything. FindNext() will never be called. // - resetOnly: If true, only Reset() will be called, if anything. FindNext() will never be called.
// Return Value: // Return Value:
// - <none> // - <none>
SearchResults ControlCore::Search(SearchRequest request) SearchResults ControlCore::Search(const SearchRequest& request)
{ {
const auto lock = _terminal->LockForWriting(); const auto lock = _terminal->LockForWriting();
@ -1745,15 +1745,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WI_SetFlagIf(flags, SearchFlag::RegularExpression, request.RegularExpression); WI_SetFlagIf(flags, SearchFlag::RegularExpression, request.RegularExpression);
const auto searchInvalidated = _searcher.IsStale(*_terminal.get(), request.Text, flags); const auto searchInvalidated = _searcher.IsStale(*_terminal.get(), request.Text, flags);
if (searchInvalidated || !request.ResetOnly) if (searchInvalidated || request.ExecuteSearch)
{ {
std::vector<til::point_span> oldResults; std::vector<til::point_span> oldResults;
til::point_span oldFocused;
if (const auto focused = _terminal->GetSearchHighlightFocused())
{
oldFocused = *focused;
}
if (searchInvalidated) if (searchInvalidated)
{ {
@ -1762,18 +1756,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_terminal->SetSearchHighlights(_searcher.Results()); _terminal->SetSearchHighlights(_searcher.Results());
} }
if (!request.ResetOnly) if (request.ExecuteSearch)
{ {
_searcher.FindNext(!request.GoForward); _searcher.FindNext(!request.GoForward);
} }
_terminal->SetSearchHighlightFocused(gsl::narrow<size_t>(std::max<ptrdiff_t>(0, _searcher.CurrentMatch()))); _terminal->SetSearchHighlightFocused(gsl::narrow<size_t>(std::max<ptrdiff_t>(0, _searcher.CurrentMatch())));
_renderer->TriggerSearchHighlight(oldResults); _renderer->TriggerSearchHighlight(oldResults);
}
if (const auto focused = _terminal->GetSearchHighlightFocused(); focused && *focused != oldFocused) if (request.ScrollIntoView)
{ {
_terminal->ScrollToSearchHighlight(request.ScrollOffset); _terminal->ScrollToSearchHighlight(request.ScrollOffset);
}
} }
int32_t totalMatches = 0; int32_t totalMatches = 0;

View File

@ -225,7 +225,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void SetSelectionAnchor(const til::point position); void SetSelectionAnchor(const til::point position);
void SetEndSelectionPoint(const til::point position); void SetEndSelectionPoint(const til::point position);
SearchResults Search(SearchRequest request); SearchResults Search(const SearchRequest& request);
const std::vector<til::point_span>& SearchResultRows() const noexcept; const std::vector<til::point_span>& SearchResultRows() const noexcept;
void ClearSearch(); void ClearSearch();

View File

@ -55,7 +55,8 @@ namespace Microsoft.Terminal.Control
Boolean GoForward; Boolean GoForward;
Boolean CaseSensitive; Boolean CaseSensitive;
Boolean RegularExpression; Boolean RegularExpression;
Boolean ResetOnly; Boolean ExecuteSearch;
Boolean ScrollIntoView;
Int32 ScrollOffset; Int32 ScrollOffset;
}; };

View File

@ -714,8 +714,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
} }
else else
{ {
const auto request = SearchRequest{ _searchBox->Text(), goForward, _searchBox->CaseSensitive(), _searchBox->RegularExpression(), false, _searchScrollOffset }; _handleSearchResults(_core.Search(SearchRequest{
_handleSearchResults(_core.Search(request)); .Text = _searchBox->Text(),
.GoForward = goForward,
.CaseSensitive = _searchBox->CaseSensitive(),
.RegularExpression = _searchBox->RegularExpression(),
.ExecuteSearch = true,
.ScrollIntoView = true,
.ScrollOffset = _searchScrollOffset,
}));
} }
} }
@ -749,8 +756,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{ {
if (_searchBox && _searchBox->IsOpen()) if (_searchBox && _searchBox->IsOpen())
{ {
const auto request = SearchRequest{ text, goForward, caseSensitive, regularExpression, false, _searchScrollOffset }; _handleSearchResults(_core.Search(SearchRequest{
_handleSearchResults(_core.Search(request)); .Text = text,
.GoForward = goForward,
.CaseSensitive = caseSensitive,
.RegularExpression = regularExpression,
.ExecuteSearch = true,
.ScrollIntoView = true,
.ScrollOffset = _searchScrollOffset,
}));
} }
} }
@ -769,11 +783,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{ {
if (_searchBox && _searchBox->IsOpen()) if (_searchBox && _searchBox->IsOpen())
{ {
// We only want to update the search results based on the new text. Set _handleSearchResults(_core.Search(SearchRequest{
// `resetOnly` to true so we don't accidentally update the current match index. .Text = text,
const auto request = SearchRequest{ text, goForward, caseSensitive, regularExpression, true, _searchScrollOffset }; .GoForward = goForward,
const auto result = _core.Search(request); .CaseSensitive = caseSensitive,
_handleSearchResults(result); .RegularExpression = regularExpression,
.ExecuteSearch = false,
.ScrollIntoView = true,
.ScrollOffset = _searchScrollOffset,
}));
} }
} }
@ -3742,8 +3760,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto goForward = _searchBox->GoForward(); const auto goForward = _searchBox->GoForward();
const auto caseSensitive = _searchBox->CaseSensitive(); const auto caseSensitive = _searchBox->CaseSensitive();
const auto regularExpression = _searchBox->RegularExpression(); const auto regularExpression = _searchBox->RegularExpression();
const auto request = SearchRequest{ text, goForward, caseSensitive, regularExpression, true, _searchScrollOffset }; _handleSearchResults(_core.Search(SearchRequest{
_handleSearchResults(_core.Search(request)); .Text = text,
.GoForward = goForward,
.CaseSensitive = caseSensitive,
.RegularExpression = regularExpression,
.ExecuteSearch = false,
.ScrollIntoView = false,
.ScrollOffset = _searchScrollOffset,
}));
} }
void TermControl::_handleSearchResults(SearchResults results) void TermControl::_handleSearchResults(SearchResults results)