Skip to content

Commit

Permalink
Update to highlight all search results
Browse files Browse the repository at this point in the history
microsoft#7561
Follows the existing selection code as much as possible.
  • Loading branch information
e82eric committed Oct 25, 2023
1 parent d0d3039 commit 8a5dfc6
Show file tree
Hide file tree
Showing 30 changed files with 291 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/buffer/out/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,34 @@ const til::point_span* Search::GetCurrent() const noexcept

bool Search::SelectCurrent() const
{
std::vector<til::inclusive_rect> toSelect;

if (const auto s = GetCurrent())
{
// Convert buffer selection offsets into the equivalent screen coordinates
// required by SelectNewRegion, taking line renditions into account.
const auto& textBuffer = _renderData->GetTextBuffer();
const auto selStart = textBuffer.BufferToScreenPosition(s->start);
const auto selEnd = textBuffer.BufferToScreenPosition(s->end);

_renderData->SelectNewRegion(selStart, selEnd);

for (const auto& r : _results)
{
const auto rbStart = textBuffer.BufferToScreenPosition(r.start);
const auto rbEnd = textBuffer.BufferToScreenPosition(r.end);

til::inclusive_rect re;
re.top = rbStart.y;
re.bottom = rbEnd.y;
re.left = rbStart.x;
re.right = rbEnd.x;

toSelect.emplace_back(re);
}

_renderData->SelectSearchRegions(toSelect);

return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// modifier key. We'll wait for a real keystroke to dismiss the
// GH #7395 - don't update selection when taking PrintScreen
// selection.

return _terminal->IsSelectionActive() && ::Microsoft::Terminal::Core::Terminal::IsInputKey(vkey);
}

Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,12 @@ class Microsoft::Terminal::Core::Terminal final :

std::pair<COLORREF, COLORREF> GetAttributeColors(const TextAttribute& attr) const noexcept override;
std::vector<Microsoft::Console::Types::Viewport> GetSelectionRects() noexcept override;
std::vector<Microsoft::Console::Types::Viewport> GetSearchSelectionRects() noexcept override;
const bool IsSelectionActive() const noexcept override;
const bool IsBlockSelection() const noexcept override;
void ClearSelection() override;
void SelectNewRegion(const til::point coordStart, const til::point coordEnd) override;
void SelectSearchRegions(std::vector<til::inclusive_rect> source) override;
const til::point GetSelectionAnchor() const noexcept override;
const til::point GetSelectionEnd() const noexcept override;
const std::wstring_view GetConsoleTitle() const noexcept override;
Expand Down Expand Up @@ -370,6 +372,7 @@ class Microsoft::Terminal::Core::Terminal final :
til::point pivot;
};
std::optional<SelectionAnchors> _selection;
std::vector<til::inclusive_rect> _searchSelections;
bool _blockSelection = false;
std::wstring _wordDelimiters;
SelectionExpansion _multiClickSelectionMode = SelectionExpansion::Char;
Expand Down Expand Up @@ -459,6 +462,7 @@ class Microsoft::Terminal::Core::Terminal final :
#pragma region TextSelection
// These methods are defined in TerminalSelection.cpp
std::vector<til::inclusive_rect> _GetSelectionRects() const noexcept;
std::vector<til::inclusive_rect> _GetSearchSelectionRects() const noexcept;
std::vector<til::point_span> _GetSelectionSpans() const noexcept;
std::pair<til::point, til::point> _PivotSelection(const til::point targetPos, bool& targetStart) const noexcept;
std::pair<til::point, til::point> _ExpandSelectionAnchors(std::pair<til::point, til::point> anchors) const;
Expand Down
31 changes: 31 additions & 0 deletions src/cascadia/TerminalCore/TerminalSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,34 @@ std::vector<til::inclusive_rect> Terminal::_GetSelectionRects() const noexcept
return result;
}

