diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index dc235b0602..3255c5fba3 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -697,12 +697,24 @@ bool Pane::SwapPanes(std::shared_ptr first, std::shared_ptr second) // Refocus the last pane if there was a pane focused if (const auto focus = first->GetActivePane()) { - focus->_Focus(); + // GH#18184: manually focus the pane and content. + // _Focus() results in no-op because the pane was _lastActive + focus->GotFocus.raise(focus, FocusState::Programmatic); + if (const auto& lastContent{ focus->GetLastFocusedContent() }) + { + lastContent.Focus(FocusState::Programmatic); + } } if (const auto focus = second->GetActivePane()) { - focus->_Focus(); + // GH#18184: manually focus the pane and content. + // _Focus() results in no-op because the pane was _lastActive + focus->GotFocus.raise(focus, FocusState::Programmatic); + if (const auto& lastContent{ focus->GetLastFocusedContent() }) + { + lastContent.Focus(FocusState::Programmatic); + } } return true; diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index a96adb7a1d..61d699a6cc 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -955,6 +955,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + void ControlCore::SetHighContrastMode(const bool enabled) + { + _terminal->SetHighContrastMode(enabled); + } + Control::IControlSettings ControlCore::Settings() { return *_settings; diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 8e99e26155..2453670d3f 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -94,6 +94,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateSettings(const Control::IControlSettings& settings, const IControlAppearance& newAppearance); void ApplyAppearance(const bool focused); + void SetHighContrastMode(const bool enabled); Control::IControlSettings Settings(); Control::IControlAppearance FocusedAppearance() const; Control::IControlAppearance UnfocusedAppearance() const; diff --git a/src/cascadia/TerminalControl/ControlCore.idl b/src/cascadia/TerminalControl/ControlCore.idl index 528bc11458..bc704a1342 100644 --- a/src/cascadia/TerminalControl/ControlCore.idl +++ b/src/cascadia/TerminalControl/ControlCore.idl @@ -102,6 +102,7 @@ namespace Microsoft.Terminal.Control IControlAppearance FocusedAppearance { get; }; IControlAppearance UnfocusedAppearance { get; }; Boolean HasUnfocusedAppearance(); + void SetHighContrastMode(Boolean enabled); UInt64 SwapChainHandle { get; }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b38c651e3d..67809d4cea 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -257,6 +257,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation return get_self(_termControl->_core); } + static Windows::UI::ViewManagement::AccessibilitySettings& _GetAccessibilitySettings() + { + static Windows::UI::ViewManagement::AccessibilitySettings accessibilitySettings; + return accessibilitySettings; + } + TermControl::TermControl(IControlSettings settings, Control::IControlAppearance unfocusedAppearance, TerminalConnection::ITerminalConnection connection) : @@ -276,6 +282,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core = _interactivity.Core(); + // If high contrast mode was changed, update the appearance appropriately. + _core.SetHighContrastMode(_GetAccessibilitySettings().HighContrast()); + _revokers.HighContrastChanged = _GetAccessibilitySettings().HighContrastChanged(winrt::auto_revoke, [weakThis{ get_weak() }](const Windows::UI::ViewManagement::AccessibilitySettings& a11ySettings, auto&&) { + if (auto termControl = weakThis.get()) + { + termControl->_core.SetHighContrastMode(a11ySettings.HighContrast()); + termControl->_core.ApplyAppearance(termControl->_focused); + } + }); + // This event is specifically triggered by the renderer thread, a BG thread. Use a weak ref here. _revokers.RendererEnteredErrorState = _core.RendererEnteredErrorState(winrt::auto_revoke, { get_weak(), &TermControl::_RendererEnteredErrorState }); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 2e8fadd850..7fe3db1be0 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -362,7 +362,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation }; bool _InitializeTerminal(const InitializeReason reason); safe_void_coroutine _restoreInBackground(); - void _SetFontSize(int fontSize); void _TappedHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e); void _KeyDownHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e); void _KeyUpHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e); @@ -394,8 +393,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _SwapChainSizeChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::SizeChangedEventArgs& e); void _SwapChainScaleChanged(const Windows::UI::Xaml::Controls::SwapChainPanel& sender, const Windows::Foundation::IInspectable& args); - void _TerminalTabColorChanged(const std::optional color); - void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args); bool _CapturePointer(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e); @@ -480,6 +477,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // These are set up in _InitializeTerminal Control::ControlCore::RendererWarning_revoker RendererWarning; Control::ControlCore::SwapChainChanged_revoker SwapChainChanged; + Windows::UI::ViewManagement::AccessibilitySettings::HighContrastChanged_revoker HighContrastChanged; Control::ControlInteractivity::OpenHyperlink_revoker interactivityOpenHyperlink; Control::ControlInteractivity::ScrollPositionChanged_revoker interactivityScrollPositionChanged; diff --git a/src/cascadia/TerminalCore/ICoreAppearance.idl b/src/cascadia/TerminalCore/ICoreAppearance.idl index fa0364a322..d86fdd4262 100644 --- a/src/cascadia/TerminalCore/ICoreAppearance.idl +++ b/src/cascadia/TerminalCore/ICoreAppearance.idl @@ -23,7 +23,8 @@ namespace Microsoft.Terminal.Core { Never, Indexed, - Always + Always, + Automatic }; // TerminalCore declares its own Color struct to avoid depending diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 68d7178187..039b251144 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -143,7 +143,15 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance) renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBold, appearance.IntenseIsBold()); renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, appearance.IntenseIsBright()); - switch (appearance.AdjustIndistinguishableColors()) + // If AIC is set to Automatic, + // update the value based on if high contrast mode is enabled. + AdjustTextMode deducedAIC = appearance.AdjustIndistinguishableColors(); + if (deducedAIC == AdjustTextMode::Automatic) + { + deducedAIC = _highContrastMode ? AdjustTextMode::Indexed : AdjustTextMode::Never; + } + + switch (deducedAIC) { case AdjustTextMode::Always: renderSettings.SetRenderMode(RenderSettings::Mode::IndexedDistinguishableColors, false); @@ -213,6 +221,11 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance) _NotifyScrollEvent(); } +void Terminal::SetHighContrastMode(bool hc) noexcept +{ + _highContrastMode = hc; +} + void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) { auto& engine = reinterpret_cast(_stateMachine->Engine()); diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 1459c39fc3..afbf873da9 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -92,6 +92,7 @@ public: void UpdateSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings); void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance); + void SetHighContrastMode(bool hc) noexcept; void SetFontInfo(const FontInfo& fontInfo); void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle); void SetVtChecksumReportSupport(const bool enabled); @@ -382,6 +383,7 @@ private: std::wstring _answerbackMessage; std::wstring _workingDirectory; + bool _highContrastMode = false; // This default fake font value is only used to check if the font is a raster font. // Otherwise, the font is changed to a real value with the renderer via TriggerFontChange. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 82d7e15eb7..ae0eaa9c8d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -1110,6 +1110,10 @@ Always An option to choose from for the "adjust indistinguishable colors" setting. When selected, we will adjust the text colors for visibility. + + Automatic + An option to choose from for the "adjust indistinguishable colors" setting. When selected, we will adjust the text colors for visibility only when the colors are part of this profile's color scheme's color table if and only if high contrast mode is enabled. + Bar ( ┃ ) {Locked="┃"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a vertical bar. The character in the parentheses is used to show what it looks like. diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 80c14b960f..d86eb0dc0f 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -136,7 +136,7 @@ Author(s): X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center) \ X(hstring, BackgroundImagePath, "backgroundImage") \ X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \ - X(Core::AdjustTextMode, AdjustIndistinguishableColors, "adjustIndistinguishableColors", Core::AdjustTextMode::Never) \ + X(Core::AdjustTextMode, AdjustIndistinguishableColors, "adjustIndistinguishableColors", Core::AdjustTextMode::Automatic) \ X(bool, UseAcrylic, "useAcrylic", false) // Intentionally omitted Appearance settings: diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 94432ca3da..0d0e63248e 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -35,10 +35,11 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::CursorStyle) // - Helper for converting a user-specified adjustTextMode value to its corresponding enum JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::AdjustTextMode) { - JSON_MAPPINGS(3) = { + JSON_MAPPINGS(4) = { pair_type{ "never", ValueType::Never }, pair_type{ "indexed", ValueType::Indexed }, pair_type{ "always", ValueType::Always }, + pair_type{ "automatic", ValueType::Automatic }, }; // Override mapping parser to add boolean parsing diff --git a/src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp b/src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp index 19d6f50cc8..c4baf36a39 100644 --- a/src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp +++ b/src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp @@ -45,7 +45,15 @@ std::wstring VsDevCmdGenerator::GetProfileCommandLine(const VsSetupConfiguration // The "-startdir" parameter will prevent "vsdevcmd" from automatically // setting the shell path so the path in the profile will be used instead. #if defined(_M_ARM64) - commandLine.append(LR"(" -startdir=none -arch=arm64 -host_arch=x64)"); + commandLine.append(LR"(" -startdir=none -arch=arm64 -host_arch=)"); + if (instance.VersionInRange(L"[17.4,")) + { + commandLine.append(LR"(arm64)"); + } + else + { + commandLine.append(LR"(x64)"); + } #elif defined(_M_AMD64) commandLine.append(LR"(" -startdir=none -arch=x64 -host_arch=x64)"); #else diff --git a/src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp b/src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp index 22c17cd98a..ce14532107 100644 --- a/src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp +++ b/src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp @@ -39,17 +39,43 @@ std::wstring VsDevShellGenerator::GetProfileName(const VsSetupConfiguration::VsS std::wstring VsDevShellGenerator::GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const { - // The triple-quotes are a PowerShell path escape sequence that can safely be stored in a JSON object. - // The "SkipAutomaticLocation" parameter will prevent "Enter-VsDevShell" from automatically setting the shell path - // so the path in the profile will be used instead. + // Build this in stages, so reserve space now std::wstring commandLine; commandLine.reserve(256); - commandLine.append(LR"(powershell.exe -NoExit -Command "&{Import-Module """)"); + + // Try to detect if `pwsh.exe` is available in the PATH, if so we want to use that + // Allow some extra space in case user put it somewhere odd + // We do need to allocate space for the full path even if we don't want to paste the whole thing in + wchar_t pwshPath[MAX_PATH] = { 0 }; + const auto pwshExeName = L"pwsh.exe"; + if (SearchPathW(nullptr, pwshExeName, nullptr, MAX_PATH, pwshPath, nullptr)) + { + commandLine.append(pwshExeName); + } + else + { + commandLine.append(L"powershell.exe"); + } + + // The triple-quotes are a PowerShell path escape sequence that can safely be stored in a JSON object. + // The "SkipAutomaticLocation" parameter will prevent "Enter-VsDevShell" from automatically setting the shell path + // so the path in the profile will be used instead + commandLine.append(LR"( -NoExit -Command "&{Import-Module """)"); commandLine.append(GetDevShellModulePath(instance)); commandLine.append(LR"("""; Enter-VsDevShell )"); commandLine.append(instance.GetInstanceId()); #if defined(_M_ARM64) - commandLine.append(LR"( -SkipAutomaticLocation -DevCmdArguments """-arch=arm64 -host_arch=x64"""}")"); + // This part stays constant no matter what + commandLine.append(LR"( -SkipAutomaticLocation -DevCmdArguments """-arch=arm64 -host_arch=)"); + if (instance.VersionInRange(L"[17.4,")) + { + commandLine.append(LR"("arm64 """}")"); + } + // If an old version of VS is installed without ARM64 host support + else + { + commandLine.append(LR"("x64 """}")"); + } #elif defined(_M_AMD64) commandLine.append(LR"( -SkipAutomaticLocation -DevCmdArguments """-arch=x64 -host_arch=x64"""}")"); #else diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h index 42c3b1b9d3..107773da06 100644 --- a/src/cascadia/inc/ControlProperties.h +++ b/src/cascadia/inc/ControlProperties.h @@ -14,7 +14,7 @@ X(til::color, SelectionBackground, DEFAULT_FOREGROUND) \ X(bool, IntenseIsBold) \ X(bool, IntenseIsBright, true) \ - X(winrt::Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors, winrt::Microsoft::Terminal::Core::AdjustTextMode::Never) + X(winrt::Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors, winrt::Microsoft::Terminal::Core::AdjustTextMode::Automatic) // --------------------------- Control Appearance --------------------------- // All of these settings are defined in IControlAppearance.