Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Windows 10 title bar borders #36429

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this note be inline at call sites, or on the function itself?

// 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
Loading