From 2ffcf1738626c4e68ce37f038ec2a479220c3ac5 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 19:20:51 +0200 Subject: [PATCH 1/4] Integration: apply #87 TranslateSettingsWindow.cs --- src/ui/Features/Translate/TranslateSettingsWindow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/Features/Translate/TranslateSettingsWindow.cs b/src/ui/Features/Translate/TranslateSettingsWindow.cs index df9b4f86f9a..47df1d6cb28 100644 --- a/src/ui/Features/Translate/TranslateSettingsWindow.cs +++ b/src/ui/Features/Translate/TranslateSettingsWindow.cs @@ -81,6 +81,7 @@ public TranslateSettingsWindow(TranslateSettingsViewModel vm) TextWrapping = Avalonia.Media.TextWrapping.Wrap, }.BindIsVisible(vm, nameof(vm.PromptIsVisible)) .BindText(vm, nameof(vm.PromptText)); + promptTextBox.WithLabeledBy(labelPrompt); var buttonOk = UiUtil.MakeButtonOk(vm.OkCommand); var buttonCancel = UiUtil.MakeButtonCancel(vm.CancelCommand); From b99ceff8ce976af02484fceb1329c7ced216b2ba Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 19:20:58 +0200 Subject: [PATCH 2/4] Integration: apply #87 VoiceManagerWindow.cs --- .../Video/TextToSpeech/VoiceManager/VoiceManagerWindow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/Features/Video/TextToSpeech/VoiceManager/VoiceManagerWindow.cs b/src/ui/Features/Video/TextToSpeech/VoiceManager/VoiceManagerWindow.cs index e0371eeb79c..4b0fb39aa7a 100644 --- a/src/ui/Features/Video/TextToSpeech/VoiceManager/VoiceManagerWindow.cs +++ b/src/ui/Features/Video/TextToSpeech/VoiceManager/VoiceManagerWindow.cs @@ -504,6 +504,7 @@ private Control MakeDetailsPane(VoiceManagerViewModel vm) HorizontalAlignment = HorizontalAlignment.Stretch, [!TextBox.TextProperty] = new Binding(nameof(vm.Transcript)) { Mode = BindingMode.TwoWay }, }; + transcriptBox.WithLabeledBy(transcriptHeader); var transcriptPanel = new StackPanel { From 535f17f80211d26a7906e4e5d597b689c5e1a247 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 19:21:05 +0200 Subject: [PATCH 3/4] Integration: apply #87 AccessibleNamesTests.cs --- tests/UI/Logic/AccessibleNamesTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/UI/Logic/AccessibleNamesTests.cs b/tests/UI/Logic/AccessibleNamesTests.cs index 387887d73f6..c6ebcf5f15c 100644 --- a/tests/UI/Logic/AccessibleNamesTests.cs +++ b/tests/UI/Logic/AccessibleNamesTests.cs @@ -21,7 +21,9 @@ namespace UITests.Logic; /// by the window or derived from its visible label by /// (#12087: "I hear a value followed by combo box, but no label telling me which setting /// I am changing"). This opens every tool window that takes a single DI-resolvable view -/// model and lists the inputs that still have no name. +/// model and lists the inputs that still have no name. Hidden inputs are included because +/// AccessibleLabels.Apply runs once when the window loads; controls that become visible later +/// do not get a second inference pass. /// public class AccessibleNamesTests { @@ -80,7 +82,7 @@ public void EveryInputInEveryWindow_HasAnAccessibleName() { foreach (var control in window.GetLogicalDescendants().OfType()) { - if (!AccessibleLabels.IsInput(control) || control.TemplatedParent != null || !control.IsEffectivelyVisible) + if (!AccessibleLabels.IsInput(control) || control.TemplatedParent != null) { continue; } From 0d4792c14017457c2d80ec2390cef3bafd7c7806 Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 19:26:27 +0200 Subject: [PATCH 4/4] Integration: enable all accessibility fail-closed gates --- tests/UI/Logic/AccessibleNamesTests.cs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/UI/Logic/AccessibleNamesTests.cs b/tests/UI/Logic/AccessibleNamesTests.cs index c6ebcf5f15c..3f4b7527212 100644 --- a/tests/UI/Logic/AccessibleNamesTests.cs +++ b/tests/UI/Logic/AccessibleNamesTests.cs @@ -45,6 +45,7 @@ public void EveryInputInEveryWindow_HasAnAccessibleName() .ToList(); var unnamed = new StringBuilder(); + var openFailures = new StringBuilder(); var opened = 0; var skipped = new List(); foreach (var type in windowTypes) @@ -73,7 +74,8 @@ public void EveryInputInEveryWindow_HasAnAccessibleName() } catch (Exception e) { - skipped.Add($"{type.Name} ({(e as TargetInvocationException)?.InnerException?.GetType().Name ?? e.GetType().Name})"); + var cause = (e as TargetInvocationException)?.InnerException ?? e; + openFailures.AppendLine($"{type.Name}: {cause.GetType().Name}: {cause.Message}"); continue; } @@ -101,27 +103,20 @@ public void EveryInputInEveryWindow_HasAnAccessibleName() } } + Assert.True(openFailures.Length == 0, $"Windows that failed to open:\n{openFailures}"); Assert.True(opened > 50, $"Only {opened} windows opened; skipped: {string.Join(", ", skipped)}"); Assert.True(unnamed.Length == 0, $"Inputs without an accessible name ({opened} windows opened, {skipped.Count} skipped):\n{unnamed}"); } /// - /// Runs pending dispatcher jobs, ignoring what they throw. Some view models probe media - /// on a background thread from Loaded and post a message box back (Video OCR: "unable - /// to read video"); when that post lands after the window is closed, showing the box - /// throws "Cannot show a window with a closed owner" - a timing artifact of opening - /// windows without files, not an accessibility finding. + /// Runs pending dispatcher jobs. Unexpected dispatcher failures must fail the test; + /// the Video OCR closed-owner race that previously required suppression is now fixed + /// at the source by checking whether its window is already closing before showing the + /// message box (upstream 6840e797). /// private static void DrainJobs() { - try - { - Dispatcher.UIThread.RunJobs(); - } - catch (Exception) - { - // Ignored - see summary. - } + Dispatcher.UIThread.RunJobs(); } private static string Describe(Control control)