[PR #16611] Improve Search Highlighting #30959

Closed
opened 2026-01-31 09:44:05 +00:00 by claunia · 0 comments
Owner

Original Pull Request: https://github.com/microsoft/terminal/pull/16611

State: closed
Merged: Yes


The changeset involves:

  • Decoupling Selection and Search Highlighting code paths.
  • We no longer invalidate search highlights when:
    • Left-clicking on terminal
    • A new selection is made
    • Left-clicking on Search-box
    • Dispatching Find Next/Prev Match Action. (The search highlight was removed after pressing the first key of the Action's key combination)
    • And, anything that doesn't change buffer content, shouldn't invalidate the highlighted region (E.g. Cursor movement)
  • Highlighting foreground color is actually applied to the highlighted text.
  • Double-clicking on SearchBox no longer starts a text selection in the terminal.
  • Selected text is properly populated in the Search Box (#16355)

Closes: #16355

image

Some Implementation Details

Detecting text layout changes in the Control layer

As Search Highlight regions need to be removed when new text is added, or the existing text is re-arranged due to window resize or similar events, a new event TextLayoutUpdated is added that notifies CoreControl of any text layout changes. The event is used to invalidate and remove all search highlight regions from the buffer (because the regions might not be fresh anymore.

The new event is raised when:

  1. AdaptDispatch writes new text into the buffer.
  2. MainBuffer is switched to AltBuffer or vice-versa.
  3. The user resized the window.
  4. Font size changed.
  5. Zoom level changed.

(Intensionally,) It's not raised when:

  1. Buffer is scrolled.
  2. The text cursor is moved.

When ControlCore receives a TextLayoutUpdated event, it clears the Search Highlights in the render data, and raises an UpdateSearchResults event to notify TermControl to update the Search UI (SearchBoxControl).

In the future, we can use TextLayoutUpdated event to start a new search which would refresh the results automatically after a slight delay (throttled). VSCode already does this today.

How does AtlasEngine draw the highlighted regions?

We follow a similar idea as for drawing the Selection region. When new regions are available, the old+new regions are marked invalidated. Later, a call to _drawHighlighted() is made at the end of PaintBufferLine() to override the highlighted regions' colors with highlight colors. The highlighting colors replace the buffer colors while search highlights are active.

Note that to paint search highlights, we currently invalidate the row completely. This forces text shaping for the rows in the viewport that have at least one highlighted region. This is done to keep the (already lengthy) PR... simple. We could take advantage of the fact that only colors have changed and not the characters (or glyphs). I'm expecting that this could be improved like:

  1. When search regions are added, we add the highlighting colors to the color bitmaps without causing text shaping.
  2. When search regions are removed, we re-fill the color bitmaps with the original colors from the Buffer.

Validation Steps:

  • New text, window resize, font size changes, zooming, and pasting content into the terminal removes search highlights.
  • highlighting colors override the foreground and background color of the text (in the rendered output).
  • Blinking, faded, reverse video, Intense text is highlighted as expected.
**Original Pull Request:** https://github.com/microsoft/terminal/pull/16611 **State:** closed **Merged:** Yes --- ### The changeset involves: - Decoupling Selection and Search Highlighting code paths. - We no longer invalidate search highlights when: - Left-clicking on terminal - A new selection is made - Left-clicking on Search-box - Dispatching Find Next/Prev Match Action. (The search highlight was removed after pressing the first key of the Action's key combination) - And, anything that doesn't change buffer content, shouldn't invalidate the highlighted region (E.g. Cursor movement) - Highlighting foreground color is *actually* applied to the highlighted text. - Double-clicking on SearchBox no longer starts a text selection in the terminal. - Selected text is properly populated in the Search Box (#16355) Closes: #16355 ![image](https://github.com/microsoft/terminal/assets/55626797/8fd0345b-a8b2-4bc2-a25e-15d710127b63) ## Some Implementation Details ### Detecting text layout changes in the Control layer As Search Highlight regions need to be removed when new text is added, or the existing text is re-arranged due to window resize or similar events, a new event `TextLayoutUpdated` is added that notifies `CoreControl` of any text layout changes. The event is used to invalidate and remove all search highlight regions from the buffer (because the regions might not be _fresh_ anymore. The new event is raised when: 1. `AdaptDispatch` writes new text into the buffer. 2. MainBuffer is switched to AltBuffer or vice-versa. 3. The user resized the window. 4. Font size changed. 5. Zoom level changed. (Intensionally,) It's not raised when: 1. Buffer is scrolled. 2. The text cursor is moved. When `ControlCore` receives a `TextLayoutUpdated` event, it clears the Search Highlights in the *render data*, and raises an `UpdateSearchResults` event to notify `TermControl` to update the Search UI (`SearchBoxControl`). In the future, we can use `TextLayoutUpdated` event to start a new search which would refresh the results automatically after a slight delay (throttled). *VSCode already does this today*. ### How does AtlasEngine draw the highlighted regions? We follow a similar idea as for drawing the Selection region. When new regions are available, the old+new regions are marked invalidated. Later, a call to `_drawHighlighted()` is made at the end of `PaintBufferLine()` to override the highlighted regions' colors with highlight colors. The highlighting colors replace the buffer colors while search highlights are active. Note that to paint search highlights, we currently invalidate the row completely. This forces text shaping for the rows in the viewport that have at least one highlighted region. This is done to keep the (already lengthy) PR... simple. We could take advantage of the fact that only colors have changed and not the characters (or glyphs). I'm expecting that this could be improved like: 1. When search regions are added, we add the highlighting colors to the color bitmaps without causing text shaping. 2. When search regions are removed, we re-fill the color bitmaps with the original colors from the Buffer. ## Validation Steps: - New text, window resize, font size changes, zooming, and pasting content into the terminal removes search highlights. - highlighting colors override the foreground and background color of the text (in the rendered output). - Blinking, faded, reverse video, Intense text is highlighted as expected.
claunia added the pull-request label 2026-01-31 09:44:05 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#30959