Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
@@ -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))
|
||||
+ {
|
||||
+ 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];
|
||||
+ 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;
|
||||
+ }
|
||||
+ 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,64 +1528,57 @@ index 932d209..336150a 100644
|
||||
+ annInfo);
|
||||
+ }
|
||||
+ self.cachedCompletionAnnouncement = announceText;
|
||||
+ self.cachedCompletionOverlayStart = currentOverlayStart;
|
||||
+ self.cachedCompletionOverlayEnd = currentOverlayEnd;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ self.cachedCompletionAnnouncement = nil;
|
||||
+ self.cachedCompletionOverlayStart = 0;
|
||||
+ self.cachedCompletionOverlayEnd = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ self.cachedCompletionAnnouncement = nil;
|
||||
+ self.cachedCompletionOverlayStart = 0;
|
||||
+ self.cachedCompletionOverlayEnd = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if ([self isAccessibilityFocused])
|
||||
+ {
|
||||
+ 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++)
|
||||
+ {
|
||||
+ 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)
|
||||
+ if (ns_ax_find_completion_overlay_range (b, point,
|
||||
+ ¤tOverlayStart,
|
||||
+ ¤tOverlayEnd))
|
||||
+ {
|
||||
+ NSUInteger ax_s = [self accessibilityIndexForCharpos:
|
||||
+ ov_start];
|
||||
+ currentOverlayStart];
|
||||
+ NSUInteger ax_e = [self accessibilityIndexForCharpos:
|
||||
+ ov_end];
|
||||
+ currentOverlayEnd];
|
||||
+ 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);
|
||||
@@ -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.cachedCompletionOverlayStart = 0;
|
||||
+ self.cachedCompletionOverlayEnd = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ 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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user