Skip to content

Commit d8c8807

Browse files
committed
feature flag; fix scroll bug; clear QF on enter
1 parent 48a36be commit d8c8807

File tree

10 files changed

+113
-198
lines changed

10 files changed

+113
-198
lines changed

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 4 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,160 +2908,14 @@ namespace winrt::TerminalApp::implementation
29082908
{
29092909
assert(!Dispatcher().HasThreadAccess());
29102910

2911-
#if 0
2912-
static constexpr CLSID CLSID_PackageManager = { 0xC53A4F16, 0x787E, 0x42A4, 0xB3, 0x04, 0x29, 0xEF, 0xFB, 0x4B, 0xF5, 0x97 }; //C53A4F16-787E-42A4-B304-29EFFB4BF597
2913-
static constexpr CLSID CLSID_FindPackagesOptions = { 0x572DED96, 0x9C60, 0x4526, { 0x8F, 0x92, 0xEE, 0x7D, 0x91, 0xD3, 0x8C, 0x1A } }; //572DED96-9C60-4526-8F92-EE7D91D38C1A
2914-
static constexpr CLSID CLSID_PackageMatchFilter = { 0xD02C9DAF, 0x99DC, 0x429C, { 0xB5, 0x03, 0x4E, 0x50, 0x4E, 0x4A, 0xB0, 0x00 } }; //D02C9DAF-99DC-429C-B503-4E504E4AB000
2915-
2916-
static constexpr unsigned int maxSuggestions = 5;
2917-
bool tooManySuggestions = false;
2918-
2919-
// TODO CARLOS: this is where we fail! "Class not registered" error
2920-
PackageManager pkgManager = winrt::create_instance<PackageManager>(CLSID_PackageManager, CLSCTX_ALL);
2921-
auto catalogRef = pkgManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog::OpenWindowsCatalog);
2922-
auto connectResult = catalogRef.Connect();
2923-
int retryCount = 0;
2924-
while (connectResult.Status() != ConnectResultStatus::Ok && retryCount < 3)
2925-
{
2926-
connectResult = catalogRef.Connect();
2927-
++retryCount;
2928-
}
2929-
if (connectResult.Status() != ConnectResultStatus::Ok)
2911+
if (!Feature_QuickFix::IsEnabled())
29302912
{
2931-
return;
2932-
}
2933-
auto catalog = connectResult.PackageCatalog();
2934-
2935-
// Perform the query (search by command)
2936-
auto packageMatchFilter = winrt::create_instance<PackageMatchFilter>(CLSID_PackageMatchFilter, CLSCTX_ALL);
2937-
auto findPackagesOptions = winrt::create_instance<FindPackagesOptions>(CLSID_FindPackagesOptions, CLSCTX_ALL);
2938-
2939-
// Helper lambda to apply a filter to the query
2940-
auto applyPackageMatchFilter = [&packageMatchFilter, &findPackagesOptions](PackageMatchField field, PackageFieldMatchOption matchOption, hstring query) {
2941-
// Configure filter
2942-
packageMatchFilter.Field(field);
2943-
packageMatchFilter.Option(matchOption);
2944-
packageMatchFilter.Value(query);
2945-
2946-
// Apply filter
2947-
findPackagesOptions.ResultLimit(maxSuggestions + 1u);
2948-
findPackagesOptions.Filters().Clear();
2949-
findPackagesOptions.Filters().Append(packageMatchFilter);
2950-
};
2951-
2952-
// Helper lambda to retrieve the best matching package(s) from the query's result
2953-
auto tryGetBestMatchingPackage = [&tooManySuggestions](IVectorView<MatchResult> matches) {
2954-
std::vector<CatalogPackage> results;
2955-
results.reserve(std::min(matches.Size(), maxSuggestions));
2956-
if (matches.Size() == 1)
2957-
{
2958-
// One match --> return the package
2959-
results.emplace_back(matches.GetAt(0).CatalogPackage());
2960-
}
2961-
else if (matches.Size() > 1)
2962-
{
2963-
// Multiple matches --> display top 5 matches (prioritize best matches first)
2964-
std::queue<CatalogPackage> bestExactMatches, secondaryMatches, tertiaryMatches;
2965-
for (auto match : matches)
2966-
{
2967-
switch (match.MatchCriteria().Option())
2968-
{
2969-
case PackageFieldMatchOption::EqualsCaseInsensitive:
2970-
case PackageFieldMatchOption::Equals:
2971-
bestExactMatches.push(match.CatalogPackage());
2972-
break;
2973-
case PackageFieldMatchOption::StartsWithCaseInsensitive:
2974-
secondaryMatches.push(match.CatalogPackage());
2975-
break;
2976-
case PackageFieldMatchOption::ContainsCaseInsensitive:
2977-
tertiaryMatches.push(match.CatalogPackage());
2978-
break;
2979-
}
2980-
}
2981-
2982-
// Now return the top maxSuggestions
2983-
while (results.size() < maxSuggestions)
2984-
{
2985-
if (bestExactMatches.size() > 0)
2986-
{
2987-
results.emplace_back(bestExactMatches.front());
2988-
bestExactMatches.pop();
2989-
}
2990-
else if (secondaryMatches.size() > 0)
2991-
{
2992-
results.emplace_back(secondaryMatches.front());
2993-
secondaryMatches.pop();
2994-
}
2995-
else if (tertiaryMatches.size() > 0)
2996-
{
2997-
results.emplace_back(tertiaryMatches.front());
2998-
tertiaryMatches.pop();
2999-
}
3000-
else
3001-
{
3002-
break;
3003-
}
3004-
}
3005-
}
3006-
tooManySuggestions = matches.Size() > maxSuggestions;
3007-
return results;
3008-
};
3009-
3010-
// Search by command
3011-
auto missingCmd = args.MissingCommand();
3012-
std::wstring searchOption = L"command";
3013-
applyPackageMatchFilter(PackageMatchField::Command, PackageFieldMatchOption::StartsWithCaseInsensitive, missingCmd);
3014-
auto findPackagesResult = catalog.FindPackages(findPackagesOptions);
3015-
auto matches = findPackagesResult.Matches();
3016-
auto pkgList = tryGetBestMatchingPackage(matches);
3017-
if (pkgList.empty())
3018-
{
3019-
// No matches found --> search by name
3020-
applyPackageMatchFilter(PackageMatchField::Name, PackageFieldMatchOption::ContainsCaseInsensitive, missingCmd);
3021-
3022-
findPackagesResult = catalog.FindPackages(findPackagesOptions);
3023-
matches = findPackagesResult.Matches();
3024-
pkgList = tryGetBestMatchingPackage(matches);
3025-
searchOption = L"name";
3026-
3027-
if (pkgList.empty())
3028-
{
3029-
// No matches found --> search by moniker
3030-
applyPackageMatchFilter(PackageMatchField::Moniker, PackageFieldMatchOption::ContainsCaseInsensitive, missingCmd);
3031-
3032-
// Perform the query (search by name)
3033-
findPackagesResult = catalog.FindPackages(findPackagesOptions);
3034-
matches = findPackagesResult.Matches();
3035-
pkgList = tryGetBestMatchingPackage(matches);
3036-
searchOption = L"moniker";
3037-
}
2913+
co_return;
30382914
}
30392915

