Skip to content
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
20 changes: 20 additions & 0 deletions RetroBar/Controls/Clock.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ private void Initialize()
Settings.Instance.PropertyChanged += Settings_PropertyChanged;
SystemEvents.TimeChanged += TimeChanged;
SystemEvents.UserPreferenceChanged += UserPreferenceChanged;

UpdateTextScaling();
}

private void UpdateTextScaling()
{
// Only scale within the actual taskbar; the properties window preview hosts this
// same control without the taskbar's ScaleTransform, so it should stay unscaled.
double scale = Window.GetWindow(this) is RetroBar.Taskbar ? Settings.Instance.TaskbarScale : 1.0;
TextScaler.ApplyScaling(this, scale);
}

private void StartClock()
Expand Down Expand Up @@ -93,6 +103,16 @@ private void Settings_PropertyChanged(object sender, System.ComponentModel.Prope
{
UpdateUserCulture();
}
else if (e.PropertyName == nameof(Settings.TaskbarScale))
{
UpdateTextScaling();
}
else if (e.PropertyName == nameof(Settings.Theme))
{
// The clock template (and its base font size) is swapped on theme change;
// re-apply once that has happened.
Dispatcher.BeginInvoke(new Action(UpdateTextScaling), DispatcherPriority.Loaded);
}
}

private void Clock_Tick(object sender, EventArgs args)
Expand Down
11 changes: 7 additions & 4 deletions RetroBar/Controls/InputLanguage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
</Thumb>
<WrapPanel x:Name="InputLanguageDockPanel"
Style="{DynamicResource LanguageBar}">
<TextBlock x:Name="InputLanguageText"
Style="{DynamicResource InputLanguage}"
Text="{Binding Path=LocaleIdentifier, Converter={StaticResource cultureInfoToLocaleNameConverter}, ConverterParameter=TwoLetterIsoLanguageName, Mode=OneWay}">
</TextBlock>
<Border x:Name="InputLanguageBox"
Style="{DynamicResource InputLanguageBox}">
<TextBlock x:Name="InputLanguageText"
Style="{DynamicResource InputLanguage}"
Text="{Binding Path=LocaleIdentifier, Converter={StaticResource cultureInfoToLocaleNameConverter}, ConverterParameter=TwoLetterIsoLanguageName, Mode=OneWay}">
</TextBlock>
</Border>
</WrapPanel>
</DockPanel>

Expand Down
56 changes: 53 additions & 3 deletions RetroBar/Controls/InputLanguage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using ManagedShell.Common.Helpers;
using ManagedShell.Common.Logging;
Expand Down Expand Up @@ -46,6 +47,46 @@ private void Initialize()
}

Settings.Instance.PropertyChanged += Settings_PropertyChanged;

UpdateTextScaling();
}

// The unscaled box size from the InputLanguageBox style, captured once so the scaling
// doesn't hard-code it.
private double _baseBoxHeight = double.NaN;
private double _baseBoxMinWidth = double.NaN;

private void UpdateTextScaling()
{
// Only scale within the actual taskbar; the properties window preview hosts this
// same control without the taskbar's ScaleTransform, so it should stay unscaled.
double scale = Window.GetWindow(this) is RetroBar.Taskbar ? Settings.Instance.TaskbarScale : 1.0;

if (double.IsNaN(_baseBoxHeight))
{
_baseBoxHeight = InputLanguageBox.Height;
_baseBoxMinWidth = InputLanguageBox.MinWidth;
}

// Render the whole indicator at real, pixel-aligned sizes with a 1/scale
// counter-transform, so both the box and the text stay crisp (no fractional-pixel
// blur) and the text centers in real-pixel space rather than in the taskbar's
// fractional scaled space. The base font size comes from the current theme's
// GlobalFontSize.
if (scale > 1.0 && Application.Current.TryFindResource("GlobalFontSize") is double baseFontSize)
{
InputLanguageBox.LayoutTransform = new ScaleTransform(1.0 / scale, 1.0 / scale);
InputLanguageBox.Height = Math.Round(_baseBoxHeight * scale);
InputLanguageBox.MinWidth = Math.Round(_baseBoxMinWidth * scale);
InputLanguageText.FontSize = Math.Round(baseFontSize * scale);
}
else
{
InputLanguageBox.LayoutTransform = null;
InputLanguageBox.ClearValue(FrameworkElement.HeightProperty);
InputLanguageBox.ClearValue(FrameworkElement.MinWidthProperty);
InputLanguageText.ClearValue(TextBlock.FontSizeProperty);
}
}

private void SetLocaleIdentifier()
Expand Down Expand Up @@ -122,17 +163,17 @@ private void LayoutWatchTick(object sender, EventArgs args)

if (InstalledLanguagesCount() == 1)
{
InputLanguageText.Visibility = Visibility.Collapsed;
InputLanguageBox.Visibility = Visibility.Collapsed;
}
else
{
InputLanguageText.Visibility = Visibility.Visible;
InputLanguageBox.Visibility = Visibility.Visible;
}
}
else
{
JapaneseImeRemove();
InputLanguageText.Visibility = Visibility.Visible;
InputLanguageBox.Visibility = Visibility.Visible;
}
}

