From 95a009ef9a8192a422052ee32d263041fd0f3212 Mon Sep 17 00:00:00 2001 From: Ionite Date: Mon, 17 Aug 2026 15:27:58 -0700 Subject: [PATCH] feat: accessible names for icon-only controls and --overlay-popups flag UI Automation (and screen readers) saw icon-only buttons as their content's ToString - "FluentAvalonia.UI.Controls.SymbolIcon" - making them indistinguishable. Adds AutomationProperties.Name to the package card action buttons, the DocsHelpButton theme, and the NavigationView pane toggle. Adds --overlay-popups to render popups inside the window on Windows (already the default on Linux/macOS), so window captures and the window's automation subtree include open flyouts and dropdowns. Platform options are now composed into one instance per platform before applying: .With() replaces the registered options wholesale, so the per-flag instances were silently dropping earlier settings (X11 OverlayPopups under --disable-gpu-rendering, macOS OverlayPopups under any rendering flag). Co-Authored-By: Lykos (Fable 5) --- StabilityMatrix.Avalonia/Models/AppArgs.cs | 8 +++ StabilityMatrix.Avalonia/Program.cs | 49 +++++-------------- .../ControlThemes/DocsHelpButtonStyles.axaml | 1 + .../Views/MainWindow.axaml | 7 +++ .../MainPackageManagerView.axaml | 16 +++++- .../AutomationNameTests.cs | 47 ++++++++++++++++++ 6 files changed, 90 insertions(+), 38 deletions(-) create mode 100644 StabilityMatrix.UITests/AutomationNameTests.cs diff --git a/StabilityMatrix.Avalonia/Models/AppArgs.cs b/StabilityMatrix.Avalonia/Models/AppArgs.cs index 66441ad34..ab11f68fd 100644 --- a/StabilityMatrix.Avalonia/Models/AppArgs.cs +++ b/StabilityMatrix.Avalonia/Models/AppArgs.cs @@ -74,6 +74,14 @@ public class AppArgs [Option("vulkan", HelpText = "Prefer Vulkan rendering")] public bool UseVulkanRendering { get; set; } + /// + /// Flag to render popups (flyouts, dropdowns, menus) inside the window instead of as + /// separate OS windows, so window captures and UI automation can see them. + /// Popups are clipped to the window bounds in this mode. + /// + [Option("overlay-popups", HelpText = "Render popups inside the window (for UI automation / capture)")] + public bool UseOverlayPopups { get; set; } + /// /// Override global app home directory /// Defaults to (%APPDATA%|~/.config)/StabilityMatrix diff --git a/StabilityMatrix.Avalonia/Program.cs b/StabilityMatrix.Avalonia/Program.cs index 25b17cf31..838b018d0 100644 --- a/StabilityMatrix.Avalonia/Program.cs +++ b/StabilityMatrix.Avalonia/Program.cs @@ -236,56 +236,31 @@ public static AppBuilder BuildAvaloniaApp() var app = AppBuilder.Configure().UsePlatformDetect().WithInterFont().LogToTrace(); - if (Compat.IsLinux) - { - app = app.With(new X11PlatformOptions { OverlayPopups = true, WmClass = "stabilitymatrix" }); - } - else if (Compat.IsMacOS) - { - app = app.With(new AvaloniaNativePlatformOptions { OverlayPopups = true }); - } + // .With() replaces the registered options instance wholesale, so each platform's + // options must be composed into a single object before applying. + var win32Options = new Win32PlatformOptions { OverlayPopups = Args.UseOverlayPopups }; + var x11Options = new X11PlatformOptions { OverlayPopups = true, WmClass = "stabilitymatrix" }; + var macOptions = new AvaloniaNativePlatformOptions { OverlayPopups = true }; if (Args.UseOpenGlRendering) { - app = app.With( - new Win32PlatformOptions - { - RenderingMode = [Win32RenderingMode.Wgl, Win32RenderingMode.Software], - } - ); + win32Options.RenderingMode = [Win32RenderingMode.Wgl, Win32RenderingMode.Software]; } if (Args.UseVulkanRendering) { - app = app.With( - new X11PlatformOptions - { - RenderingMode = [X11RenderingMode.Vulkan], - WmClass = "stabilitymatrix", - } - ) - .With(new Win32PlatformOptions { RenderingMode = [Win32RenderingMode.Vulkan] }); + win32Options.RenderingMode = [Win32RenderingMode.Vulkan]; + x11Options.RenderingMode = [X11RenderingMode.Vulkan]; } if (Args.DisableGpuRendering) { - app = app.With(new Win32PlatformOptions { RenderingMode = new[] { Win32RenderingMode.Software } }) - .With( - new X11PlatformOptions - { - RenderingMode = new[] { X11RenderingMode.Software }, - WmClass = "stabilitymatrix", - } - ) - .With( - new AvaloniaNativePlatformOptions - { - RenderingMode = new[] { AvaloniaNativeRenderingMode.Software }, - } - ); + win32Options.RenderingMode = [Win32RenderingMode.Software]; + x11Options.RenderingMode = [X11RenderingMode.Software]; + macOptions.RenderingMode = [AvaloniaNativeRenderingMode.Software]; } - return app; + return app.With(win32Options).With(x11Options).With(macOptions); } private static void HandleUpdateReplacement() diff --git a/StabilityMatrix.Avalonia/Styles/ControlThemes/DocsHelpButtonStyles.axaml b/StabilityMatrix.Avalonia/Styles/ControlThemes/DocsHelpButtonStyles.axaml index 5d5aeaee6..80d6b8f6e 100644 --- a/StabilityMatrix.Avalonia/Styles/ControlThemes/DocsHelpButtonStyles.axaml +++ b/StabilityMatrix.Avalonia/Styles/ControlThemes/DocsHelpButtonStyles.axaml @@ -25,6 +25,7 @@ + diff --git a/StabilityMatrix.Avalonia/Views/MainWindow.axaml b/StabilityMatrix.Avalonia/Views/MainWindow.axaml index 30ecc7b21..c6b9900df 100644 --- a/StabilityMatrix.Avalonia/Views/MainWindow.axaml +++ b/StabilityMatrix.Avalonia/Views/MainWindow.axaml @@ -38,6 +38,13 @@ + + + + + + Classes="transparent" + ToolTip.Tip="More Options"> @@ -347,6 +349,7 @@