// Method Description:
// - Helper to determine the selected region of the buffer. Used for rendering.
// Return Value:
// - A vector of rectangles representing the regions to select, line by line. They are absolute coordinates relative to the buffer origin.
std::vector<til::inclusive_rect> Terminal::_GetSearchSelectionRects() const noexcept
{
std::vector<til::inclusive_rect> result;

try
{
std::vector<til::inclusive_rect> result;
for (const auto& selection : _searchSelections)
{
const auto start = til::point{ selection.left, selection.top };
const auto end = til::point{ selection.right, selection.top };
const auto adj = _activeBuffer().GetTextRects(start, end, _blockSelection, false);
for (auto a : adj)
{
result.emplace_back(a);
}
}

return result;
}
CATCH_LOG();
return result;
}

// Method Description:
// - Identical to GetTextRects if it's a block selection, else returns a single span for the whole selection.
// Return Value:
Expand Down Expand Up @@ -243,6 +271,7 @@ void Terminal::SetSelectionEnd(const til::point viewportPos, std::optional<Selec
// expand both anchors
std::tie(_selection->start, _selection->end) = expandedAnchors;
}

_selectionMode = SelectionInteractionMode::Mouse;
_selectionIsTargetingUrl = false;
}
Expand Down Expand Up @@ -824,6 +853,7 @@ void Terminal::_MoveByBuffer(SelectionDirection direction, til::point& pos) noex
void Terminal::ClearSelection()
{
_assertLocked();
_searchSelections.clear();
_selection = std::nullopt;
_selectionMode = SelectionInteractionMode::None;
_selectionIsTargetingUrl = false;
Expand Down Expand Up @@ -888,6 +918,7 @@ void Terminal::_ScrollToPoint(const til::point pos)
const auto amtBelowView = pos.y - visibleViewport.BottomInclusive();
_scrollOffset -= amtBelowView;
}

_NotifyScrollEvent();
_activeBuffer().TriggerScroll();
}
Expand Down
35 changes: 35 additions & 0 deletions src/cascadia/TerminalCore/terminalrenderdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,24 @@ catch (...)
return {};
}

std::vector<Microsoft::Console::Types::Viewport> Terminal::GetSearchSelectionRects() noexcept
try
{
std::vector<Viewport> result;

for (const auto& lineRect : _GetSearchSelectionRects())
{
result.emplace_back(Viewport::FromInclusive(lineRect));
}

return result;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return {};
}

void Terminal::SelectNewRegion(const til::point coordStart, const til::point coordEnd)
{
#pragma warning(push)
Expand Down Expand Up @@ -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)
{
_searchSelections.clear();
for (auto& rect : rects)
{
rect.top -= _VisibleStartIndex();
rect.bottom -= _VisibleStartIndex();

const auto realStart = _ConvertToBufferCell(til::point{ rect.left, rect.top });
const auto realEnd = _ConvertToBufferCell(til::point{ rect.right, rect.bottom });

auto rr = til::inclusive_rect{ realStart.x, realStart.y, realEnd.x, realEnd.y };

_searchSelections.emplace_back(rr);
}
}

const std::wstring_view Terminal::GetConsoleTitle() const noexcept
{
_assertLocked();
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ namespace
HRESULT PaintBufferLine(std::span<const Cluster> /*clusters*/, til::point /*coord*/, bool /*fTrimLeft*/, bool /*lineWrapped*/) noexcept { return S_OK; }
HRESULT PaintBufferGridLines(GridLineSet /*lines*/, COLORREF /*color*/, size_t /*cchLine*/, til::point /*coordTarget*/) noexcept { return S_OK; }
HRESULT PaintSelection(const til::rect& /*rect*/) noexcept { return S_OK; }
HRESULT PaintSelections(const std::vector<til::rect>& /*rects*/) noexcept { return S_OK; }
HRESULT PaintCursor(const CursorOptions& /*options*/) noexcept { return S_OK; }
HRESULT UpdateDrawingBrushes(const TextAttribute& /*textAttributes*/, const RenderSettings& /*renderSettings*/, gsl::not_null<IRenderData*> /*pData*/, bool /*usingSoftFont*/, bool /*isSettingDefaultBrushes*/) noexcept { return S_OK; }
HRESULT UpdateFont(const FontInfoDesired& /*FontInfoDesired*/, _Out_ FontInfo& /*FontInfo*/) noexcept { return S_OK; }
Expand Down
25 changes: 25 additions & 0 deletions src/host/renderData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ std::vector<Viewport> RenderData::GetSelectionRects() noexcept
return result;
}

