Skip to content

Commit

Permalink
[WinUI3]Fix Windows 10 title bar borders (#36429)
Browse files Browse the repository at this point in the history
* Fix borders for windows in the Settings UI

* Fix HOSTS window

* Fix Advanced Paste

* Fix Environment Variables

* Fix File Locksmith

* Fix Peek, with a caveat

* Fix Registry Preview

* Remove unused imports

* Clean up imports in OobeShellPage

* Move OSVersionHelper from Common.UI up into ManagedCommon
  • Loading branch information
pingzing authored Jan 13, 2025
1 parent aa9f3bb commit df48a33
Show file tree
Hide file tree
Showing 23 changed files with 68 additions and 25 deletions.
12 changes: 12 additions & 0 deletions src/common/ManagedCommon/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

using System;

namespace Common.UI
namespace ManagedCommon
{
public static class OSVersionHelper
{
public static bool IsWindows10()
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Minor < 22000;
}

public static bool IsWindows11()
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;
Expand Down
15 changes: 15 additions & 0 deletions src/common/ManagedCommon/WindowHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,20 @@ public static void BringToForeground(IntPtr handle)
}
}
}

/// <summary>
/// Workaround for a WinUI bug on Windows 10 in which a window's top border is always
/// black. Calls <c>DwmExtendFrameIntoClientArea()</c> with a <c>cyTopHeight</c> of 2 to force
/// the window's top border to be visible.<br/><br/>
/// Is a no-op on versions other than Windows 10.
/// </summary>
public static void ForceTopBorder1PixelInsetOnWindows10(IntPtr handle)
{
if (OSVersionHelper.IsWindows10())
{
var margins = new NativeMethods.MARGINS { cxLeftWidth = 0, cxRightWidth = 0, cyBottomHeight = 0, cyTopHeight = 2 };
NativeMethods.DwmExtendFrameIntoClientArea(handle, ref margins);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ double GetHeight(int maxCustomActionCount) =>
};

WindowHelpers.BringToForeground(this.GetWindowHandle());
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());
}

private void OnActivated(object sender, WindowActivatedEventArgs args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public MainWindow()
var handle = this.GetWindowHandle();
RegisterWindow(handle);

WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(handle);
WindowHelpers.BringToForeground(handle);

MainPage = App.GetService<EnvironmentVariablesMainPage>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,6 +22,7 @@ public MainWindow(bool isElevated)
SetTitleBar(AppTitleBar);
Activated += MainWindow_Activated;
AppWindow.SetIcon("Assets/FileLocksmith/Icon.ico");
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());

var loader = ResourceLoaderInstance.ResourceLoader;
var title = isElevated ? loader.GetString("AppAdminTitle") : loader.GetString("AppTitle");
Expand Down
1 change: 1 addition & 0 deletions src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public MainWindow()

var handle = this.GetWindowHandle();

WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(handle);
WindowHelpers.BringToForeground(handle);
Activated += MainWindow_Activated;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System;

using ColorPicker.Helpers;
using Common.UI;
using ManagedCommon;
using Wpf.Ui.Controls;

namespace ColorPicker
Expand Down
3 changes: 1 addition & 2 deletions src/modules/imageresizer/ui/Views/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
using System;
using System.Collections.Generic;
using System.Linq;

using Common.UI;
using ImageResizer.ViewModels;
using ManagedCommon;
using Microsoft.Win32;
using Wpf.Ui.Controls;

Expand Down
7 changes: 4 additions & 3 deletions src/modules/launcher/PowerLauncher/Helper/ThemeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Windows;
using System.Windows.Media;
using ManagedCommon;
using Microsoft.Win32;
using Wox.Infrastructure.Image;
using Wox.Infrastructure.UserSettings;
Expand Down Expand Up @@ -50,7 +51,7 @@ private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventAr

