From ecf0f78b4e872587d7dfe2cb77c65af05faa96c8 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 18:30:29 +0200 Subject: [PATCH 1/9] Fix borders for windows in the Settings UI --- src/common/ManagedCommon/NativeMethods.cs | 12 ++++++++++++ src/common/ManagedCommon/WindowHelpers.cs | 12 ++++++++++++ src/settings-ui/Settings.UI/Helpers/WindowHelper.cs | 2 ++ src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs | 7 +++++++ .../SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs | 4 ++++ .../Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs | 2 ++ 6 files changed, 39 insertions(+) diff --git a/src/common/ManagedCommon/NativeMethods.cs b/src/common/ManagedCommon/NativeMethods.cs index feffafa94637..998010f10a29 100644 --- a/src/common/ManagedCommon/NativeMethods.cs +++ b/src/common/ManagedCommon/NativeMethods.cs @@ -42,6 +42,9 @@ internal static class NativeMethods [DllImport("user32.dll")] internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); + [DllImport("dwmapi")] + internal static extern IntPtr DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset); + [StructLayout(LayoutKind.Sequential)] public struct INPUT { @@ -100,5 +103,14 @@ internal enum INPUTTYPE : uint INPUT_KEYBOARD = 1, INPUT_HARDWARE = 2, } + + [StructLayout(LayoutKind.Sequential)] + internal struct MARGINS + { + public int cxLeftWidth; + public int cxRightWidth; + public int cyTopHeight; + public int cyBottomHeight; + } } } diff --git a/src/common/ManagedCommon/WindowHelpers.cs b/src/common/ManagedCommon/WindowHelpers.cs index bd9d3347229b..1a1c43132393 100644 --- a/src/common/ManagedCommon/WindowHelpers.cs +++ b/src/common/ManagedCommon/WindowHelpers.cs @@ -35,5 +35,17 @@ public static void BringToForeground(IntPtr handle) } } } + + /// + /// Workaround for a WinUI bug on Windows 10 in which a window's top border is always + /// black. Calls DwmExtendFrameIntoClientArea() with a cyTopHeight of 2 to force + /// the window's top border to be visible.