// Method Description:
// - Retrieves one rectangle per line describing the area of the viewport
// that should be highlighted in some way to represent a user-interactive selection
// Return Value:
// - Vector of Viewports describing the area selected
std::vector<Viewport> RenderData::GetSearchSelectionRects() noexcept
{
std::vector<Viewport> result;

try
{
for (const auto& select : Selection::Instance().GetSelectionRects())
{
result.emplace_back(Viewport::FromInclusive(select));
}
}
CATCH_LOG();

return result;
}

// Method Description:
// - Lock the console for reading the contents of the buffer. Ensures that the
// contents of the console won't be changed in the middle of a paint
Expand Down Expand Up @@ -369,6 +390,10 @@ void RenderData::SelectNewRegion(const til::point coordStart, const til::point c
Selection::Instance().SelectNewRegion(coordStart, coordEnd);
}

void RenderData::SelectSearchRegions(std::vector<til::inclusive_rect> source)
{
}

// Routine Description:
// - Gets the current selection anchor position
// Arguments:
Expand Down
2 changes: 2 additions & 0 deletions src/host/renderData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class RenderData final :
const FontInfo& GetFontInfo() const noexcept override;

std::vector<Microsoft::Console::Types::Viewport> GetSelectionRects() noexcept override;
std::vector<Microsoft::Console::Types::Viewport> GetSearchSelectionRects() noexcept override;

void LockConsole() noexcept override;
void UnlockConsole() noexcept override;
Expand Down Expand Up @@ -54,6 +55,7 @@ class RenderData final :
const bool IsBlockSelection() const noexcept override;
void ClearSelection() override;
void SelectNewRegion(const til::point coordStart, const til::point coordEnd) override;
void SelectSearchRegions(std::vector<til::inclusive_rect> source) override;
const til::point GetSelectionAnchor() const noexcept override;
const til::point GetSelectionEnd() const noexcept override;
const bool IsUiaDataInitialized() const noexcept override { return true; }
Expand Down
9 changes: 9 additions & 0 deletions src/host/ut_host/VtIoTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ class MockRenderData : public IRenderData
return std::vector<Microsoft::Console::Types::Viewport>{};
}

std::vector<Microsoft::Console::Types::Viewport> GetSearchSelectionRects() noexcept override
{
return std::vector<Microsoft::Console::Types::Viewport>{};
}

void LockConsole() noexcept override
{
}
Expand Down Expand Up @@ -363,6 +368,10 @@ class MockRenderData : public IRenderData
{
}

void SelectSearchRegions(std::vector<til::inclusive_rect> /*source*/) override
{
}

const til::point GetSelectionAnchor() const noexcept
{
return {};
Expand Down
5 changes: 5 additions & 0 deletions src/interactivity/onecore/BgfxEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ CATCH_RETURN()
return S_OK;
}

[[nodiscard]] HRESULT BgfxEngine::PaintSelections(const std::vector<til::rect>& /*rects*/) noexcept
{
return S_OK;
}