Expand All @@ -156,6 +197,15 @@ private void Settings_PropertyChanged(object sender, System.ComponentModel.Prope
StopWatch();
}
}
else if (e.PropertyName == nameof(Settings.TaskbarScale))
{
UpdateTextScaling();
}
else if (e.PropertyName == nameof(Settings.Theme))
{
// The base font size can change with the theme; re-apply once it has loaded.
Dispatcher.BeginInvoke(new Action(UpdateTextScaling), DispatcherPriority.Loaded);
}
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
Expand Down
18 changes: 18 additions & 0 deletions RetroBar/Controls/TaskButton.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using ManagedShell.Common.Helpers;
using ManagedShell.Interop;
using ManagedShell.WindowsTasks;
Expand Down Expand Up @@ -83,6 +84,15 @@ private void Animate()
storyboard.Begin();
}

private void UpdateTextScaling()
{
// Only scale within the actual taskbar; the properties window preview uses its own
// markup (not this control), so this never runs unscaled, but the guard keeps it
// consistent with the clock and input language indicator.
double scale = System.Windows.Window.GetWindow(this) is RetroBar.Taskbar ? Settings.Instance.TaskbarScale : 1.0;
TextScaler.ApplyScaling(this, scale);
}

private void TaskButton_OnLoaded(object sender, RoutedEventArgs e)
{
Window = DataContext as ApplicationWindow;
Expand All @@ -105,6 +115,8 @@ private void TaskButton_OnLoaded(object sender, RoutedEventArgs e)
Animate();
}

UpdateTextScaling();

_isLoaded = true;
}

Expand Down Expand Up @@ -285,6 +297,12 @@ private void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
if (e.PropertyName == nameof(Settings.Theme))
{
SetStyle();
// The base font size can change with the theme; re-apply once it has loaded.
Dispatcher.BeginInvoke(new Action(UpdateTextScaling), DispatcherPriority.Loaded);
}
else if (e.PropertyName == nameof(Settings.TaskbarScale))
{
UpdateTextScaling();
}
}

Expand Down
26 changes: 18 additions & 8 deletions RetroBar/Themes/System.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -910,21 +910,31 @@
</Style.Triggers>
</Style>

<Style TargetType="Border"
x:Key="InputLanguageBox">
<Setter Property="Background"
Value="{DynamicResource InputLanguageBackground}"/>
<Setter Property="MinWidth"
Value="16"/>
<Setter Property="Height"
Value="16"/>
<!-- Hard pixel edges so the box stays crisp even when scaling places it on a
fractional device pixel (a solid rectangle otherwise anti-aliases its edges). -->
<Setter Property="RenderOptions.EdgeMode"
Value="Aliased"/>
</Style>

<Style TargetType="TextBlock"
x:Key="InputLanguage"
BasedOn="{StaticResource GlobalFonts}">
<Setter Property="Foreground"
Value="{DynamicResource InputLanguageForeground}" />
<Setter Property="Background"
Value="{DynamicResource InputLanguageBackground}"/>
<Setter Property="MinWidth"
Value="16"/>
<Setter Property="Height"
Value="16"/>
<Setter Property="Padding"
Value="0,1,0,0" />
<Setter Property="TextAlignment"
Value="Center" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>

<Style TargetType="Button"
Expand Down
6 changes: 3 additions & 3 deletions RetroBar/Themes/Windows Vista Aero.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -1436,9 +1436,9 @@
</Style.Triggers>
</Style>

<Style TargetType="TextBlock"
x:Key="InputLanguage"
BasedOn="{StaticResource InputLanguage}">
<Style TargetType="Border"
x:Key="InputLanguageBox"
BasedOn="{StaticResource InputLanguageBox}">
<Setter Property="Margin"
Value="0,6,0,0" />
<Setter Property="HorizontalAlignment"
Expand Down
52 changes: 52 additions & 0 deletions RetroBar/Utilities/TextScaler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace RetroBar.Utilities
{
// Renders the TextBlocks within a control at a real, pixel-aligned font size when the
// taskbar is scaled, instead of letting the taskbar's ScaleTransform stretch text that
// was laid out at its base size (which pushes glyphs off the pixel grid and looks blurry).
//
// Each TextBlock gets FontSize = round(baseFontSize * scale) and a 1/scale counter-transform,
// so its glyphs render with a net identity transform (crisp) while it still occupies the
// scaled layout slot. The base size is read back from the element each call (after clearing
// our previous override), so repeated calls don't compound and the base stays correct when
// the theme changes it.
public static class TextScaler
{
public static void ApplyScaling(DependencyObject root, double scale)
{
if (root == null)
{
return;
}

int count = VisualTreeHelper.GetChildrenCount(root);

for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(root, i);

if (child is TextBlock textBlock)
{
// Drop our previous override so FontSize reverts to the (theme) base size.
textBlock.ClearValue(TextBlock.FontSizeProperty);

if (scale > 1.0)
{
textBlock.FontSize = Math.Round(textBlock.FontSize * scale);
textBlock.LayoutTransform = new ScaleTransform(1.0 / scale, 1.0 / scale);
}
else
{
textBlock.ClearValue(FrameworkElement.LayoutTransformProperty);
}
}

ApplyScaling(child, scale);
}
}
}
}