Automatically enable AdjustIndistinguishableColors if High Contrast mode enabled

This commit is contained in:
Carlos Zamora
2024-05-31 16:16:36 -07:00
parent fa8273065f
commit c9c997e117
26 changed files with 109 additions and 21 deletions

View File

@@ -663,6 +663,11 @@ namespace winrt::TerminalApp::implementation
globals.MinimizeToNotificationArea();
}
void AppLogic::SetHighContrast(bool highContrast)
{
_settings.HighContrastMode(highContrast);
}
bool AppLogic::AllowHeadless()
{
if (!_loadedInitialSettings)

View File

@@ -65,6 +65,7 @@ namespace winrt::TerminalApp::implementation
bool IsolatedMode();
bool AllowHeadless();
bool RequestsTrayIcon();
void SetHighContrast(bool highContrast);
TerminalApp::TerminalWindow CreateNewWindow();

View File

@@ -45,6 +45,7 @@ namespace TerminalApp
Boolean IsolatedMode { get; };
Boolean AllowHeadless { get; };
Boolean RequestsTrayIcon { get; };
void SetHighContrast(Boolean highContrast);
FindTargetWindowResult FindTargetWindow(String[] args);

View File

@@ -339,11 +339,13 @@ namespace winrt::TerminalApp::implementation
RestartTerminalRequested.raise(*this, nullptr);
}
void TerminalPaneContent::UpdateSettings(const CascadiaSettings& /*settings*/)
void TerminalPaneContent::UpdateSettings(const CascadiaSettings& settings)
{
if (const auto& settings{ _cache.TryLookup(_profile) })
if (const auto& cachedSettings{ _cache.TryLookup(_profile) })
{
_control.UpdateControlSettings(settings.DefaultSettings(), settings.UnfocusedSettings());
auto cachedDefaultSettings = cachedSettings.DefaultSettings();
cachedDefaultSettings.HighContrastMode(settings.HighContrastMode());
_control.UpdateControlSettings(cachedDefaultSettings, cachedSettings.UnfocusedSettings());
}
}

View File

@@ -864,6 +864,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_cellHeight = CSSLengthPercentage::FromString(_settings->CellHeight().c_str());
_runtimeOpacity = std::nullopt;
_runtimeFocusedOpacity = std::nullopt;
_terminal->SetHighContrastInfo(settings.HighContrastMode());
// Manually turn off acrylic if they turn off transparency.
_runtimeUseAcrylic = _settings->Opacity() < 1.0 && _settings->UseAcrylic();

View File

@@ -26,6 +26,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
CONTROL_SETTINGS(SETTINGS_GEN)
#undef SETTINGS_GEN
WINRT_PROPERTY(bool, HighContrastMode, false);
private:
winrt::com_ptr<ControlAppearance> _unfocusedAppearance{ nullptr };
winrt::com_ptr<ControlAppearance> _focusedAppearance{ nullptr };

View File

@@ -70,5 +70,7 @@ namespace Microsoft.Terminal.Control
Boolean RepositionCursorWithMouse { get; };
// NOTE! When adding something here, make sure to update ControlProperties.h too!
// Non-serialized settings
Boolean HighContrastMode;
};
}

View File

@@ -361,7 +361,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);
@@ -393,8 +392,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<til::color> color);
void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args);
bool _CapturePointer(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);

View File

@@ -23,7 +23,9 @@ namespace Microsoft.Terminal.Core
{
Never,
Indexed,
Always
Always,
AutomaticIndexed,
AutomaticAlways
};
// TerminalCore declares its own Color struct to avoid depending

View File

@@ -141,7 +141,22 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBold, appearance.IntenseIsBold());
renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, appearance.IntenseIsBright());
switch (appearance.AdjustIndistinguishableColors())
// If we're in high contrast mode and AIC is set to Automatic Indexed/Always,
// fallback to Indexed/Always respectively.
const auto deducedAIC = [this, &appearance]() {
const auto initialAIC = appearance.AdjustIndistinguishableColors();
switch (initialAIC)
{
case AdjustTextMode::AutomaticIndexed:
return _highContrastMode ? AdjustTextMode::Indexed : AdjustTextMode::Never;
case AdjustTextMode::AutomaticAlways:
return _highContrastMode ? AdjustTextMode::Always : AdjustTextMode::Never;
default:
return initialAIC;
}
}();
switch (deducedAIC)
{
case AdjustTextMode::Always:
renderSettings.SetRenderMode(RenderSettings::Mode::IndexedDistinguishableColors, false);
@@ -211,6 +226,11 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
_NotifyScrollEvent();
}
void Terminal::SetHighContrastInfo(bool hc)
{
_highContrastMode = hc;
}
void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
{
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());

