From f16248eb89dcb45921d1faf2b37a483cd4e1ce7c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 06:03:44 +0000 Subject: [PATCH 1/4] Initial plan From 733f9c29190839255bff7fe67cd39451ba738b56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 06:08:07 +0000 Subject: [PATCH 2/4] Fix Win10 icon font fallback Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com> --- .../A2UI/Hosting/SurfaceHost.cs | 3 ++- .../Rendering/Renderers/DisplayRenderers.cs | 3 ++- .../Rendering/Renderers/UnknownRenderer.cs | 3 ++- .../Chat/OpenClawChatTimeline.cs | 4 ++-- .../Chat/OpenClawComposer.cs | 14 ++++++------ .../Helpers/FluentIconCatalog.cs | 5 ++++- .../FluentIconCatalogTests.cs | 22 +++++++++++++++++++ 7 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/OpenClaw.Tray.WinUI/A2UI/Hosting/SurfaceHost.cs b/src/OpenClaw.Tray.WinUI/A2UI/Hosting/SurfaceHost.cs index 8b0480f5b..9e4314373 100644 --- a/src/OpenClaw.Tray.WinUI/A2UI/Hosting/SurfaceHost.cs +++ b/src/OpenClaw.Tray.WinUI/A2UI/Hosting/SurfaceHost.cs @@ -9,6 +9,7 @@ using OpenClawTray.A2UI.Protocol; using OpenClawTray.A2UI.Rendering; using OpenClawTray.A2UI.Theming; +using OpenClawTray.Helpers; namespace OpenClawTray.A2UI.Hosting; @@ -260,7 +261,7 @@ private static FrameworkElement BuildErrorPlaceholder(string componentName, stri stack.Children.Add(new FontIcon { Glyph = "", - FontFamily = new FontFamily("Segoe Fluent Icons"), + FontFamily = FluentIconCatalog.SymbolThemeFontFamily, }); stack.Children.Add(new TextBlock { diff --git a/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/DisplayRenderers.cs b/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/DisplayRenderers.cs index f815c8ed8..da7fdab3f 100644 --- a/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/DisplayRenderers.cs +++ b/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/DisplayRenderers.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using OpenClawTray.A2UI.Protocol; +using OpenClawTray.Helpers; namespace OpenClawTray.A2UI.Rendering.Renderers; @@ -232,7 +233,7 @@ public FrameworkElement Render(A2UIComponentDef c, RenderContext ctx) { var fontIcon = new FontIcon { - FontFamily = new FontFamily("Segoe Fluent Icons"), + FontFamily = FluentIconCatalog.SymbolThemeFontFamily, FontSize = 16, }; var nameVal = ctx.GetValue(c, "name"); diff --git a/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/UnknownRenderer.cs b/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/UnknownRenderer.cs index 5ff534a29..1f3e44262 100644 --- a/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/UnknownRenderer.cs +++ b/src/OpenClaw.Tray.WinUI/A2UI/Rendering/Renderers/UnknownRenderer.cs @@ -3,6 +3,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using OpenClawTray.A2UI.Protocol; +using OpenClawTray.Helpers; namespace OpenClawTray.A2UI.Rendering.Renderers; @@ -29,7 +30,7 @@ public FrameworkElement Render(A2UIComponentDef component, RenderContext ctx) stack.Children.Add(new FontIcon { Glyph = "", // outlined warning - FontFamily = new FontFamily("Segoe Fluent Icons"), + FontFamily = FluentIconCatalog.SymbolThemeFontFamily, }); var template = OpenClawTray.Helpers.LocalizationHelper.GetString("A2UI_UnsupportedComponent"); stack.Children.Add(new TextBlock diff --git a/src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs b/src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs index 962880d92..36eae8248 100644 --- a/src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs +++ b/src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs @@ -785,7 +785,7 @@ Element HoverIcon(string entryId, string actionKey, string glyph, string ackGlyp TextBlock(shownGlyph) .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons, Segoe MDL2 Assets"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 14; t.FontWeight = Microsoft.UI.Text.FontWeights.Light; t.Foreground = shownColor; @@ -1062,7 +1062,7 @@ Element RenderUserEntry(ChatTimelineItem entry, bool startsBurst, bool endsBurst TextBlock(fileGlyph) .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 16; t.Foreground = userBubbleFg; t.VerticalAlignment = VerticalAlignment.Center; diff --git a/src/OpenClaw.Tray.WinUI/Chat/OpenClawComposer.cs b/src/OpenClaw.Tray.WinUI/Chat/OpenClawComposer.cs index bf8f6184e..53b26b681 100644 --- a/src/OpenClaw.Tray.WinUI/Chat/OpenClawComposer.cs +++ b/src/OpenClaw.Tray.WinUI/Chat/OpenClawComposer.cs @@ -425,7 +425,7 @@ public override Element Render() TextBlock("\uE711") // Cancel glyph .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 10; }), () => Props.OnAttachmentRemoved?.Invoke()) @@ -491,7 +491,7 @@ public override Element Render() thumb = TextBlock("\uEB9F") .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 16; t.VerticalAlignment = VerticalAlignment.Center; }); @@ -505,7 +505,7 @@ public override Element Render() TextBlock("\uE711") .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 10; t.HorizontalAlignment = HorizontalAlignment.Center; t.VerticalAlignment = VerticalAlignment.Center; @@ -554,7 +554,7 @@ public override Element Render() TextBlock("\uE8A5") // Page glyph .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = 12; t.VerticalAlignment = VerticalAlignment.Center; }) @@ -685,7 +685,7 @@ Element IconButton(string glyph, string tip, Action onClick, Brush? foreground = TextBlock(glyph) .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = composerIconSize; // Always set foreground explicitly so element diffing resets it. t.Foreground = foreground @@ -773,7 +773,7 @@ Element IconButton(string glyph, string tip, Action onClick, Brush? foreground = TextBlock(sendGlyph) .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = composerIconSize; }) .Foreground(glyphBrush), @@ -819,7 +819,7 @@ Element IconButton(string glyph, string tip, Action onClick, Brush? foreground = TextBlock(stopGlyph) .Set(t => { - t.FontFamily = new FontFamily("Segoe Fluent Icons"); + t.FontFamily = FluentIconCatalog.SymbolThemeFontFamily; t.FontSize = composerIconSize; }) .Foreground(new SolidColorBrush(Colors.White)), diff --git a/src/OpenClaw.Tray.WinUI/Helpers/FluentIconCatalog.cs b/src/OpenClaw.Tray.WinUI/Helpers/FluentIconCatalog.cs index 3cfe50795..7bf2f04a8 100644 --- a/src/OpenClaw.Tray.WinUI/Helpers/FluentIconCatalog.cs +++ b/src/OpenClaw.Tray.WinUI/Helpers/FluentIconCatalog.cs @@ -103,6 +103,9 @@ public static class FluentIconCatalog public const string Workspace = "\uE8DA"; // OpenLocal (alias of Folder) public const string Cron = "\uE787"; // Calendar — Cron / scheduled jobs (matches HubWindow search mapping) + public static FontFamily SymbolThemeFontFamily => + (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"]; + /// /// Builds a for the given PUA glyph using the /// system-resolved SymbolThemeFontFamily so the icon honors @@ -114,7 +117,7 @@ public static FontIcon Build(string glyph, double size = 16) return new FontIcon { Glyph = glyph, - FontFamily = (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"], + FontFamily = SymbolThemeFontFamily, FontSize = size, }; } diff --git a/tests/OpenClaw.Tray.Tests/FluentIconCatalogTests.cs b/tests/OpenClaw.Tray.Tests/FluentIconCatalogTests.cs index 2a074f8fb..f2b055b16 100644 --- a/tests/OpenClaw.Tray.Tests/FluentIconCatalogTests.cs +++ b/tests/OpenClaw.Tray.Tests/FluentIconCatalogTests.cs @@ -95,6 +95,28 @@ public void Catalog_DefinesBuildHelper() Assert.Contains("SymbolThemeFontFamily", src); } + [Fact] + public void NativeWinUiSources_DoNotHardcodeSegoeFluentIcons() + { + var root = Path.Combine(TestRepositoryPaths.GetRepositoryRoot(), "src", "OpenClaw.Tray.WinUI"); + var offenders = Directory + .EnumerateFiles(root, "*", SearchOption.AllDirectories) + .Where(path => path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) + || path.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase)) + .SelectMany(path => File.ReadLines(path) + .Select((line, index) => (path, line, lineNumber: index + 1))) + .Where(item => item.line.Contains("new FontFamily(\"Segoe Fluent Icons\")", StringComparison.Ordinal) + || item.line.Contains("FontFamily=\"Segoe Fluent Icons\"", StringComparison.Ordinal)) + .Select(item => $"{Path.GetRelativePath(TestRepositoryPaths.GetRepositoryRoot(), item.path)}:{item.lineNumber}") + .ToArray(); + + Assert.True( + offenders.Length == 0, + "Use FluentIconCatalog.SymbolThemeFontFamily so icon glyphs fall back to Segoe MDL2 Assets on Windows 10:" + + Environment.NewLine + + string.Join(Environment.NewLine, offenders)); + } + } /// From bc97b817584e4bc08df60aa2e87253ccfacf9bc9 Mon Sep 17 00:00:00 2001 From: Scott Hanselman Date: Sun, 21 Jun 2026 13:36:48 -0700 Subject: [PATCH 3/4] Fix icon font fallback test coverage Extend the Windows 10 icon font fallback fix to setup UI glyphs and tighten the guard test so it skips build artifacts while catching fully qualified FontFamily hardcodes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/OpenClaw.SetupEngine.UI/IconFonts.cs | 10 ++++++ .../Pages/CapabilitiesPage.xaml.cs | 2 +- .../Pages/CompletePage.xaml | 4 +-- .../Pages/PermissionsPage.xaml | 2 +- .../Pages/PermissionsPage.xaml.cs | 4 +-- .../Pages/ProgressPage.xaml.cs | 2 +- .../FluentIconCatalogTests.cs | 35 ++++++++++++++----- 7 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 src/OpenClaw.SetupEngine.UI/IconFonts.cs diff --git a/src/OpenClaw.SetupEngine.UI/IconFonts.cs b/src/OpenClaw.SetupEngine.UI/IconFonts.cs new file mode 100644 index 000000000..21927ba42 --- /dev/null +++ b/src/OpenClaw.SetupEngine.UI/IconFonts.cs @@ -0,0 +1,10 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; + +namespace OpenClaw.SetupEngine.UI; + +internal static class IconFonts +{ + public static FontFamily SymbolThemeFontFamily => + (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"]; +} diff --git a/src/OpenClaw.SetupEngine.UI/Pages/CapabilitiesPage.xaml.cs b/src/OpenClaw.SetupEngine.UI/Pages/CapabilitiesPage.xaml.cs index ea8beca16..079ed6efc 100644 --- a/src/OpenClaw.SetupEngine.UI/Pages/CapabilitiesPage.xaml.cs +++ b/src/OpenClaw.SetupEngine.UI/Pages/CapabilitiesPage.xaml.cs @@ -74,7 +74,7 @@ private void BuildToggles() var icon = new TextBlock { Text = glyph, - FontFamily = new Microsoft.UI.Xaml.Media.FontFamily("Segoe Fluent Icons"), + FontFamily = IconFonts.SymbolThemeFontFamily, FontSize = 20, VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 12, 0), diff --git a/src/OpenClaw.SetupEngine.UI/Pages/CompletePage.xaml b/src/OpenClaw.SetupEngine.UI/Pages/CompletePage.xaml index fbc581b74..57ec04df3 100644 --- a/src/OpenClaw.SetupEngine.UI/Pages/CompletePage.xaml +++ b/src/OpenClaw.SetupEngine.UI/Pages/CompletePage.xaml @@ -19,7 +19,7 @@ CornerRadius="48" HorizontalAlignment="Center" Margin="0,0,0,20" Visibility="Collapsed" Background="#3CFF4444"> - @@ -58,7 +58,7 @@ Margin="0,20,0,0"> - diff --git a/src/OpenClaw.SetupEngine.UI/Pages/PermissionsPage.xaml b/src/OpenClaw.SetupEngine.UI/Pages/PermissionsPage.xaml index 02cc125d9..c153f3738 100644 --- a/src/OpenClaw.SetupEngine.UI/Pages/PermissionsPage.xaml +++ b/src/OpenClaw.SetupEngine.UI/Pages/PermissionsPage.xaml @@ -27,7 +27,7 @@