diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index ac01af8cb3b..88794eda57c 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -1461,7 +1461,19 @@ namespace winrt::TerminalApp::implementation } // Aggregate all the commands from the different sources that - // the user selected. + // the user selected. This is the order presented to the user + + if (WI_IsFlagSet(source, SuggestionsSource::QuickFixes) && + context != nullptr && + context.QuickFixes() != nullptr) + { + // \ue74c --> OEM icon + const auto recentCommands = Command::HistoryToCommands(context.QuickFixes(), hstring{ L"" }, false, hstring{ L"\ue74c" }); + for (const auto& t : recentCommands) + { + commandsCollection.push_back(t); + } + } // Tasks are all the sendInput commands the user has saved in // their settings file. Ask the ActionMap for those. @@ -1488,18 +1500,6 @@ namespace winrt::TerminalApp::implementation } } - if (WI_IsFlagSet(source, SuggestionsSource::QuickFixes) && - context != nullptr && - context.QuickFixes() != nullptr) - { - // \ue74c --> OEM icon - const auto recentCommands = Command::HistoryToCommands(context.QuickFixes(), hstring{ L"" }, false, hstring{ L"\ue74c" }); - for (const auto& t : recentCommands) - { - commandsCollection.push_back(t); - } - } - // Open the palette with all these commands in it. _OpenSuggestions(_GetActiveControl(), winrt::single_threaded_vector(std::move(commandsCollection)), @@ -1593,4 +1593,14 @@ namespace winrt::TerminalApp::implementation _ShowAboutDialog(); args.Handled(true); } + + void TerminalPage::_HandleQuickFix(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + if (const auto& control{ _GetActiveControl() }) + { + const auto handled = control.OpenQuickFixMenu(); + args.Handled(handled); + } + } } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 6bc3d488b5b..e53a8ada1c4 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -340,6 +340,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } }); + if constexpr (Feature_QuickFix::IsEnabled()) + { + QuickFixMenu().Closed([weakThis = get_weak()](auto&&, auto&&) { + if (auto control{ weakThis.get() }; control && !control->_IsClosing()) + { + // Expand the quick fix button if it's collapsed (looks nicer) + if (control->_quickFixButtonCollapsible) + { + VisualStateManager::GoToState(*control, StateCollapsed, false); + } + } + }); + } } void TermControl::_QuickFixButton_PointerEntered(const IInspectable& /*sender*/, const PointerRoutedEventArgs& /*e*/) @@ -3555,8 +3568,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (Feature_QuickFix::IsEnabled()) { - auto quickFixBtn = FindName(L"QuickFixButton").as(); - quickFixBtn.Height(args.Height() / dpiScale); + QuickFixButton().Height(args.Height() / dpiScale); QuickFixIcon().FontSize(static_cast(args.Width() / dpiScale)); RefreshQuickFixMenu(); } @@ -3892,6 +3904,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation return std::max(CharacterDimensions().Width * 2.0 / 3.0, GetPadding().Left); } + bool TermControl::OpenQuickFixMenu() + { + if constexpr (Feature_QuickFix::IsEnabled()) + { + if (_core.QuickFixesAvailable()) + { + // Expand the quick fix button if it's collapsed (looks nicer) + if (_quickFixButtonCollapsible) + { + VisualStateManager::GoToState(*this, StateNormal, false); + } + auto quickFixBtn = QuickFixButton(); + quickFixBtn.Flyout().ShowAt(quickFixBtn); + return true; + } + } + return false; + } + void TermControl::RefreshQuickFixMenu() { if (!Feature_QuickFix::IsEnabled()) @@ -3899,7 +3930,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } - auto quickFixBtn = FindName(L"QuickFixButton").as(); + auto quickFixBtn = QuickFixButton(); if (!_core.QuickFixesAvailable()) { quickFixBtn.Visibility(Visibility::Collapsed); @@ -3920,7 +3951,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto viewportBufferPosition = rd->GetViewport(); const auto cursorBufferPosition = rd->GetCursorPosition(); rd->UnlockConsole(); - if (cursorBufferPosition.y < viewportBufferPosition.Top() || cursorBufferPosition.y > viewportBufferPosition.BottomExclusive()) + if (cursorBufferPosition.y < viewportBufferPosition.Top() || cursorBufferPosition.y > viewportBufferPosition.BottomInclusive()) { quickFixBtn.Visibility(Visibility::Collapsed); return; diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 241eb1d6c7a..13166e18c7a 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -182,6 +182,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void RawWriteString(const winrt::hstring& text); void ShowContextMenu(); + bool OpenQuickFixMenu(); void RefreshQuickFixMenu(); void ClearQuickFix(); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index bc003c3e667..7b643ad1cb3 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -149,6 +149,7 @@ namespace Microsoft.Terminal.Control Double QuickFixButtonCollapsedWidth { get; }; void ShowContextMenu(); + Boolean OpenQuickFixMenu(); void RefreshQuickFixMenu(); void ClearQuickFix(); diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index c6301dd1eeb..01987a3bd5e 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1597,12 +1597,13 @@ void Terminal::ColorSelection(const TextAttribute& attr, winrt::Microsoft::Termi } // Method Description: -// - Returns the position of the cursor relative to the active viewport +// - Returns the position of the cursor relative to the visible viewport til::point Terminal::GetViewportRelativeCursorPosition() const noexcept { const auto absoluteCursorPosition{ GetCursorPosition() }; - const auto viewport{ _GetMutableViewport() }; - return absoluteCursorPosition - viewport.Origin(); + const auto mutableViewport{ _GetMutableViewport() }; + const auto relativeCursorPos = absoluteCursorPosition - mutableViewport.Origin(); + return { relativeCursorPos.x, relativeCursorPos.y + _scrollOffset }; } void Terminal::PreviewText(std::wstring_view input) diff --git a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp index 8fe015b8b15..e4f0205a2dd 100644 --- a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp @@ -98,6 +98,7 @@ static constexpr std::string_view RestartConnectionKey{ "restartConnection" }; static constexpr std::string_view ToggleBroadcastInputKey{ "toggleBroadcastInput" }; static constexpr std::string_view OpenScratchpadKey{ "experimental.openScratchpad" }; static constexpr std::string_view OpenAboutKey{ "openAbout" }; +static constexpr std::string_view QuickFixKey{ "quickFix" }; static constexpr std::string_view ActionKey{ "action" }; @@ -438,6 +439,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { ShortcutAction::ToggleBroadcastInput, RS_(L"ToggleBroadcastInputCommandKey") }, { ShortcutAction::OpenScratchpad, RS_(L"OpenScratchpadKey") }, { ShortcutAction::OpenAbout, RS_(L"OpenAboutCommandKey") }, + { ShortcutAction::QuickFix, RS_(L"QuickFixCommandKey") }, }; }(); diff --git a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h index 2432b40e12c..daeb1f399bd 100644 --- a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h +++ b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h @@ -111,7 +111,8 @@ ON_ALL_ACTIONS(RestartConnection) \ ON_ALL_ACTIONS(ToggleBroadcastInput) \ ON_ALL_ACTIONS(OpenScratchpad) \ - ON_ALL_ACTIONS(OpenAbout) + ON_ALL_ACTIONS(OpenAbout) \ + ON_ALL_ACTIONS(QuickFix) #define ALL_SHORTCUT_ACTIONS_WITH_ARGS \ ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \ diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index f4b39abc297..33ee2ef2942 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -734,4 +734,7 @@ Save Snippet + + Open quick fix menu + diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index f6713e265b0..1d2b8f2c472 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -447,6 +447,8 @@ { "command": "restoreLastClosed", "id": "Terminal.RestoreLastClosed" }, { "command": "openAbout", "id": "Terminal.OpenAboutDialog" }, { "command": "experimental.openTasks", "id": "Terminal.OpenTasks" }, + { "command": "quickFix", "id": "Terminal.QuickFix" }, + { "command": { "action": "showSuggestions", "source": "all"}, "id": "Terminal.Suggestions" }, // Tab Management // "command": "closeTab" is unbound by default. @@ -639,6 +641,7 @@ { "keys":"ctrl+shift+p", "id": "Terminal.ToggleCommandPalette" }, { "keys":"win+sc(41)", "id": "Terminal.QuakeMode" }, { "keys": "alt+space", "id": "Terminal.OpenSystemMenu" }, + { "keys": "ctrl+shift+period", "id": "Terminal.Suggestions" }, // Tab Management // "command": "closeTab" is unbound by default.