View File

@@ -92,6 +92,7 @@ public:
void UpdateSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings);
void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance);
void SetHighContrastInfo(bool hc);
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.

View File

@@ -942,6 +942,14 @@
<value>Always</value>
<comment>An option to choose from for the "adjust indistinguishable colors" setting. When selected, we will adjust the text colors for visibility.</comment>
</data>
<data name="Profile_AdjustIndistinguishableColorsAutomaticIndexed.Content" xml:space="preserve">
<value>When High Contrast is enabled, only for colors in the color scheme</value>
<comment>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.</comment>
</data>
<data name="Profile_AdjustIndistinguishableColorsAutomaticAlways.Content" xml:space="preserve">
<value>When High Contrast Mode is enabled, all colors</value>
<comment>An option to choose from for the "adjust indistinguishable colors" setting. When selected, we will adjust the text colors for visibility if and only if high contrast mode is enabled.</comment>
</data>
<data name="Profile_CursorShapeBar.Content" xml:space="preserve">
<value>Bar ( ┃ )</value>
<comment>{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.</comment>

View File

@@ -23,6 +23,8 @@ using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Windows::Foundation::Collections;
using namespace Microsoft::Console;
bool CascadiaSettings::_highContrastMode{ false };
// Creating a child of a profile requires us to copy certain
// required attributes. This method handles those attributes.
//
@@ -53,6 +55,16 @@ std::string_view Model::implementation::LoadStringResource(int resourceID)
return { reinterpret_cast<const char*>(ptr), sz };
}
bool CascadiaSettings::HighContrastMode()
{
return _highContrastMode;
}
void CascadiaSettings::HighContrastMode(bool value)
{
_highContrastMode = value;
}
winrt::hstring CascadiaSettings::Hash() const noexcept
{
return _hash;

View File

@@ -114,6 +114,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::hstring ApplicationDisplayName();
static winrt::hstring ApplicationVersion();
static bool IsPortableMode();
static bool HighContrastMode();
static void HighContrastMode(bool value);
CascadiaSettings() noexcept = default;
CascadiaSettings(const winrt::hstring& userJSON, const winrt::hstring& inboxJSON);
@@ -158,6 +160,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static const std::filesystem::path& _settingsPath();
static const std::filesystem::path& _releaseSettingsPath();
static winrt::hstring _calculateHash(std::string_view settings, const FILETIME& lastWriteTime);
static bool _highContrastMode;
winrt::com_ptr<implementation::Profile> _createNewProfile(const std::wstring_view& name) const;
Model::Profile _getProfileForCommandLine(const winrt::hstring& commandLine) const;

View File

@@ -16,6 +16,7 @@ namespace Microsoft.Terminal.Settings.Model
static String SettingsPath { get; };
static String DefaultSettingsPath { get; };
static Boolean IsPortableMode { get; };
static Boolean HighContrastMode;
static String ApplicationDisplayName { get; };
static String ApplicationVersion { get; };

View File

@@ -178,6 +178,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, bool, ReloadEnvironmentVariables, true);
WINRT_PROPERTY(bool, HighContrastMode, false);
private:
std::optional<std::array<Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE>> _ColorTable;
std::span<Microsoft::Terminal::Core::Color> _getColorTableImpl();

View File

@@ -35,10 +35,12 @@ 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(5) = {
pair_type{ "never", ValueType::Never },
pair_type{ "indexed", ValueType::Indexed },
pair_type{ "always", ValueType::Always },
pair_type{ "automaticIndexed", ValueType::AutomaticIndexed },
pair_type{ "automaticAlways", ValueType::AutomaticAlways },
};
// Override mapping parser to add boolean parsing

View File