[[nodiscard]] HRESULT BgfxEngine::PaintCursor(const CursorOptions& options) noexcept
try
{
Expand Down
1 change: 1 addition & 0 deletions src/interactivity/onecore/BgfxEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace Microsoft::Console::Render
const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(GridLineSet const lines, COLORREF const color, size_t const cchLine, til::point const coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const til::rect& rect) noexcept override;
[[nodiscard]] HRESULT PaintSelections(const std::vector<til::rect>& rects) noexcept override;

[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;

Expand Down
45 changes: 45 additions & 0 deletions src/renderer/atlas/AtlasEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,51 @@ try
}
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintSelections(const std::vector<til::rect>& rects) noexcept
try
{
// Unfortunately there's no step after Renderer::_PaintBufferOutput that
// would inform us that it's done with the last AtlasEngine::PaintBufferLine.
// As such we got to call _flushBufferLine() here just to be sure.
_flushBufferLine();

for (auto rect : rects)
{
const auto y = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.top, 0, _p.s->viewportCellCount.y));
const auto from = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.left, 0, _p.s->viewportCellCount.x - 1));
const auto to = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.right, from, _p.s->viewportCellCount.x));

if (y < _p.rows.size() && rect.top >= 0)
{
auto& row = *_p.rows[y];

auto it = std::find_if(row.searchSelections.begin(), row.searchSelections.end(), [&from](const SearchSelection& selection) {
return selection.from == from;
});

if (it != row.searchSelections.end())
{
if (to > it->to)
{
it->to = to;
}
}
else
{
auto s = SearchSelection{ from, to };
row.searchSelections.emplace_back(s);
}

_p.dirtyRectInPx.left = std::min(_p.dirtyRectInPx.left, from * _p.s->font->cellSize.x);
_p.dirtyRectInPx.top = std::min(_p.dirtyRectInPx.top, y * _p.s->font->cellSize.y);
_p.dirtyRectInPx.right = std::max(_p.dirtyRectInPx.right, to * _p.s->font->cellSize.x);
_p.dirtyRectInPx.bottom = std::max(_p.dirtyRectInPx.bottom, _p.dirtyRectInPx.top + _p.s->font->cellSize.y);
}
}
return S_OK;
}
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintCursor(const CursorOptions& options) noexcept
try
{
Expand Down
1 change: 1 addition & 0 deletions src/renderer/atlas/AtlasEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace Microsoft::Console::Render::Atlas
[[nodiscard]] HRESULT PaintBufferLine(std::span<const Cluster> clusters, til::point coord, bool fTrimLeft, bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(GridLineSet lines, COLORREF color, size_t cchLine, til::point coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const til::rect& rect) noexcept override;
[[nodiscard]] HRESULT PaintSelections(const std::vector<til::rect>& rects) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const RenderSettings& renderSettings, gsl::not_null<IRenderData*> pData, bool usingSoftFont, bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept override;
Expand Down
33 changes: 33 additions & 0 deletions src/renderer/atlas/BackendD3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ void BackendD3D::Render(RenderingPayload& p)
_drawBackground(p);
_drawCursorBackground(p);
_drawText(p);
_drawSearchSelections(p);
_drawSelection(p);
#if ATLAS_DEBUG_SHOW_DIRTY
_debugShowDirty(p);
Expand Down Expand Up @@ -2066,6 +2067,38 @@ size_t BackendD3D::_drawCursorForegroundSlowPath(const CursorRect& c, size_t off
return addedInstances;
}

void BackendD3D::_drawSearchSelections(const RenderingPayload& p)
{
u16 y = 0;

for (const auto& row : p.rows)
{
if (!row->searchSelections.empty())
{
for (auto s : row->searchSelections)
{
if (s.from != row->selectionFrom)
{
_appendQuad() = {
.shadingType = ShadingType::Selection,
.position = {
p.s->font->cellSize.x * s.from,
p.s->font->cellSize.y * y,
},
.size = {
static_cast<u16>(p.s->font->cellSize.x * (s.to - s.from)),
p.s->font->cellSize.y,
},
.color = p.s->misc->searchSelectionColor,
};
}
}
}

y++;
}
}

void BackendD3D::_drawSelection(const RenderingPayload& p)
{
u16 y = 0;
Expand Down
Loading

0 comments on commit 8a5dfc6

Please sign in to comment.