patches: update VoiceOver patch (v15.9 candidate)

This commit is contained in:
2026-02-26 17:29:33 +01:00
parent fa4748eb4c
commit 8ae3f0b367

View File

@@ -1,8 +1,19 @@
diff --git a/src/nsterm.h b/src/nsterm.h From 0084027a7680cbfb1449f091312ac21ed3794a6c Mon Sep 17 00:00:00 2001
index 7c1ee4c..2e2c80f 100644 From: Daneel <daneel@sukany.cz>
--- a/src/nsterm.h Date: Thu, 26 Feb 2026 17:30:09 +0100
+++ b/src/nsterm.h Subject: [PATCH] ns: implement AXBoundsForRange and VoiceOver interaction
@@ -453,6 +453,58 @@ enum ns_return_frame_mode fixes
---
nsterm.h | 68 ++
nsterm.m | 1968 +++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 1855 insertions(+), 181 deletions(-)
diff --git a/nsterm.h b/nsterm.h
index 7c1ee4c..719eeba 100644
--- a/nsterm.h
+++ b/nsterm.h
@@ -453,6 +453,59 @@ enum ns_return_frame_mode
@end @end
@@ -46,6 +57,7 @@ index 7c1ee4c..2e2c80f 100644
+@property (nonatomic, assign) ptrdiff_t cachedModiff; +@property (nonatomic, assign) ptrdiff_t cachedModiff;
+@property (nonatomic, assign) ptrdiff_t cachedPoint; +@property (nonatomic, assign) ptrdiff_t cachedPoint;
+@property (nonatomic, assign) BOOL cachedMarkActive; +@property (nonatomic, assign) BOOL cachedMarkActive;
+@property (nonatomic, copy) NSString *cachedCompletionAnnouncement;
+- (void)invalidateTextCache; +- (void)invalidateTextCache;
+- (void)postAccessibilityNotificationsForFrame:(struct frame *)f; +- (void)postAccessibilityNotificationsForFrame:(struct frame *)f;
+- (ptrdiff_t)charposForAccessibilityIndex:(NSUInteger)ax_idx; +- (ptrdiff_t)charposForAccessibilityIndex:(NSUInteger)ax_idx;
@@ -61,7 +73,7 @@ index 7c1ee4c..2e2c80f 100644
/* ========================================================================== /* ==========================================================================
The main Emacs view The main Emacs view
@@ -471,6 +523,14 @@ enum ns_return_frame_mode @@ -471,6 +524,14 @@ enum ns_return_frame_mode
#ifdef NS_IMPL_COCOA #ifdef NS_IMPL_COCOA
char *old_title; char *old_title;
BOOL maximizing_resize; BOOL maximizing_resize;
@@ -76,7 +88,7 @@ index 7c1ee4c..2e2c80f 100644
#endif #endif
BOOL font_panel_active; BOOL font_panel_active;
NSFont *font_panel_result; NSFont *font_panel_result;
@@ -528,6 +588,13 @@ enum ns_return_frame_mode @@ -528,6 +589,13 @@ enum ns_return_frame_mode
- (void)windowWillExitFullScreen; - (void)windowWillExitFullScreen;
- (void)windowDidExitFullScreen; - (void)windowDidExitFullScreen;
- (void)windowDidBecomeKey; - (void)windowDidBecomeKey;
@@ -90,10 +102,10 @@ index 7c1ee4c..2e2c80f 100644
@end @end
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/nsterm.m b/nsterm.m
index 932d209..416e5a4 100644 index 932d209..336150a 100644
--- a/src/nsterm.m --- a/nsterm.m
+++ b/src/nsterm.m +++ b/nsterm.m
@@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f) @@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f)
unblock_input (); unblock_input ();
@@ -144,7 +156,7 @@ index 932d209..416e5a4 100644
ns_focus (f, NULL, 0); ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -6849,261 +6885,1380 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) @@ -6849,261 +6885,1511 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
/* ========================================================================== /* ==========================================================================
@@ -568,10 +580,12 @@ index 932d209..416e5a4 100644
+@synthesize cachedModiff; +@synthesize cachedModiff;
+@synthesize cachedPoint; +@synthesize cachedPoint;
+@synthesize cachedMarkActive; +@synthesize cachedMarkActive;
+@synthesize cachedCompletionAnnouncement;
+- (void)dealloc +- (void)dealloc
+{ +{
+ [cachedText release]; + [cachedText release];
+ [cachedCompletionAnnouncement release];
+ if (visibleRuns) + if (visibleRuns)
+ xfree (visibleRuns); + xfree (visibleRuns);
+ [super dealloc]; + [super dealloc];
@@ -1199,8 +1213,8 @@ index 932d209..416e5a4 100644
+ direction = 3; + direction = 3;
+ +
+ /* Compute granularity from movement distance. + /* Compute granularity from movement distance.
+ Check if we crossed a newline → line movement (3). + Prefer robust line-range comparison for vertical movement,
+ Otherwise single char (1) or unknown (0). */ + otherwise single char (1) or unknown (0). */
+ NSInteger granularity = 0; + NSInteger granularity = 0;
+ [self ensureTextCache]; + [self ensureTextCache];
+ if (cachedText && oldPoint > 0) + if (cachedText && oldPoint > 0)
@@ -1210,22 +1224,21 @@ index 932d209..416e5a4 100644
+ granularity = 1; /* Character. */ + granularity = 1; /* Character. */
+ else + else
+ { + {
+ /* Check for line crossing by looking for newlines
+ between old and new position. */
+ NSUInteger lo = [self accessibilityIndexForCharpos:
+ MIN (oldPoint, point)];
+ NSUInteger hi = [self accessibilityIndexForCharpos:
+ MAX (oldPoint, point)];
+ NSUInteger tlen = [cachedText length]; + NSUInteger tlen = [cachedText length];
+ if (lo < tlen && hi <= tlen) + NSUInteger oldIdx = [self accessibilityIndexForCharpos:oldPoint];
+ { + NSUInteger newIdx = [self accessibilityIndexForCharpos:point];
+ NSRange searchRange = NSMakeRange (lo, hi - lo); + if (oldIdx > tlen)
+ NSRange nl = [cachedText rangeOfString:@"\n" + oldIdx = tlen;
+ options:0 + if (newIdx > tlen)
+ range:searchRange]; + newIdx = tlen;
+ if (nl.location != NSNotFound) +
+ granularity = 3; /* Line. */ + NSRange oldLine = [cachedText lineRangeForRange:
+ } + NSMakeRange (oldIdx, 0)];
+ NSRange newLine = [cachedText lineRangeForRange:
+ NSMakeRange (newIdx, 0)];
+ if (oldLine.location != newLine.location)
+ granularity = 3; /* Line. */
+
+ } + }
+ } + }
+ +
@@ -1307,19 +1320,19 @@ index 932d209..416e5a4 100644
+ } + }
+ } + }
+ +
+ /* 3) Fallback: check completions-highlight overlay span. */ + /* 3) Fallback: check completions-highlight overlay span at point. */
+ if (!announceText) + if (!announceText)
+ { + {
+ Lisp_Object faceSym = intern ("completions-highlight");
+ Lisp_Object overlays = Foverlays_at (make_fixnum (point), Qnil); + Lisp_Object overlays = Foverlays_at (make_fixnum (point), Qnil);
+ Lisp_Object tail; + Lisp_Object tail;
+ for (tail = overlays; CONSP (tail); tail = XCDR (tail)) + for (tail = overlays; CONSP (tail); tail = XCDR (tail))
+ { + {
+ Lisp_Object ov = XCAR (tail); + Lisp_Object ov = XCAR (tail);
+ Lisp_Object face = Foverlay_get (ov, Qface); + Lisp_Object face = Foverlay_get (ov, Qface);
+ if (EQ (face, intern ("completions-highlight")) + if (EQ (face, faceSym)
+ || (CONSP (face) + || (CONSP (face)
+ && !NILP (Fmemq (intern ("completions-highlight"), + && !NILP (Fmemq (faceSym, face))))
+ face))))
+ { + {
+ ptrdiff_t ov_start = OVERLAY_START (ov); + ptrdiff_t ov_start = OVERLAY_START (ov);
+ ptrdiff_t ov_end = OVERLAY_END (ov); + ptrdiff_t ov_end = OVERLAY_END (ov);
@@ -1338,6 +1351,47 @@ index 932d209..416e5a4 100644
+ } + }
+ } + }
+ +
+ /* 4) Fallback: scan for completions-highlight anywhere in buffer.
+ TAB cycling can move highlight without moving point. */
+ if (!announceText)
+ {
+ Lisp_Object faceSym = intern ("completions-highlight");
+ ptrdiff_t begv2 = BUF_BEGV (b);
+ ptrdiff_t zv2 = BUF_ZV (b);
+ ptrdiff_t scanPos;
+ BOOL found = NO;
+
+ for (scanPos = begv2; scanPos < zv2 && !found; scanPos++)
+ {
+ Lisp_Object overlays = Foverlays_at (make_fixnum (scanPos), Qnil);
+ Lisp_Object tail;
+ for (tail = overlays; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object ov = XCAR (tail);
+ Lisp_Object face = Foverlay_get (ov, Qface);
+ if (EQ (face, faceSym)
+ || (CONSP (face)
+ && !NILP (Fmemq (faceSym, face))))
+ {
+ ptrdiff_t ov_start = OVERLAY_START (ov);
+ ptrdiff_t ov_end = OVERLAY_END (ov);
+ if (ov_end > ov_start)
+ {
+ NSUInteger ax_s = [self accessibilityIndexForCharpos:
+ ov_start];
+ NSUInteger ax_e = [self accessibilityIndexForCharpos:
+ ov_end];
+ if (ax_e > ax_s && ax_e <= [cachedText length])
+ announceText = [cachedText substringWithRange:
+ NSMakeRange (ax_s, ax_e - ax_s)];
+ }
+ found = YES;
+ break;
+ }
+ }
+ }
+ }
+
+ if (b != oldb2) + if (b != oldb2)
+ set_buffer_internal_1 (oldb2); + set_buffer_internal_1 (oldb2);
+ +
@@ -1364,20 +1418,109 @@ index 932d209..416e5a4 100644
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]]; + [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if ([announceText length] > 0) + if ([announceText length] > 0)
+ { + {
+ NSDictionary *annInfo = @{ + if (![announceText isEqualToString:self.cachedCompletionAnnouncement])
+ NSAccessibilityAnnouncementKey: announceText, + {
+ NSAccessibilityPriorityKey: + NSDictionary *annInfo = @{
+ @(NSAccessibilityPriorityHigh) + NSAccessibilityAnnouncementKey: announceText,
+ }; + NSAccessibilityPriorityKey:
+ NSAccessibilityPostNotificationWithUserInfo ( + @(NSAccessibilityPriorityHigh)
+ NSApp, + };
+ NSAccessibilityAnnouncementRequestedNotification, + NSAccessibilityPostNotificationWithUserInfo (
+ annInfo); + NSApp,
+ NSAccessibilityAnnouncementRequestedNotification,
+ annInfo);
+ }
+ self.cachedCompletionAnnouncement = announceText;
+ } + }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ } + }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ } + }
+ +
+ } + }
+ else
+ {
+ if ([self isAccessibilityFocused])
+ self.cachedCompletionAnnouncement = nil;
+ else
+ {
+ [self ensureTextCache];
+ if (cachedText)
+ {
+ NSString *announceText = nil;
+ struct buffer *oldb2 = current_buffer;
+ if (b != current_buffer)
+ set_buffer_internal_1 (b);
+
+ Lisp_Object faceSym = intern ("completions-highlight");
+ ptrdiff_t begv2 = BUF_BEGV (b);
+ ptrdiff_t zv2 = BUF_ZV (b);
+ ptrdiff_t scanPos;
+ BOOL found = NO;
+
+ for (scanPos = begv2; scanPos < zv2 && !found; scanPos++)
+ {
+ Lisp_Object overlays = Foverlays_at (make_fixnum (scanPos), Qnil);
+ Lisp_Object tail;
+ for (tail = overlays; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object ov = XCAR (tail);
+ Lisp_Object face = Foverlay_get (ov, Qface);
+ if (EQ (face, faceSym)
+ || (CONSP (face)
+ && !NILP (Fmemq (faceSym, face))))
+ {
+ ptrdiff_t ov_start = OVERLAY_START (ov);
+ ptrdiff_t ov_end = OVERLAY_END (ov);
+ if (ov_end > ov_start)
+ {
+ NSUInteger ax_s = [self accessibilityIndexForCharpos:
+ ov_start];
+ NSUInteger ax_e = [self accessibilityIndexForCharpos:
+ ov_end];
+ if (ax_e > ax_s && ax_e <= [cachedText length])
+ announceText = [cachedText substringWithRange:
+ NSMakeRange (ax_s, ax_e - ax_s)];
+ }
+ found = YES;
+ break;
+ }
+ }
+ }
+
+ if (b != oldb2)
+ set_buffer_internal_1 (oldb2);
+
+ if (announceText)
+ {
+ announceText = [announceText stringByTrimmingCharactersInSet:
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if ([announceText length] > 0)
+ {
+ if (![announceText isEqualToString:self.cachedCompletionAnnouncement])
+ {
+ NSDictionary *annInfo = @{
+ NSAccessibilityAnnouncementKey: announceText,
+ NSAccessibilityPriorityKey:
+ @(NSAccessibilityPriorityHigh)
+ };
+ NSAccessibilityPostNotificationWithUserInfo (
+ NSApp,
+ NSAccessibilityAnnouncementRequestedNotification,
+ annInfo);
+ }
+ self.cachedCompletionAnnouncement = announceText;
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ }
+ }
+ }
+} +}
+ +
+@end +@end
@@ -1706,7 +1849,7 @@ index 932d209..416e5a4 100644
{ {
/* FIXME: What should happen for key sequences with more than /* FIXME: What should happen for key sequences with more than
one character? */ one character? */
@@ -8237,6 +9392,27 @@ ns_in_echo_area (void) @@ -8237,6 +9523,27 @@ ns_in_echo_area (void)
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
@@ -1734,7 +1877,7 @@ index 932d209..416e5a4 100644
} }
@@ -9474,6 +10650,297 @@ ns_in_echo_area (void) @@ -9474,6 +10781,297 @@ ns_in_echo_area (void)
return fs_state; return fs_state;
} }
@@ -2032,7 +2175,7 @@ index 932d209..416e5a4 100644
@end /* EmacsView */ @end /* EmacsView */
@@ -9941,6 +11408,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) @@ -9941,6 +11539,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return [super accessibilityAttributeValue:attribute]; return [super accessibilityAttributeValue:attribute];
} }
@@ -2047,3 +2190,6 @@ index 932d209..416e5a4 100644
#endif /* NS_IMPL_COCOA */ #endif /* NS_IMPL_COCOA */
/* Constrain size and placement of a frame. /* Constrain size and placement of a frame.
--
2.43.0