+ /// Has no visible effect on Windows 11. + ///
+ public static void ForceTopBorder1PixelInset(IntPtr handle) + { + var margins = new NativeMethods.MARGINS { cxLeftWidth = 0, cxRightWidth = 0, cyBottomHeight = 0, cyTopHeight = 2 }; + NativeMethods.DwmExtendFrameIntoClientArea(handle, ref margins); + } } } diff --git a/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs b/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs index 489e2b9a4a80..bcb74389f1d0 100644 --- a/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs @@ -8,6 +8,8 @@ using System.Text.Json; using Microsoft.UI.Xaml; +using WinRT.Interop; +using static Common.UI.SettingsDeepLink; namespace Microsoft.PowerToys.Settings.UI.Helpers { diff --git a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs index 85f64f62cc79..d2e0fa23fd44 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs @@ -241,6 +241,10 @@ private void OnLaunchedFromRunner(string[] cmdArgs) // https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground // Need to call SetForegroundWindow to actually gain focus. WindowHelpers.BringToForeground(settingsWindow.GetWindowHandle()); + + // https://github.com/microsoft/microsoft-ui-xaml/issues/8948 - A window's top border incorrectly + // renders as black on Windows 10. + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(settingsWindow)); } else { @@ -255,6 +259,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs) OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview); oobeWindow.Activate(); oobeWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(settingsWindow)); SetOobeWindow(oobeWindow); } else if (ShowScoobe) @@ -263,6 +268,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs) OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew); scoobeWindow.Activate(); scoobeWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(settingsWindow)); SetOobeWindow(scoobeWindow); } else if (ShowFlyout) @@ -310,6 +316,7 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar // Window is also needed to show MessageDialog settingsWindow = new MainWindow(); settingsWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(settingsWindow)); settingsWindow.Activate(); settingsWindow.NavigateToSection(StartupPage); ShowMessageDialog("The application is running in Debug mode.", "DEBUG"); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs index 02df4de73582..27bde476d9ca 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs @@ -7,11 +7,14 @@ using System.Globalization; using global::PowerToys.GPOWrapper; +using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.OOBE.Enums; using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using WinRT.Interop; namespace Microsoft.PowerToys.Settings.UI.OOBE.Views { @@ -306,6 +309,7 @@ private void SetTitleBar() // A custom title bar is required for full window theme and Mica support. // https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization u.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(u)); u.SetTitleBar(AppTitleBar); } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs index 9ff088b78736..18fcf7be5fd4 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs @@ -14,6 +14,7 @@ using Microsoft.UI.Xaml.Controls; using Windows.Data.Json; using Windows.System; +using WinRT.Interop; namespace Microsoft.PowerToys.Settings.UI.Views { @@ -421,6 +422,7 @@ private void SetTitleBar() // A custom title bar is required for full window theme and Mica support. // https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization u.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(WindowNative.GetWindowHandle(u)); u.SetTitleBar(AppTitleBar); var loader = ResourceLoaderInstance.ResourceLoader; AppTitleBarText.Text = App.IsElevated ? loader.GetString("SettingsWindow_AdminTitle") : loader.GetString("SettingsWindow_Title"); From 9b1161b7c64e5f20380d4c680ec27f51fcb8308f Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 18:30:47 +0200 Subject: [PATCH 2/9] Fix HOSTS window --- src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs index d1632c21ee6e..da97eb5189be 100644 --- a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs +++ b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs @@ -39,6 +39,7 @@ public MainWindow() var handle = this.GetWindowHandle(); + WindowHelpers.ForceTopBorder1PixelInset(handle); WindowHelpers.BringToForeground(handle); Activated += MainWindow_Activated; From b2fe2b185db0c91c29d03969d9ec7568ff54b731 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 20:24:45 +0200 Subject: [PATCH 3/9] Fix Advanced Paste --- .../AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs index 18295f231567..68fe7d6c6bb2 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs @@ -82,6 +82,7 @@ double GetHeight(int maxCustomActionCount) => }; WindowHelpers.BringToForeground(this.GetWindowHandle()); + WindowHelpers.ForceTopBorder1PixelInset(this.GetWindowHandle()); } private void OnActivated(object sender, WindowActivatedEventArgs args) From 2cd50e594868f536b114725fc9f7cf8bdaafbe92 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 20:37:13 +0200 Subject: [PATCH 4/9] Fix Environment Variables --- .../EnvironmentVariablesXAML/MainWindow.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs index 891fadfe1df9..4a6d929e3eb2 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs @@ -40,6 +40,7 @@ public MainWindow() var handle = this.GetWindowHandle(); RegisterWindow(handle); + WindowHelpers.ForceTopBorder1PixelInset(handle); WindowHelpers.BringToForeground(handle); MainPage = App.GetService(); From 0da6d7f151a2df9d6dc9681f0801a86d2270dacc Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 20:38:52 +0200 Subject: [PATCH 5/9] Fix File Locksmith --- .../FileLocksmithUI/FileLocksmithXAML/MainWindow.xaml.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithXAML/MainWindow.xaml.cs b/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithXAML/MainWindow.xaml.cs index 324044d49f0b..0b8d814a3658 100644 --- a/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithXAML/MainWindow.xaml.cs +++ b/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithXAML/MainWindow.xaml.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System; - +using ManagedCommon; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; @@ -22,6 +22,7 @@ public MainWindow(bool isElevated) SetTitleBar(AppTitleBar); Activated += MainWindow_Activated; AppWindow.SetIcon("Assets/FileLocksmith/Icon.ico"); + WindowHelpers.ForceTopBorder1PixelInset(this.GetWindowHandle()); var loader = ResourceLoaderInstance.ResourceLoader; var title = isElevated ? loader.GetString("AppAdminTitle") : loader.GetString("AppTitle"); From 623b84ed96a15bae5fe9d0e13c0cf91a188480e2 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 20:53:34 +0200 Subject: [PATCH 6/9] Fix Peek, with a caveat --- src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs | 3 ++- src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs b/src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs index ae94b0cb4462..43828cb8c69e 100644 --- a/src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs +++ b/src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs @@ -48,7 +48,8 @@ public MainWindow() ViewModel = Application.Current.GetService(); TitleBarControl.SetTitleBarToWindow(this); - AppWindow.TitleBar.ExtendsContentIntoTitleBar = true; + ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(this.GetWindowHandle()); AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall; AppWindow.SetIcon("Assets/Peek/Icon.ico"); diff --git a/src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs b/src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs index 17d9724d7999..7e2759cc5dbc 100644 --- a/src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs +++ b/src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs @@ -231,7 +231,7 @@ private void UpdateTitleBarCustomization(MainWindow mainWindow) if (AppWindowTitleBar.IsCustomizationSupported()) { AppWindow appWindow = mainWindow.AppWindow; - appWindow.TitleBar.ExtendsContentIntoTitleBar = true; + mainWindow.ExtendsContentIntoTitleBar = true; appWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent; appWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; appWindow.TitleBar.ButtonForegroundColor = ThemeHelpers.GetAppTheme() == AppTheme.Light ? Colors.DarkSlateGray : Colors.White; From 01caed5df01c7d45acdb2d86ab6339db9c0c1076 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 21:01:32 +0200 Subject: [PATCH 7/9] Fix Registry Preview --- .../RegistryPreview/RegistryPreviewXAML/MainWindow.xaml.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/MainWindow.xaml.cs b/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/MainWindow.xaml.cs index 4c0a3566e5fe..ad504e34f9ff 100644 --- a/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/MainWindow.xaml.cs +++ b/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/MainWindow.xaml.cs @@ -38,8 +38,8 @@ internal MainWindow() OpenWindowPlacementFile(settingsFolder, windowPlacementFile); // Update the Win32 looking window with the correct icon (and grab the appWindow handle for later) - IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this); - Microsoft.UI.WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle); + IntPtr windowHandle = this.GetWindowHandle(); + WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle); appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId); appWindow.SetIcon("Assets\\RegistryPreview\\RegistryPreview.ico"); @@ -49,6 +49,7 @@ internal MainWindow() // Extend the canvas to include the title bar so the app can support theming ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInset(windowHandle); SetTitleBar(titleBar); // if have settings, update the location of the window From f5dbc57217ad98a86537a583de3c7068314172c7 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 21:09:26 +0200 Subject: [PATCH 8/9] Remove unused imports --- src/settings-ui/Settings.UI/Helpers/WindowHelper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs b/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs index bcb74389f1d0..489e2b9a4a80 100644 --- a/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/WindowHelper.cs @@ -8,8 +8,6 @@ using System.Text.Json; using Microsoft.UI.Xaml; -using WinRT.Interop; -using static Common.UI.SettingsDeepLink; namespace Microsoft.PowerToys.Settings.UI.Helpers { From 1b5906c97f7e530e266fb708d153183542015a78 Mon Sep 17 00:00:00 2001 From: pingzing Date: Wed, 18 Dec 2024 21:10:53 +0200 Subject: [PATCH 9/9] Clean up imports in OobeShellPage --- .../Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs index 27bde476d9ca..82a9a9e595ae 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs @@ -6,9 +6,7 @@ using System.Collections.ObjectModel; using System.Globalization; -using global::PowerToys.GPOWrapper; using ManagedCommon; -using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.OOBE.Enums; using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;