mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
CmdPal: Transparent window (#45159)
## Summary This PR adds: - Backdrop material customization - Alongside acrylic, the following options are now available: - Transparent background - Mica background - Background material opacity - Lets you control how transparent the background is ## Pictures? Pictures! <img width="1491" height="928" alt="image" src="https://github.com/user-attachments/assets/ff4e9e06-fcf1-4f05-bc0a-fb70dc4f39be" /> https://github.com/user-attachments/assets/84e83279-afab-481e-b904-f054318c5d2f <img width="977" height="628" alt="image" src="https://github.com/user-attachments/assets/241a228d-af3f-448a-94a6-0a282218bd8c" /> ## PR Checklist - [x] Closes: #44197 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
This commit is contained in:
@@ -18,6 +18,8 @@ namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDisposable
|
||||
{
|
||||
private static readonly Color DefaultTintColor = Color.FromArgb(255, 0, 120, 212);
|
||||
|
||||
private static readonly ObservableCollection<Color> WindowsColorSwatches = [
|
||||
|
||||
// row 0
|
||||
@@ -128,10 +130,13 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ColorizationModeIndex));
|
||||
OnPropertyChanged(nameof(IsCustomTintVisible));
|
||||
OnPropertyChanged(nameof(IsCustomTintIntensityVisible));
|
||||
OnPropertyChanged(nameof(IsColorIntensityVisible));
|
||||
OnPropertyChanged(nameof(IsImageTintIntensityVisible));
|
||||
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||
OnPropertyChanged(nameof(IsBackgroundControlsVisible));
|
||||
OnPropertyChanged(nameof(IsNoBackgroundVisible));
|
||||
OnPropertyChanged(nameof(IsAccentColorControlsVisible));
|
||||
OnPropertyChanged(nameof(IsResetButtonVisible));
|
||||
|
||||
if (value == ColorizationMode.WindowsAccentColor)
|
||||
{
|
||||
@@ -179,6 +184,19 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
{
|
||||
_settings.CustomThemeColorIntensity = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
public int BackgroundImageTintIntensity
|
||||
{
|
||||
get => _settings.BackgroundImageTintIntensity;
|
||||
set
|
||||
{
|
||||
_settings.BackgroundImageTintIntensity = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||
Save();
|
||||
}
|
||||
}
|
||||
@@ -279,12 +297,108 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
};
|
||||
}
|
||||
|
||||
public int BackdropOpacity
|
||||
{
|
||||
get => _settings.BackdropOpacity;
|
||||
set
|
||||
{
|
||||
if (_settings.BackdropOpacity != value)
|
||||
{
|
||||
_settings.BackdropOpacity = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(EffectiveBackdropStyle));
|
||||
OnPropertyChanged(nameof(EffectiveImageOpacity));
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int BackdropStyleIndex
|
||||
{
|
||||
get => (int)_settings.BackdropStyle;
|
||||
set
|
||||
{
|
||||
var newStyle = (BackdropStyle)value;
|
||||
if (_settings.BackdropStyle != newStyle)
|
||||
{
|
||||
_settings.BackdropStyle = newStyle;
|
||||
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(IsBackdropOpacityVisible));
|
||||
OnPropertyChanged(nameof(IsMicaBackdropDescriptionVisible));
|
||||
OnPropertyChanged(nameof(IsBackgroundSettingsEnabled));
|
||||
OnPropertyChanged(nameof(IsBackgroundNotAvailableVisible));
|
||||
|
||||
if (!IsBackgroundSettingsEnabled)
|
||||
{
|
||||
IsColorizationDetailsExpanded = false;
|
||||
}
|
||||
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the backdrop opacity slider should be visible.
|
||||
/// </summary>
|
||||
public bool IsBackdropOpacityVisible =>
|
||||
BackdropStyles.Get(_settings.BackdropStyle).SupportsOpacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the backdrop description (for styles without options) should be visible.
|
||||
/// </summary>
|
||||
public bool IsMicaBackdropDescriptionVisible =>
|
||||
!BackdropStyles.Get(_settings.BackdropStyle).SupportsOpacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether background/colorization settings are available.
|
||||
/// </summary>
|
||||
public bool IsBackgroundSettingsEnabled =>
|
||||
BackdropStyles.Get(_settings.BackdropStyle).SupportsColorization;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the "not available" message should be shown (inverse of IsBackgroundSettingsEnabled).
|
||||
/// </summary>
|
||||
public bool IsBackgroundNotAvailableVisible =>
|
||||
!BackdropStyles.Get(_settings.BackdropStyle).SupportsColorization;
|
||||
|
||||
public BackdropStyle? EffectiveBackdropStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return style when transparency/blur is visible (not fully opaque Acrylic)
|
||||
// - Clear/Mica/MicaAlt/AcrylicThin always show their effect
|
||||
// - Acrylic shows effect only when opacity < 100
|
||||
if (_settings.BackdropStyle != BackdropStyle.Acrylic || _settings.BackdropOpacity < 100)
|
||||
{
|
||||
return _settings.BackdropStyle;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public double EffectiveImageOpacity =>
|
||||
EffectiveBackdropStyle is not null
|
||||
? (BackgroundImageOpacity / 100f) * Math.Sqrt(_settings.BackdropOpacity / 100.0)
|
||||
: (BackgroundImageOpacity / 100f);
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsColorizationDetailsExpanded { get; set; }
|
||||
|
||||
public bool IsCustomTintVisible => _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.Image;
|
||||
|
||||
public bool IsCustomTintIntensityVisible => _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.WindowsAccentColor or ColorizationMode.Image;
|
||||
public bool IsColorIntensityVisible => _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.WindowsAccentColor;
|
||||
|
||||
public bool IsImageTintIntensityVisible => _settings.ColorizationMode is ColorizationMode.Image;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effective tint intensity for the preview, based on the current colorization mode.
|
||||
/// </summary>
|
||||
public int EffectiveTintIntensity => _settings.ColorizationMode is ColorizationMode.Image
|
||||
? _settings.BackgroundImageTintIntensity
|
||||
: _settings.CustomThemeColorIntensity;
|
||||
|
||||
public bool IsBackgroundControlsVisible => _settings.ColorizationMode is ColorizationMode.Image;
|
||||
|
||||
@@ -292,16 +406,21 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
|
||||
public bool IsAccentColorControlsVisible => _settings.ColorizationMode is ColorizationMode.WindowsAccentColor;
|
||||
|
||||
public AcrylicBackdropParameters EffectiveBackdrop { get; private set; } = new(Colors.Black, Colors.Black, 0.5f, 0.5f);
|
||||
public bool IsResetButtonVisible => _settings.ColorizationMode is ColorizationMode.Image;
|
||||
|
||||
public BackdropParameters EffectiveBackdrop { get; private set; } = new(Colors.Black, Colors.Black, 0.5f, 0.5f);
|
||||
|
||||
public ElementTheme EffectiveTheme => _elementThemeOverride ?? _themeService.Current.Theme;
|
||||
|
||||
public Color EffectiveThemeColor => ColorizationMode switch
|
||||
{
|
||||
ColorizationMode.WindowsAccentColor => _currentSystemAccentColor,
|
||||
ColorizationMode.CustomColor or ColorizationMode.Image => ThemeColor,
|
||||
_ => Colors.Transparent,
|
||||
};
|
||||
public Color EffectiveThemeColor =>
|
||||
!BackdropStyles.Get(_settings.BackdropStyle).SupportsColorization
|
||||
? Colors.Transparent
|
||||
: ColorizationMode switch
|
||||
{
|
||||
ColorizationMode.WindowsAccentColor => _currentSystemAccentColor,
|
||||
ColorizationMode.CustomColor or ColorizationMode.Image => ThemeColor,
|
||||
_ => Colors.Transparent,
|
||||
};
|
||||
|
||||
// Since the blur amount is absolute, we need to scale it down for the preview (which is smaller than full screen).
|
||||
public int EffectiveBackgroundImageBlurAmount => (int)Math.Round(BackgroundImageBlurAmount / 4f);
|
||||
@@ -309,11 +428,13 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
public double EffectiveBackgroundImageBrightness => BackgroundImageBrightness / 100.0;
|
||||
|
||||
public ImageSource? EffectiveBackgroundImageSource =>
|
||||
ColorizationMode is ColorizationMode.Image
|
||||
&& !string.IsNullOrWhiteSpace(BackgroundImagePath)
|
||||
&& Uri.TryCreate(BackgroundImagePath, UriKind.RelativeOrAbsolute, out var uri)
|
||||
? new Microsoft.UI.Xaml.Media.Imaging.BitmapImage(uri)
|
||||
: null;
|
||||
!BackdropStyles.Get(_settings.BackdropStyle).SupportsBackgroundImage
|
||||
? null
|
||||
: ColorizationMode is ColorizationMode.Image
|
||||
&& !string.IsNullOrWhiteSpace(BackgroundImagePath)
|
||||
&& Uri.TryCreate(BackgroundImagePath, UriKind.RelativeOrAbsolute, out var uri)
|
||||
? new Microsoft.UI.Xaml.Media.Imaging.BitmapImage(uri)
|
||||
: null;
|
||||
|
||||
public AppearanceSettingsViewModel(IThemeService themeService, SettingsModel settings)
|
||||
{
|
||||
@@ -327,7 +448,7 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
|
||||
Reapply();
|
||||
|
||||
IsColorizationDetailsExpanded = _settings.ColorizationMode != ColorizationMode.None;
|
||||
IsColorizationDetailsExpanded = _settings.ColorizationMode != ColorizationMode.None && IsBackgroundSettingsEnabled;
|
||||
}
|
||||
|
||||
private void UiSettingsOnColorValuesChanged(UISettings sender, object args) => _uiDispatcher.TryEnqueue(() => UpdateAccentColor(sender));
|
||||
@@ -357,6 +478,8 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
// Theme services recalculates effective color and opacity based on current settings.
|
||||
EffectiveBackdrop = _themeService.Current.BackdropParameters;
|
||||
OnPropertyChanged(nameof(EffectiveBackdrop));
|
||||
OnPropertyChanged(nameof(EffectiveBackdropStyle));
|
||||
OnPropertyChanged(nameof(EffectiveImageOpacity));
|
||||
OnPropertyChanged(nameof(EffectiveBackgroundImageBrightness));
|
||||
OnPropertyChanged(nameof(EffectiveBackgroundImageSource));
|
||||
OnPropertyChanged(nameof(EffectiveThemeColor));
|
||||
@@ -379,7 +502,28 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
BackgroundImageBlurAmount = 0;
|
||||
BackgroundImageFit = BackgroundImageFit.UniformToFill;
|
||||
BackgroundImageOpacity = 100;
|
||||
ColorIntensity = 0;
|
||||
BackgroundImageTintIntensity = 0;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ResetAppearanceSettings()
|
||||
{
|
||||
// Reset theme
|
||||
Theme = UserTheme.Default;
|
||||
|
||||
// Reset backdrop settings
|
||||
BackdropStyleIndex = (int)BackdropStyle.Acrylic;
|
||||
BackdropOpacity = 100;
|
||||
|
||||
// Reset background image settings
|
||||
BackgroundImagePath = string.Empty;
|
||||
ResetBackgroundImageProperties();
|
||||
|
||||
// Reset colorization
|
||||
ColorizationMode = ColorizationMode.None;
|
||||
ThemeColor = DefaultTintColor;
|
||||
ColorIntensity = 100;
|
||||
BackgroundImageTintIntensity = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the type of system backdrop controller to use.
|
||||
/// </summary>
|
||||
public enum BackdropControllerKind
|
||||
{
|
||||
/// <summary>
|
||||
/// Solid color with alpha transparency (TransparentTintBackdrop).
|
||||
/// </summary>
|
||||
Solid,
|
||||
|
||||
/// <summary>
|
||||
/// Desktop Acrylic with default blur (DesktopAcrylicKind.Default).
|
||||
/// </summary>
|
||||
Acrylic,
|
||||
|
||||
/// <summary>
|
||||
/// Desktop Acrylic with thinner blur (DesktopAcrylicKind.Thin).
|
||||
/// </summary>
|
||||
AcrylicThin,
|
||||
|
||||
/// <summary>
|
||||
/// Mica effect (MicaKind.Base).
|
||||
/// </summary>
|
||||
Mica,
|
||||
|
||||
/// <summary>
|
||||
/// Mica alternate/darker variant (MicaKind.BaseAlt).
|
||||
/// </summary>
|
||||
MicaAlt,
|
||||
|
||||
/// <summary>
|
||||
/// Custom backdrop implementation.
|
||||
/// </summary>
|
||||
Custom,
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the visual backdrop style for the window.
|
||||
/// </summary>
|
||||
public enum BackdropStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard desktop acrylic with blur effect.
|
||||
/// </summary>
|
||||
Acrylic,
|
||||
|
||||
/// <summary>
|
||||
/// Solid color with alpha transparency (no blur).
|
||||
/// </summary>
|
||||
Clear,
|
||||
|
||||
/// <summary>
|
||||
/// Mica effect that samples the desktop wallpaper.
|
||||
/// </summary>
|
||||
Mica,
|
||||
|
||||
/// <summary>
|
||||
/// Thinner acrylic variant with more transparency.
|
||||
/// </summary>
|
||||
AcrylicThin,
|
||||
|
||||
/// <summary>
|
||||
/// Mica alternate variant (darker).
|
||||
/// </summary>
|
||||
MicaAlt,
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration parameters for a backdrop style.
|
||||
/// </summary>
|
||||
public sealed record BackdropStyleConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of system backdrop controller to use.
|
||||
/// </summary>
|
||||
public required BackdropControllerKind ControllerKind { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base tint opacity before user adjustments.
|
||||
/// </summary>
|
||||
public required float BaseTintOpacity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base luminosity opacity before user adjustments.
|
||||
/// </summary>
|
||||
public required float BaseLuminosityOpacity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the brush type to use for preview approximation.
|
||||
/// </summary>
|
||||
public required PreviewBrushKind PreviewBrush { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fixed opacity for styles that don't support user adjustment (e.g., Mica).
|
||||
/// When <see cref="SupportsOpacity"/> is false, this value is used as the effective opacity.
|
||||
/// </summary>
|
||||
public float FixedOpacity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports custom colorization (tint colors).
|
||||
/// </summary>
|
||||
public bool SupportsColorization { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports custom background images.
|
||||
/// </summary>
|
||||
public bool SupportsBackgroundImage { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports opacity adjustment.
|
||||
/// </summary>
|
||||
public bool SupportsOpacity { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Computes the effective tint opacity based on this style's configuration.
|
||||
/// </summary>
|
||||
/// <param name="userOpacity">User's backdrop opacity setting (0-1 normalized).</param>
|
||||
/// <param name="baseTintOpacityOverride">Optional override for base tint opacity (used by colorful theme).</param>
|
||||
/// <returns>The effective opacity to apply.</returns>
|
||||
public float ComputeEffectiveOpacity(float userOpacity, float? baseTintOpacityOverride = null)
|
||||
{
|
||||
// For styles that don't support opacity (Mica), use FixedOpacity
|
||||
if (!SupportsOpacity && FixedOpacity > 0)
|
||||
{
|
||||
return FixedOpacity;
|
||||
}
|
||||
|
||||
// For Solid: only user opacity matters (controls alpha of solid color)
|
||||
if (ControllerKind == BackdropControllerKind.Solid)
|
||||
{
|
||||
return userOpacity;
|
||||
}
|
||||
|
||||
// For blur effects: multiply base opacity with user opacity
|
||||
var baseTint = baseTintOpacityOverride ?? BaseTintOpacity;
|
||||
return baseTint * userOpacity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Central registry of backdrop style configurations.
|
||||
/// </summary>
|
||||
public static class BackdropStyles
|
||||
{
|
||||
private static readonly Dictionary<BackdropStyle, BackdropStyleConfig> Configs = new()
|
||||
{
|
||||
[BackdropStyle.Acrylic] = new()
|
||||
{
|
||||
ControllerKind = BackdropControllerKind.Acrylic,
|
||||
BaseTintOpacity = 0.5f,
|
||||
BaseLuminosityOpacity = 0.9f,
|
||||
PreviewBrush = PreviewBrushKind.Acrylic,
|
||||
},
|
||||
[BackdropStyle.AcrylicThin] = new()
|
||||
{
|
||||
ControllerKind = BackdropControllerKind.AcrylicThin,
|
||||
BaseTintOpacity = 0.0f,
|
||||
BaseLuminosityOpacity = 0.85f,
|
||||
PreviewBrush = PreviewBrushKind.Acrylic,
|
||||
},
|
||||
[BackdropStyle.Mica] = new()
|
||||
{
|
||||
ControllerKind = BackdropControllerKind.Mica,
|
||||
BaseTintOpacity = 0.0f,
|
||||
BaseLuminosityOpacity = 1.0f,
|
||||
PreviewBrush = PreviewBrushKind.Solid,
|
||||
FixedOpacity = 0.96f,
|
||||
SupportsOpacity = false,
|
||||
},
|
||||
[BackdropStyle.MicaAlt] = new()
|
||||
{
|
||||
ControllerKind = BackdropControllerKind.MicaAlt,
|
||||
BaseTintOpacity = 0.0f,
|
||||
BaseLuminosityOpacity = 1.0f,
|
||||
PreviewBrush = PreviewBrushKind.Solid,
|
||||
FixedOpacity = 0.98f,
|
||||
SupportsOpacity = false,
|
||||
},
|
||||
[BackdropStyle.Clear] = new()
|
||||
{
|
||||
ControllerKind = BackdropControllerKind.Solid,
|
||||
BaseTintOpacity = 1.0f,
|
||||
BaseLuminosityOpacity = 1.0f,
|
||||
PreviewBrush = PreviewBrushKind.Solid,
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration for the specified backdrop style.
|
||||
/// </summary>
|
||||
public static BackdropStyleConfig Get(BackdropStyle style) =>
|
||||
Configs.TryGetValue(style, out var config) ? config : Configs[BackdropStyle.Acrylic];
|
||||
|
||||
/// <summary>
|
||||
/// Gets all registered backdrop styles.
|
||||
/// </summary>
|
||||
public static IEnumerable<BackdropStyle> All => Configs.Keys;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable
|
||||
public partial Stretch BackgroundImageStretch { get; private set; } = Stretch.Fill;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(EffectiveImageOpacity))]
|
||||
public partial double BackgroundImageOpacity { get; private set; }
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -39,6 +40,30 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable
|
||||
[ObservableProperty]
|
||||
public partial bool ShowBackgroundImage { get; private set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(EffectiveBackdropStyle))]
|
||||
[NotifyPropertyChangedFor(nameof(EffectiveImageOpacity))]
|
||||
public partial BackdropStyle BackdropStyle { get; private set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(EffectiveBackdropStyle))]
|
||||
[NotifyPropertyChangedFor(nameof(EffectiveImageOpacity))]
|
||||
public partial float BackdropOpacity { get; private set; } = 1.0f;
|
||||
|
||||
// Returns null when no transparency needed (BlurImageControl uses this to decide source type)
|
||||
public BackdropStyle? EffectiveBackdropStyle =>
|
||||
BackdropStyle == BackdropStyle.Clear ||
|
||||
BackdropStyle == BackdropStyle.Mica ||
|
||||
BackdropOpacity < 1.0f
|
||||
? BackdropStyle
|
||||
: null;
|
||||
|
||||
// When transparency is enabled, use square root curve so image stays visible longer as backdrop fades
|
||||
public double EffectiveImageOpacity =>
|
||||
EffectiveBackdropStyle is not null
|
||||
? BackgroundImageOpacity * Math.Sqrt(BackdropOpacity)
|
||||
: BackgroundImageOpacity;
|
||||
|
||||
public MainWindowViewModel(IThemeService themeService)
|
||||
{
|
||||
_themeService = themeService;
|
||||
@@ -58,6 +83,9 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable
|
||||
BackgroundImageTintIntensity = _themeService.Current.TintIntensity;
|
||||
BackgroundImageBlurAmount = _themeService.Current.BlurAmount;
|
||||
|
||||
BackdropStyle = _themeService.Current.BackdropParameters.Style;
|
||||
BackdropOpacity = _themeService.Current.BackdropOpacity;
|
||||
|
||||
ShowBackgroundImage = BackgroundImageSource != null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the brush type to use for backdrop preview approximation.
|
||||
/// </summary>
|
||||
public enum PreviewBrushKind
|
||||
{
|
||||
/// <summary>
|
||||
/// SolidColorBrush with computed alpha.
|
||||
/// </summary>
|
||||
Solid,
|
||||
|
||||
/// <summary>
|
||||
/// AcrylicBrush with blur effect.
|
||||
/// </summary>
|
||||
Acrylic,
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Windows.UI;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels.Services;
|
||||
|
||||
public sealed record AcrylicBackdropParameters(Color TintColor, Color FallbackColor, float TintOpacity, float LuminosityOpacity);
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Windows.UI;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for configuring the window backdrop appearance.
|
||||
/// </summary>
|
||||
/// <param name="TintColor">The tint color applied to the backdrop.</param>
|
||||
/// <param name="FallbackColor">The fallback color when backdrop effects are unavailable.</param>
|
||||
/// <param name="EffectiveOpacity">
|
||||
/// The effective opacity for the backdrop, pre-computed by the theme provider.
|
||||
/// For Acrylic style: TintOpacity * BackdropOpacity.
|
||||
/// For Clear style: BackdropOpacity (controls the solid color alpha).
|
||||
/// </param>
|
||||
/// <param name="EffectiveLuminosityOpacity">
|
||||
/// The effective luminosity opacity for Acrylic backdrop, pre-computed by the theme provider.
|
||||
/// Computed as LuminosityOpacity * BackdropOpacity.
|
||||
/// </param>
|
||||
/// <param name="Style">The backdrop style (Acrylic or Clear).</param>
|
||||
public sealed record BackdropParameters(
|
||||
Color TintColor,
|
||||
Color FallbackColor,
|
||||
float EffectiveOpacity,
|
||||
float EffectiveLuminosityOpacity,
|
||||
BackdropStyle Style = BackdropStyle.Acrylic);
|
||||
@@ -51,12 +51,23 @@ public sealed class ThemeSnapshot
|
||||
public required double BackgroundImageOpacity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effective acrylic backdrop parameters based on current settings and theme.
|
||||
/// Gets the effective backdrop parameters based on current settings and theme.
|
||||
/// </summary>
|
||||
/// <returns>The resolved <c>AcrylicBackdropParameters</c> to apply.</returns>
|
||||
public required AcrylicBackdropParameters BackdropParameters { get; init; }
|
||||
/// <returns>The resolved <c>BackdropParameters</c> to apply.</returns>
|
||||
public required BackdropParameters BackdropParameters { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw backdrop opacity setting (0-1 range).
|
||||
/// Used for determining if transparency is enabled and for image opacity calculations.
|
||||
/// </summary>
|
||||
public required float BackdropOpacity { get; init; }
|
||||
|
||||
public required int BlurAmount { get; init; }
|
||||
|
||||
public required float BackgroundBrightness { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether colorization is active (accent color, custom color, or image mode).
|
||||
/// </summary>
|
||||
public required bool HasColorization { get; init; }
|
||||
}
|
||||
|
||||
@@ -74,6 +74,8 @@ public partial class SettingsModel : ObservableObject
|
||||
|
||||
public int CustomThemeColorIntensity { get; set; } = 100;
|
||||
|
||||
public int BackgroundImageTintIntensity { get; set; }
|
||||
|
||||
public int BackgroundImageOpacity { get; set; } = 20;
|
||||
|
||||
public int BackgroundImageBlurAmount { get; set; }
|
||||
@@ -84,6 +86,10 @@ public partial class SettingsModel : ObservableObject
|
||||
|
||||
public string? BackgroundImagePath { get; set; }
|
||||
|
||||
public BackdropStyle BackdropStyle { get; set; }
|
||||
|
||||
public int BackdropOpacity { get; set; } = 100;
|
||||
|
||||
// END SETTINGS
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Reference in New Issue
Block a user