patches: restore full-line AnnouncementRequested for C-n/C-p
This commit is contained in:
@@ -1,21 +1,19 @@
|
|||||||
From f58ceb517c9bff049dcc7bf315062f1fa80c85b2 Mon Sep 17 00:00:00 2001
|
From 515d3e0cfc42c1c9f907359b1dff379206d940a7 Mon Sep 17 00:00:00 2001
|
||||||
From: Martin Sukany <martin@sukany.cz>
|
From: Martin Sukany <martin@sukany.cz>
|
||||||
Date: Fri, 27 Feb 2026 12:49:43 +0100
|
Date: Fri, 27 Feb 2026 12:59:28 +0100
|
||||||
Subject: [PATCH] ns: implement VoiceOver accessibility (hybrid notification
|
Subject: [PATCH] ns: implement VoiceOver accessibility (restore line
|
||||||
strategy)
|
announcement fallback)
|
||||||
|
|
||||||
Notification architecture:
|
C-n/C-p need explicit AnnouncementRequested for line text; VoiceOver
|
||||||
- SelectedTextChanged ALWAYS posted for focused element (interrupts
|
processes these differently from arrow keys. Restore full-line
|
||||||
VoiceOver auto-read, updates braille displays)
|
fallback announcement for all line moves (not just completion-string).
|
||||||
- For character moves: omit granularity from userInfo so VoiceOver
|
SelectedTextChanged(granularity=line) + AnnouncementRequested(line text)
|
||||||
cannot derive speech; post AnnouncementRequested with char AT point
|
does NOT cause double-speech for lines (same text = VoiceOver deduplicates
|
||||||
- For word/line: include granularity (VoiceOver reads word/line correctly)
|
or announcement replaces; unlike character moves where the texts differ).
|
||||||
- Word granularity: same-line moves > 1 UTF-16 unit (fixes M-f/M-b)
|
|
||||||
- Non-focused: AnnouncementRequested only (completions)
|
|
||||||
---
|
---
|
||||||
src/nsterm.h | 109 ++
|
src/nsterm.h | 109 ++
|
||||||
src/nsterm.m | 2727 +++++++++++++++++++++++++++++++++++++++++++++++---
|
src/nsterm.m | 2756 +++++++++++++++++++++++++++++++++++++++++++++++---
|
||||||
2 files changed, 2687 insertions(+), 149 deletions(-)
|
2 files changed, 2716 insertions(+), 149 deletions(-)
|
||||||
|
|
||||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||||
index 7c1ee4c..6c95673 100644
|
index 7c1ee4c..6c95673 100644
|
||||||
@@ -152,7 +150,7 @@ index 7c1ee4c..6c95673 100644
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||||
index 932d209..d33299b 100644
|
index 932d209..4288e68 100644
|
||||||
--- a/src/nsterm.m
|
--- a/src/nsterm.m
|
||||||
+++ b/src/nsterm.m
|
+++ b/src/nsterm.m
|
||||||
@@ -46,6 +46,7 @@ Updated by Christian Limpach (chris@nice.ch)
|
@@ -46,6 +46,7 @@ Updated by Christian Limpach (chris@nice.ch)
|
||||||
@@ -213,7 +211,7 @@ index 932d209..d33299b 100644
|
|||||||
ns_focus (f, NULL, 0);
|
ns_focus (f, NULL, 0);
|
||||||
|
|
||||||
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
||||||
@@ -6849,219 +6886,2280 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
|
@@ -6849,219 +6886,2309 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
|
||||||
|
|
||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
|
|
||||||
@@ -2062,23 +2060,51 @@ index 932d209..d33299b 100644
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ /* For focused line moves: announce line text (or completion
|
+ /* For focused line moves: always announce line text explicitly.
|
||||||
+ candidate for horizontal multi-column layouts).
|
+ SelectedTextChanged with granularity=line works for arrow
|
||||||
+ VoiceOver already reads the line via SelectedTextChanged
|
+ keys, but C-n/C-p need the explicit announcement (VoiceOver
|
||||||
+ with granularity=line, but for completion-list-mode we need
|
+ processes these keystrokes differently from arrows).
|
||||||
+ to announce just the candidate, not the whole line. */
|
+ In completion-list-mode, read the completion candidate
|
||||||
|
+ instead of the whole line. */
|
||||||
+ if (cachedText
|
+ if (cachedText
|
||||||
+ && granularity == ns_ax_text_selection_granularity_line)
|
+ && granularity == ns_ax_text_selection_granularity_line)
|
||||||
+ {
|
+ {
|
||||||
|
+ NSString *announceText = nil;
|
||||||
|
+
|
||||||
|
+ /* 1. completion--string at point. */
|
||||||
+ Lisp_Object cstr
|
+ Lisp_Object cstr
|
||||||
+ = Fget_char_property (make_fixnum (point),
|
+ = Fget_char_property (make_fixnum (point),
|
||||||
+ intern ("completion--string"), Qnil);
|
+ intern ("completion--string"), Qnil);
|
||||||
+ NSString *compText
|
+ announceText = ns_ax_completion_string_from_prop (cstr);
|
||||||
+ = ns_ax_completion_string_from_prop (cstr);
|
+
|
||||||
+ if (compText)
|
+ /* 2. Fallback: full line text. */
|
||||||
|
+ if (!announceText)
|
||||||
|
+ {
|
||||||
|
+ NSUInteger point_idx
|
||||||
|
+ = [self accessibilityIndexForCharpos:point];
|
||||||
|
+ if (point_idx <= [cachedText length])
|
||||||
|
+ {
|
||||||
|
+ NSInteger lineNum
|
||||||
|
+ = [self accessibilityLineForIndex:point_idx];
|
||||||
|
+ NSRange lineRange
|
||||||
|
+ = [self accessibilityRangeForLine:lineNum];
|
||||||
|
+ if (lineRange.location != NSNotFound
|
||||||
|
+ && lineRange.length > 0
|
||||||
|
+ && NSMaxRange (lineRange) <= [cachedText length])
|
||||||
|
+ announceText
|
||||||
|
+ = [cachedText substringWithRange:lineRange];
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (announceText)
|
||||||
|
+ {
|
||||||
|
+ announceText = [announceText
|
||||||
|
+ stringByTrimmingCharactersInSet:
|
||||||
|
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||||
|
+ if ([announceText length] > 0)
|
||||||
+ {
|
+ {
|
||||||
+ NSDictionary *annInfo = @{
|
+ NSDictionary *annInfo = @{
|
||||||
+ NSAccessibilityAnnouncementKey: compText,
|
+ NSAccessibilityAnnouncementKey: announceText,
|
||||||
+ NSAccessibilityPriorityKey:
|
+ NSAccessibilityPriorityKey:
|
||||||
+ @(NSAccessibilityPriorityHigh)
|
+ @(NSAccessibilityPriorityHigh)
|
||||||
+ };
|
+ };
|
||||||
@@ -2089,6 +2115,7 @@ index 932d209..d33299b 100644
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ /* --- Completions announcement ---
|
+ /* --- Completions announcement ---
|
||||||
+ When point changes in a non-focused buffer (e.g. *Completions*
|
+ When point changes in a non-focused buffer (e.g. *Completions*
|
||||||
@@ -2643,7 +2670,7 @@ index 932d209..d33299b 100644
|
|||||||
unsigned fnKeysym = 0;
|
unsigned fnKeysym = 0;
|
||||||
static NSMutableArray *nsEvArray;
|
static NSMutableArray *nsEvArray;
|
||||||
unsigned int flags = [theEvent modifierFlags];
|
unsigned int flags = [theEvent modifierFlags];
|
||||||
@@ -8237,6 +10335,28 @@ - (void)windowDidBecomeKey /* for direct calls */
|
@@ -8237,6 +10364,28 @@ - (void)windowDidBecomeKey /* for direct calls */
|
||||||
XSETFRAME (event.frame_or_window, emacsframe);
|
XSETFRAME (event.frame_or_window, emacsframe);
|
||||||
kbd_buffer_store_event (&event);
|
kbd_buffer_store_event (&event);
|
||||||
ns_send_appdefined (-1); // Kick main loop
|
ns_send_appdefined (-1); // Kick main loop
|
||||||
@@ -2672,7 +2699,7 @@ index 932d209..d33299b 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -9474,6 +11594,307 @@ - (int) fullscreenState
|
@@ -9474,6 +11623,307 @@ - (int) fullscreenState
|
||||||
return fs_state;
|
return fs_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2980,7 +3007,7 @@ index 932d209..d33299b 100644
|
|||||||
@end /* EmacsView */
|
@end /* EmacsView */
|
||||||
|
|
||||||
|
|
||||||
@@ -11303,6 +13724,14 @@ Convert an X font name (XLFD) to an NS font name.
|
@@ -11303,6 +13753,14 @@ Convert an X font name (XLFD) to an NS font name.
|
||||||
DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic");
|
DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic");
|
||||||
DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion");
|
DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user