mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 03:36:44 +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
|
public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDisposable
|
||||||
{
|
{
|
||||||
|
private static readonly Color DefaultTintColor = Color.FromArgb(255, 0, 120, 212);
|
||||||
|
|
||||||
private static readonly ObservableCollection<Color> WindowsColorSwatches = [
|
private static readonly ObservableCollection<Color> WindowsColorSwatches = [
|
||||||
|
|
||||||
// row 0
|
// row 0
|
||||||
@@ -128,10 +130,13 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
OnPropertyChanged(nameof(ColorizationModeIndex));
|
OnPropertyChanged(nameof(ColorizationModeIndex));
|
||||||
OnPropertyChanged(nameof(IsCustomTintVisible));
|
OnPropertyChanged(nameof(IsCustomTintVisible));
|
||||||
OnPropertyChanged(nameof(IsCustomTintIntensityVisible));
|
OnPropertyChanged(nameof(IsColorIntensityVisible));
|
||||||
|
OnPropertyChanged(nameof(IsImageTintIntensityVisible));
|
||||||
|
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||||
OnPropertyChanged(nameof(IsBackgroundControlsVisible));
|
OnPropertyChanged(nameof(IsBackgroundControlsVisible));
|
||||||
OnPropertyChanged(nameof(IsNoBackgroundVisible));
|
OnPropertyChanged(nameof(IsNoBackgroundVisible));
|
||||||
OnPropertyChanged(nameof(IsAccentColorControlsVisible));
|
OnPropertyChanged(nameof(IsAccentColorControlsVisible));
|
||||||
|
OnPropertyChanged(nameof(IsResetButtonVisible));
|
||||||
|
|
||||||
if (value == ColorizationMode.WindowsAccentColor)
|
if (value == ColorizationMode.WindowsAccentColor)
|
||||||
{
|
{
|
||||||
@@ -179,6 +184,19 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
|||||||
{
|
{
|
||||||
_settings.CustomThemeColorIntensity = value;
|
_settings.CustomThemeColorIntensity = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int BackgroundImageTintIntensity
|
||||||
|
{
|
||||||
|
get => _settings.BackgroundImageTintIntensity;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_settings.BackgroundImageTintIntensity = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(EffectiveTintIntensity));
|
||||||
Save();
|
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]
|
[ObservableProperty]
|
||||||
public partial bool IsColorizationDetailsExpanded { get; set; }
|
public partial bool IsColorizationDetailsExpanded { get; set; }
|
||||||
|
|
||||||
public bool IsCustomTintVisible => _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.Image;
|
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;
|
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 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 ElementTheme EffectiveTheme => _elementThemeOverride ?? _themeService.Current.Theme;
|
||||||
|
|
||||||
public Color EffectiveThemeColor => ColorizationMode switch
|
public Color EffectiveThemeColor =>
|
||||||
{
|
!BackdropStyles.Get(_settings.BackdropStyle).SupportsColorization
|
||||||
ColorizationMode.WindowsAccentColor => _currentSystemAccentColor,
|
? Colors.Transparent
|
||||||
ColorizationMode.CustomColor or ColorizationMode.Image => ThemeColor,
|
: ColorizationMode switch
|
||||||
_ => Colors.Transparent,
|
{
|
||||||
};
|
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).
|
// 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);
|
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 double EffectiveBackgroundImageBrightness => BackgroundImageBrightness / 100.0;
|
||||||
|
|
||||||
public ImageSource? EffectiveBackgroundImageSource =>
|
public ImageSource? EffectiveBackgroundImageSource =>
|
||||||
ColorizationMode is ColorizationMode.Image
|
!BackdropStyles.Get(_settings.BackdropStyle).SupportsBackgroundImage
|
||||||
&& !string.IsNullOrWhiteSpace(BackgroundImagePath)
|
? null
|
||||||
&& Uri.TryCreate(BackgroundImagePath, UriKind.RelativeOrAbsolute, out var uri)
|
: ColorizationMode is ColorizationMode.Image
|
||||||
? new Microsoft.UI.Xaml.Media.Imaging.BitmapImage(uri)
|
&& !string.IsNullOrWhiteSpace(BackgroundImagePath)
|
||||||
: null;
|
&& Uri.TryCreate(BackgroundImagePath, UriKind.RelativeOrAbsolute, out var uri)
|
||||||
|
? new Microsoft.UI.Xaml.Media.Imaging.BitmapImage(uri)
|
||||||
|
: null;
|
||||||
|
|
||||||
public AppearanceSettingsViewModel(IThemeService themeService, SettingsModel settings)
|
public AppearanceSettingsViewModel(IThemeService themeService, SettingsModel settings)
|
||||||
{
|
{
|
||||||
@@ -327,7 +448,7 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
|||||||
|
|
||||||
Reapply();
|
Reapply();
|
||||||
|
|
||||||
IsColorizationDetailsExpanded = _settings.ColorizationMode != ColorizationMode.None;
|
IsColorizationDetailsExpanded = _settings.ColorizationMode != ColorizationMode.None && IsBackgroundSettingsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UiSettingsOnColorValuesChanged(UISettings sender, object args) => _uiDispatcher.TryEnqueue(() => UpdateAccentColor(sender));
|
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.
|
// Theme services recalculates effective color and opacity based on current settings.
|
||||||
EffectiveBackdrop = _themeService.Current.BackdropParameters;
|
EffectiveBackdrop = _themeService.Current.BackdropParameters;
|
||||||
OnPropertyChanged(nameof(EffectiveBackdrop));
|
OnPropertyChanged(nameof(EffectiveBackdrop));
|
||||||
|
OnPropertyChanged(nameof(EffectiveBackdropStyle));
|
||||||
|
OnPropertyChanged(nameof(EffectiveImageOpacity));
|
||||||
OnPropertyChanged(nameof(EffectiveBackgroundImageBrightness));
|
OnPropertyChanged(nameof(EffectiveBackgroundImageBrightness));
|
||||||
OnPropertyChanged(nameof(EffectiveBackgroundImageSource));
|
OnPropertyChanged(nameof(EffectiveBackgroundImageSource));
|
||||||
OnPropertyChanged(nameof(EffectiveThemeColor));
|
OnPropertyChanged(nameof(EffectiveThemeColor));
|
||||||
@@ -379,7 +502,28 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
|||||||
BackgroundImageBlurAmount = 0;
|
BackgroundImageBlurAmount = 0;
|
||||||
BackgroundImageFit = BackgroundImageFit.UniformToFill;
|
BackgroundImageFit = BackgroundImageFit.UniformToFill;
|
||||||
BackgroundImageOpacity = 100;
|
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()
|
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;
|
public partial Stretch BackgroundImageStretch { get; private set; } = Stretch.Fill;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(EffectiveImageOpacity))]
|
||||||
public partial double BackgroundImageOpacity { get; private set; }
|
public partial double BackgroundImageOpacity { get; private set; }
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
@@ -39,6 +40,30 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial bool ShowBackgroundImage { get; private set; }
|
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)
|
public MainWindowViewModel(IThemeService themeService)
|
||||||
{
|
{
|
||||||
_themeService = themeService;
|
_themeService = themeService;
|
||||||
@@ -58,6 +83,9 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable
|
|||||||
BackgroundImageTintIntensity = _themeService.Current.TintIntensity;
|
BackgroundImageTintIntensity = _themeService.Current.TintIntensity;
|
||||||
BackgroundImageBlurAmount = _themeService.Current.BlurAmount;
|
BackgroundImageBlurAmount = _themeService.Current.BlurAmount;
|
||||||
|
|
||||||
|
BackdropStyle = _themeService.Current.BackdropParameters.Style;
|
||||||
|
BackdropOpacity = _themeService.Current.BackdropOpacity;
|
||||||
|
|
||||||
ShowBackgroundImage = BackgroundImageSource != null;
|
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; }
|
public required double BackgroundImageOpacity { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <returns>The resolved <c>AcrylicBackdropParameters</c> to apply.</returns>
|
/// <returns>The resolved <c>BackdropParameters</c> to apply.</returns>
|
||||||
public required AcrylicBackdropParameters BackdropParameters { get; init; }
|
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 int BlurAmount { get; init; }
|
||||||
|
|
||||||
public required float BackgroundBrightness { 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 CustomThemeColorIntensity { get; set; } = 100;
|
||||||
|
|
||||||
|
public int BackgroundImageTintIntensity { get; set; }
|
||||||
|
|
||||||
public int BackgroundImageOpacity { get; set; } = 20;
|
public int BackgroundImageOpacity { get; set; } = 20;
|
||||||
|
|
||||||
public int BackgroundImageBlurAmount { get; set; }
|
public int BackgroundImageBlurAmount { get; set; }
|
||||||
@@ -84,6 +86,10 @@ public partial class SettingsModel : ObservableObject
|
|||||||
|
|
||||||
public string? BackgroundImagePath { get; set; }
|
public string? BackgroundImagePath { get; set; }
|
||||||
|
|
||||||
|
public BackdropStyle BackdropStyle { get; set; }
|
||||||
|
|
||||||
|
public int BackdropOpacity { get; set; } = 100;
|
||||||
|
|
||||||
// END SETTINGS
|
// END SETTINGS
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
@@ -288,7 +288,6 @@ internal sealed partial class BlurImageControl : Control
|
|||||||
_effectBrush?.Dispose();
|
_effectBrush?.Dispose();
|
||||||
_effectBrush = effectFactory.CreateBrush();
|
_effectBrush = effectFactory.CreateBrush();
|
||||||
|
|
||||||
// Set initial source
|
|
||||||
if (ImageSource is not null)
|
if (ImageSource is not null)
|
||||||
{
|
{
|
||||||
_imageBrush ??= _compositor.CreateSurfaceBrush();
|
_imageBrush ??= _compositor.CreateSurfaceBrush();
|
||||||
|
|||||||
@@ -16,24 +16,38 @@
|
|||||||
CornerRadius="8"
|
CornerRadius="8"
|
||||||
Translation="0,0,8">
|
Translation="0,0,8">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
<!-- Clear style: SolidColorBrush with computed alpha (window backdrop) -->
|
||||||
<Border
|
<Border
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
|
BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
Visibility="{x:Bind h:BindTransformers.NegateVisibility(ShowBackgroundImage), Mode=OneWay}">
|
Visibility="{x:Bind ClearVisibility, Mode=OneWay}">
|
||||||
|
<Border.Background>
|
||||||
|
<SolidColorBrush Color="{x:Bind EffectiveClearColor, Mode=OneWay}" />
|
||||||
|
</Border.Background>
|
||||||
|
</Border>
|
||||||
|
<!-- Acrylic/Mica style: AcrylicBrush with effective opacity (window backdrop) -->
|
||||||
|
<Border
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
Visibility="{x:Bind AcrylicVisibility, Mode=OneWay}">
|
||||||
<Border.Background>
|
<Border.Background>
|
||||||
<AcrylicBrush
|
<AcrylicBrush
|
||||||
FallbackColor="{x:Bind PreviewBackgroundColor, Mode=OneWay}"
|
FallbackColor="{x:Bind PreviewBackgroundColor, Mode=OneWay}"
|
||||||
TintColor="{x:Bind PreviewBackgroundColor, Mode=OneWay}"
|
TintColor="{x:Bind PreviewBackgroundColor, Mode=OneWay}"
|
||||||
TintOpacity="{x:Bind PreviewBackgroundOpacity, Mode=OneWay}" />
|
TintOpacity="{x:Bind PreviewEffectiveOpacity, Mode=OneWay}" />
|
||||||
</Border.Background>
|
</Border.Background>
|
||||||
</Border>
|
</Border>
|
||||||
|
<!-- Background image (inside window, on top of backdrop) -->
|
||||||
<local:BlurImageControl
|
<local:BlurImageControl
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
BlurAmount="{x:Bind PreviewBackgroundImageBlurAmount, Mode=OneWay}"
|
BlurAmount="{x:Bind PreviewBackgroundImageBlurAmount, Mode=OneWay}"
|
||||||
ImageBrightness="{x:Bind PreviewBackgroundImageBrightness, Mode=OneWay}"
|
ImageBrightness="{x:Bind PreviewBackgroundImageBrightness, Mode=OneWay}"
|
||||||
|
ImageOpacity="{x:Bind PreviewBackgroundImageOpacity, Mode=OneWay}"
|
||||||
ImageSource="{x:Bind PreviewBackgroundImageSource, Mode=OneWay}"
|
ImageSource="{x:Bind PreviewBackgroundImageSource, Mode=OneWay}"
|
||||||
ImageStretch="{x:Bind ToStretch(PreviewBackgroundImageFit), Mode=OneWay}"
|
ImageStretch="{x:Bind ToStretch(PreviewBackgroundImageFit), Mode=OneWay}"
|
||||||
IsHitTestVisible="False"
|
IsHitTestVisible="False"
|
||||||
|
|||||||
@@ -12,13 +12,11 @@ namespace Microsoft.CmdPal.UI.Controls;
|
|||||||
|
|
||||||
public sealed partial class CommandPalettePreview : UserControl
|
public sealed partial class CommandPalettePreview : UserControl
|
||||||
{
|
{
|
||||||
public static readonly DependencyProperty PreviewBackgroundOpacityProperty = DependencyProperty.Register(nameof(PreviewBackgroundOpacity), typeof(double), typeof(CommandPalettePreview), new PropertyMetadata(0d));
|
public static readonly DependencyProperty PreviewBackgroundColorProperty = DependencyProperty.Register(nameof(PreviewBackgroundColor), typeof(Color), typeof(CommandPalettePreview), new PropertyMetadata(default(Color), OnBackdropPropertyChanged));
|
||||||
|
|
||||||
public static readonly DependencyProperty PreviewBackgroundColorProperty = DependencyProperty.Register(nameof(PreviewBackgroundColor), typeof(Color), typeof(CommandPalettePreview), new PropertyMetadata(default(Color)));
|
public static readonly DependencyProperty PreviewBackgroundImageSourceProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageSource), typeof(ImageSource), typeof(CommandPalettePreview), new PropertyMetadata(null, OnBackgroundImageSourceChanged));
|
||||||
|
|
||||||
public static readonly DependencyProperty PreviewBackgroundImageSourceProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageSource), typeof(ImageSource), typeof(CommandPalettePreview), new PropertyMetadata(null, PropertyChangedCallback));
|
public static readonly DependencyProperty PreviewBackgroundImageOpacityProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageOpacity), typeof(double), typeof(CommandPalettePreview), new PropertyMetadata(1.0));
|
||||||
|
|
||||||
public static readonly DependencyProperty PreviewBackgroundImageOpacityProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageOpacity), typeof(int), typeof(CommandPalettePreview), new PropertyMetadata(0));
|
|
||||||
|
|
||||||
public static readonly DependencyProperty PreviewBackgroundImageFitProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageFit), typeof(BackgroundImageFit), typeof(CommandPalettePreview), new PropertyMetadata(default(BackgroundImageFit)));
|
public static readonly DependencyProperty PreviewBackgroundImageFitProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageFit), typeof(BackgroundImageFit), typeof(CommandPalettePreview), new PropertyMetadata(default(BackgroundImageFit)));
|
||||||
|
|
||||||
@@ -30,7 +28,18 @@ public sealed partial class CommandPalettePreview : UserControl
|
|||||||
|
|
||||||
public static readonly DependencyProperty PreviewBackgroundImageTintIntensityProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageTintIntensity), typeof(int), typeof(CommandPalettePreview), new PropertyMetadata(0));
|
public static readonly DependencyProperty PreviewBackgroundImageTintIntensityProperty = DependencyProperty.Register(nameof(PreviewBackgroundImageTintIntensity), typeof(int), typeof(CommandPalettePreview), new PropertyMetadata(0));
|
||||||
|
|
||||||
public static readonly DependencyProperty ShowBackgroundImageProperty = DependencyProperty.Register(nameof(ShowBackgroundImage), typeof(Visibility), typeof(CommandPalettePreview), new PropertyMetadata(Visibility.Collapsed));
|
public static readonly DependencyProperty ShowBackgroundImageProperty = DependencyProperty.Register(nameof(ShowBackgroundImage), typeof(Visibility), typeof(CommandPalettePreview), new PropertyMetadata(Visibility.Collapsed, OnVisibilityPropertyChanged));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty PreviewBackdropStyleProperty = DependencyProperty.Register(nameof(PreviewBackdropStyle), typeof(BackdropStyle?), typeof(CommandPalettePreview), new PropertyMetadata(null, OnVisibilityPropertyChanged));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty PreviewEffectiveOpacityProperty = DependencyProperty.Register(nameof(PreviewEffectiveOpacity), typeof(double), typeof(CommandPalettePreview), new PropertyMetadata(1.0, OnBackdropPropertyChanged));
|
||||||
|
|
||||||
|
// Computed read-only dependency properties
|
||||||
|
public static readonly DependencyProperty EffectiveClearColorProperty = DependencyProperty.Register(nameof(EffectiveClearColor), typeof(Color), typeof(CommandPalettePreview), new PropertyMetadata(default(Color)));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty AcrylicVisibilityProperty = DependencyProperty.Register(nameof(AcrylicVisibility), typeof(Visibility), typeof(CommandPalettePreview), new PropertyMetadata(Visibility.Visible));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ClearVisibilityProperty = DependencyProperty.Register(nameof(ClearVisibility), typeof(Visibility), typeof(CommandPalettePreview), new PropertyMetadata(Visibility.Collapsed));
|
||||||
|
|
||||||
public BackgroundImageFit PreviewBackgroundImageFit
|
public BackgroundImageFit PreviewBackgroundImageFit
|
||||||
{
|
{
|
||||||
@@ -38,12 +47,6 @@ public sealed partial class CommandPalettePreview : UserControl
|
|||||||
set { SetValue(PreviewBackgroundImageFitProperty, value); }
|
set { SetValue(PreviewBackgroundImageFitProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double PreviewBackgroundOpacity
|
|
||||||
{
|
|
||||||
get { return (double)GetValue(PreviewBackgroundOpacityProperty); }
|
|
||||||
set { SetValue(PreviewBackgroundOpacityProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color PreviewBackgroundColor
|
public Color PreviewBackgroundColor
|
||||||
{
|
{
|
||||||
get { return (Color)GetValue(PreviewBackgroundColorProperty); }
|
get { return (Color)GetValue(PreviewBackgroundColorProperty); }
|
||||||
@@ -56,10 +59,10 @@ public sealed partial class CommandPalettePreview : UserControl
|
|||||||
set { SetValue(PreviewBackgroundImageSourceProperty, value); }
|
set { SetValue(PreviewBackgroundImageSourceProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int PreviewBackgroundImageOpacity
|
public double PreviewBackgroundImageOpacity
|
||||||
{
|
{
|
||||||
get { return (int)GetValue(PreviewBackgroundImageOpacityProperty); }
|
get => (double)GetValue(PreviewBackgroundImageOpacityProperty);
|
||||||
set { SetValue(PreviewBackgroundImageOpacityProperty, value); }
|
set => SetValue(PreviewBackgroundImageOpacityProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double PreviewBackgroundImageBrightness
|
public double PreviewBackgroundImageBrightness
|
||||||
@@ -92,12 +95,48 @@ public sealed partial class CommandPalettePreview : UserControl
|
|||||||
set => SetValue(ShowBackgroundImageProperty, value);
|
set => SetValue(ShowBackgroundImageProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BackdropStyle? PreviewBackdropStyle
|
||||||
|
{
|
||||||
|
get => (BackdropStyle?)GetValue(PreviewBackdropStyleProperty);
|
||||||
|
set => SetValue(PreviewBackdropStyleProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the effective opacity for the backdrop, pre-computed by the theme provider.
|
||||||
|
/// For Acrylic style: used directly as TintOpacity.
|
||||||
|
/// For Clear style: used to compute the alpha channel of the solid color.
|
||||||
|
/// </summary>
|
||||||
|
public double PreviewEffectiveOpacity
|
||||||
|
{
|
||||||
|
get => (double)GetValue(PreviewEffectiveOpacityProperty);
|
||||||
|
set => SetValue(PreviewEffectiveOpacityProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computed read-only properties
|
||||||
|
public Color EffectiveClearColor
|
||||||
|
{
|
||||||
|
get => (Color)GetValue(EffectiveClearColorProperty);
|
||||||
|
private set => SetValue(EffectiveClearColorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility AcrylicVisibility
|
||||||
|
{
|
||||||
|
get => (Visibility)GetValue(AcrylicVisibilityProperty);
|
||||||
|
private set => SetValue(AcrylicVisibilityProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility ClearVisibility
|
||||||
|
{
|
||||||
|
get => (Visibility)GetValue(ClearVisibilityProperty);
|
||||||
|
private set => SetValue(ClearVisibilityProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public CommandPalettePreview()
|
public CommandPalettePreview()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
private static void OnBackgroundImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (d is not CommandPalettePreview preview)
|
if (d is not CommandPalettePreview preview)
|
||||||
{
|
{
|
||||||
@@ -107,7 +146,46 @@ public sealed partial class CommandPalettePreview : UserControl
|
|||||||
preview.ShowBackgroundImage = e.NewValue is ImageSource ? Visibility.Visible : Visibility.Collapsed;
|
preview.ShowBackgroundImage = e.NewValue is ImageSource ? Visibility.Visible : Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double ToOpacity(int value) => value / 100.0;
|
private static void OnBackdropPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (d is not CommandPalettePreview preview)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
preview.UpdateComputedClearColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnVisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (d is not CommandPalettePreview preview)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
preview.UpdateComputedVisibilityProperties();
|
||||||
|
preview.UpdateComputedClearColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateComputedClearColor()
|
||||||
|
{
|
||||||
|
EffectiveClearColor = Color.FromArgb(
|
||||||
|
(byte)(PreviewEffectiveOpacity * 255),
|
||||||
|
PreviewBackgroundColor.R,
|
||||||
|
PreviewBackgroundColor.G,
|
||||||
|
PreviewBackgroundColor.B);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateComputedVisibilityProperties()
|
||||||
|
{
|
||||||
|
var config = BackdropStyles.Get(PreviewBackdropStyle ?? BackdropStyle.Acrylic);
|
||||||
|
|
||||||
|
// Show backdrop effect based on style (on top of any background image)
|
||||||
|
AcrylicVisibility = config.PreviewBrush == PreviewBrushKind.Acrylic
|
||||||
|
? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
ClearVisibility = config.PreviewBrush == PreviewBrushKind.Solid
|
||||||
|
? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
private double ToTintIntensity(int value) => value / 100.0;
|
private double ToTintIntensity(int value) => value / 100.0;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
BlurAmount="{x:Bind ViewModel.BackgroundImageBlurAmount, Mode=OneWay}"
|
BlurAmount="{x:Bind ViewModel.BackgroundImageBlurAmount, Mode=OneWay}"
|
||||||
ImageBrightness="{x:Bind ViewModel.BackgroundImageBrightness, Mode=OneWay}"
|
ImageBrightness="{x:Bind ViewModel.BackgroundImageBrightness, Mode=OneWay}"
|
||||||
ImageOpacity="{x:Bind ViewModel.BackgroundImageOpacity, Mode=OneWay}"
|
ImageOpacity="{x:Bind ViewModel.EffectiveImageOpacity, Mode=OneWay}"
|
||||||
ImageSource="{x:Bind ViewModel.BackgroundImageSource, Mode=OneWay}"
|
ImageSource="{x:Bind ViewModel.BackgroundImageSource, Mode=OneWay}"
|
||||||
ImageStretch="{x:Bind ViewModel.BackgroundImageStretch, Mode=OneWay}"
|
ImageStretch="{x:Bind ViewModel.BackgroundImageStretch, Mode=OneWay}"
|
||||||
IsHitTestVisible="False"
|
IsHitTestVisible="False"
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ using Windows.ApplicationModel.Activation;
|
|||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
using Windows.Graphics;
|
using Windows.Graphics;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
|
using Windows.UI;
|
||||||
using Windows.Win32;
|
using Windows.Win32;
|
||||||
using Windows.Win32.Foundation;
|
using Windows.Win32.Foundation;
|
||||||
using Windows.Win32.Graphics.Dwm;
|
using Windows.Win32.Graphics.Dwm;
|
||||||
@@ -80,7 +81,9 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
private int _sessionErrorCount;
|
private int _sessionErrorCount;
|
||||||
|
|
||||||
private DesktopAcrylicController? _acrylicController;
|
private DesktopAcrylicController? _acrylicController;
|
||||||
|
private MicaController? _micaController;
|
||||||
private SystemBackdropConfiguration? _configurationSource;
|
private SystemBackdropConfiguration? _configurationSource;
|
||||||
|
private bool _isUpdatingBackdrop;
|
||||||
private TimeSpan _autoGoHomeInterval = Timeout.InfiniteTimeSpan;
|
private TimeSpan _autoGoHomeInterval = Timeout.InfiniteTimeSpan;
|
||||||
|
|
||||||
private WindowPosition _currentWindowPosition = new();
|
private WindowPosition _currentWindowPosition = new();
|
||||||
@@ -109,7 +112,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetAcrylic();
|
InitializeBackdropSupport();
|
||||||
|
|
||||||
_hiddenOwnerBehavior.ShowInTaskbar(this, Debugger.IsAttached);
|
_hiddenOwnerBehavior.ShowInTaskbar(this, Debugger.IsAttached);
|
||||||
|
|
||||||
@@ -158,7 +161,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
App.Current.Services.GetService<SettingsModel>()!.SettingsChanged += SettingsChangedHandler;
|
App.Current.Services.GetService<SettingsModel>()!.SettingsChanged += SettingsChangedHandler;
|
||||||
|
|
||||||
// Make sure that we update the acrylic theme when the OS theme changes
|
// Make sure that we update the acrylic theme when the OS theme changes
|
||||||
RootElement.ActualThemeChanged += (s, e) => DispatcherQueue.TryEnqueue(UpdateAcrylic);
|
RootElement.ActualThemeChanged += (s, e) => DispatcherQueue.TryEnqueue(UpdateBackdrop);
|
||||||
|
|
||||||
// Hardcoding event name to avoid bringing in the PowerToys.interop dependency. Event name must match CMDPAL_SHOW_EVENT from shared_constants.h
|
// Hardcoding event name to avoid bringing in the PowerToys.interop dependency. Event name must match CMDPAL_SHOW_EVENT from shared_constants.h
|
||||||
NativeEventWaiter.WaitForEventLoop("Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a", () =>
|
NativeEventWaiter.WaitForEventLoop("Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a", () =>
|
||||||
@@ -185,7 +188,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
private void ThemeServiceOnThemeChanged(object? sender, ThemeChangedEventArgs e)
|
private void ThemeServiceOnThemeChanged(object? sender, ThemeChangedEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateAcrylic();
|
UpdateBackdrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LocalKeyboardListener_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e)
|
private static void LocalKeyboardListener_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e)
|
||||||
@@ -280,48 +283,170 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
_autoGoHomeTimer.Interval = _autoGoHomeInterval;
|
_autoGoHomeTimer.Interval = _autoGoHomeInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetAcrylic()
|
private void InitializeBackdropSupport()
|
||||||
{
|
{
|
||||||
if (DesktopAcrylicController.IsSupported())
|
if (DesktopAcrylicController.IsSupported() || MicaController.IsSupported())
|
||||||
{
|
{
|
||||||
// Hooking up the policy object.
|
|
||||||
_configurationSource = new SystemBackdropConfiguration
|
_configurationSource = new SystemBackdropConfiguration
|
||||||
{
|
{
|
||||||
// Initial configuration state.
|
|
||||||
IsInputActive = true,
|
IsInputActive = true,
|
||||||
};
|
};
|
||||||
UpdateAcrylic();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAcrylic()
|
private void UpdateBackdrop()
|
||||||
{
|
{
|
||||||
|
// Prevent re-entrance when backdrop changes trigger ActualThemeChanged
|
||||||
|
if (_isUpdatingBackdrop)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isUpdatingBackdrop = true;
|
||||||
|
|
||||||
|
var backdrop = _themeService.Current.BackdropParameters;
|
||||||
|
var isImageMode = ViewModel.ShowBackgroundImage;
|
||||||
|
var config = BackdropStyles.Get(backdrop.Style);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_acrylicController != null)
|
switch (config.ControllerKind)
|
||||||
{
|
{
|
||||||
_acrylicController.RemoveAllSystemBackdropTargets();
|
case BackdropControllerKind.Solid:
|
||||||
_acrylicController.Dispose();
|
CleanupBackdropControllers();
|
||||||
|
var tintColor = Color.FromArgb(
|
||||||
|
(byte)(backdrop.EffectiveOpacity * 255),
|
||||||
|
backdrop.TintColor.R,
|
||||||
|
backdrop.TintColor.G,
|
||||||
|
backdrop.TintColor.B);
|
||||||
|
SetupTransparentBackdrop(tintColor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BackdropControllerKind.Mica:
|
||||||
|
case BackdropControllerKind.MicaAlt:
|
||||||
|
SetupMica(backdrop, isImageMode, config.ControllerKind);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BackdropControllerKind.Acrylic:
|
||||||
|
case BackdropControllerKind.AcrylicThin:
|
||||||
|
default:
|
||||||
|
SetupDesktopAcrylic(backdrop, isImageMode, config.ControllerKind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var backdrop = _themeService.Current.BackdropParameters;
|
|
||||||
_acrylicController = new DesktopAcrylicController
|
|
||||||
{
|
|
||||||
TintColor = backdrop.TintColor,
|
|
||||||
TintOpacity = backdrop.TintOpacity,
|
|
||||||
FallbackColor = backdrop.FallbackColor,
|
|
||||||
LuminosityOpacity = backdrop.LuminosityOpacity,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Enable the system backdrop.
|
|
||||||
// Note: Be sure to have "using WinRT;" to support the Window.As<...>() call.
|
|
||||||
_acrylicController.AddSystemBackdropTarget(this.As<ICompositionSupportsSystemBackdrop>());
|
|
||||||
_acrylicController.SetSystemBackdropConfiguration(_configurationSource);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError("Failed to update backdrop", ex);
|
Logger.LogError("Failed to update backdrop", ex);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isUpdatingBackdrop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupTransparentBackdrop(Color tintColor)
|
||||||
|
{
|
||||||
|
if (SystemBackdrop is TransparentTintBackdrop existingBackdrop)
|
||||||
|
{
|
||||||
|
existingBackdrop.TintColor = tintColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SystemBackdrop = new TransparentTintBackdrop { TintColor = tintColor };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanupBackdropControllers()
|
||||||
|
{
|
||||||
|
if (_acrylicController is not null)
|
||||||
|
{
|
||||||
|
_acrylicController.RemoveAllSystemBackdropTargets();
|
||||||
|
_acrylicController.Dispose();
|
||||||
|
_acrylicController = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_micaController is not null)
|
||||||
|
{
|
||||||
|
_micaController.RemoveAllSystemBackdropTargets();
|
||||||
|
_micaController.Dispose();
|
||||||
|
_micaController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupDesktopAcrylic(BackdropParameters backdrop, bool isImageMode, BackdropControllerKind kind)
|
||||||
|
{
|
||||||
|
CleanupBackdropControllers();
|
||||||
|
|
||||||
|
// Fall back to solid color if acrylic not supported
|
||||||
|
if (_configurationSource is null || !DesktopAcrylicController.IsSupported())
|
||||||
|
{
|
||||||
|
SetupTransparentBackdrop(backdrop.FallbackColor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DesktopAcrylicController and SystemBackdrop can't be active simultaneously
|
||||||
|
SystemBackdrop = null;
|
||||||
|
|
||||||
|
// Image mode: no tint here, BlurImageControl handles it (avoids double-tinting)
|
||||||
|
var effectiveTintOpacity = isImageMode
|
||||||
|
? 0.0f
|
||||||
|
: backdrop.EffectiveOpacity;
|
||||||
|
|
||||||
|
_acrylicController = new DesktopAcrylicController
|
||||||
|
{
|
||||||
|
Kind = kind == BackdropControllerKind.AcrylicThin
|
||||||
|
? DesktopAcrylicKind.Thin
|
||||||
|
: DesktopAcrylicKind.Default,
|
||||||
|
TintColor = backdrop.TintColor,
|
||||||
|
TintOpacity = effectiveTintOpacity,
|
||||||
|
FallbackColor = backdrop.FallbackColor,
|
||||||
|
LuminosityOpacity = backdrop.EffectiveLuminosityOpacity,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Requires "using WinRT;" for Window.As<>()
|
||||||
|
_acrylicController.AddSystemBackdropTarget(this.As<ICompositionSupportsSystemBackdrop>());
|
||||||
|
_acrylicController.SetSystemBackdropConfiguration(_configurationSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupMica(BackdropParameters backdrop, bool isImageMode, BackdropControllerKind kind)
|
||||||
|
{
|
||||||
|
CleanupBackdropControllers();
|
||||||
|
|
||||||
|
// Fall back to solid color if Mica not supported
|
||||||
|
if (_configurationSource is null || !MicaController.IsSupported())
|
||||||
|
{
|
||||||
|
SetupTransparentBackdrop(backdrop.FallbackColor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MicaController and SystemBackdrop can't be active simultaneously
|
||||||
|
SystemBackdrop = null;
|
||||||
|
_configurationSource.Theme = _themeService.Current.Theme == ElementTheme.Dark
|
||||||
|
? SystemBackdropTheme.Dark
|
||||||
|
: SystemBackdropTheme.Light;
|
||||||
|
|
||||||
|
var hasColorization = _themeService.Current.HasColorization || isImageMode;
|
||||||
|
|
||||||
|
_micaController = new MicaController
|
||||||
|
{
|
||||||
|
Kind = kind == BackdropControllerKind.MicaAlt
|
||||||
|
? MicaKind.BaseAlt
|
||||||
|
: MicaKind.Base,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only set tint properties when colorization is active
|
||||||
|
// Otherwise let system handle light/dark theme defaults automatically
|
||||||
|
if (hasColorization)
|
||||||
|
{
|
||||||
|
// Image mode: no tint here, BlurImageControl handles it (avoids double-tinting)
|
||||||
|
_micaController.TintColor = backdrop.TintColor;
|
||||||
|
_micaController.TintOpacity = isImageMode ? 0.0f : backdrop.EffectiveOpacity;
|
||||||
|
_micaController.FallbackColor = backdrop.FallbackColor;
|
||||||
|
_micaController.LuminosityOpacity = backdrop.EffectiveLuminosityOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
_micaController.AddSystemBackdropTarget(this.As<ICompositionSupportsSystemBackdrop>());
|
||||||
|
_micaController.SetSystemBackdropConfiguration(_configurationSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowHwnd(IntPtr hwndValue, MonitorBehavior target)
|
private void ShowHwnd(IntPtr hwndValue, MonitorBehavior target)
|
||||||
@@ -637,12 +762,8 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
private void DisposeAcrylic()
|
private void DisposeAcrylic()
|
||||||
{
|
{
|
||||||
if (_acrylicController is not null)
|
CleanupBackdropControllers();
|
||||||
{
|
_configurationSource = null!;
|
||||||
_acrylicController.Dispose();
|
|
||||||
_acrylicController = null!;
|
|
||||||
_configurationSource = null!;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates our window s.t. the top of the window is draggable.
|
// Updates our window s.t. the top of the window is draggable.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
using CommunityToolkit.WinUI.Helpers;
|
using CommunityToolkit.WinUI.Helpers;
|
||||||
using Microsoft.CmdPal.UI.Helpers;
|
using Microsoft.CmdPal.UI.Helpers;
|
||||||
|
using Microsoft.CmdPal.UI.ViewModels;
|
||||||
using Microsoft.CmdPal.UI.ViewModels.Services;
|
using Microsoft.CmdPal.UI.ViewModels.Services;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
@@ -34,7 +35,7 @@ internal sealed class ColorfulThemeProvider : IThemeProvider
|
|||||||
_uiSettings = uiSettings;
|
_uiSettings = uiSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AcrylicBackdropParameters GetAcrylicBackdrop(ThemeContext context)
|
public BackdropParameters GetBackdropParameters(ThemeContext context)
|
||||||
{
|
{
|
||||||
var isLight = context.Theme == ElementTheme.Light ||
|
var isLight = context.Theme == ElementTheme.Light ||
|
||||||
(context.Theme == ElementTheme.Default &&
|
(context.Theme == ElementTheme.Default &&
|
||||||
@@ -53,7 +54,26 @@ internal sealed class ColorfulThemeProvider : IThemeProvider
|
|||||||
var colorIntensity = isLight ? 0.6f * colorIntensityUser : colorIntensityUser;
|
var colorIntensity = isLight ? 0.6f * colorIntensityUser : colorIntensityUser;
|
||||||
var effectiveBgColor = ColorBlender.Blend(baseColor, blended, colorIntensity);
|
var effectiveBgColor = ColorBlender.Blend(baseColor, blended, colorIntensity);
|
||||||
|
|
||||||
return new AcrylicBackdropParameters(effectiveBgColor, effectiveBgColor, 0.8f, 0.8f);
|
var transparencyMode = context.BackdropStyle ?? BackdropStyle.Acrylic;
|
||||||
|
var config = BackdropStyles.Get(transparencyMode);
|
||||||
|
|
||||||
|
// For colorful theme, boost tint opacity to show color better through blur
|
||||||
|
// But not for styles with fixed opacity (Mica) - they handle their own opacity
|
||||||
|
var baseTintOpacity = config.ControllerKind == BackdropControllerKind.Solid || !config.SupportsOpacity
|
||||||
|
? (float?)null // Use default
|
||||||
|
: Math.Max(config.BaseTintOpacity, 0.8f);
|
||||||
|
|
||||||
|
var effectiveOpacity = config.ComputeEffectiveOpacity(context.BackdropOpacity, baseTintOpacity);
|
||||||
|
var effectiveLuminosityOpacity = config.SupportsOpacity
|
||||||
|
? config.BaseLuminosityOpacity * context.BackdropOpacity
|
||||||
|
: config.BaseLuminosityOpacity;
|
||||||
|
|
||||||
|
return new BackdropParameters(
|
||||||
|
TintColor: effectiveBgColor,
|
||||||
|
FallbackColor: effectiveBgColor,
|
||||||
|
EffectiveOpacity: effectiveOpacity,
|
||||||
|
EffectiveLuminosityOpacity: effectiveLuminosityOpacity,
|
||||||
|
Style: transparencyMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ColorBlender
|
private static class ColorBlender
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ using Microsoft.CmdPal.UI.ViewModels.Services;
|
|||||||
namespace Microsoft.CmdPal.UI.Services;
|
namespace Microsoft.CmdPal.UI.Services;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides theme identification, resource path resolution, and creation of acrylic
|
/// Provides theme identification, resource path resolution, and creation of backdrop
|
||||||
/// backdrop parameters based on the current <see cref="ThemeContext"/>.
|
/// parameters based on the current <see cref="ThemeContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Implementations should expose a stable <see cref="ThemeKey"/> and a valid XAML resource
|
/// Implementations should expose a stable <see cref="ThemeKey"/> and a valid XAML resource
|
||||||
/// dictionary path via <see cref="ResourcePath"/>. The
|
/// dictionary path via <see cref="ResourcePath"/>. The
|
||||||
/// <see cref="GetAcrylicBackdrop(ThemeContext)"/> method computes
|
/// <see cref="GetBackdropParameters(ThemeContext)"/> method computes
|
||||||
/// <see cref="AcrylicBackdropParameters"/> using the supplied theme context.
|
/// <see cref="BackdropParameters"/> using the supplied theme context.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal interface IThemeProvider
|
internal interface IThemeProvider
|
||||||
{
|
{
|
||||||
@@ -30,9 +30,9 @@ internal interface IThemeProvider
|
|||||||
string ResourcePath { get; }
|
string ResourcePath { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates acrylic backdrop parameters based on the provided theme context.
|
/// Creates backdrop parameters based on the provided theme context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The current theme context, including theme, tint, and optional background details.</param>
|
/// <param name="context">The current theme context, including theme, tint, transparency mode, and optional background details.</param>
|
||||||
/// <returns>The computed <see cref="AcrylicBackdropParameters"/> for the backdrop.</returns>
|
/// <returns>The computed <see cref="BackdropParameters"/> for the backdrop.</returns>
|
||||||
AcrylicBackdropParameters GetAcrylicBackdrop(ThemeContext context);
|
BackdropParameters GetBackdropParameters(ThemeContext context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using Microsoft.CmdPal.UI.ViewModels;
|
||||||
using Microsoft.CmdPal.UI.ViewModels.Services;
|
using Microsoft.CmdPal.UI.ViewModels.Services;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
@@ -28,16 +29,28 @@ internal sealed class NormalThemeProvider : IThemeProvider
|
|||||||
|
|
||||||
public string ResourcePath => "ms-appx:///Styles/Theme.Normal.xaml";
|
public string ResourcePath => "ms-appx:///Styles/Theme.Normal.xaml";
|
||||||
|
|
||||||
public AcrylicBackdropParameters GetAcrylicBackdrop(ThemeContext context)
|
public BackdropParameters GetBackdropParameters(ThemeContext context)
|
||||||
{
|
{
|
||||||
var isLight = context.Theme == ElementTheme.Light ||
|
var isLight = context.Theme == ElementTheme.Light ||
|
||||||
(context.Theme == ElementTheme.Default &&
|
(context.Theme == ElementTheme.Default &&
|
||||||
_uiSettings.GetColorValue(UIColorType.Background).R > 128);
|
_uiSettings.GetColorValue(UIColorType.Background).R > 128);
|
||||||
|
|
||||||
return new AcrylicBackdropParameters(
|
var backdropStyle = context.BackdropStyle ?? BackdropStyle.Acrylic;
|
||||||
|
var config = BackdropStyles.Get(backdropStyle);
|
||||||
|
|
||||||
|
// Apply light/dark theme adjustment to luminosity
|
||||||
|
var baseLuminosityOpacity = isLight
|
||||||
|
? config.BaseLuminosityOpacity
|
||||||
|
: Math.Min(config.BaseLuminosityOpacity + 0.06f, 1.0f);
|
||||||
|
|
||||||
|
var effectiveOpacity = config.ComputeEffectiveOpacity(context.BackdropOpacity);
|
||||||
|
var effectiveLuminosityOpacity = baseLuminosityOpacity * context.BackdropOpacity;
|
||||||
|
|
||||||
|
return new BackdropParameters(
|
||||||
TintColor: isLight ? LightBaseColor : DarkBaseColor,
|
TintColor: isLight ? LightBaseColor : DarkBaseColor,
|
||||||
FallbackColor: isLight ? LightBaseColor : DarkBaseColor,
|
FallbackColor: isLight ? LightBaseColor : DarkBaseColor,
|
||||||
TintOpacity: 0.5f,
|
EffectiveOpacity: effectiveOpacity,
|
||||||
LuminosityOpacity: isLight ? 0.9f : 0.96f);
|
EffectiveLuminosityOpacity: effectiveLuminosityOpacity,
|
||||||
|
Style: backdropStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,16 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using Microsoft.CmdPal.UI.ViewModels;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.UI.Services;
|
namespace Microsoft.CmdPal.UI.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Input parameters for theme computation, passed to theme providers.
|
||||||
|
/// </summary>
|
||||||
internal sealed record ThemeContext
|
internal sealed record ThemeContext
|
||||||
{
|
{
|
||||||
public ElementTheme Theme { get; init; }
|
public ElementTheme Theme { get; init; }
|
||||||
@@ -21,4 +25,8 @@ internal sealed record ThemeContext
|
|||||||
public double BackgroundImageOpacity { get; init; }
|
public double BackgroundImageOpacity { get; init; }
|
||||||
|
|
||||||
public int? ColorIntensity { get; init; }
|
public int? ColorIntensity { get; init; }
|
||||||
|
|
||||||
|
public BackdropStyle? BackdropStyle { get; init; }
|
||||||
|
|
||||||
|
public float BackdropOpacity { get; init; } = 1.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,10 +72,13 @@ internal sealed partial class ThemeService : IThemeService, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// provider selection
|
// provider selection
|
||||||
var intensity = Math.Clamp(_settings.CustomThemeColorIntensity, 0, 100);
|
var themeColorIntensity = Math.Clamp(_settings.CustomThemeColorIntensity, 0, 100);
|
||||||
IThemeProvider provider = intensity > 0 && _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.WindowsAccentColor or ColorizationMode.Image
|
var imageTintIntensity = Math.Clamp(_settings.BackgroundImageTintIntensity, 0, 100);
|
||||||
? _colorfulThemeProvider
|
var effectiveColorIntensity = _settings.ColorizationMode == ColorizationMode.Image
|
||||||
: _normalThemeProvider;
|
? imageTintIntensity
|
||||||
|
: themeColorIntensity;
|
||||||
|
|
||||||
|
IThemeProvider provider = UseColorfulProvider(effectiveColorIntensity) ? _colorfulThemeProvider : _normalThemeProvider;
|
||||||
|
|
||||||
// Calculate values
|
// Calculate values
|
||||||
var tint = _settings.ColorizationMode switch
|
var tint = _settings.ColorizationMode switch
|
||||||
@@ -96,32 +99,39 @@ internal sealed partial class ThemeService : IThemeService, IDisposable
|
|||||||
};
|
};
|
||||||
var opacity = Math.Clamp(_settings.BackgroundImageOpacity, 0, 100) / 100.0;
|
var opacity = Math.Clamp(_settings.BackgroundImageOpacity, 0, 100) / 100.0;
|
||||||
|
|
||||||
// create context and offload to actual theme provider
|
// create input and offload to actual theme provider
|
||||||
var context = new ThemeContext
|
var context = new ThemeContext
|
||||||
{
|
{
|
||||||
Tint = tint,
|
Tint = tint,
|
||||||
ColorIntensity = intensity,
|
ColorIntensity = effectiveColorIntensity,
|
||||||
Theme = effectiveTheme,
|
Theme = effectiveTheme,
|
||||||
BackgroundImageSource = imageSource,
|
BackgroundImageSource = imageSource,
|
||||||
BackgroundImageStretch = stretch,
|
BackgroundImageStretch = stretch,
|
||||||
BackgroundImageOpacity = opacity,
|
BackgroundImageOpacity = opacity,
|
||||||
|
BackdropStyle = _settings.BackdropStyle,
|
||||||
|
BackdropOpacity = Math.Clamp(_settings.BackdropOpacity, 0, 100) / 100f,
|
||||||
};
|
};
|
||||||
var backdrop = provider.GetAcrylicBackdrop(context);
|
var backdrop = provider.GetBackdropParameters(context);
|
||||||
var blur = _settings.BackgroundImageBlurAmount;
|
var blur = _settings.BackgroundImageBlurAmount;
|
||||||
var brightness = _settings.BackgroundImageBrightness;
|
var brightness = _settings.BackgroundImageBrightness;
|
||||||
|
|
||||||
// Create public snapshot (no provider!)
|
// Create public snapshot (no provider!)
|
||||||
|
var hasColorization = effectiveColorIntensity > 0
|
||||||
|
&& _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.WindowsAccentColor or ColorizationMode.Image;
|
||||||
|
|
||||||
var snapshot = new ThemeSnapshot
|
var snapshot = new ThemeSnapshot
|
||||||
{
|
{
|
||||||
Tint = tint,
|
Tint = tint,
|
||||||
TintIntensity = intensity / 100f,
|
TintIntensity = effectiveColorIntensity / 100f,
|
||||||
Theme = effectiveTheme,
|
Theme = effectiveTheme,
|
||||||
BackgroundImageSource = imageSource,
|
BackgroundImageSource = imageSource,
|
||||||
BackgroundImageStretch = stretch,
|
BackgroundImageStretch = stretch,
|
||||||
BackgroundImageOpacity = opacity,
|
BackgroundImageOpacity = opacity,
|
||||||
BackdropParameters = backdrop,
|
BackdropParameters = backdrop,
|
||||||
|
BackdropOpacity = context.BackdropOpacity,
|
||||||
BlurAmount = blur,
|
BlurAmount = blur,
|
||||||
BackgroundBrightness = brightness / 100f,
|
BackgroundBrightness = brightness / 100f,
|
||||||
|
HasColorization = hasColorization,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bundle with provider for internal use
|
// Bundle with provider for internal use
|
||||||
@@ -138,6 +148,12 @@ internal sealed partial class ThemeService : IThemeService, IDisposable
|
|||||||
ThemeChanged?.Invoke(this, new ThemeChangedEventArgs());
|
ThemeChanged?.Invoke(this, new ThemeChangedEventArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool UseColorfulProvider(int effectiveColorIntensity)
|
||||||
|
{
|
||||||
|
return _settings.ColorizationMode == ColorizationMode.Image
|
||||||
|
|| (effectiveColorIntensity > 0 && _settings.ColorizationMode is ColorizationMode.CustomColor or ColorizationMode.WindowsAccentColor);
|
||||||
|
}
|
||||||
|
|
||||||
private static BitmapImage? LoadImageSafe(string? path)
|
private static BitmapImage? LoadImageSafe(string? path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
@@ -195,13 +211,15 @@ internal sealed partial class ThemeService : IThemeService, IDisposable
|
|||||||
{
|
{
|
||||||
Tint = Colors.Transparent,
|
Tint = Colors.Transparent,
|
||||||
Theme = ElementTheme.Light,
|
Theme = ElementTheme.Light,
|
||||||
BackdropParameters = new AcrylicBackdropParameters(Colors.Black, Colors.Black, 0.5f, 0.5f),
|
BackdropParameters = new BackdropParameters(Colors.Black, Colors.Black, EffectiveOpacity: 0.5f, EffectiveLuminosityOpacity: 0.5f),
|
||||||
|
BackdropOpacity = 1.0f,
|
||||||
BackgroundImageOpacity = 1,
|
BackgroundImageOpacity = 1,
|
||||||
BackgroundImageSource = null,
|
BackgroundImageSource = null,
|
||||||
BackgroundImageStretch = Stretch.Fill,
|
BackgroundImageStretch = Stretch.Fill,
|
||||||
BlurAmount = 0,
|
BlurAmount = 0,
|
||||||
TintIntensity = 1.0f,
|
TintIntensity = 1.0f,
|
||||||
BackgroundBrightness = 0,
|
BackgroundBrightness = 0,
|
||||||
|
HasColorization = false,
|
||||||
},
|
},
|
||||||
Provider = _normalThemeProvider,
|
Provider = _normalThemeProvider,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,18 +22,50 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Spacing="{StaticResource SettingsCardSpacing}">
|
Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
|
|
||||||
<ptControls:ScreenPreview Margin="0,0,0,16" HorizontalAlignment="Left">
|
<StackPanel
|
||||||
<ptControls:CommandPalettePreview
|
Margin="0,0,0,16"
|
||||||
PreviewBackgroundColor="{x:Bind ViewModel.Appearance.EffectiveBackdrop.TintColor, Mode=OneWay}"
|
HorizontalAlignment="Left"
|
||||||
PreviewBackgroundImageBlurAmount="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageBlurAmount, Mode=OneWay}"
|
Orientation="Horizontal"
|
||||||
PreviewBackgroundImageBrightness="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageBrightness, Mode=OneWay}"
|
Spacing="16">
|
||||||
PreviewBackgroundImageFit="{x:Bind ViewModel.Appearance.BackgroundImageFit, Mode=OneWay}"
|
<ptControls:ScreenPreview>
|
||||||
PreviewBackgroundImageSource="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageSource, Mode=OneWay}"
|
<ptControls:CommandPalettePreview
|
||||||
PreviewBackgroundImageTint="{x:Bind ViewModel.Appearance.EffectiveThemeColor, Mode=OneWay}"
|
PreviewBackdropStyle="{x:Bind ViewModel.Appearance.EffectiveBackdropStyle, Mode=OneWay}"
|
||||||
PreviewBackgroundImageTintIntensity="{x:Bind ViewModel.Appearance.ColorIntensity, Mode=OneWay}"
|
PreviewBackgroundColor="{x:Bind ViewModel.Appearance.EffectiveBackdrop.TintColor, Mode=OneWay}"
|
||||||
PreviewBackgroundOpacity="{x:Bind ViewModel.Appearance.EffectiveBackdrop.TintOpacity, Mode=OneWay}"
|
PreviewBackgroundImageBlurAmount="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageBlurAmount, Mode=OneWay}"
|
||||||
RequestedTheme="{x:Bind ViewModel.Appearance.EffectiveTheme, Mode=OneWay}" />
|
PreviewBackgroundImageBrightness="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageBrightness, Mode=OneWay}"
|
||||||
</ptControls:ScreenPreview>
|
PreviewBackgroundImageFit="{x:Bind ViewModel.Appearance.BackgroundImageFit, Mode=OneWay}"
|
||||||
|
PreviewBackgroundImageOpacity="{x:Bind ViewModel.Appearance.EffectiveImageOpacity, Mode=OneWay}"
|
||||||
|
PreviewBackgroundImageSource="{x:Bind ViewModel.Appearance.EffectiveBackgroundImageSource, Mode=OneWay}"
|
||||||
|
PreviewBackgroundImageTint="{x:Bind ViewModel.Appearance.EffectiveThemeColor, Mode=OneWay}"
|
||||||
|
PreviewBackgroundImageTintIntensity="{x:Bind ViewModel.Appearance.EffectiveTintIntensity, Mode=OneWay}"
|
||||||
|
PreviewEffectiveOpacity="{x:Bind ViewModel.Appearance.EffectiveBackdrop.EffectiveOpacity, Mode=OneWay}"
|
||||||
|
RequestedTheme="{x:Bind ViewModel.Appearance.EffectiveTheme, Mode=OneWay}" />
|
||||||
|
</ptControls:ScreenPreview>
|
||||||
|
<StackPanel VerticalAlignment="Bottom" Spacing="8">
|
||||||
|
<Button
|
||||||
|
x:Uid="Settings_AppearancePage_OpenCommandPaletteButton"
|
||||||
|
MinWidth="200"
|
||||||
|
HorizontalContentAlignment="Left"
|
||||||
|
Click="OpenCommandPalette_Click"
|
||||||
|
Style="{StaticResource SubtleButtonStyle}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<FontIcon FontSize="16" Glyph="" />
|
||||||
|
<TextBlock x:Uid="Settings_AppearancePage_OpenCommandPaletteButton_Text" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
x:Uid="Settings_AppearancePage_ResetAppearanceButton"
|
||||||
|
MinWidth="200"
|
||||||
|
HorizontalContentAlignment="Left"
|
||||||
|
Command="{x:Bind ViewModel.Appearance.ResetAppearanceSettingsCommand}"
|
||||||
|
Style="{StaticResource SubtleButtonStyle}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<FontIcon FontSize="16" Glyph="" />
|
||||||
|
<TextBlock x:Uid="Settings_AppearancePage_ResetAppearanceButton_Text" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="Settings_GeneralPage_AppTheme_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=}">
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_AppTheme_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||||
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.Appearance.ThemeIndex, Mode=TwoWay}">
|
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.Appearance.ThemeIndex, Mode=TwoWay}">
|
||||||
@@ -62,19 +94,67 @@
|
|||||||
</ComboBox>
|
</ComboBox>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Uid="Settings_GeneralPage_BackdropStyle_SettingsCard"
|
||||||
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
|
IsExpanded="{x:Bind ViewModel.Appearance.IsBackdropOpacityVisible, Mode=OneWay}">
|
||||||
|
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.Appearance.BackdropStyleIndex, Mode=TwoWay}">
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_BackdropStyle_Acrylic" />
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_BackdropStyle_Transparent" />
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_BackdropStyle_Mica" />
|
||||||
|
<!-- Hidden: preview not working well, kept to preserve index mapping -->
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_BackdropStyle_AcrylicThin" Visibility="Collapsed" />
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_BackdropStyle_MicaAlt" />
|
||||||
|
</ComboBox>
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
<!-- Mica description (no opacity control) -->
|
||||||
|
<controls:SettingsCard
|
||||||
|
x:Uid="Settings_GeneralPage_MicaBackdrop_SettingsCard"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
ContentAlignment="Vertical"
|
||||||
|
Visibility="{x:Bind ViewModel.Appearance.IsMicaBackdropDescriptionVisible, Mode=OneWay}">
|
||||||
|
<TextBlock
|
||||||
|
x:Uid="Settings_GeneralPage_MicaBackdrop_DescriptionTextBlock"
|
||||||
|
Margin="24"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
HorizontalTextAlignment="Center"
|
||||||
|
TextAlignment="Center"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
<!-- Opacity slider (for non-Mica styles) -->
|
||||||
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_BackdropOpacity_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsBackdropOpacityVisible, Mode=OneWay}">
|
||||||
|
<Slider
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="0"
|
||||||
|
StepFrequency="1"
|
||||||
|
Value="{x:Bind ViewModel.Appearance.BackdropOpacity, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
<controls:SettingsExpander
|
<controls:SettingsExpander
|
||||||
x:Uid="Settings_GeneralPage_Background_SettingsExpander"
|
x:Uid="Settings_GeneralPage_Background_SettingsExpander"
|
||||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
|
IsEnabled="{x:Bind ViewModel.Appearance.IsBackgroundSettingsEnabled, Mode=OneWay}"
|
||||||
IsExpanded="{x:Bind ViewModel.Appearance.IsColorizationDetailsExpanded, Mode=TwoWay}">
|
IsExpanded="{x:Bind ViewModel.Appearance.IsColorizationDetailsExpanded, Mode=TwoWay}">
|
||||||
<ComboBox
|
<Grid>
|
||||||
x:Uid="Settings_GeneralPage_ColorizationMode"
|
<ComboBox
|
||||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
x:Uid="Settings_GeneralPage_ColorizationMode"
|
||||||
SelectedIndex="{x:Bind ViewModel.Appearance.ColorizationModeIndex, Mode=TwoWay}">
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_None" />
|
SelectedIndex="{x:Bind ViewModel.Appearance.ColorizationModeIndex, Mode=TwoWay}"
|
||||||
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_WindowsAccent" />
|
Visibility="{x:Bind ViewModel.Appearance.IsBackgroundSettingsEnabled, Mode=OneWay}">
|
||||||
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_CustomColor" />
|
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_None" />
|
||||||
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_Image" />
|
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_WindowsAccent" />
|
||||||
</ComboBox>
|
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_CustomColor" />
|
||||||
|
<ComboBoxItem x:Uid="Settings_GeneralPage_ColorizationMode_Image" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock
|
||||||
|
x:Uid="Settings_GeneralPage_Background_NotAvailable"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Visibility="{x:Bind ViewModel.Appearance.IsBackgroundNotAvailableVisible, Mode=OneWay}" />
|
||||||
|
</Grid>
|
||||||
<controls:SettingsExpander.Items>
|
<controls:SettingsExpander.Items>
|
||||||
<!-- none -->
|
<!-- none -->
|
||||||
<controls:SettingsCard
|
<controls:SettingsCard
|
||||||
@@ -155,7 +235,7 @@
|
|||||||
PaletteColors="{x:Bind ViewModel.Appearance.Swatches}"
|
PaletteColors="{x:Bind ViewModel.Appearance.Swatches}"
|
||||||
SelectedColor="{x:Bind ViewModel.Appearance.ThemeColor, Mode=TwoWay}" />
|
SelectedColor="{x:Bind ViewModel.Appearance.ThemeColor, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
<controls:SettingsCard x:Uid="Settings_GeneralPage_BackgroundTintIntensity_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsCustomTintIntensityVisible, Mode=OneWay}">
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_BackgroundTintIntensity_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsColorIntensityVisible, Mode=OneWay}">
|
||||||
<Slider
|
<Slider
|
||||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
Maximum="100"
|
Maximum="100"
|
||||||
@@ -163,9 +243,17 @@
|
|||||||
StepFrequency="1"
|
StepFrequency="1"
|
||||||
Value="{x:Bind ViewModel.Appearance.ColorIntensity, Mode=TwoWay}" />
|
Value="{x:Bind ViewModel.Appearance.ColorIntensity, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_ImageTintIntensity_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsImageTintIntensityVisible, Mode=OneWay}">
|
||||||
|
<Slider
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
Maximum="100"
|
||||||
|
Minimum="0"
|
||||||
|
StepFrequency="1"
|
||||||
|
Value="{x:Bind ViewModel.Appearance.BackgroundImageTintIntensity, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<!-- Reset background image properties -->
|
<!-- Reset appearance properties -->
|
||||||
<controls:SettingsCard x:Uid="Settings_GeneralPage_BackgroundImage_ResetProperties_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsBackgroundControlsVisible, Mode=OneWay}">
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_BackgroundImage_ResetProperties_SettingsCard" Visibility="{x:Bind ViewModel.Appearance.IsResetButtonVisible, Mode=OneWay}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
<Button x:Uid="Settings_GeneralPage_Background_ResetImagePropertiesButton" Command="{x:Bind ViewModel.Appearance.ResetBackgroundImagePropertiesCommand}" />
|
<Button x:Uid="Settings_GeneralPage_Background_ResetImagePropertiesButton" Command="{x:Bind ViewModel.Appearance.ResetBackgroundImagePropertiesCommand}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -3,8 +3,13 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
|
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||||
|
using Microsoft.CmdPal.UI.Events;
|
||||||
|
using Microsoft.CmdPal.UI.Messages;
|
||||||
using Microsoft.CmdPal.UI.ViewModels;
|
using Microsoft.CmdPal.UI.ViewModels;
|
||||||
|
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||||
using Microsoft.CmdPal.UI.ViewModels.Services;
|
using Microsoft.CmdPal.UI.ViewModels.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.UI;
|
using Microsoft.UI;
|
||||||
@@ -12,6 +17,7 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Documents;
|
using Microsoft.UI.Xaml.Documents;
|
||||||
using Microsoft.Windows.Storage.Pickers;
|
using Microsoft.Windows.Storage.Pickers;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.UI.Settings;
|
namespace Microsoft.CmdPal.UI.Settings;
|
||||||
|
|
||||||
@@ -86,4 +92,9 @@ public sealed partial class AppearancePage : Page
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OpenCommandPalette_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(string.Empty, HWND.Null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -577,6 +577,9 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<data name="Settings_GeneralPage_BackgroundTintIntensity_SettingsCard.Header" xml:space="preserve">
|
<data name="Settings_GeneralPage_BackgroundTintIntensity_SettingsCard.Header" xml:space="preserve">
|
||||||
<value>Color intensity</value>
|
<value>Color intensity</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_ImageTintIntensity_SettingsCard.Header" xml:space="preserve">
|
||||||
|
<value>Color intensity</value>
|
||||||
|
</data>
|
||||||
<data name="OptionalColorPickerButton_UnsetTextBlock.Text" xml:space="preserve">
|
<data name="OptionalColorPickerButton_UnsetTextBlock.Text" xml:space="preserve">
|
||||||
<value>Choose color</value>
|
<value>Choose color</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -668,7 +671,7 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<value>Background image</value>
|
<value>Background image</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Settings_GeneralPage_NoBackground_DescriptionTextBlock.Text" xml:space="preserve">
|
<data name="Settings_GeneralPage_NoBackground_DescriptionTextBlock.Text" xml:space="preserve">
|
||||||
<value>No settings</value>
|
<value>No additional settings are available.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Settings_GeneralPage_Background_SettingsExpander.Header" xml:space="preserve">
|
<data name="Settings_GeneralPage_Background_SettingsExpander.Header" xml:space="preserve">
|
||||||
<value>Background</value>
|
<value>Background</value>
|
||||||
@@ -676,6 +679,9 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<data name="Settings_GeneralPage_Background_SettingsExpander.Description" xml:space="preserve">
|
<data name="Settings_GeneralPage_Background_SettingsExpander.Description" xml:space="preserve">
|
||||||
<value>Choose a custom background color or image</value>
|
<value>Choose a custom background color or image</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_Background_NotAvailable.Text" xml:space="preserve">
|
||||||
|
<value>Not available with Mica</value>
|
||||||
|
</data>
|
||||||
<data name="Settings_GeneralPage_WindowsAccentColor_SettingsCard.Header" xml:space="preserve">
|
<data name="Settings_GeneralPage_WindowsAccentColor_SettingsCard.Header" xml:space="preserve">
|
||||||
<value>System accent color</value>
|
<value>System accent color</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -692,7 +698,7 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<value>Restore defaults</value>
|
<value>Restore defaults</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Settings_GeneralPage_Background_ResetImagePropertiesButton.Content" xml:space="preserve">
|
<data name="Settings_GeneralPage_Background_ResetImagePropertiesButton.Content" xml:space="preserve">
|
||||||
<value>Reset</value>
|
<value>Reset image settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Settings_GeneralPage_WindowsAccentColor_SettingsCard_Description1.Text" xml:space="preserve">
|
<data name="Settings_GeneralPage_WindowsAccentColor_SettingsCard_Description1.Text" xml:space="preserve">
|
||||||
<value>Change the system accent in Windows Settings:</value>
|
<value>Change the system accent in Windows Settings:</value>
|
||||||
@@ -727,4 +733,45 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<data name="Settings_GeneralPage_VersionNo" xml:space="preserve">
|
<data name="Settings_GeneralPage_VersionNo" xml:space="preserve">
|
||||||
<value>Version {0}</value>
|
<value>Version {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropOpacity_SettingsCard.Header" xml:space="preserve">
|
||||||
|
<value>Opacity</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_SettingsCard.Header" xml:space="preserve">
|
||||||
|
<value>Material</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_SettingsCard.Description" xml:space="preserve">
|
||||||
|
<value>Select the visual material used for the window background</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_Acrylic.Content" xml:space="preserve">
|
||||||
|
<value>Acrylic (default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_Transparent.Content" xml:space="preserve">
|
||||||
|
<value>Transparent</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_Mica.Content" xml:space="preserve">
|
||||||
|
<value>Mica</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_AcrylicThin.Content" xml:space="preserve">
|
||||||
|
<value>Thin Acrylic</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_BackdropStyle_MicaAlt.Content" xml:space="preserve">
|
||||||
|
<value>Mica Alt</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_MicaBackdrop_DescriptionTextBlock.Text" xml:space="preserve">
|
||||||
|
<value>Mica automatically adapts to your desktop wallpaper. Custom backgrounds and opacity settings are not available for this material.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_AppearancePage_OpenCommandPaletteButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Open Command Palette</value>
|
||||||
|
<comment>Button to open the Command Palette window to preview appearance changes</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_AppearancePage_OpenCommandPaletteButton_Text.Text" xml:space="preserve">
|
||||||
|
<value>Open Command Palette</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_AppearancePage_ResetAppearanceButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Reset appearance settings</value>
|
||||||
|
<comment>Button to reset all appearance settings to their default values</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_AppearancePage_ResetAppearanceButton_Text.Text" xml:space="preserve">
|
||||||
|
<value>Reset to defaults</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Reference in New Issue
Block a user