diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index ed9677cff2c..45758a0042b 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -554,6 +554,11 @@ public void RemoveDropShadowEffectFromCurrentTheme() ThemeHelper.CopyStyle(windowBorderStyle, newWindowBorderStyle); // Copy Setters, excluding the Effect setter and updating the Margin setter + // Only adjust margin if there's actually a shadow effect to remove, + // preventing it from shrinking on repeated calls. + bool hasEffect = windowBorderStyle.Setters.OfType() + .Any(s => s.Property == UIElement.EffectProperty); + foreach (var setterBase in windowBorderStyle.Setters) { if (setterBase is Setter setter) @@ -562,7 +567,7 @@ public void RemoveDropShadowEffectFromCurrentTheme() if (setter.Property == UIElement.EffectProperty) continue; // Update Margin by subtracting the extra margin we added for the shadow - if (setter.Property == FrameworkElement.MarginProperty) + if (hasEffect && setter.Property == FrameworkElement.MarginProperty) { var currentMargin = (Thickness)setter.Value; var newMargin = new Thickness( @@ -635,20 +640,8 @@ await Application.Current.Dispatcher.InvokeAsync(() => // Get the actual backdrop type and drop shadow effect settings var (backdropType, useDropShadowEffect) = GetActualValue(); - // Remove OS minimizing/maximizing animation - // Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 3); - - // The timing of adding the shadow effect should vary depending on whether the theme is transparent. - if (BlurEnabled) - { - AutoDropShadow(useDropShadowEffect); - } SetBlurForWindow(_settings.Theme, backdropType); - - if (!BlurEnabled) - { - AutoDropShadow(useDropShadowEffect); - } + AutoDropShadow(useDropShadowEffect); }, DispatcherPriority.Render); } @@ -725,12 +718,26 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType) // Apply the blur effect Win32Helper.DWMSetBackdropForWindow(mainWindow, backdropType); ColorizeWindow(theme, backdropType); + + // DWM renders rounded corners for backdrop windows + SetWindowCornerPreference("Round"); + + // Clear any stale directly-set WindowBorderStyle that might shadow + // the merged dictionary entry we just modified above. + if (Application.Current.Resources.Contains("WindowBorderStyle")) + Application.Current.Resources.Remove("WindowBorderStyle"); + + // For blur themes the resize border defaults to the system thickness. + SetResizeBoarderThickness(null); } else { // Apply default style when Blur is disabled Win32Helper.DWMSetBackdropForWindow(mainWindow, BackdropTypes.None); ColorizeWindow(theme, backdropType); + + // Non-blur themes use the default window corner preference + SetWindowCornerPreference("Default"); } UpdateResourceDictionary(dict); @@ -738,26 +745,15 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType) private void AutoDropShadow(bool useDropShadowEffect) { + if (BlurEnabled) + return; // Blur themes have no drop shadow effect + if (useDropShadowEffect) { - if (BlurEnabled && Win32Helper.IsBackdropSupported()) - { - // For themes with blur enabled, the window border is rendered by the system, - // so we set corner preference to round and remove drop shadow effect to avoid rendering issues. - SetWindowCornerPreference("Round"); - RemoveDropShadowEffectFromCurrentTheme(); - } - else - { - // For themes without blur, we set corner preference to default and add drop shadow effect. - SetWindowCornerPreference("Default"); - AddDropShadowEffectToCurrentTheme(); - } + AddDropShadowEffectToCurrentTheme(); } else { - // When drop shadow effect is disabled, we set corner preference to default and remove drop shadow effect. - SetWindowCornerPreference("Default"); RemoveDropShadowEffectFromCurrentTheme(); } } diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index 8c5633cfef5..acebfcfe37e 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -14,6 +14,7 @@ VIRTUAL_KEY EnumWindows DwmSetWindowAttribute +DwmExtendFrameIntoClientArea DWM_SYSTEMBACKDROP_TYPE DWM_WINDOW_CORNER_PREFERENCE diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 67d0edb7888..feafcfcdaa0 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -21,6 +21,7 @@ using Windows.Win32.Graphics.Dwm; using Windows.Win32.System.Power; using Windows.Win32.System.Threading; +using Windows.Win32.UI.Controls; using Windows.Win32.UI.Input.KeyboardAndMouse; using Windows.Win32.UI.Shell.Common; using Windows.Win32.UI.WindowsAndMessaging; @@ -61,6 +62,14 @@ public static unsafe bool DWMSetBackdropForWindow(Window window, BackdropTypes b _ => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_AUTO }; + // The backdrop renders in the non-client frame area. WindowStyle=None + // removes that area, so we extend it across the entire client area. + // This is harmless when backdrop is None or blur not enabled + // as DWM has nothing to render in the extended area. + // https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmextendframeintoclientarea + var margins = new MARGINS { cxLeftWidth = -1, cxRightWidth = -1, cyTopHeight = -1, cyBottomHeight = -1 }; + PInvoke.DwmExtendFrameIntoClientArea(GetWindowHandle(window), in margins); + return PInvoke.DwmSetWindowAttribute( GetWindowHandle(window), DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE,