patches: update VoiceOver patch (v15.9 candidate)
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user