From 0c13f5d6a39e69ccff7c887583c10c889a02ec82 Mon Sep 17 00:00:00 2001 From: Daneel Date: Sun, 1 Mar 2026 09:14:52 +0100 Subject: [PATCH] =?UTF-8?q?patches:=20fix=20O(position)=20lag=20=E2=80=94?= =?UTF-8?q?=20O(1)=20fast=20path=20in=20accessibilityIndexForCharpos:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit accessibilityIndexForCharpos: walked composed character sequences from run.ax_start up to the target charpos offset. For a run covering an entire ASCII buffer, chars_in = pt - BUF_BEGV, making each call O(cursor_position). This method is called from ensureTextCache on EVERY redisplay frame (as part of the cache validity check), making each frame O(position) even when the buffer is completely unchanged. At line 34,000 of a large file this is ~1,000,000 iterations per frame. Fix: when ax_length == length for a run (all single-unit characters), the ax_index is simply ax_start + chars_in. O(1) instead of O(N). This is the symmetric counterpart to the charposForAccessibilityIndex: fast path added in the previous commit. Both conversion directions now run in O(1) for pure-ASCII buffers. --- ...fer-accessibility-element-core-proto.patch | 28 ++++++-- ...tification-dispatch-and-mode-line-el.patch | 6 +- ...ive-span-elements-for-Tab-navigation.patch | 6 +- ...essibility-with-EmacsView-and-redisp.patch | 16 ++--- ...r-accessibility-section-to-macOS-app.patch | 2 +- ...lay-completion-candidates-for-VoiceO.patch | 71 +++++++++++++------ ...d-frame-completion-candidates-for-Vo.patch | 16 ++--- 7 files changed, 94 insertions(+), 51 deletions(-) diff --git a/patches/0002-ns-implement-buffer-accessibility-element-core-proto.patch b/patches/0002-ns-implement-buffer-accessibility-element-core-proto.patch index e6d1ae1..f899260 100644 --- a/patches/0002-ns-implement-buffer-accessibility-element-core-proto.patch +++ b/patches/0002-ns-implement-buffer-accessibility-element-core-proto.patch @@ -1,4 +1,4 @@ -From 1b45f1f5ae3fe88836c8bfe60233e9a078a50641 Mon Sep 17 00:00:00 2001 +From a0c39d23ba91ee2e6a80f58ac263513326d3653c Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 12:58:11 +0100 Subject: [PATCH 2/8] ns: implement buffer accessibility element (core @@ -18,14 +18,14 @@ setAccessibilityFocused. Tested on macOS 14 with VoiceOver. Verified: buffer reading, line-by-line navigation, word/character announcements. --- - src/nsterm.m | 1112 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 1112 insertions(+) + src/nsterm.m | 1128 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 1128 insertions(+) diff --git a/src/nsterm.m b/src/nsterm.m -index e516946..4d54940 100644 +index e516946..999ca0d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m -@@ -7614,6 +7614,1118 @@ - (id)accessibilityTopLevelUIElement +@@ -7614,6 +7614,1134 @@ - (id)accessibilityTopLevelUIElement @end @@ -474,10 +474,26 @@ index e516946..4d54940 100644 + lo = mid + 1; + else + { ++<<<<<<< Updated upstream + /* Found: charpos is inside this run. Compute UTF-16 delta + directly from cachedText — no Lisp calls needed. */ ++======= ++ /* Found: charpos is inside this run. Compute UTF-16 delta. ++ Fast path for pure-ASCII runs (ax_length == length): every ++ Emacs charpos maps to exactly one UTF-16 code unit, so the ++ conversion is O(1). This matters because ensureTextCache ++ calls this method on every redisplay frame to validate the ++ cache --- a O(cursor_position) loop here means O(position) ++ cost per frame even when the buffer is unchanged. ++ Multi-byte runs fall through to the sequence walk, bounded ++ by run length (visible window), not total buffer size. */ ++>>>>>>> Stashed changes + NSUInteger chars_in = (NSUInteger)(charpos - r->charpos); -+ if (chars_in == 0 || !cachedText) ++ if (chars_in == 0) ++ return r->ax_start; ++ if (r->ax_length == (NSUInteger) r->length) ++ return r->ax_start + chars_in; ++ if (!cachedText) + return r->ax_start; + NSUInteger run_end_ax = r->ax_start + r->ax_length; + NSUInteger scan = r->ax_start; diff --git a/patches/0003-ns-add-buffer-notification-dispatch-and-mode-line-el.patch b/patches/0003-ns-add-buffer-notification-dispatch-and-mode-line-el.patch index c52121c..5c349b0 100644 --- a/patches/0003-ns-add-buffer-notification-dispatch-and-mode-line-el.patch +++ b/patches/0003-ns-add-buffer-notification-dispatch-and-mode-line-el.patch @@ -1,4 +1,4 @@ -From 545547dca37282a5a9bc858e0ccac724aa87b3d8 Mon Sep 17 00:00:00 2001 +From 683ddf23e2a4d4c981d2947d475f2c02a41ce66b Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 12:58:11 +0100 Subject: [PATCH 3/8] ns: add buffer notification dispatch and mode-line @@ -24,10 +24,10 @@ region selection feedback, completion popups, mode-line reading. 1 file changed, 545 insertions(+) diff --git a/src/nsterm.m b/src/nsterm.m -index 4d54940..a73b7f5 100644 +index 999ca0d..239666d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m -@@ -8726,6 +8726,551 @@ - (NSRect)accessibilityFrame +@@ -8742,6 +8742,551 @@ - (NSRect)accessibilityFrame @end diff --git a/patches/0004-ns-add-interactive-span-elements-for-Tab-navigation.patch b/patches/0004-ns-add-interactive-span-elements-for-Tab-navigation.patch index bb36048..139a35b 100644 --- a/patches/0004-ns-add-interactive-span-elements-for-Tab-navigation.patch +++ b/patches/0004-ns-add-interactive-span-elements-for-Tab-navigation.patch @@ -1,4 +1,4 @@ -From a1c42c0fefc4cc942884c0fe44520717742e4dba Mon Sep 17 00:00:00 2001 +From 78b8d79ec5505165d6864cc65c7b3703a57e441c Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 12:58:11 +0100 Subject: [PATCH 4/8] ns: add interactive span elements for Tab navigation @@ -17,10 +17,10 @@ Tested on macOS 14. Verified: Tab-cycling through org-mode links, 1 file changed, 286 insertions(+) diff --git a/src/nsterm.m b/src/nsterm.m -index a73b7f5..98ff027 100644 +index 239666d..94a4602 100644 --- a/src/nsterm.m +++ b/src/nsterm.m -@@ -9271,6 +9271,292 @@ - (NSRect)accessibilityFrame +@@ -9287,6 +9287,292 @@ - (NSRect)accessibilityFrame @end diff --git a/patches/0005-ns-integrate-accessibility-with-EmacsView-and-redisp.patch b/patches/0005-ns-integrate-accessibility-with-EmacsView-and-redisp.patch index 48bf467..38f1a30 100644 --- a/patches/0005-ns-integrate-accessibility-with-EmacsView-and-redisp.patch +++ b/patches/0005-ns-integrate-accessibility-with-EmacsView-and-redisp.patch @@ -1,4 +1,4 @@ -From ae1c7d6451f5a6be397f50c314e03b43b4e47b5c Mon Sep 17 00:00:00 2001 +From 7aab25d3ba9b41d3d81693b04d8d74812cad9139 Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 12:58:11 +0100 Subject: [PATCH 5/8] ns: integrate accessibility with EmacsView and redisplay @@ -51,7 +51,7 @@ index 80661a9..2b1f9e6 100644 ** Re-introduced dictation, lost in Emacs v30 (macOS). We lost macOS dictation in v30 when migrating to NSTextInputClient. diff --git a/src/nsterm.m b/src/nsterm.m -index 98ff027..0a70f3e 100644 +index 94a4602..51813b5 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1258,7 +1258,7 @@ If a completion candidate is selected (overlay or child frame), @@ -157,7 +157,7 @@ index 98ff027..0a70f3e 100644 static BOOL ns_ax_find_completion_overlay_range (struct buffer *b, ptrdiff_t point, ptrdiff_t *out_start, -@@ -8727,7 +8777,6 @@ - (NSRect)accessibilityFrame +@@ -8743,7 +8793,6 @@ - (NSRect)accessibilityFrame @end @@ -165,7 +165,7 @@ index 98ff027..0a70f3e 100644 /* =================================================================== EmacsAccessibilityBuffer (Notifications) — AX event dispatch -@@ -9272,7 +9321,6 @@ - (NSRect)accessibilityFrame +@@ -9288,7 +9337,6 @@ - (NSRect)accessibilityFrame @end @@ -173,7 +173,7 @@ index 98ff027..0a70f3e 100644 /* =================================================================== EmacsAccessibilityInteractiveSpan — helpers and implementation =================================================================== */ -@@ -9602,6 +9650,7 @@ - (void)dealloc +@@ -9618,6 +9666,7 @@ - (void)dealloc [layer release]; #endif @@ -181,7 +181,7 @@ index 98ff027..0a70f3e 100644 [[self menu] release]; [super dealloc]; } -@@ -10950,6 +10999,32 @@ - (void)windowDidBecomeKey /* for direct calls */ +@@ -10966,6 +11015,32 @@ - (void)windowDidBecomeKey /* for direct calls */ XSETFRAME (event.frame_or_window, emacsframe); kbd_buffer_store_event (&event); ns_send_appdefined (-1); // Kick main loop @@ -214,7 +214,7 @@ index 98ff027..0a70f3e 100644 } -@@ -12187,6 +12262,332 @@ - (int) fullscreenState +@@ -12203,6 +12278,332 @@ - (int) fullscreenState return fs_state; } @@ -547,7 +547,7 @@ index 98ff027..0a70f3e 100644 @end /* EmacsView */ -@@ -14187,12 +14588,17 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with +@@ -14203,12 +14604,17 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with ns_use_srgb_colorspace = YES; DEFVAR_BOOL ("ns-accessibility-enabled", ns_accessibility_enabled, diff --git a/patches/0006-doc-add-VoiceOver-accessibility-section-to-macOS-app.patch b/patches/0006-doc-add-VoiceOver-accessibility-section-to-macOS-app.patch index 12b177f..ae8ba69 100644 --- a/patches/0006-doc-add-VoiceOver-accessibility-section-to-macOS-app.patch +++ b/patches/0006-doc-add-VoiceOver-accessibility-section-to-macOS-app.patch @@ -1,4 +1,4 @@ -From 4341052ad931a98b8453368753b596e7743132b8 Mon Sep 17 00:00:00 2001 +From 0accd96937592f4e9bc95356287367f0c56e0f5b Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 12:58:11 +0100 Subject: [PATCH 6/8] doc: add VoiceOver accessibility section to macOS diff --git a/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch b/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch index 3899545..9f3c617 100644 --- a/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch +++ b/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch @@ -1,4 +1,4 @@ -From 8dd1a4cd6d3f58a3c6f9454ba1690a442c2048fe Mon Sep 17 00:00:00 2001 +From a8172542efe800cf6d29759007c9f826630da881 Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 14:46:25 +0100 Subject: [PATCH 7/8] ns: announce overlay completion candidates for VoiceOver @@ -45,8 +45,8 @@ Key implementation details: Independent overlay branch, BUF_CHARS_MODIFF gating, candidate --- src/nsterm.h | 1 + - src/nsterm.m | 332 ++++++++++++++++++++++++++++++++++++++++++++------- - 2 files changed, 290 insertions(+), 43 deletions(-) + src/nsterm.m | 352 ++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 306 insertions(+), 47 deletions(-) diff --git a/src/nsterm.h b/src/nsterm.h index 6e830de..2102fb9 100644 @@ -61,7 +61,7 @@ index 6e830de..2102fb9 100644 @property (nonatomic, assign) BOOL cachedMarkActive; @property (nonatomic, copy) NSString *cachedCompletionAnnouncement; diff --git a/src/nsterm.m b/src/nsterm.m -index 0a70f3e..c74eaf1 100644 +index 51813b5..7ce683d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -7254,11 +7254,154 @@ Accessibility virtual elements (macOS / Cocoa only) @@ -307,16 +307,43 @@ index 0a70f3e..c74eaf1 100644 NSUInteger lo = 0, hi = visibleRunCount; while (lo < hi) { -@@ -8110,7 +8245,7 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos +@@ -8109,10 +8244,6 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos + lo = mid + 1; else { - /* Found: charpos is inside this run. Compute UTF-16 delta +-<<<<<<< Updated upstream +- /* Found: charpos is inside this run. Compute UTF-16 delta - directly from cachedText — no Lisp calls needed. */ +-======= + /* Found: charpos is inside this run. Compute UTF-16 delta. + Fast path for pure-ASCII runs (ax_length == length): every + Emacs charpos maps to exactly one UTF-16 code unit, so the +@@ -8122,7 +8253,23 @@ conversion is O(1). This matters because ensureTextCache + cost per frame even when the buffer is unchanged. + Multi-byte runs fall through to the sequence walk, bounded + by run length (visible window), not total buffer size. */ +->>>>>>> Stashed changes ++ NSUInteger chars_in = (NSUInteger)(charpos - r->charpos); ++ if (chars_in == 0) ++ return r->ax_start; ++ if (r->ax_length == (NSUInteger) r->length) ++ return r->ax_start + chars_in; ++ if (!cachedText) ++ return r->ax_start; ++ NSUInteger run_end_ax = r->ax_start + r->ax_length; ++ NSUInteger scan = r->ax_start; ++ for (NSUInteger c = 0; c < chars_in && scan < run_end_ax; c++) ++ { ++ NSRange seq = [cachedText ++ rangeOfComposedCharacterSequenceAtIndex:scan]; ++ scan = NSMaxRange (seq); ++ }======= + directly from cachedText --- no Lisp calls needed. */ ++>>>>>>> 8dd1a4c (ns: announce overlay completion candidates for VoiceOver) NSUInteger chars_in = (NSUInteger)(charpos - r->charpos); - if (chars_in == 0 || !cachedText) + if (chars_in == 0) return r->ax_start; -@@ -8135,10 +8270,10 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos +@@ -8151,10 +8298,10 @@ by run length (visible window), not total buffer size. */ /* Convert accessibility string index to buffer charpos. Safe to call from any thread: uses only cachedText (NSString) and @@ -329,7 +356,7 @@ index 0a70f3e..c74eaf1 100644 @synchronized (self) { if (visibleRunCount == 0) -@@ -8180,7 +8315,7 @@ the slow path (composed character sequence walk), which is +@@ -8196,7 +8343,7 @@ the slow path (composed character sequence walk), which is return cp; } } @@ -338,7 +365,7 @@ index 0a70f3e..c74eaf1 100644 if (lo > 0) { ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1]; -@@ -8202,7 +8337,7 @@ the slow path (composed character sequence walk), which is +@@ -8218,7 +8365,7 @@ the slow path (composed character sequence walk), which is deadlocking the AX server thread. This is prevented by: 1. validWindow checks WINDOW_LIVE_P and BUFFERP before every @@ -347,7 +374,7 @@ index 0a70f3e..c74eaf1 100644 2. All dispatch_sync blocks run on the main thread where no concurrent Lisp code can modify state between checks. 3. block_input prevents timer events and process output from -@@ -8556,6 +8691,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber +@@ -8572,6 +8719,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber return [self lineForAXIndex:point_idx]; } @@ -398,7 +425,7 @@ index 0a70f3e..c74eaf1 100644 - (NSRange)accessibilityRangeForLine:(NSInteger)line { if (![NSThread isMainThread]) -@@ -8778,7 +8957,7 @@ - (NSRect)accessibilityFrame +@@ -8794,7 +8985,7 @@ - (NSRect)accessibilityFrame /* =================================================================== @@ -407,7 +434,7 @@ index 0a70f3e..c74eaf1 100644 These methods notify VoiceOver of text and selection changes. Called from the redisplay cycle (postAccessibilityUpdates). -@@ -8793,7 +8972,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point +@@ -8809,7 +9000,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point if (point > self.cachedPoint && point - self.cachedPoint == 1) { @@ -416,7 +443,7 @@ index 0a70f3e..c74eaf1 100644 [self invalidateTextCache]; [self ensureTextCache]; if (cachedText) -@@ -8812,7 +8991,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point +@@ -8828,7 +9019,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point /* Update cachedPoint here so the selection-move branch does NOT fire for point changes caused by edits. WebKit and Chromium never send both ValueChanged and SelectedTextChanged for the @@ -425,7 +452,7 @@ index 0a70f3e..c74eaf1 100644 self.cachedPoint = point; NSDictionary *change = @{ -@@ -9145,16 +9324,83 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f +@@ -9161,16 +9352,83 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f BOOL markActive = !NILP (BVAR (b, mark_active)); /* --- Text changed (edit) --- */ @@ -513,7 +540,7 @@ index 0a70f3e..c74eaf1 100644 { ptrdiff_t oldPoint = self.cachedPoint; BOOL oldMarkActive = self.cachedMarkActive; -@@ -9322,7 +9568,7 @@ - (NSRect)accessibilityFrame +@@ -9338,7 +9596,7 @@ - (NSRect)accessibilityFrame /* =================================================================== @@ -522,7 +549,7 @@ index 0a70f3e..c74eaf1 100644 =================================================================== */ /* Scan visible range of window W for interactive spans. -@@ -9530,7 +9776,7 @@ - (void) setAccessibilityFocused: (BOOL) focused +@@ -9546,7 +9804,7 @@ - (void) setAccessibilityFocused: (BOOL) focused dispatch_async (dispatch_get_main_queue (), ^{ /* lwin is a Lisp_Object captured by value. This is GC-safe because Lisp_Objects are tagged integers/pointers that @@ -531,7 +558,7 @@ index 0a70f3e..c74eaf1 100644 Emacs. The WINDOW_LIVE_P check below guards against the window being deleted between capture and execution. */ if (!WINDOWP (lwin) || NILP (Fwindow_live_p (lwin))) -@@ -9556,7 +9802,7 @@ - (void) setAccessibilityFocused: (BOOL) focused +@@ -9572,7 +9830,7 @@ - (void) setAccessibilityFocused: (BOOL) focused @end @@ -540,7 +567,7 @@ index 0a70f3e..c74eaf1 100644 Methods are kept here (same .m file) so they access the ivars declared in the @interface ivar block. */ @implementation EmacsAccessibilityBuffer (InteractiveSpans) -@@ -12278,7 +12524,7 @@ - (int) fullscreenState +@@ -12294,7 +12552,7 @@ - (int) fullscreenState if (WINDOW_LEAF_P (w)) { @@ -549,7 +576,7 @@ index 0a70f3e..c74eaf1 100644 EmacsAccessibilityBuffer *elem = [existing objectForKey:[NSValue valueWithPointer:w]]; if (!elem) -@@ -12312,7 +12558,7 @@ - (int) fullscreenState +@@ -12328,7 +12586,7 @@ - (int) fullscreenState } else { @@ -558,7 +585,7 @@ index 0a70f3e..c74eaf1 100644 Lisp_Object child = w->contents; while (!NILP (child)) { -@@ -12424,7 +12670,7 @@ - (void)postAccessibilityUpdates +@@ -12440,7 +12698,7 @@ - (void)postAccessibilityUpdates accessibilityUpdating = YES; /* Detect window tree change (split, delete, new buffer). Compare @@ -567,7 +594,7 @@ index 0a70f3e..c74eaf1 100644 Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe); if (!EQ (curRoot, lastRootWindow)) { -@@ -12433,12 +12679,12 @@ - (void)postAccessibilityUpdates +@@ -12449,12 +12707,12 @@ - (void)postAccessibilityUpdates } /* If tree is stale, rebuild FIRST so we don't iterate freed diff --git a/patches/0008-ns-announce-child-frame-completion-candidates-for-Vo.patch b/patches/0008-ns-announce-child-frame-completion-candidates-for-Vo.patch index f9ac214..8dd973d 100644 --- a/patches/0008-ns-announce-child-frame-completion-candidates-for-Vo.patch +++ b/patches/0008-ns-announce-child-frame-completion-candidates-for-Vo.patch @@ -1,4 +1,4 @@ -From 35a32f4802822ee77350a6d652aa45cca38e304c Mon Sep 17 00:00:00 2001 +From fed3a06865d403db5d25074e7473c4d7c360f917 Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 16:01:29 +0100 Subject: [PATCH 8/8] ns: announce child frame completion candidates for @@ -109,7 +109,7 @@ index 2102fb9..dd98d56 100644 @end diff --git a/src/nsterm.m b/src/nsterm.m -index c74eaf1..d2f88a5 100644 +index 7ce683d..8a1316a 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -7398,6 +7398,112 @@ visual line index for Zoom (skip whitespace-only lines @@ -268,7 +268,7 @@ index c74eaf1..d2f88a5 100644 cachedTextStart = start; if (visibleRuns) -@@ -9143,6 +9258,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b +@@ -9171,6 +9286,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b ptrdiff_t currentOverlayStart = 0; ptrdiff_t currentOverlayEnd = 0; @@ -276,7 +276,7 @@ index c74eaf1..d2f88a5 100644 specpdl_ref count2 = SPECPDL_INDEX (); record_unwind_current_buffer (); if (b != current_buffer) -@@ -9301,6 +9417,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b +@@ -9329,6 +9445,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b self.cachedCompletionOverlayEnd = 0; self.cachedCompletionPoint = 0; } @@ -284,7 +284,7 @@ index c74eaf1..d2f88a5 100644 } /* ---- Notification dispatch (main entry point) ---- */ -@@ -9897,6 +10014,10 @@ - (void)dealloc +@@ -9925,6 +10042,10 @@ - (void)dealloc #endif [accessibilityElements release]; @@ -295,7 +295,7 @@ index c74eaf1..d2f88a5 100644 [[self menu] release]; [super dealloc]; } -@@ -11346,6 +11467,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f +@@ -11374,6 +11495,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f windowClosing = NO; processingCompose = NO; @@ -305,7 +305,7 @@ index c74eaf1..d2f88a5 100644 scrollbarsNeedingUpdate = 0; fs_state = FULLSCREEN_NONE; fs_before_fs = next_maximized = -1; -@@ -12654,6 +12778,80 @@ - (id)accessibilityFocusedUIElement +@@ -12682,6 +12806,80 @@ - (id)accessibilityFocusedUIElement The existing elements carry cached state (modiff, point) from the previous redisplay cycle. Rebuilding first would create fresh elements with current values, making change detection impossible. */ @@ -386,7 +386,7 @@ index c74eaf1..d2f88a5 100644 - (void)postAccessibilityUpdates { NSTRACE ("[EmacsView postAccessibilityUpdates]"); -@@ -12664,11 +12862,59 @@ - (void)postAccessibilityUpdates +@@ -12692,11 +12890,59 @@ - (void)postAccessibilityUpdates /* Re-entrance guard: VoiceOver callbacks during notification posting can trigger redisplay, which calls ns_update_end, which calls us