3040-
// Display packages in UI
3041-
if (!pkgList.empty())
3042-
{
3043-
std::vector<std::wstring> suggestions;
3044-
suggestions.reserve(pkgList.size());
3045-
for (auto pkg : pkgList)
3046-
{
3047-
suggestions.emplace_back(fmt::format(L"winget install --id {}", pkg.Id()));
3048-
}
3049-
3050-
std::wstring footer = tooManySuggestions ?
3051-
fmt::format(L"winget search --{} {}", searchOption, missingCmd) :
3052-
L"";
3053-
}
3054-
#elif defined(DEBUG) || defined(_DEBUG) || defined(DBG)
3055-
//const bool tooManySuggestions = false;
3056-
//const std::wstring searchOption = L"command";
3057-
//const std::wstring missingCmd = args.MissingCommand().data();
3058-
std::vector<std::wstring> pkgList = { L"pkg1", L"pkg2", L"pkg3" };
30592916
std::vector<hstring> suggestions;
3060-
suggestions.reserve(pkgList.size());
3061-
for (auto pkg : pkgList)
3062-
{
3063-
suggestions.emplace_back(fmt::format(L"winget install --id {}", pkg));
3064-
}
2917+
suggestions.reserve(1);
2918+
suggestions.emplace_back(fmt::format(L"winget install {}", args.MissingCommand()));
30652919

