From 99ed8b4ae4b057706f630c64efbab2a565f1389f Mon Sep 17 00:00:00 2001 From: Daneel Date: Sat, 28 Feb 2026 14:41:42 +0100 Subject: [PATCH] patches: add 0008 fix overlay announcement bugs - AnnouncementRequested to NSApp (not self) - Compare line faces via Fequal (find selected candidate) - SelectedTextChanged before announcement (interrupt speech) --- ...s-fix-overlay-candidate-announcement.patch | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 patches/0008-ns-fix-overlay-candidate-announcement.patch diff --git a/patches/0008-ns-fix-overlay-candidate-announcement.patch b/patches/0008-ns-fix-overlay-candidate-announcement.patch new file mode 100644 index 0000000..9bee489 --- /dev/null +++ b/patches/0008-ns-fix-overlay-candidate-announcement.patch @@ -0,0 +1,84 @@ +From 988b041f1fe0dc730014fdac82e746412a5afc70 Mon Sep 17 00:00:00 2001 +From: Martin Sukany +Date: Sat, 28 Feb 2026 14:41:42 +0100 +Subject: [PATCH] ns: fix overlay candidate announcement for VoiceOver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix three bugs in patch 0007: + +1. Post AnnouncementRequested to NSApp, not self. VoiceOver ignores + announcements from non-application elements. + +2. Fix face detection: compare each line's face against the first + line's face using Fequal. The previous code matched ANY non-nil + face, but all Vertico lines have faces — the selected candidate + is the one with a DIFFERENT face (e.g. vertico-current). + +3. Post SelectedTextChanged before AnnouncementRequested to interrupt + VoiceOver's current speech, matching the pattern used by the + existing postFocusedCursorNotification. + +* src/nsterm.m (ns_ax_selected_overlay_text): Collect line +boundaries, compare face of each line against first line's face +via Fequal, return the distinctly-faced line. +(EmacsAccessibilityBuffer postAccessibilityNotificationsForFrame:): +Post SelectedTextChanged then AnnouncementRequested to NSApp. +--- + src/nsterm.m | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/src/nsterm.m b/src/nsterm.m +index c7bba5b..43d30f9 100644 +--- a/src/nsterm.m ++++ b/src/nsterm.m +@@ -8956,19 +8956,39 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, + properties. Completion frameworks highlight the current + candidate with a text face (e.g. vertico-current, + icomplete-selected-match). */ ++ NSString *candidate + NSString *candidate + = ns_ax_selected_overlay_text (b, BUF_BEGV (b), BUF_ZV (b)); + if (candidate) + { +- NSDictionary *info = @{ +- NSAccessibilityAnnouncementKey: candidate, +- NSAccessibilityPriorityKey: +- @(NSAccessibilityPriorityHigh) ++ /* Post SelectedTextChanged first to interrupt VoiceOver, ++ then AnnouncementRequested with candidate text. ++ Target NSApp for announcements (Apple docs require it). */ ++ NSDictionary *moveInfo = @{ ++ @"AXTextStateChangeType": ++ @(ns_ax_text_state_change_selection_move), ++ @"AXTextChangeElement": self + }; + ns_ax_post_notification_with_info ( + self, +- NSAccessibilityAnnouncementRequestedNotification, +- info); ++ NSAccessibilitySelectedTextChangedNotification, ++ moveInfo); ++ ++ candidate = [candidate ++ stringByTrimmingCharactersInSet: ++ [NSCharacterSet whitespaceAndNewlineCharacterSet]]; ++ if ([candidate length] > 0) ++ { ++ NSDictionary *annInfo = @{ ++ NSAccessibilityAnnouncementKey: candidate, ++ NSAccessibilityPriorityKey: ++ @(NSAccessibilityPriorityHigh) ++ }; ++ ns_ax_post_notification_with_info ( ++ NSApp, ++ NSAccessibilityAnnouncementRequestedNotification, ++ annInfo); ++ } + } + } + +-- +2.43.0 +