microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.35k stars 678 forks source link

Light theme `Foreground` does not have correct value unless `RequestedTheme` is set #8392

Open MartinZikmund opened 1 year ago

MartinZikmund commented 1 year ago

Describe the bug

WinUI sets the DefaultTextForegroundThemeBrush for light theme to #E4000000 instead of fully opaque black. However, this is not applied consistently unless element-level RequestedTheme is set explicitly to Light (e.g. TextBlock.Foreground, ContentPresenter.Foreground and BitmapIcon.Foreground are all still fully opaque black).

Steps to reproduce the bug

  1. Create a blank WinUI Packaged app or a blank UWP app with WinUI 2.8
  2. In MainPage.xaml or MainWindow.xaml add the following content:
<Grid ColumnDefinitions="*,*" Loaded="Grid_Loaded">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock x:Name="TextBlock1" Text="Test" FontWeight="Black" FontSize="60" />
        <BitmapIcon x:Name="BitmapIcon1" UriSource="ms-appx:///Assets/StoreLogo.png" />
    </StackPanel>
    <StackPanel RequestedTheme="Light" Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock x:Name="TextBlock2" Text="Test" FontWeight="Black" FontSize="60" />
        <BitmapIcon x:Name="BitmapIcon2" UriSource="ms-appx:///Assets/StoreLogo.png" />
    </StackPanel>
</Grid>
  1. In the code-behind put the following:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
    Debug.WriteLine(((SolidColorBrush)TextBlock1.Foreground).Color);
    Debug.WriteLine(((SolidColorBrush)BitmapIcon1.Foreground).Color);
    Debug.WriteLine(((SolidColorBrush)TextBlock2.Foreground).Color);
    Debug.WriteLine(((SolidColorBrush)BitmapIcon2.Foreground).Color);
}
  1. Ensure your OS is running in light theme (or go to App.xaml and set the RequestedTheme there to Light).
  2. Run the application.
  3. Notice that the text and the icon on the left have fully opaque black color whereas the same is slightly lighter on the right side:

image

  1. See the debug Output window, notice the colors also match what you see on the screen:

image

Expected behavior

The #E4000000 color should be applied consistently (or fully opaque black should be used).

Screenshots

image

NuGet package version

WinUI 3 - Windows App SDK 1.3.0: 1.3.230331000 WinUI 3 - Windows App SDK 1.2.5: 1.2.230313.1 UWP + WinUI 2.8

Windows version

Windows 11 (22H2): Build 22621

Additional context

Happens even in WinUI 2.8 + UWP

Youssef1313 commented 2 months ago

This may be due to how DP default values work in WinUI.

Whenever a default value needs to be read, DependencyProperty::GetDefaultValue is called. For Foreground DPs specifically, that's calculated from CoreServices and is cached there (CCoreServices::GetDefaultTextBrush).

Then, whenever you set RequestedTheme, it will cause CFrameworkElement::NotifyThemeChangedForInheritedProperties to be called which will re-lookup DefaultTextForegroundThemeBrush. It may be that they are called at different timings of the app lifecycle where it yields different results? I'm not sure, such a hypothesis looking at the relevant pieces of code here.