30662920
co_await wil::resume_foreground(Dispatcher());
30672921

@@ -3072,7 +2926,6 @@ namespace winrt::TerminalApp::implementation
30722926
}
30732927
term.UpdateWinGetSuggestions(single_threaded_vector<hstring>(std::move(suggestions)));
30742928
term.ShowQuickFixMenu();
3075-
#endif
30762929
}
30772930

30782931
// Method Description:

src/cascadia/TerminalControl/ControlCore.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
115115
auto pfnSearchMissingCommand = [this](auto&& PH1) { _terminalSearchMissingCommand(std::forward<decltype(PH1)>(PH1)); };
116116
_terminal->SetSearchMissingCommandCallback(pfnSearchMissingCommand);
117117

118+
auto pfnClearQuickFix = [this] { _terminalClearQuickFix(); };
119+
_terminal->SetClearQuickFixCallback(pfnClearQuickFix);
120+
118121
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
119122
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
120123
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
@@ -1622,6 +1625,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
16221625
SearchMissingCommand.raise(*this, make<implementation::SearchMissingCommandEventArgs>(hstring{ missingCommand }));
16231626
}
16241627

1628+
void ControlCore::_terminalClearQuickFix()
1629+
{
1630+
ClearQuickFix.raise(*this, nullptr);
1631+
}
1632+
16251633
bool ControlCore::HasSelection() const
16261634
{
16271635
const auto lock = _terminal->LockForReading();

src/cascadia/TerminalControl/ControlCore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
287287
til::typed_event<IInspectable, Control::OpenHyperlinkEventArgs> OpenHyperlink;
288288
til::typed_event<IInspectable, Control::CompletionsChangedEventArgs> CompletionsChanged;
289289
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
290+
til::typed_event<> ClearQuickFix;
290291

291292
til::typed_event<> CloseTerminalRequested;
292293
til::typed_event<> RestartTerminalRequested;
@@ -383,6 +384,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
383384
const int velocity,
384385
const std::chrono::microseconds duration);
385386
void _terminalSearchMissingCommand(std::wstring_view missingCommand);
387+
void _terminalClearQuickFix();
386388

387389
winrt::fire_and_forget _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);
388390

src/cascadia/TerminalControl/ControlCore.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ namespace Microsoft.Terminal.Control
176176
event Windows.Foundation.TypedEventHandler<Object, Object> RendererEnteredErrorState;
177177
event Windows.Foundation.TypedEventHandler<Object, ShowWindowArgs> ShowWindowChanged;
178178
event Windows.Foundation.TypedEventHandler<Object, SearchMissingCommandEventArgs> SearchMissingCommand;
179+
event Windows.Foundation.TypedEventHandler<Object, Object> ClearQuickFix;
179180

180181
// These events are always called from the UI thread (bugs aside)
181182
event Windows.Foundation.TypedEventHandler<Object, FontSizeChangedArgs> FontSizeChanged;

src/cascadia/TerminalControl/TermControl.cpp

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
227227