private void SetSystemTheme(ManagedCommon.Theme theme)
{
_mainWindow.Background = Common.UI.OSVersionHelper.IsWindows11() is false ? SystemColors.WindowBrush : null;
_mainWindow.Background = OSVersionHelper.IsWindows11() is false ? SystemColors.WindowBrush : null;

_mainWindow.Resources.MergedDictionaries.Clear();
_mainWindow.Resources.MergedDictionaries.Add(new ResourceDictionary
Expand All @@ -66,7 +67,7 @@ private void SetSystemTheme(ManagedCommon.Theme theme)
Source = new Uri(themeString, UriKind.Absolute),
};
_mainWindow.Resources.MergedDictionaries.Add(fluentThemeDictionary);
if (!Common.UI.OSVersionHelper.IsWindows11())
if (!OSVersionHelper.IsWindows11())
{
// Apply background only on Windows 10
// Windows theme does not work properly for dark and light mode so right now set the background color manual.
Expand Down Expand Up @@ -95,7 +96,7 @@ private void SetSystemTheme(ManagedCommon.Theme theme)
{
Source = new Uri(styleThemeString, UriKind.Relative),
});
if (Common.UI.OSVersionHelper.IsWindows11())
if (OSVersionHelper.IsWindows11())
{
// Apply background only on Windows 11 to keep the same style as WPFUI
_mainWindow.Background = new SolidColorBrush
Expand Down
1 change: 1 addition & 0 deletions src/modules/launcher/PowerLauncher/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using System.Windows.Media.Imaging;

using Common.UI;
using ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Telemetry;
using PowerLauncher.Helper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

using Common.UI;
using ManagedCommon;
using Microsoft.Win32;
using Wox.Plugin.Common.VirtualDesktop.Interop;
using Wox.Plugin.Common.Win32;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/peek/Peek.UI/PeekXAML/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public MainWindow()
ViewModel = Application.Current.GetService<MainWindowViewModel>();

TitleBarControl.SetTitleBarToWindow(this);
AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;
ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
AppWindow.SetIcon("Assets/Peek/Icon.ico");

Expand Down
2 changes: 1 addition & 1 deletion src/modules/peek/Peek.UI/PeekXAML/Views/TitleBar.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand All @@ -49,6 +49,7 @@ internal MainWindow()

// Extend the canvas to include the title bar so the app can support theming
ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(windowHandle);
SetTitleBar(titleBar);

// if have settings, update the location of the window
Expand Down
3 changes: 1 addition & 2 deletions src/settings-ui/Settings.UI/Helpers/StartProcessHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Diagnostics;

using Common.UI;
using ManagedCommon;

namespace Microsoft.PowerToys.Settings.UI.Helpers
{
Expand Down
7 changes: 7 additions & 0 deletions src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
}
else
{
Expand All @@ -255,6 +259,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs)
OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview);
oobeWindow.Activate();
oobeWindow.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
SetOobeWindow(oobeWindow);
}
else if (ShowScoobe)
Expand All @@ -263,6 +268,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs)
OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew);
scoobeWindow.Activate();
scoobeWindow.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
SetOobeWindow(scoobeWindow);
}
else if (ShowFlyout)
Expand Down Expand Up @@ -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.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
settingsWindow.Activate();
settingsWindow.NavigateToSection(StartupPage);
ShowMessageDialog("The application is running in Debug mode.", "DEBUG");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
using System.Collections.ObjectModel;
using System.Globalization;

using global::PowerToys.GPOWrapper;
using ManagedCommon;
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
{
Expand Down Expand Up @@ -306,6 +307,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.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
u.SetTitleBar(AppTitleBar);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
u.SetTitleBar(AppTitleBar);
var loader = ResourceLoaderInstance.ResourceLoader;
AppTitleBarText.Text = App.IsElevated ? loader.GetString("SettingsWindow_AdminTitle") : loader.GetString("SettingsWindow_Title");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;

using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

using System;
using System.Runtime.CompilerServices;

using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
Expand Down
2 changes: 0 additions & 2 deletions src/settings-ui/Settings.UI/ViewModels/NewPlusViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
Expand Down
3 changes: 1 addition & 2 deletions src/settings-ui/Settings.UI/ViewModels/PowerOcrViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
using System.Linq;
using System.Text.Json;
using System.Timers;

using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
Expand Down

0 comments on commit df48a33

Please sign in to comment.