Merge remote-tracking branch 'refs/remotes/origin/master'

This commit is contained in:
Martin Sukany
2026-02-26 17:51:20 +01:00

View File

@@ -1,19 +1,19 @@
From 0084027a7680cbfb1449f091312ac21ed3794a6c Mon Sep 17 00:00:00 2001
From 991ef1c9f04ccfdd71482ef3df54050f314e8ab5 Mon Sep 17 00:00:00 2001
From: Daneel <daneel@sukany.cz>
Date: Thu, 26 Feb 2026 17:30:09 +0100
Date: Thu, 26 Feb 2026 17:49:52 +0100
Subject: [PATCH] ns: implement AXBoundsForRange and VoiceOver interaction
fixes
---
nsterm.h | 68 ++
nsterm.m | 1968 +++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 1855 insertions(+), 181 deletions(-)
nsterm.h | 70 ++
nsterm.m | 2058 +++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 1960 insertions(+), 168 deletions(-)
diff --git a/src/nsterm.h b/src/nsterm.h
index 7c1ee4c..719eeba 100644
index 7c1ee4c..97da979 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -453,6 +453,59 @@ enum ns_return_frame_mode
@@ -453,6 +453,61 @@ enum ns_return_frame_mode
@end
@@ -58,6 +58,8 @@ index 7c1ee4c..719eeba 100644
+@property (nonatomic, assign) ptrdiff_t cachedPoint;
+@property (nonatomic, assign) BOOL cachedMarkActive;
+@property (nonatomic, copy) NSString *cachedCompletionAnnouncement;
+@property (nonatomic, assign) ptrdiff_t cachedCompletionOverlayStart;
+@property (nonatomic, assign) ptrdiff_t cachedCompletionOverlayEnd;
+- (void)invalidateTextCache;
+- (void)postAccessibilityNotificationsForFrame:(struct frame *)f;
+- (ptrdiff_t)charposForAccessibilityIndex:(NSUInteger)ax_idx;
@@ -73,7 +75,7 @@ index 7c1ee4c..719eeba 100644
/* ==========================================================================
The main Emacs view
@@ -471,6 +524,14 @@ enum ns_return_frame_mode
@@ -471,6 +526,14 @@ enum ns_return_frame_mode
#ifdef NS_IMPL_COCOA
char *old_title;
BOOL maximizing_resize;
@@ -88,7 +90,7 @@ index 7c1ee4c..719eeba 100644
#endif
BOOL font_panel_active;
NSFont *font_panel_result;
@@ -528,6 +589,13 @@ enum ns_return_frame_mode
@@ -528,6 +591,13 @@ enum ns_return_frame_mode
- (void)windowWillExitFullScreen;
- (void)windowDidExitFullScreen;
- (void)windowDidBecomeKey;
@@ -103,7 +105,7 @@ index 7c1ee4c..719eeba 100644
diff --git a/src/nsterm.m b/src/nsterm.m
index 932d209..336150a 100644
index 932d209..8673194 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f)
@@ -156,7 +158,7 @@ index 932d209..336150a 100644
ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -6849,261 +6885,1511 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
@@ -6849,245 +6885,1611 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
/* ==========================================================================
@@ -383,57 +385,29 @@ index 932d209..336150a 100644
}
-- (void) noteUserCancelledSelection
-{
- font_panel_active = NO;
-
- if (font_panel_result)
- [font_panel_result release];
- font_panel_result = nil;
- [NSApp stop: self];
-}
-#endif
+
+/* ---- Helper: screen rect for a character range via glyph matrix ---- */
-- (Lisp_Object) showFontPanel
+
+static NSRect
+ns_ax_frame_for_range (struct window *w, EmacsView *view,
+ ptrdiff_t text_start, NSRange range)
{
- id fm = [NSFontManager sharedFontManager];
- struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
- NSFont *nsfont, *result;
- struct timespec timeout;
-#ifdef NS_IMPL_COCOA
- NSView *buttons;
- BOOL canceled;
-#endif
- font_panel_active = NO;
+ if (!w || !w->current_matrix || !view)
+ return NSZeroRect;
-#ifdef NS_IMPL_GNUSTEP
- nsfont = ((struct nsfont_info *) font)->nsfont;
-#else
- nsfont = (NSFont *) macfont_get_nsctfont (font);
-#endif
- if (font_panel_result)
- [font_panel_result release];
- font_panel_result = nil;
+ /* Convert range indices back to buffer charpos. */
+ ptrdiff_t cp_start = text_start + (ptrdiff_t) range.location;
+ ptrdiff_t cp_end = cp_start + (ptrdiff_t) range.length;
-#ifdef NS_IMPL_COCOA
- buttons
- = ns_create_font_panel_buttons (self,
- @selector (noteUserSelectedFont),
- @selector (noteUserCancelledSelection));
- [[fm fontPanel: YES] setAccessoryView: buttons];
- [buttons release];
-#endif
- [NSApp stop: self];
+ struct glyph_matrix *matrix = w->current_matrix;
+ NSRect result = NSZeroRect;
+ BOOL found = NO;
- [fm setSelectedFont: nsfont isMultiple: NO];
- [fm orderFrontFontPanel: NSApp];
+
+ for (int i = 0; i < matrix->nrows; i++)
+ {
+ struct glyph_row *row = matrix->rows + i;
@@ -441,22 +415,10 @@ index 932d209..336150a 100644
+ continue;
+ if (!row->displays_text_p && !row->ends_at_zv_p)
+ continue;
- font_panel_active = YES;
- timeout = make_timespec (0, 100000000);
+
+ ptrdiff_t row_start = MATRIX_ROW_START_CHARPOS (row);
+ ptrdiff_t row_end = MATRIX_ROW_END_CHARPOS (row);
- block_input ();
- while (font_panel_active
-#ifdef NS_IMPL_COCOA
- && (canceled = [[fm fontPanel: YES] isVisible])
-#else
- && [[fm fontPanel: YES] isVisible]
-#endif
- )
- ns_select_1 (0, NULL, NULL, NULL, &timeout, NULL, YES);
- unblock_input ();
+
+ if (row_start < cp_end && row_end > cp_start)
+ {
+ int window_x, window_y, window_width;
@@ -479,16 +441,10 @@ index 932d209..336150a 100644
+ result = NSUnionRect (result, rowRect);
+ }
+ }
- if (font_panel_result)
- [font_panel_result autorelease];
+
+ if (!found)
+ return NSZeroRect;
-#ifdef NS_IMPL_COCOA
- if (!canceled)
- font_panel_result = nil;
-#endif
+
+ /* Clip result to text area bounds. */
+ {
+ int text_area_x, text_area_y, text_area_w, text_area_h;
@@ -498,23 +454,147 @@ index 932d209..336150a 100644
+ if (NSMaxY (result) > max_y)
+ result.size.height = max_y - result.origin.y;
+ }
- result = font_panel_result;
- font_panel_result = nil;
+
+ /* Convert from EmacsView (flipped) coords to screen coords. */
+ NSRect winRect = [view convertRect:result toView:nil];
+ return [[view window] convertRectToScreen:winRect];
}
-#endif
-- (Lisp_Object) showFontPanel
+static NSUInteger
+ns_ax_utf16_length_for_buffer_range (struct buffer *b, ptrdiff_t start,
+ ptrdiff_t end)
{
- id fm = [NSFontManager sharedFontManager];
- struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
- NSFont *nsfont, *result;
- struct timespec timeout;
-#ifdef NS_IMPL_COCOA
- NSView *buttons;
- BOOL canceled;
-#endif
+ if (!b || end <= start)
+ return 0;
-#ifdef NS_IMPL_GNUSTEP
- nsfont = ((struct nsfont_info *) font)->nsfont;
-#else
- nsfont = (NSFont *) macfont_get_nsctfont (font);
-#endif
+ struct buffer *oldb = current_buffer;
+ if (b != current_buffer)
+ set_buffer_internal_1 (b);
-#ifdef NS_IMPL_COCOA
- buttons
- = ns_create_font_panel_buttons (self,
- @selector (noteUserSelectedFont),
- @selector (noteUserCancelledSelection));
- [[fm fontPanel: YES] setAccessoryView: buttons];
- [buttons release];
-#endif
+ Lisp_Object lstr = Fbuffer_substring_no_properties (make_fixnum (start),
+ make_fixnum (end));
+ NSString *nsstr = [NSString stringWithLispString:lstr];
+ NSUInteger len = [nsstr length];
- [fm setSelectedFont: nsfont isMultiple: NO];
- [fm orderFrontFontPanel: NSApp];
+ if (b != oldb)
+ set_buffer_internal_1 (oldb);
- font_panel_active = YES;
- timeout = make_timespec (0, 100000000);
+ return len;
+}
- block_input ();
- while (font_panel_active
-#ifdef NS_IMPL_COCOA
- && (canceled = [[fm fontPanel: YES] isVisible])
-#else
- && [[fm fontPanel: YES] isVisible]
-#endif
- )
- ns_select_1 (0, NULL, NULL, NULL, &timeout, NULL, YES);
- unblock_input ();
+static BOOL
+ns_ax_find_completion_overlay_range (struct buffer *b, ptrdiff_t point,
+ ptrdiff_t *out_start,
+ ptrdiff_t *out_end)
+{
+ if (!b || !out_start || !out_end)
+ return NO;
- if (font_panel_result)
- [font_panel_result autorelease];
+ Lisp_Object faceSym = intern ("completions-highlight");
+ ptrdiff_t begv = BUF_BEGV (b);
+ ptrdiff_t zv = BUF_ZV (b);
+ ptrdiff_t best_start = 0;
+ ptrdiff_t best_end = 0;
+ ptrdiff_t best_dist = PTRDIFF_MAX;
+ BOOL found = NO;
-#ifdef NS_IMPL_COCOA
- if (!canceled)
- font_panel_result = nil;
-#endif
+ for (ptrdiff_t scan = begv; scan < zv; scan++)
+ {
+ Lisp_Object overlays = Foverlays_at (make_fixnum (scan), 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)))))
+ continue;
+
+ ptrdiff_t ov_start = OVERLAY_START (ov);
+ ptrdiff_t ov_end = OVERLAY_END (ov);
+ if (ov_end <= ov_start)
+ continue;
+
+ ptrdiff_t dist = 0;
+ if (point < ov_start)
+ dist = ov_start - point;
+ else if (point > ov_end)
+ dist = point - ov_end;
+
+ if (!found || dist < best_dist
+ || (dist == best_dist
+ && (ov_start < point && best_start >= point)))
+ {
+ best_start = ov_start;
+ best_end = ov_end;
+ best_dist = dist;
+ found = YES;
+ }
+ }
+ }
- result = font_panel_result;
- font_panel_result = nil;
+ if (!found)
+ return NO;
- [[fm fontPanel: YES] setIsVisible: NO];
- font_panel_active = NO;
+ *out_start = best_start;
+ *out_end = best_end;
+ return YES;
+}
- if (result)
- return ns_font_desc_to_font_spec ([result fontDescriptor],
- result);
+@implementation EmacsAccessibilityElement
- return Qnil;
+@implementation EmacsAccessibilityElement
+
+- (NSRect)screenRectFromEmacsX:(int)x y:(int)y width:(int)ew height:(int)eh
+{
+ EmacsView *view = self.emacsView;
@@ -581,6 +661,8 @@ index 932d209..336150a 100644
+@synthesize cachedPoint;
+@synthesize cachedMarkActive;
+@synthesize cachedCompletionAnnouncement;
+@synthesize cachedCompletionOverlayStart;
+@synthesize cachedCompletionOverlayEnd;
+- (void)dealloc
+{
@@ -650,41 +732,43 @@ index 932d209..336150a 100644
- most recently updated (I guess), which is not the correct one. */
- [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
- return;
- }
+ ptrdiff_t start;
+ ns_ax_visible_run *runs = NULL;
+ NSUInteger nruns = 0;
+ NSString *text = ns_ax_buffer_text (w, &start, &runs, &nruns);
- if (nsEvArray == nil)
- nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
+
+ [cachedText release];
+ cachedText = [text retain];
+ cachedTextModiff = modiff;
+ cachedTextStart = start;
- [NSCursor setHiddenUntilMouseMoves:! NILP (Vmake_pointer_invisible)];
+
+ if (visibleRuns)
+ xfree (visibleRuns);
+ visibleRuns = runs;
+ visibleRunCount = nruns;
+}
- if (!hlinfo->mouse_face_hidden
- && FIXNUMP (Vmouse_highlight)
- && !EQ (emacsframe->tab_bar_window, hlinfo->mouse_face_window))
+
+/* ---- Index mapping ---- */
+
+/* Convert buffer charpos to accessibility string index. */
+- (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos
+{
+ struct window *w = self.emacsWindow;
+ struct buffer *b = (w && WINDOW_LEAF_P (w)) ? XBUFFER (w->contents) : NULL;
+
+ for (NSUInteger i = 0; i < visibleRunCount; i++)
{
- clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = true;
+ {
+ ns_ax_visible_run *r = &visibleRuns[i];
+ if (charpos >= r->charpos && charpos < r->charpos + r->length)
+ return r->ax_start + (NSUInteger) (charpos - r->charpos);
+ {
+ if (!b)
+ return r->ax_start;
+ NSUInteger delta = ns_ax_utf16_length_for_buffer_range (b, r->charpos,
+ charpos);
+ if (delta > r->ax_length)
+ delta = r->ax_length;
+ return r->ax_start + delta;
+ }
+ /* If charpos falls in an invisible gap before the next run,
+ map it to the start of the next visible run. */
+ if (charpos < r->charpos)
@@ -695,20 +779,43 @@ index 932d209..336150a 100644
+ {
+ ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1];
+ return last->ax_start + last->ax_length;
}
+ }
+ return 0;
+}
- if (!processingCompose)
+
+/* Convert accessibility string index to buffer charpos. */
+- (ptrdiff_t)charposForAccessibilityIndex:(NSUInteger)ax_idx
+{
+ struct window *w = self.emacsWindow;
+ struct buffer *b = (w && WINDOW_LEAF_P (w)) ? XBUFFER (w->contents) : NULL;
+
+ for (NSUInteger i = 0; i < visibleRunCount; i++)
+ {
+ ns_ax_visible_run *r = &visibleRuns[i];
+ if (ax_idx >= r->ax_start
+ && ax_idx < r->ax_start + r->ax_length)
+ return r->charpos + (ptrdiff_t) (ax_idx - r->ax_start);
+ {
+ if (!b)
+ return r->charpos;
+
+ NSUInteger target = ax_idx - r->ax_start;
+ ptrdiff_t lo = r->charpos;
+ ptrdiff_t hi = r->charpos + r->length;
+
+ while (lo < hi)
+ {
+ ptrdiff_t mid = lo + (hi - lo) / 2;
+ NSUInteger mid_len = ns_ax_utf16_length_for_buffer_range (b,
+ r->charpos,
+ mid);
+ if (mid_len < target)
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+
+ return lo;
+ }
+ }
+ /* Past end — return last charpos. */
+ if (visibleRunCount > 0)
@@ -850,7 +957,7 @@ index 932d209..336150a 100644
+
+ SET_PT_BOTH (charpos, CHAR_TO_BYTE (charpos));
+
+ /* If range has nonzero length, activate the mark. */
+ /* Keep mark state aligned with requested selection range. */
+ if (range.length > 0)
+ {
+ ptrdiff_t mark_charpos = [self charposForAccessibilityIndex:
@@ -859,7 +966,10 @@ index 932d209..336150a 100644
+ mark_charpos = BUF_ZV (b);
+ Fset_marker (BVAR (b, mark), make_fixnum (mark_charpos),
+ Fcurrent_buffer ());
+ bset_mark_active (b, Qt);
+ }
+ else
+ bset_mark_active (b, Qnil);
+
+ if (b != oldb)
+ set_buffer_internal_1 (oldb);
@@ -869,6 +979,7 @@ index 932d209..336150a 100644
+ /* Update cached state so the next notification cycle doesn't
+ re-announce this movement. */
+ self.cachedPoint = charpos;
+ self.cachedMarkActive = (range.length > 0);
+}
+
+- (void)setAccessibilityFocused:(BOOL)flag
@@ -1264,6 +1375,8 @@ index 932d209..336150a 100644
+ if (![self isAccessibilityFocused] && cachedText)
+ {
+ NSString *announceText = nil;
+ ptrdiff_t currentOverlayStart = 0;
+ ptrdiff_t currentOverlayEnd = 0;
+
+ struct buffer *oldb2 = current_buffer;
+ if (b != current_buffer)
@@ -1351,43 +1464,22 @@ index 932d209..336150a 100644
+ }
+ }
+
+ /* 4) Fallback: scan for completions-highlight anywhere in buffer.
+ TAB cycling can move highlight without moving point. */
+ /* 4) Fallback: select the best completions-highlight overlay.
+ Prefer overlay nearest to point over first-found in buffer. */
+ 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++)
+ ptrdiff_t ov_start = 0;
+ ptrdiff_t ov_end = 0;
+ if (ns_ax_find_completion_overlay_range (b, point, &ov_start, &ov_end))
+ {
+ Lisp_Object overlays = Foverlays_at (make_fixnum (scanPos), Qnil);
+ Lisp_Object tail;
+ for (tail = overlays; CONSP (tail); tail = XCDR (tail))
+ NSUInteger ax_s = [self accessibilityIndexForCharpos:ov_start];
+ NSUInteger ax_e = [self accessibilityIndexForCharpos:ov_end];
+ if (ax_e > ax_s && ax_e <= [cachedText length])
+ {
+ 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;
+ }
+ announceText = [cachedText substringWithRange:
+ NSMakeRange (ax_s, ax_e - ax_s)];
+ currentOverlayStart = ov_start;
+ currentOverlayEnd = ov_end;
+ }
+ }
+ }
@@ -1418,7 +1510,12 @@ index 932d209..336150a 100644
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if ([announceText length] > 0)
+ {
+ if (![announceText isEqualToString:self.cachedCompletionAnnouncement])
+ BOOL textChanged = ![announceText isEqualToString:
+ self.cachedCompletionAnnouncement];
+ BOOL overlayChanged =
+ (currentOverlayStart != self.cachedCompletionOverlayStart
+ || currentOverlayEnd != self.cachedCompletionOverlayEnd);
+ if (textChanged || overlayChanged)
+ {
+ NSDictionary *annInfo = @{
+ NSAccessibilityAnnouncementKey: announceText,
@@ -1431,63 +1528,56 @@ index 932d209..336150a 100644
+ annInfo);
+ }
+ self.cachedCompletionAnnouncement = announceText;
+ self.cachedCompletionOverlayStart = currentOverlayStart;
+ self.cachedCompletionOverlayEnd = currentOverlayEnd;
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ {
+ self.cachedCompletionAnnouncement = nil;
+ self.cachedCompletionOverlayStart = 0;
+ self.cachedCompletionOverlayEnd = 0;
+ }
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ {
+ self.cachedCompletionAnnouncement = nil;
+ self.cachedCompletionOverlayStart = 0;
+ self.cachedCompletionOverlayEnd = 0;
+ }
+ }
+
+ }
+ else
+ {
+ if ([self isAccessibilityFocused])
+ self.cachedCompletionAnnouncement = nil;
+ {
+ self.cachedCompletionAnnouncement = nil;
+ self.cachedCompletionOverlayStart = 0;
+ self.cachedCompletionOverlayEnd = 0;
+ }
+ else
+ {
+ [self ensureTextCache];
+ if (cachedText)
+ {
+ NSString *announceText = nil;
+ ptrdiff_t currentOverlayStart = 0;
+ ptrdiff_t currentOverlayEnd = 0;
+ 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++)
+ if (ns_ax_find_completion_overlay_range (b, point,
+ &currentOverlayStart,
+ &currentOverlayEnd))
+ {
+ 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;
+ }
+ }
+ NSUInteger ax_s = [self accessibilityIndexForCharpos:
+ currentOverlayStart];
+ NSUInteger ax_e = [self accessibilityIndexForCharpos:
+ currentOverlayEnd];
+ if (ax_e > ax_s && ax_e <= [cachedText length])
+ announceText = [cachedText substringWithRange:
+ NSMakeRange (ax_s, ax_e - ax_s)];
+ }
+
+ if (b != oldb2)
@@ -1499,7 +1589,12 @@ index 932d209..336150a 100644
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if ([announceText length] > 0)
+ {
+ if (![announceText isEqualToString:self.cachedCompletionAnnouncement])
+ BOOL textChanged = ![announceText isEqualToString:
+ self.cachedCompletionAnnouncement];
+ BOOL overlayChanged =
+ (currentOverlayStart != self.cachedCompletionOverlayStart
+ || currentOverlayEnd != self.cachedCompletionOverlayEnd);
+ if (textChanged || overlayChanged)
+ {
+ NSDictionary *annInfo = @{
+ NSAccessibilityAnnouncementKey: announceText,
@@ -1512,12 +1607,22 @@ index 932d209..336150a 100644
+ annInfo);
+ }
+ self.cachedCompletionAnnouncement = announceText;
+ self.cachedCompletionOverlayStart = currentOverlayStart;
+ self.cachedCompletionOverlayEnd = currentOverlayEnd;
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ {
+ self.cachedCompletionAnnouncement = nil;
+ self.cachedCompletionOverlayStart = 0;
+ self.cachedCompletionOverlayEnd = 0;
+ }
+ }
+ else
+ self.cachedCompletionAnnouncement = nil;
+ {
+ self.cachedCompletionAnnouncement = nil;
+ self.cachedCompletionOverlayStart = 0;
+ self.cachedCompletionOverlayEnd = 0;
+ }
+ }
+ }
+ }
@@ -1830,26 +1935,10 @@ index 932d209..336150a 100644
+ most recently updated (I guess), which is not the correct one. */
+ [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
+ return;
+ }
+
+ if (nsEvArray == nil)
+ nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
+
+ [NSCursor setHiddenUntilMouseMoves:! NILP (Vmake_pointer_invisible)];
+
+ if (!hlinfo->mouse_face_hidden
+ && FIXNUMP (Vmouse_highlight)
+ && !EQ (emacsframe->tab_bar_window, hlinfo->mouse_face_window))
+ {
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_hidden = true;
+ }
+
+ if (!processingCompose)
{
/* FIXME: What should happen for key sequences with more than
one character? */
@@ -8237,6 +9523,27 @@ ns_in_echo_area (void)
}
if (nsEvArray == nil)
@@ -8237,6 +9639,27 @@ ns_in_echo_area (void)
XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop
@@ -1877,7 +1966,7 @@ index 932d209..336150a 100644
}
@@ -9474,6 +10781,297 @@ ns_in_echo_area (void)
@@ -9474,6 +10897,297 @@ ns_in_echo_area (void)
return fs_state;
}
@@ -2175,7 +2264,7 @@ index 932d209..336150a 100644
@end /* EmacsView */
@@ -9941,6 +11539,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
@@ -9941,6 +11655,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return [super accessibilityAttributeValue:attribute];
}