未验证 提交 5502c248 编写于 作者: J Joey Robichaud 提交者: GitHub

Merge pull request #47320 from JoeRobich/remove-colorscheme-migration

Simplify ColorScheme detection
......@@ -64,8 +64,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF686868" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF686868" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF808080" />
......@@ -219,8 +219,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF686868" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF686868" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF808080" />
......@@ -374,8 +374,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF504848" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF504848" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF5B5B5B" />
......@@ -529,8 +529,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF959493" />
<Background Type="CT_RAW" Source="FF2D2C2C" />
<Foreground Type="CT_RAW" Source="FF959493" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FFC8C8C8" />
......
......@@ -70,8 +70,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF686868" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF686868" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF808080" />
......@@ -231,8 +231,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF686868" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF686868" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF808080" />
......@@ -392,8 +392,8 @@
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF504848" />
<Background Type="CT_RAW" Source="FFE6E6FA" />
<Foreground Type="CT_RAW" Source="FF504848" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FF5B5B5B" />
......@@ -544,17 +544,17 @@
<Color Name="extension method name">
<Foreground Type="CT_RAW" Source="FFDCDCAA" />
</Color>
<Color Name="property name">
</Color>
<Color Name="event name">
</Color>
<Color Name="namespace name">
</Color>
<Color Name="label name">
</Color>
<Color Name="property name">
</Color>
<Color Name="event name">
</Color>
<Color Name="namespace name">
</Color>
<Color Name="label name">
</Color>
<Color Name="inline parameter name hints">
<Foreground Type="CT_RAW" Source="FF959493" />
<Background Type="CT_RAW" Source="FF2D2C2C" />
<Foreground Type="CT_RAW" Source="FF959493" />
</Color>
<Color Name="xml doc comment - attribute name">
<Foreground Type="CT_RAW" Source="FFC8C8C8" />
......
......@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Security.Permissions;
using System.Windows;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Editor.ColorSchemes;
......@@ -21,17 +22,10 @@ namespace Microsoft.VisualStudio.LanguageServices.ColorSchemes
{
internal partial class ColorSchemeApplier
{
// Now that we are updating the theme's default color for classifications instead of updating the applied classification color, we need to
// update the classifications whose applied color matches the theme's color. These need to be reverted to the default color so that when we
// change theme colors it will be reflected in the editor.
private sealed class ForegroundColorDefaulter : ForegroundThreadAffinitizedObject
private sealed class ClassificationVerifier : ForegroundThreadAffinitizedObject
{
private readonly IServiceProvider _serviceProvider;
private readonly ColorSchemeSettings _settings;
// Holds an lookup optimized version of the ColorScheme data. An array of ColorSchemes where ColorTheme data is
// indexed by ThemeId. ColorTheme data being foreground color indexed by classification name.
private readonly ImmutableArray<ImmutableDictionary<Guid, ImmutableDictionary<string, uint>>> _colorSchemes;
private readonly ImmutableDictionary<SchemeName, ImmutableDictionary<Guid, ImmutableDictionary<string, uint>>> _colorSchemes;
private static readonly Guid TextEditorMEFItemsColorCategory = new Guid("75a05685-00a8-4ded-bae5-e7a50bfa929a");
......@@ -72,64 +66,57 @@ private sealed class ForegroundColorDefaulter : ForegroundThreadAffinitizedObjec
// The High Contrast theme is not included because we do not want to make changes when the user is in High Contrast mode.
private IVsFontAndColorStorage? _fontAndColorStorage;
private IVsFontAndColorStorage3? _fontAndColorStorage3;
private IVsFontAndColorUtilities? _fontAndColorUtilities;
private ImmutableArray<string> Classifications { get; }
public ForegroundColorDefaulter(IThreadingContext threadingContext, IServiceProvider serviceProvider, ColorSchemeSettings settings, ImmutableDictionary<SchemeName, ColorScheme> colorSchemes)
public ClassificationVerifier(IThreadingContext threadingContext, IServiceProvider serviceProvider, ImmutableDictionary<SchemeName, ColorScheme> colorSchemes)
: base(threadingContext)
{
_serviceProvider = serviceProvider;
_settings = settings;
// Convert colors schemes into an array of theme dictionaries which contain classification dictionaries of colors.
_colorSchemes = colorSchemes.Values.Select(
scheme => scheme.Themes.ToImmutableDictionary(
_colorSchemes = colorSchemes.ToImmutableDictionary(
nameAndScheme => nameAndScheme.Key,
nameAndScheme => nameAndScheme.Value.Themes.ToImmutableDictionary(
theme => theme.Guid,
theme => theme.Category.Colors
.Where(color => color.Foreground.HasValue)
.ToImmutableDictionary(
color => color.Name,
color => color.Foreground!.Value)))
.ToImmutableArray();
.ToImmutableDictionary(color => color.Name, color => color.Foreground!.Value)));
// Gather all the classifications from the core and scheme dictionaries.
var coreClassifications = DarkThemeForeground.Keys.Concat(BlueLightThemeForeground.Keys).Distinct();
var colorSchemeClassifications = _colorSchemes.SelectMany(scheme => scheme.Values.SelectMany(theme => theme.Keys)).Distinct();
var colorSchemeClassifications = _colorSchemes.Values.SelectMany(scheme => scheme.Values.SelectMany(theme => theme.Keys)).Distinct();
Classifications = coreClassifications.Concat(colorSchemeClassifications).ToImmutableArray();
}
private void EnsureInitialized()
{
if (_fontAndColorStorage is object)
{
return;
}
_fontAndColorStorage = _serviceProvider.GetService<SVsFontAndColorStorage, IVsFontAndColorStorage>();
// IVsFontAndColorStorage3 has methods to default classifications but does not include the methods defined in IVsFontAndColorStorage
_fontAndColorStorage3 = (IVsFontAndColorStorage3)_fontAndColorStorage!;
_fontAndColorUtilities = (IVsFontAndColorUtilities)_fontAndColorStorage!;
}
/// <summary>
/// Determines if all Classification foreground colors are DefaultColor or can be safely reverted to DefaultColor.
/// Determines if any Classification foreground colors have been customized in Fonts and Colors.
/// </summary>
public bool AreClassificationsDefaultable(Guid themeId)
public bool AreForegroundColorsCustomized(SchemeName schemeName, Guid themeId)
{
AssertIsForeground();
EnsureInitialized();
// Ensure we are initialized
if (_fontAndColorStorage is null)
{
_fontAndColorStorage = _serviceProvider.GetService<SVsFontAndColorStorage, IVsFontAndColorStorage>();
_fontAndColorUtilities = (IVsFontAndColorUtilities)_fontAndColorStorage!;
}
// Make no changes when in high contast mode or in unknown theme.
if (SystemParameters.HighContrast || !IsSupportedTheme(themeId))
if (SystemParameters.HighContrast ||
!_colorSchemes.TryGetValue(schemeName, out var colorScheme) ||
!colorScheme.TryGetValue(themeId, out var colorSchemeTheme))
{
return false;
}
var coreThemeColors = (themeId == KnownColorThemes.Dark)
? DarkThemeForeground
: BlueLightThemeForeground;
// Open Text Editor category for readonly access and do not load items if they are defaulted.
if (_fontAndColorStorage!.OpenCategory(TextEditorMEFItemsColorCategory, (uint)__FCSTORAGEFLAGS.FCSF_READONLY) != VSConstants.S_OK)
if (_fontAndColorStorage.OpenCategory(TextEditorMEFItemsColorCategory, (uint)__FCSTORAGEFLAGS.FCSF_READONLY) != VSConstants.S_OK)
{
// We were unable to access color information.
return false;
......@@ -137,11 +124,19 @@ public bool AreClassificationsDefaultable(Guid themeId)
try
{
foreach (var scheme in _colorSchemes)
foreach (var classification in Classifications)
{
var schemeThemeColors = scheme[themeId];
var colorItems = new ColorableItemInfo[1];
if (_fontAndColorStorage.GetItem(classification, colorItems) != VSConstants.S_OK)
{
// Classifications that are still defaulted will not have entries.
continue;
}
var colorItem = colorItems[0];
if (AreClassificationsDefaultableToScheme(themeId, schemeThemeColors))
if (IsClassificationCustomized(coreThemeColors, colorSchemeTheme, colorItem, classification))
{
return true;
}
......@@ -155,80 +150,49 @@ public bool AreClassificationsDefaultable(Guid themeId)
return false;
}
private bool IsSupportedTheme(Guid themeId)
=> _colorSchemes.Any(scheme => scheme.ContainsKey(themeId));
private bool AreClassificationsDefaultableToScheme(Guid themeId, ImmutableDictionary<string, uint> schemeThemeColors)
{
AssertIsForeground();
foreach (var classification in Classifications)
{
var colorItems = new ColorableItemInfo[1];
if (_fontAndColorStorage!.GetItem(classification, colorItems) != VSConstants.S_OK)
{
// Classifications that are still defaulted will not have entries.
continue;
}
var colorItem = colorItems[0];
if (!IsClassificationDefaultable(themeId, schemeThemeColors, colorItem, classification))
{
return false;
}
}
return true;
}
/// <summary>
/// Determines if the ColorableItemInfo's Foreground is already defaulted or if the Info can be reverted to its default state.
/// This requires checking both background color and font configuration, since reverting will reset all information for the item.
/// Determines if the ColorableItemInfo's Foreground has been customized to a color that doesn't match the
/// selected scheme.
/// </summary>
private bool IsClassificationDefaultable(Guid themeId, ImmutableDictionary<string, uint> schemeThemeColors, ColorableItemInfo colorItem, string classification)
private bool IsClassificationCustomized(
ImmutableDictionary<string, uint> coreThemeColors,
ImmutableDictionary<string, uint> schemeThemeColors,
ColorableItemInfo colorItem,
string classification)
{
AssertIsForeground();
Contract.ThrowIfNull(_fontAndColorUtilities);
var foregroundColorRef = colorItem.crForeground;
if (_fontAndColorUtilities!.GetColorType(colorItem.crForeground, out var foregroundColorType) != VSConstants.S_OK)
if (_fontAndColorUtilities.GetColorType(foregroundColorRef, out var foregroundColorType) != VSConstants.S_OK)
{
// Without being able to check color type, we cannot make a determination.
return false;
}
if (_fontAndColorUtilities!.GetColorType(colorItem.crBackground, out var backgroundColorType) != VSConstants.S_OK)
// If the color is defaulted then it isn't customized.
if (foregroundColorType == (int)__VSCOLORTYPE.CT_AUTOMATIC)
{
// Without being able to check color type, we cannot make a determination.
return false;
}
return foregroundColorType switch
// Since the color type isn't default then it has been customized, we will
// perform an additional check for RGB colors to see if the customized color
// matches the color scheme color.
if (foregroundColorType != (int)__VSCOLORTYPE.CT_RAW)
{
// The item's foreground is already defaulted and there is no work to be done.
(int)__VSCOLORTYPE.CT_AUTOMATIC => true,
// The item's foreground is set. Does it match the scheme's color and is the rest of the item defaulted?
(int)__VSCOLORTYPE.CT_RAW => IsForegroundTheSchemeColor(themeId, schemeThemeColors, classification, colorItem.crForeground)
&& backgroundColorType == (int)__VSCOLORTYPE.CT_AUTOMATIC
&& colorItem.dwFontFlags == (uint)FONTFLAGS.FF_DEFAULT,
_ => false
};
}
private bool IsForegroundTheSchemeColor(Guid themeId, ImmutableDictionary<string, uint> schemeThemeColors, string classification, uint foregroundColorRef)
{
var coreThemeColors = (themeId == KnownColorThemes.Dark)
? DarkThemeForeground
: BlueLightThemeForeground;
return true;
}
if (coreThemeColors.TryGetValue(classification, out var coreColor))
{
return foregroundColorRef == coreColor;
return foregroundColorRef != coreColor;
}
if (schemeThemeColors.TryGetValue(classification, out var schemeColor))
{
return foregroundColorRef == schemeColor;
return foregroundColorRef != schemeColor;
}
// Since Classification inheritance isn't represented in the scheme files,
......@@ -240,70 +204,7 @@ private bool IsForegroundTheSchemeColor(Guid themeId, ImmutableDictionary<string
_ => coreThemeColors[ClassificationTypeNames.Identifier]
};
return foregroundColorRef == fallbackColor;
}
/// <summary>
/// Reverts Classifications to their default state.
/// </summary>
public void DefaultClassifications(bool isThemeCustomized)
{
AssertIsForeground();
var themeId = _settings.GetThemeId();
// Make no changes when in high contast mode, in unknown theme, in customized theme, or if theme has been defaulted.
if (SystemParameters.HighContrast || !IsSupportedTheme(themeId) || isThemeCustomized || _settings.HasThemeBeenDefaulted[themeId])
{
return;
}
// Open Text Editor category for read/write.
if (_fontAndColorStorage!.OpenCategory(TextEditorMEFItemsColorCategory, (uint)__FCSTORAGEFLAGS.FCSF_PROPAGATECHANGES) != VSConstants.S_OK)
{
// We were unable to access color information.
return;
}
try
{
foreach (var classification in Classifications)
{
DefaultClassification(classification);
}
}
finally
{
_fontAndColorStorage.CloseCategory();
}
_settings.HasThemeBeenDefaulted[themeId] = true;
}
private void DefaultClassification(string classification)
{
AssertIsForeground();
EnsureInitialized();
var colorItems = new ColorableItemInfo[1];
if (_fontAndColorStorage!.GetItem(classification, colorItems) != VSConstants.S_OK)
{
// Classifications that are still defaulted will not have entries.
return;
}
var colorItem = colorItems[0];
// If the foreground is the automatic color then no need to default the classification,
// since it will pull in the theme's color.
if (_fontAndColorUtilities!.GetColorType(colorItem.crForeground, out var foregroundColorType) == VSConstants.S_OK
&& foregroundColorType == (int)__VSCOLORTYPE.CT_AUTOMATIC)
{
return;
}
_fontAndColorStorage3!.RevertItemToDefault(classification);
return foregroundColorRef != fallbackColor;
}
}
}
......
......@@ -5,16 +5,13 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.Editor.ColorSchemes;
using Microsoft.CodeAnalysis.Editor.Options;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using NativeMethods = Microsoft.CodeAnalysis.Editor.Wpf.Utilities.NativeMethods;
......@@ -31,14 +28,10 @@ private class ColorSchemeSettings
private readonly IServiceProvider _serviceProvider;
private readonly VisualStudioWorkspace _workspace;
public HasThemeBeenDefaultedIndexer HasThemeBeenDefaulted { get; }
public ColorSchemeSettings(IServiceProvider serviceProvider, VisualStudioWorkspace visualStudioWorkspace)
{
_serviceProvider = serviceProvider;
_workspace = visualStudioWorkspace;
HasThemeBeenDefaulted = new HasThemeBeenDefaultedIndexer(visualStudioWorkspace);
}
public ImmutableDictionary<SchemeName, ColorScheme> GetColorSchemes()
......@@ -115,7 +108,7 @@ public SchemeName GetConfiguredColorScheme()
: ColorSchemeOptions.ColorScheme.DefaultValue;
}
public void MigrateToColorSchemeSetting(bool isThemeCustomized)
public void MigrateToColorSchemeSetting()
{
// Get the preview feature flag value.
var useEnhancedColorsSetting = _workspace.Options.GetOption(ColorSchemeOptions.LegacyUseEnhancedColors);
......@@ -126,85 +119,13 @@ public void MigrateToColorSchemeSetting(bool isThemeCustomized)
return;
}
// Since we did not apply 2019 colors if the theme had been customized, default customized themes to 2017 colors.
var colorScheme = (useEnhancedColorsSetting != ColorSchemeOptions.UseEnhancedColors.DoNotUse && !isThemeCustomized)
? SchemeName.VisualStudio2019
: SchemeName.VisualStudio2017;
var colorScheme = useEnhancedColorsSetting == ColorSchemeOptions.UseEnhancedColors.DoNotUse
? SchemeName.VisualStudio2017
: SchemeName.VisualStudio2019;
_workspace.SetOptions(_workspace.Options.WithChangedOption(ColorSchemeOptions.ColorScheme, colorScheme));
_workspace.SetOptions(_workspace.Options.WithChangedOption(ColorSchemeOptions.LegacyUseEnhancedColors, ColorSchemeOptions.UseEnhancedColors.Migrated));
}
public Guid GetThemeId()
{
// Look up the value from the new roamed theme property first and
// fallback to the original roamed theme property if that fails.
var themeIdString = _workspace.Options.GetOption(VisualStudioColorTheme.CurrentThemeNew)
?? _workspace.Options.GetOption(VisualStudioColorTheme.CurrentTheme);
return Guid.TryParse(themeIdString, out var themeId) ? themeId : Guid.Empty;
}
private static class VisualStudioColorTheme
{
private const string CurrentThemeValueName = "Microsoft.VisualStudio.ColorTheme";
private const string CurrentThemeValueNameNew = "Microsoft.VisualStudio.ColorThemeNew";
public static readonly Option<string?> CurrentTheme = new Option<string?>(nameof(VisualStudioColorTheme),
nameof(CurrentTheme),
defaultValue: null,
storageLocations: new RoamingProfileStorageLocation(CurrentThemeValueName));
public static readonly Option<string?> CurrentThemeNew = new Option<string?>(nameof(VisualStudioColorTheme),
nameof(CurrentThemeNew),
defaultValue: null,
storageLocations: new RoamingProfileStorageLocation(CurrentThemeValueNameNew));
}
public sealed class HasThemeBeenDefaultedIndexer
{
private readonly VisualStudioWorkspace _workspace;
public HasThemeBeenDefaultedIndexer(VisualStudioWorkspace visualStudioWorkspace)
=> _workspace = visualStudioWorkspace;
public bool this[Guid themeId]
{
get => _workspace.Options.GetOption(HasThemeBeenDefaultedOptions.Options[themeId]);
set => _workspace.SetOptions(_workspace.Options.WithChangedOption(HasThemeBeenDefaultedOptions.Options[themeId], value));
}
}
internal class HasThemeBeenDefaultedOptions
{
internal static readonly ImmutableDictionary<Guid, Option<bool>> Options = new Dictionary<Guid, Option<bool>>
{
[KnownColorThemes.Blue] = CreateHasThemeBeenDefaultedOption(KnownColorThemes.Blue),
[KnownColorThemes.Light] = CreateHasThemeBeenDefaultedOption(KnownColorThemes.Light),
[KnownColorThemes.Dark] = CreateHasThemeBeenDefaultedOption(KnownColorThemes.Dark),
[KnownColorThemes.AdditionalContrast] = CreateHasThemeBeenDefaultedOption(KnownColorThemes.AdditionalContrast)
}.ToImmutableDictionary();
private static Option<bool> CreateHasThemeBeenDefaultedOption(Guid themeId)
{
return new Option<bool>(nameof(ColorSchemeApplier), $"{nameof(HasThemeBeenDefaultedOptions)}{themeId}", defaultValue: false,
storageLocations: new RoamingProfileStorageLocation($@"Roslyn\ColorSchemeApplier\HasThemeBeenDefaulted\{themeId}"));
}
}
[ExportOptionProvider, Shared]
internal class HasThemeBeenDefaultedOptionProvider : IOptionProvider
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public HasThemeBeenDefaultedOptionProvider()
{
}
public ImmutableArray<IOption> Options => HasThemeBeenDefaultedOptions.Options.Values.ToImmutableArray<IOption>();
}
}
}
}
......@@ -13,7 +13,6 @@
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.CodeAnalysis.Editor.ColorSchemes;
using Microsoft.CodeAnalysis.Editor.Options;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
......@@ -32,12 +31,11 @@ internal sealed partial class ColorSchemeApplier : ForegroundThreadAffinitizedOb
{
private readonly IServiceProvider _serviceProvider;
private readonly ColorSchemeSettings _settings;
private readonly ClassificationVerifier _classificationVerifier;
private readonly ImmutableDictionary<SchemeName, ColorScheme> _colorSchemes;
private readonly AsyncLazy<ImmutableDictionary<SchemeName, ImmutableArray<RegistryItem>>> _colorSchemeRegistryItems;
private readonly ForegroundColorDefaulter _colorDefaulter;
private bool _isInitialized = false;
private bool _migrationAttempted = false;
private bool _isDisposed = false;
[ImportingConstructor]
......@@ -52,7 +50,7 @@ internal sealed partial class ColorSchemeApplier : ForegroundThreadAffinitizedOb
_settings = new ColorSchemeSettings(_serviceProvider, visualStudioWorkspace);
_colorSchemes = _settings.GetColorSchemes();
_colorDefaulter = new ForegroundColorDefaulter(threadingContext, serviceProvider, _settings, _colorSchemes);
_classificationVerifier = new ClassificationVerifier(threadingContext, serviceProvider, _colorSchemes);
_colorSchemeRegistryItems = new AsyncLazy<ImmutableDictionary<SchemeName, ImmutableArray<RegistryItem>>>(GetColorSchemeRegistryItemsAsync, cacheResult: true);
}
......@@ -66,48 +64,51 @@ public void Dispose()
public void Initialize()
{
AssertIsForeground();
if (!_isInitialized)
{
_isInitialized = true;
return;
}
_ = _colorSchemeRegistryItems.GetValueAsync(CancellationToken.None);
AssertIsForeground();
// We need to update the theme whenever the Editor Color Scheme setting changes or the VS Theme changes.
var settingsManager = (ISettingsManager)_serviceProvider.GetService(typeof(SVsSettingsPersistenceManager));
settingsManager.GetSubset(ColorSchemeOptions.ColorSchemeSettingKey).SettingChangedAsync += ColorSchemeChangedAsync;
_isInitialized = true;
VSColorTheme.ThemeChanged += VSColorTheme_ThemeChanged;
_ = _colorSchemeRegistryItems.GetValueAsync(CancellationToken.None);
// Since the Roslyn colors are now defined in the Roslyn repo and no longer applied by the VS pkgdef built from EditorColors.xml,
// We attempt to apply a color scheme when the Roslyn package is loaded. This is our chance to update the configuration registry
// with the Roslyn colors before they are seen by the user. This is important because the MEF exported Roslyn classification
// colors are only applicable to the Blue and Light VS themes.
// We need to update the theme whenever the Editor Color Scheme setting changes or the VS Theme changes.
var settingsManager = (ISettingsManager)_serviceProvider.GetService(typeof(SVsSettingsPersistenceManager));
settingsManager.GetSubset(ColorSchemeOptions.ColorSchemeSettingKey).SettingChangedAsync += ColorSchemeChangedAsync;
// When we update the colors we also flag that this is potentially a theme change, as settings could have synced over from a
// different VS instance and we may need to perform additional work to default colors that match our scheme.
UpdateColorScheme(themeChanged: true);
}
VSColorTheme.ThemeChanged += VSColorTheme_ThemeChanged;
// Try to migrate the `useEnhancedColorsSetting` to the new `ColorScheme` setting.
_settings.MigrateToColorSchemeSetting();
// Since the Roslyn colors are now defined in the Roslyn repo and no longer applied by the VS pkgdef built from EditorColors.xml,
// We attempt to apply a color scheme when the Roslyn package is loaded. This is our chance to update the configuration registry
// with the Roslyn colors before they are seen by the user. This is important because the MEF exported Roslyn classification
// colors are only applicable to the Blue and Light VS themes.
UpdateColorScheme();
}
private Task<ImmutableDictionary<SchemeName, ImmutableArray<RegistryItem>>> GetColorSchemeRegistryItemsAsync(CancellationToken arg)
=> SpecializedTasks.FromResult(_colorSchemes.ToImmutableDictionary(kvp => kvp.Key, kvp => RegistryItemConverter.Convert(kvp.Value)));
private void VSColorTheme_ThemeChanged(ThemeChangedEventArgs e)
=> QueueColorSchemeUpdate(themeChanged: true);
=> QueueColorSchemeUpdate();
private async Task ColorSchemeChangedAsync(object sender, PropertyChangedEventArgs args)
=> await QueueColorSchemeUpdate();
private IVsTask QueueColorSchemeUpdate(bool themeChanged = false)
private IVsTask QueueColorSchemeUpdate()
{
// Wait until things have settled down from the theme change, since we will potentially be changing theme colors.
return VsTaskLibraryHelper.CreateAndStartTask(
VsTaskLibraryHelper.ServiceInstance, VsTaskRunContext.UIThreadBackgroundPriority, () => UpdateColorScheme(themeChanged));
VsTaskLibraryHelper.ServiceInstance, VsTaskRunContext.UIThreadBackgroundPriority, () => UpdateColorScheme());
}
private void UpdateColorScheme(bool themeChanged = false)
private void UpdateColorScheme()
{
AssertIsForeground();
......@@ -117,20 +118,6 @@ private void UpdateColorScheme(bool themeChanged = false)
return;
}
if (!_migrationAttempted)
{
_migrationAttempted = true;
// Try to migrate the `useEnhancedColorsSetting` to the new `ColorScheme` setting.
_settings.MigrateToColorSchemeSetting(IsThemeCustomized());
}
if (themeChanged)
{
// Default Foreground colors if they match our theme colors.
_colorDefaulter.DefaultClassifications(IsThemeCustomized());
}
// If the color scheme has updated, apply the scheme.
if (TryGetUpdatedColorScheme(out var colorScheme))
{
......@@ -165,7 +152,7 @@ private bool TryGetUpdatedColorScheme([NotNullWhen(returnValue: true)] out Schem
}
public bool IsSupportedTheme()
=> IsSupportedTheme(_settings.GetThemeId());
=> IsSupportedTheme(GetThemeId());
public bool IsSupportedTheme(Guid themeId)
{
......@@ -175,7 +162,21 @@ public bool IsSupportedTheme(Guid themeId)
}
public bool IsThemeCustomized()
=> !_colorDefaulter.AreClassificationsDefaultable(_settings.GetThemeId());
=> _classificationVerifier.AreForegroundColorsCustomized(_settings.GetConfiguredColorScheme(), GetThemeId());
public Guid GetThemeId()
{
AssertIsForeground();
dynamic colorThemeService = _serviceProvider.GetService(typeof(SVsColorThemeService));
return (Guid)colorThemeService.CurrentTheme.ThemeId;
}
// NOTE: This service is not public or intended for use by teams/individuals outside of Microsoft. Any data stored is subject to deletion without warning.
[Guid("0d915b59-2ed7-472a-9de8-9161737ea1c5")]
private interface SVsColorThemeService
{
}
// NOTE: This service is not public or intended for use by teams/individuals outside of Microsoft. Any data stored is subject to deletion without warning.
[Guid("9B164E40-C3A2-4363-9BC5-EB4039DEF653")]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册