@@ -1574,7 +1574,7 @@ void AppHost::_handleSendContent(const winrt::Windows::Foundation::IInspectable&
// Bubble the update settings request up to the emperor. We're being called on
// the Window thread, but the Emperor needs to update the settings on the _main_
// thread.
void AppHost::_requestUpdateSettings()
void AppHost::_requestUpdateSettings(bool highContrastEnabled)
{
UpdateSettingsRequested.raise();
UpdateSettingsRequested.raise(highContrastEnabled);
}

View File

@@ -32,7 +32,7 @@ public:
static void s_DisplayMessageBox(const winrt::TerminalApp::ParseCommandlineResult& message);
til::event<winrt::delegate<void()>> UpdateSettingsRequested;
til::event<winrt::delegate<void(bool)>> UpdateSettingsRequested;
private:
std::unique_ptr<IslandWindow> _window;
@@ -151,7 +151,7 @@ private:
void _handleAttach(const winrt::Windows::Foundation::IInspectable& sender,
winrt::Microsoft::Terminal::Remoting::AttachRequest args);
void _requestUpdateSettings();
void _requestUpdateSettings(bool highContrastEnabled);
// Page -> us -> monarch
void _handleReceiveContent(const winrt::Windows::Foundation::IInspectable& sender,

View File

@@ -758,6 +758,8 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
// themes, color schemes that might depend on the OS theme
if (param == L"ImmersiveColorSet")
{
bool updateSettings = false;
// GH#15732: Don't update the settings, unless the theme
// _actually_ changed. ImmersiveColorSet gets sent more often
// than just on a theme change. It notably gets sent when the PC
@@ -766,7 +768,28 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
if (isCurrentlyDark != _currentSystemThemeIsDark)
{
_currentSystemThemeIsDark = isCurrentlyDark;
UpdateSettingsRequested.raise();
updateSettings = true;
}
bool isCurrentlyHighContrast = []() {
HIGHCONTRAST hc = { 0 };
hc.cbSize = sizeof(HIGHCONTRAST);
if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0))
{
return (bool)(hc.dwFlags & HCF_HIGHCONTRASTON);
}
return false;
}();
if (isCurrentlyHighContrast != _currentHighContrastModeState)
{
_currentHighContrastModeState = isCurrentlyHighContrast;
updateSettings = true;
}
if (updateSettings)
{
UpdateSettingsRequested.raise(_currentHighContrastModeState);
}
}
}

View File

@@ -87,7 +87,7 @@ public:
til::event<winrt::delegate<void()>> WindowMoved;
til::event<winrt::delegate<void(bool)>> WindowVisibilityChanged;
til::event<winrt::delegate<void()>> UpdateSettingsRequested;
til::event<winrt::delegate<void(bool)>> UpdateSettingsRequested;
protected:
void ForceResize()
@@ -118,6 +118,7 @@ protected:
RECT _rcWorkBeforeFullscreen{};
UINT _dpiBeforeFullscreen{ 96 };
bool _currentSystemThemeIsDark{ true };
bool _currentHighContrastModeState{ false };
void _coldInitialize();
void _warmInitialize();

View File

@@ -850,9 +850,10 @@ safe_void_coroutine WindowEmperor::_windowIsQuakeWindowChanged(winrt::Windows::F
co_await wil::resume_foreground(this->_dispatcher);
_checkWindowsForNotificationIcon();
}
safe_void_coroutine WindowEmperor::_windowRequestUpdateSettings()
safe_void_coroutine WindowEmperor::_windowRequestUpdateSettings(bool highContrastEnabled)
{
// We MUST be on the main thread to update the settings. We will crash when trying to enumerate fragment extensions otherwise.
co_await wil::resume_foreground(this->_dispatcher);
_app.Logic().SetHighContrast(highContrastEnabled);
_app.Logic().ReloadSettings();
}

View File

@@ -62,7 +62,7 @@ private:
void _numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&);
safe_void_coroutine _windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::Foundation::IInspectable args);
safe_void_coroutine _windowRequestUpdateSettings();
safe_void_coroutine _windowRequestUpdateSettings(bool highContrastEnabled);
void _createMessageWindow();

View File

@@ -33,7 +33,7 @@ void WindowThread::CreateHost()
_manager,
_peasant);
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this]() { UpdateSettingsRequested.raise(); });
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this](bool highContrastEnabled) { UpdateSettingsRequested.raise(highContrastEnabled); });
winrt::init_apartment(winrt::apartment_type::single_threaded);
@@ -113,7 +113,7 @@ bool WindowThread::KeepWarm()
// state transitions. In this case, the window is actually being woken up.
if (msg.message == AppHost::WM_REFRIGERATE)
{
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this]() { UpdateSettingsRequested.raise(); });
_UpdateSettingsRequestedToken = _host->UpdateSettingsRequested([this](bool highContrastEnabled) { UpdateSettingsRequested.raise(highContrastEnabled); });
// Re-initialize the host here, on the window thread
_host->Initialize();
return true;

View File

@@ -25,7 +25,7 @@ public:
uint64_t PeasantID();
til::event<winrt::delegate<void()>> UpdateSettingsRequested;
til::event<winrt::delegate<void(bool)>> UpdateSettingsRequested;
private:
winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };

View File

@@ -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::AutomaticIndexed)
// --------------------------- Control Appearance ---------------------------
// All of these settings are defined in IControlAppearance.