228228
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
229229

230+
_revokers.ClearQuickFix = _core.ClearQuickFix(winrt::auto_revoke, { get_weak(), &TermControl::_clearQuickFix });
231+
230232
// Initialize the terminal only once the swapchainpanel is loaded - that
231233
// way, we'll be able to query the real pixel size it got on layout
232234
_layoutUpdatedRevoker = SwapChainPanel().LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {
@@ -337,9 +339,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
337339
}
338340
});
339341

340-
auto quickFixBtn{ QuickFixButton() };
341-
quickFixBtn.PointerEntered({ get_weak(), &TermControl::QuickFixButton_PointerEntered });
342-
quickFixBtn.PointerExited({ get_weak(), &TermControl::QuickFixButton_PointerExited });
342+
if (Feature_QuickFix::IsEnabled())
343+
{
344+
auto quickFixBtn{ QuickFixButton() };
345+
quickFixBtn.PointerEntered({ get_weak(), &TermControl::QuickFixButton_PointerEntered });
346+
quickFixBtn.PointerExited({ get_weak(), &TermControl::QuickFixButton_PointerExited });
347+
}
343348
}
344349

345350
void TermControl::QuickFixButton_PointerEntered(const IInspectable& /*sender*/, const PointerRoutedEventArgs& /*e*/)
@@ -827,10 +832,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
827832
// update. If we enabled scrollbar marks, then great, when we handle
828833
// that message, we'll redraw them.
829834

830-
// update the position of the quick fix menu (in case we changed the padding)
831-
if (QuickFixButton().Visibility() == Visibility::Visible)
835+
if (Feature_QuickFix::IsEnabled())
832836
{
833-
ShowQuickFixMenu();
837+
// update the position of the quick fix menu (in case we changed the padding)
838+
if (_quickFixesAvailable)
839+
{
840+
ShowQuickFixMenu();
841+
}
834842
}
835843
}
836844

@@ -2333,7 +2341,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
23332341
_updateSelectionMarkers(nullptr, winrt::make<UpdateSelectionMarkersEventArgs>(false));
23342342
}
23352343

2336-
if (QuickFixButton().Visibility() == Visibility::Visible)
2344+
if (_quickFixesAvailable)
23372345
{
23382346
ShowQuickFixMenu();
23392347
}
@@ -3514,12 +3522,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
35143522
scaleMarker(SelectionStartMarker());
35153523
scaleMarker(SelectionEndMarker());
35163524

3517-
auto quickFixBtn = QuickFixButton();
3518-
quickFixBtn.Height(args.Height() / dpiScale);
3519-
QuickFixIcon().FontSize(std::min(static_cast<double>(args.Width() / dpiScale), GetPadding().Left));
3520-
if (quickFixBtn.Visibility() == Visibility::Visible)
3525+
if (Feature_QuickFix::IsEnabled())
35213526
{
3522-
ShowQuickFixMenu();
3527+
auto quickFixBtn = QuickFixButton();
3528+
quickFixBtn.Height(args.Height() / dpiScale);
3529+
QuickFixIcon().FontSize(std::min(static_cast<double>(args.Width() / dpiScale), GetPadding().Left));
3530+
if (quickFixBtn.Visibility() == Visibility::Visible)
3531+
{
3532+
ShowQuickFixMenu();
3533+
}
35233534
}
35243535
}
35253536

