-
Notifications
You must be signed in to change notification settings - Fork 8.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Highlight all search results while the search box is open #16227
Conversation
@microsoft-github-policy-service agree |
This comment has been minimized.
This comment has been minimized.
577bcc0
to
d8c0771
Compare
microsoft#7561 Follows the existing selection code as much as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little concerned about how this works when you have >10k search results (which can easily happen if you search for a common letter like e
). Preferably this PR should get more performance enhancements, but I don't consider them necessary to approve this PR. I can do them myself later on.
This is the wrong place to put it, because conhost (aka OpenConsole) doesn't use this information. Additionally, this method runs every time you click "next" or "previous" so this would be a waste of compute since the _results array doesn't change. I would put this here: https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalControl/ControlCore.cpp#L1605C9-L1609 FYI never forget to std::move container classes whenever you pass them by value. Otherwise you make a copy just to throw away the original soon after.
This code rejoins neighboring search results, but is that really such a common scenario that it outweighs the cost of turning this O(n) outer loop into O(n^2)? Previously we only had a 1 selection overlay per row at most (the regular, manual selection by a user). Now, with an arbitrary number of disjoint selections per row, the technically best approach is to resize RenderingPayload::colorBitmap to contain 3 textures and not just 2. Right now the bitmap contains the background and foreground bitmaps back to back, but it could also contain a bitmap for the selection. Then, in BackendD3D we simply overlay this bitmap on top of the previously drawn text, similar to how we draw the background as the first step. But making this change is fairly challenging and I don't expect you to make it.
This code rejoins neighboring search results, but is that really such a common scenario that it outweighs the cost of turning this O(n) outer loop into O(n^2)? Previously we only had a 1 selection overlay per row at most (the regular, manual selection by a user). Now, with an arbitrary number of disjoint selections per row, the technically best approach is to resize RenderingPayload::colorBitmap to contain 3 textures and not just 2. Right now the bitmap contains the background and foreground bitmaps back to back, but it could also contain a bitmap for the selection. Then, in BackendD3D we simply overlay this bitmap on top of the previously drawn text, similar to how we draw the background as the first step. But making this change is fairly challenging and I don't expect you to make it.
@lhecker just a quick heads up, I think this is ready for another round of reviews. (No rush just wasn't sure what the protocol for alerting you was). |
Honestly, after reading through it once, I couldn't find any other obvious flaws. If you don't mind, I'll wait a bit before I approve it though, because I want to think about it some more. Long-term I want to simplify the rendering code, so that you don't need to implement a bunch of methods to introduce a feature like this one. I'd like to make it so that there's a "rendering payload" struct, similar to the |
src/renderer/atlas/common.h
Outdated
@@ -377,6 +377,7 @@ namespace Microsoft::Console::Render::Atlas | |||
{ | |||
u32 backgroundColor = 0; | |||
u32 selectionColor = 0x7fffffff; | |||
u32 searchSelectionColor = 0x5fff0000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant to ask about this, the blue I used probably isn't a great default, should I try to add this as setting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally speaking, I wouldn't consider that important. Some of the most popular applications don't have configurable highlight colors, including Chromium and Word.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this value is no longer used. Should we remove it?
While writing my previous comment I realized that Chromium changes the background and foreground color of text when marking it as highlighted: It also doesn't seem to care about the current background color because picking the same color makes the highlight invisible: Should we perhaps do the same? Get rid of Residential selection expert, @DHowett, what say thee? |
Should we perhaps do the same? Get rid of _drawSearchSelections and just manipulate the background/foreground colors of the highlighted text (see second half of AtlasEngine::PaintBufferLine)? Residential selection expert, @DHowett, what say thee? #5fff0000, aka rgba(255, 0, 0, 0.37) overlay or fixed #ff9632 background with #000000 foreground color, like Chromium?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Made an attempt at this, does the diff look like what you were thinking? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this! I only have a few questions before I can sign off.
Thanks so much for bearing with us, and contributing a really awesome feature!
src/renderer/atlas/common.h
Outdated
@@ -377,6 +377,7 @@ namespace Microsoft::Console::Render::Atlas | |||
{ | |||
u32 backgroundColor = 0; | |||
u32 selectionColor = 0x7fffffff; | |||
u32 searchSelectionColor = 0x5fff0000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this value is no longer used. Should we remove it?
// - Vector of Viewports describing the area selected | ||
std::vector<Viewport> RenderData::GetSearchSelectionRects() noexcept | ||
{ | ||
return {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conhost performance question: it's cheap to return an empty vector, right?
Gut check... it looks like it is "cheap enough", at least on x64:
#include <vector>
std::vector<int> foo() {
return {};
}
__$ReturnUdt$ = 32
std::vector<int,std::allocator<int> > foo(void) PROC ; foo, COMDAT
$LN13:
sub rsp, 24
xor eax, eax
mov QWORD PTR [rcx], rax
mov QWORD PTR [rcx+8], rax
mov QWORD PTR [rcx+16], rax
mov rax, rcx
add rsp, 24
ret 0
std::vector<int,std::allocator<int> > foo(void) ENDP ; foo
@@ -188,6 +206,23 @@ void Terminal::SelectNewRegion(const til::point coordStart, const til::point coo | |||
SetSelectionEnd(realCoordEnd, SelectionExpansion::Char); | |||
} | |||
|
|||
void Terminal::SelectSearchRegions(std::vector<til::inclusive_rect> rects) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lhecker do we need to use any of your locks here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say no. I moved all locking calls to outside of the Terminal
class to make the code more consistent. If you were talking about the _assertLocked()
, then I'd also say no, because this will be indirectly covered through the _VisibleStartIndex
(we could add _assertLocked()
to all member functions in the future if we wanted to).
auto rr = til::inclusive_rect{ realStart.x, realStart.y, realEnd.x, realEnd.y }; | ||
|
||
_searchSelections.emplace_back(rr); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was expecting to find something here poking the renderer.. like TriggerSelection
. Is that already happening because we're also making a new selection when we search?
I am worried about the hidden coupling here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think right now it is relying on this call to trigger selection.
_renderer->TriggerSelection(); |
Something does feel weird when I compare it to have the normal selection from _search.SelectCurrent() works.
Would it make sense to move the _searcher.HighlightSelections() here?
// We don't want to show the markers so manually tell it to clear it. |
Or to add a TriggerSelection call here?
_searcher.MoveToCurrentSelection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a really good question. I think that you'll want to do it any time you are done changing _searchSelections
. @lhecker might have a better opinion here.
I tried out your branch! It works really, really well. Congrats!
I only found one issue.
When I delete the search with backspace, or close it, the highlights stick around... but the search is no longer active. So next time the screen updates, they all go away.
I think this might be because of the missing TriggerSelection
!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
somewhat long story on the selections not getting cleared when the last char is deleted from the search box. I was trying to match the behavior from the release that I had on my machine and it looked like the "current" selection highlight stuck around after deleting the last char and then I cross referenced visual studio and it looked like it also left the highlights so I thought it might be a pattern and didn't want to change any existing behavior.
For clearing all selections, I think this would work.
e82eric@4dc6305
For leaving the current selection highlighted but clearing all of the other highlights, I think this would work.
e82eric@3854b8b
For clearing the selections after the search box is closed, I actually like the behavior where it leaves the selections highlighted, It gives me context if I want to go into mark mode (about what is going to get selected).
I think it is possible to clear the selections after closing the search box.
e82eric@8a61353
Let me know if any of these make sense or if there is another approach and I can update the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That all makes sense!
should be cleared.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any obvious flaws personally. I think we should merge this now and fix any issues that arise later (ourselves) once we test this.
@e82eric thanks so much for doing this! Pretty brave of you to jump into this area and just start making a difference. 😄 |
Hey I just want to chime in here: I've been selfhosting canary builds with this PR for a while now, and I have found this INFINITELY more helpful than I thought it would be. Thanks again @e82eric! |
No problem! |
… wraps to next line (#16691) Hi, I realized I had a bug in my pull request for search selections where when the highlight is wrapped it causes the selection to select back to start of the current line instead of wrapping to the next line. PR where I introduced this bug: #16227 (cherry picked from commit bef2340) Service-Card-Id: 91808626 Service-Version: 1.20
Why was it reverted? Can I have this feature on 1.20+? |
It was not ready to be released to a hundred million people via the stable version.
Yes, but only the “+” part of “1.20+” |
Because this was reverted, Or is this PR still complete as-is and just waiting to be re-released? |
Hi! First time contributor, wanted to try to add highlighting for all search results.
Summary of the Pull Request
Update to highlight all search results
References and Relevant Issues
Closes #7561
Detailed Description of the Pull Request / Additional comments
Follows the existing selection code as much as possible.
Updated logic that finds selection rectangles to also identify search rectangles.
Added structure to ShapedRow to track the search selections.
Validation Steps Performed
PR Checklist