mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
CmdPal: Reduce DockWindow backdrop switching and visual artifacts (#46309)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This PR reduces "blinking" of dock when (any) CmdPal settings changes. It handles only backdrop, not icons. - Avoids recreating the acrylic controller when the effective backdrop parameters have not changed. - Reuses the transparent backdrop instead of reassigning it during dock refreshes. - Cleans up backdrop controllers only when switching backdrop modes or disposing the window. - Removes obsolete dock-specific backdrop helper logic now handled directly in DockWindow. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #46308 <!-- - [ ] 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:
@@ -4,7 +4,6 @@
|
||||
|
||||
using Microsoft.CmdPal.UI.ViewModels.Settings;
|
||||
using Windows.Win32;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Dock;
|
||||
|
||||
@@ -32,16 +31,6 @@ internal static class DockSettingsToViews
|
||||
};
|
||||
}
|
||||
|
||||
public static Microsoft.UI.Xaml.Media.SystemBackdrop? GetSystemBackdrop(DockBackdrop backdrop)
|
||||
{
|
||||
return backdrop switch
|
||||
{
|
||||
DockBackdrop.Transparent => new TransparentTintBackdrop(),
|
||||
DockBackdrop.Acrylic => null,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
|
||||
public static uint GetAppBarEdge(DockSide side)
|
||||
{
|
||||
return side switch
|
||||
|
||||
@@ -59,6 +59,8 @@ public sealed partial class DockWindow : WindowEx,
|
||||
private DockControl _dock;
|
||||
private DesktopAcrylicController? _acrylicController;
|
||||
private SystemBackdropConfiguration? _configurationSource;
|
||||
private bool _isUpdatingBackdrop;
|
||||
private BackdropParameters? _lastAppliedAcrylicBackdrop;
|
||||
private DockSize _lastSize;
|
||||
|
||||
// Store the original WndProc
|
||||
@@ -78,6 +80,7 @@ public sealed partial class DockWindow : WindowEx,
|
||||
viewModel = serviceProvider.GetService<DockViewModel>()!;
|
||||
_themeService = serviceProvider.GetRequiredService<IThemeService>();
|
||||
_themeService.ThemeChanged += ThemeService_ThemeChanged;
|
||||
InitializeBackdropSupport();
|
||||
_windowViewModel = new DockWindowViewModel(_themeService);
|
||||
_dock = new DockControl(viewModel);
|
||||
|
||||
@@ -156,14 +159,7 @@ public sealed partial class DockWindow : WindowEx,
|
||||
private void UpdateSettingsOnUiThread()
|
||||
{
|
||||
this.viewModel.UpdateSettings(_settings);
|
||||
|
||||
SystemBackdrop = DockSettingsToViews.GetSystemBackdrop(_settings.Backdrop);
|
||||
|
||||
// If the backdrop is acrylic, things are more complicated
|
||||
if (_settings.Backdrop == DockBackdrop.Acrylic)
|
||||
{
|
||||
SetAcrylic();
|
||||
}
|
||||
UpdateBackdrop();
|
||||
|
||||
_dock.UpdateSettings(_settings);
|
||||
var side = DockSettingsToViews.GetAppBarEdge(_settings.Side);
|
||||
@@ -183,31 +179,98 @@ public sealed partial class DockWindow : WindowEx,
|
||||
CreateAppBar(_hwnd);
|
||||
}
|
||||
|
||||
// We want to use DesktopAcrylicKind.Thin and custom colors as this is the default material
|
||||
// other Shell surfaces are using, this cannot be set in XAML however.
|
||||
private void SetAcrylic()
|
||||
private void InitializeBackdropSupport()
|
||||
{
|
||||
if (DesktopAcrylicController.IsSupported())
|
||||
{
|
||||
// Hooking up the policy object.
|
||||
_configurationSource = new SystemBackdropConfiguration
|
||||
{
|
||||
// Initial configuration state.
|
||||
IsInputActive = true,
|
||||
};
|
||||
UpdateAcrylic();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAcrylic()
|
||||
private void UpdateBackdrop()
|
||||
{
|
||||
if (_acrylicController != null)
|
||||
// Prevent re-entrance when backdrop changes trigger theme refresh work.
|
||||
if (_isUpdatingBackdrop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isUpdatingBackdrop = true;
|
||||
|
||||
try
|
||||
{
|
||||
switch (_settings.Backdrop)
|
||||
{
|
||||
case DockBackdrop.Transparent:
|
||||
if (SystemBackdrop is not TransparentTintBackdrop)
|
||||
{
|
||||
CleanupBackdropControllers();
|
||||
SetupTransparentBackdrop();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DockBackdrop.Acrylic:
|
||||
default:
|
||||
SetupDesktopAcrylic(_themeService.CurrentDockTheme.BackdropParameters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to update dock backdrop", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingBackdrop = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupTransparentBackdrop()
|
||||
{
|
||||
if (SystemBackdrop is not TransparentTintBackdrop)
|
||||
{
|
||||
SystemBackdrop = new TransparentTintBackdrop();
|
||||
}
|
||||
|
||||
_lastAppliedAcrylicBackdrop = null;
|
||||
}
|
||||
|
||||
private void CleanupBackdropControllers()
|
||||
{
|
||||
if (_acrylicController is not null)
|
||||
{
|
||||
_acrylicController.RemoveAllSystemBackdropTargets();
|
||||
_acrylicController.Dispose();
|
||||
_acrylicController = null;
|
||||
}
|
||||
|
||||
var backdrop = _themeService.CurrentDockTheme.BackdropParameters;
|
||||
_lastAppliedAcrylicBackdrop = null;
|
||||
}
|
||||
|
||||
private void SetupDesktopAcrylic(BackdropParameters backdrop)
|
||||
{
|
||||
var needsAcrylicUpdate = _acrylicController is null || _lastAppliedAcrylicBackdrop != backdrop;
|
||||
if (!needsAcrylicUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CleanupBackdropControllers();
|
||||
|
||||
// Fall back to the transparent backdrop if acrylic is not supported.
|
||||
if (_configurationSource is null || !DesktopAcrylicController.IsSupported())
|
||||
{
|
||||
SetupTransparentBackdrop();
|
||||
return;
|
||||
}
|
||||
|
||||
// DesktopAcrylicController and SystemBackdrop can't be active simultaneously.
|
||||
SystemBackdrop = null;
|
||||
|
||||
_acrylicController = new DesktopAcrylicController
|
||||
{
|
||||
Kind = DesktopAcrylicKind.Thin,
|
||||
@@ -221,29 +284,20 @@ public sealed partial class DockWindow : WindowEx,
|
||||
// Note: Be sure to have "using WinRT;" to support the Window.As<...>() call.
|
||||
_acrylicController.AddSystemBackdropTarget(this.As<ICompositionSupportsSystemBackdrop>());
|
||||
_acrylicController.SetSystemBackdropConfiguration(_configurationSource);
|
||||
_lastAppliedAcrylicBackdrop = backdrop;
|
||||
}
|
||||
|
||||
private void DisposeAcrylic()
|
||||
{
|
||||
if (_acrylicController is not null)
|
||||
{
|
||||
_acrylicController.Dispose();
|
||||
_acrylicController = null!;
|
||||
_configurationSource = null!;
|
||||
}
|
||||
CleanupBackdropControllers();
|
||||
_configurationSource = null;
|
||||
}
|
||||
|
||||
private void ThemeService_ThemeChanged(object? sender, ThemeChangedEventArgs e)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
// We only need to handle acrylic here.
|
||||
// Transparent background is handled directly in XAML by binding to
|
||||
// the DockWindowViewModel's ColorizationColor properties.
|
||||
if (_settings.Backdrop == DockBackdrop.Acrylic)
|
||||
{
|
||||
UpdateAcrylic();
|
||||
}
|
||||
UpdateBackdrop();
|
||||
|
||||
// ActualTheme / RequestedTheme sync,
|
||||
// as pilfered from WindowThemeSynchronizer
|
||||
|
||||
Reference in New Issue
Block a user