@@ -3820,21 +3831,38 @@ namespace winrt::Microsoft::Terminal::Control::implementation
38203831
void TermControl::ShowQuickFixMenu()
38213832
{
38223833
auto quickFixBtn{ QuickFixButton() };
3834+
_quickFixesAvailable = true;
38233835

38243836
// If the gutter is narrow, display the collapsed version
38253837
const auto& termPadding = GetPadding();
38263838

38273839
_quickFixButtonCollapsible = termPadding.Left < CharacterDimensions().Width;
38283840
VisualStateManager::GoToState(*this, !_quickFixButtonCollapsible ? StateNormal : StateCollapsed, false);
38293841

3830-
// draw the button in the gutter
3831-
Controls::Canvas::SetLeft(quickFixBtn, -termPadding.Left);
3842+
const auto rd = get_self<ControlCore>(_core)->GetRenderData();
3843+
rd->LockConsole();
3844+
const auto viewportBufferPosition = rd->GetViewport();
3845+
const auto cursorBufferPosition = rd->GetCursorPosition();
3846+
rd->UnlockConsole();
3847+
if (cursorBufferPosition.y < viewportBufferPosition.Top() || cursorBufferPosition.y > viewportBufferPosition.BottomExclusive())
3848+
{
3849+
quickFixBtn.Visibility(Visibility::Collapsed);
3850+
return;
3851+
}
38323852

3853+
// draw the button in the gutter
38333854
const auto& cursorPosInDips = CursorPositionInDips();
3855+
Controls::Canvas::SetLeft(quickFixBtn, -termPadding.Left);
38343856
Controls::Canvas::SetTop(quickFixBtn, cursorPosInDips.Y);
38353857
quickFixBtn.Visibility(Visibility::Visible);
38363858
}
38373859

3860+
void TermControl::_clearQuickFix(const IInspectable& /*sender*/, const IInspectable& /*args*/)
3861+
{
3862+
_quickFixesAvailable = false;
3863+
QuickFixButton().Visibility(Visibility::Collapsed);
3864+
}
3865+
38383866
void TermControl::_PasteCommandHandler(const IInspectable& /*sender*/,
38393867
const IInspectable& /*args*/)
38403868
{

src/cascadia/TerminalControl/TermControl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
248248
bool _focused{ false };
249249
bool _initializedTerminal{ false };
250250
bool _quickFixButtonCollapsible{ false };
251+
bool _quickFixesAvailable{ false };
251252

252253
std::shared_ptr<ThrottledFuncLeading> _playWarningBell;
253254

@@ -402,6 +403,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
402403

403404
void _contextMenuHandler(IInspectable sender, Control::ContextMenuRequestedEventArgs args);
404405
void _showContextMenuAt(const til::point& controlRelativePos);
406+
void _clearQuickFix(const IInspectable& sender, const IInspectable& args);
405407

406408
void _PasteCommandHandler(const IInspectable& sender, const IInspectable& args);
407409
void _CopyCommandHandler(const IInspectable& sender, const IInspectable& args);
@@ -433,6 +435,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
433435
Control::ControlCore::CompletionsChanged_revoker CompletionsChanged;
434436
Control::ControlCore::RestartTerminalRequested_revoker RestartTerminalRequested;
435437
Control::ControlCore::SearchMissingCommand_revoker SearchMissingCommand;
438+
Control::ControlCore::ClearQuickFix_revoker ClearQuickFix;
436439

437440
// These are set up in _InitializeTerminal
438441
Control::ControlCore::RendererWarning_revoker RendererWarning;

src/cascadia/TerminalControl/TermControl.xaml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,15 +1376,7 @@
13761376
</Grid>
13771377

13781378
<VisualStateManager.VisualStateGroups>
1379-
<VisualStateGroup x:Name="CommonStates">
1380-
<VisualStateGroup.Transitions>
1381-
<VisualTransition GeneratedDuration="0:0:0.5"
1382-
From="Collapsed"
1383-
To="Normal" />
1384-
<VisualTransition GeneratedDuration="0:0:0.5"
1385-
From="Normal"
1386-
To="Collapsed" />
1387-
</VisualStateGroup.Transitions>
1379+
<VisualStateGroup x:Name="QuickFixButtonStates">
13881380
<VisualState x:Name="Normal" />
13891381
<VisualState x:Name="Collapsed">
13901382
<VisualState.Setters>

0 commit comments

Comments
 (0)