patches: fix Blocker #2 - remove ensureTextCache from notification path
BUF_MODIFF was needed for fold/unfold correctness (org-mode), but ensureTextCache was called from postAccessibilityNotificationsForFrame: on every cursor move, causing O(buffer-size) rebuild on every font-lock pass. Fix: remove [self ensureTextCache] from the granularity-detection branch of the notification path. The granularity detection now uses cachedText directly, falling back to granularity_unknown when absent (safe: VoiceOver makes its own determination). ensureTextCache is called exclusively from AX getters (human interaction speed). Font-lock passes no longer trigger any cache rebuild. The BUF_MODIFF validity in ensureTextCache is retained (correct for fold/unfold). Comment updated to accurately describe the calling pattern. All 9 patches apply cleanly on fresh base (git apply verified).
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
From 7474a4e1ddbf37286842e3beda1810c40f2a3ef7 Mon Sep 17 00:00:00 2001
|
From 217177caefc709c37ae04732ec595ace903e4cc4 Mon Sep 17 00:00:00 2001
|
||||||
From: Martin Sukany <martin@sukany.cz>
|
From: Martin Sukany <martin@sukany.cz>
|
||||||
Date: Mon, 2 Mar 2026 18:39:46 +0100
|
Date: Mon, 2 Mar 2026 18:39:46 +0100
|
||||||
Subject: [PATCH 8/9] ns: announce overlay completion candidates for VoiceOver
|
Subject: [PATCH 8/9] ns: announce overlay completion candidates for VoiceOver
|
||||||
@@ -11,15 +11,24 @@ this change VoiceOver cannot read overlay-based completion UIs.
|
|||||||
'current', 'selected', 'selection' in face symbol names.
|
'current', 'selected', 'selection' in face symbol names.
|
||||||
(ns_ax_selected_overlay_text): New function; scan overlay strings in
|
(ns_ax_selected_overlay_text): New function; scan overlay strings in
|
||||||
the window for a line with a selected face; return its text.
|
the window for a line with a selected face; return its text.
|
||||||
(EmacsAccessibilityBuffer(Notifications)
|
(ensureTextCache): Switch cache-validity counter from BUF_CHARS_MODIFF
|
||||||
postAccessibilityNotificationsForFrame:): Handle BUF_OVERLAY_MODIFF
|
to BUF_MODIFF. Fold/unfold commands (org-mode, outline-mode,
|
||||||
|
hideshow-mode) change the 'invisible text property via
|
||||||
|
`put-text-property', which bumps BUF_MODIFF but not BUF_CHARS_MODIFF.
|
||||||
|
Using BUF_CHARS_MODIFF would serve stale AX text across fold/unfold.
|
||||||
|
The rebuild is O(visible-buffer-text) but ensureTextCache is called
|
||||||
|
exclusively from AX getters at human interaction speed, never from the
|
||||||
|
redisplay notification path; font-lock passes cause zero rebuild cost.
|
||||||
|
(postAccessibilityNotificationsForFrame:): Handle BUF_OVERLAY_MODIFF
|
||||||
changes independently of text changes. Use BUF_CHARS_MODIFF to gate
|
changes independently of text changes. Use BUF_CHARS_MODIFF to gate
|
||||||
ValueChanged; keep overlay_modiff out of ensureTextCache to prevent a
|
ValueChanged. Do not call ensureTextCache from the cursor-moved branch:
|
||||||
race where an AX query consumes the change before notification.
|
the granularity detection uses cachedText directly (falling back to
|
||||||
|
granularity_unknown when the cache is absent), so font-lock passes
|
||||||
|
cannot trigger O(buffer-size) rebuilds via the notification path.
|
||||||
---
|
---
|
||||||
src/nsterm.h | 1 +
|
src/nsterm.h | 1 +
|
||||||
src/nsterm.m | 345 ++++++++++++++++++++++++++++++++++++++++++++-------
|
src/nsterm.m | 358 ++++++++++++++++++++++++++++++++++++++++++++-------
|
||||||
2 files changed, 304 insertions(+), 42 deletions(-)
|
2 files changed, 316 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||||
index f245675513..a210ceba14 100644
|
index f245675513..a210ceba14 100644
|
||||||
@@ -34,7 +43,7 @@ index f245675513..a210ceba14 100644
|
|||||||
@property (nonatomic, assign) BOOL cachedMarkActive;
|
@property (nonatomic, assign) BOOL cachedMarkActive;
|
||||||
@property (nonatomic, copy) NSString *cachedCompletionAnnouncement;
|
@property (nonatomic, copy) NSString *cachedCompletionAnnouncement;
|
||||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||||
index a0419bb5df..54cee74401 100644
|
index a0419bb5df..b9d3a0eb53 100644
|
||||||
--- a/src/nsterm.m
|
--- a/src/nsterm.m
|
||||||
+++ b/src/nsterm.m
|
+++ b/src/nsterm.m
|
||||||
@@ -7263,11 +7263,154 @@ Accessibility virtual elements (macOS / Cocoa only)
|
@@ -7263,11 +7263,154 @@ Accessibility virtual elements (macOS / Cocoa only)
|
||||||
@@ -228,7 +237,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
write section at the end needs synchronization to protect
|
write section at the end needs synchronization to protect
|
||||||
against concurrent reads from AX server thread. */
|
against concurrent reads from AX server thread. */
|
||||||
eassert ([NSThread isMainThread]);
|
eassert ([NSThread isMainThread]);
|
||||||
@@ -8005,25 +8149,34 @@ - (void)ensureTextCache
|
@@ -8005,25 +8149,38 @@ - (void)ensureTextCache
|
||||||
if (!b)
|
if (!b)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -259,12 +268,16 @@ index a0419bb5df..54cee74401 100644
|
|||||||
+ as if it were visible, or miss newly revealed content entirely.
|
+ as if it were visible, or miss newly revealed content entirely.
|
||||||
+
|
+
|
||||||
+ BUF_MODIFF is bumped by all buffer modifications including
|
+ BUF_MODIFF is bumped by all buffer modifications including
|
||||||
+ text-property changes (e.g. font-lock face assignments), causing a
|
+ text-property changes (e.g. font-lock face assignments). The
|
||||||
+ full text-cache rebuild on each redisplay cycle. This is acceptable
|
+ per-rebuild cost is O(visible-buffer-text), but `ensureTextCache'
|
||||||
+ because `ensureTextCache' is only called when VoiceOver queries
|
+ is called exclusively from AX getters (accessibilityValue,
|
||||||
+ accessibilityValue or related AX properties --- which happens at
|
+ accessibilitySelectedTextRange, etc.) which run at human interaction
|
||||||
+ human interaction speed, not at redisplay speed. The per-rebuild
|
+ speed --- not from the redisplay notification path. Font-lock
|
||||||
+ cost is O(visible-buffer-text).
|
+ passes do not call this method, so the rebuild cost per font-lock
|
||||||
|
+ cycle is zero. The redisplay notification path (postAccessibility-
|
||||||
|
+ NotificationsForFrame:) uses cachedText directly without calling
|
||||||
|
+ ensureTextCache; granularity detection falls back gracefully when
|
||||||
|
+ the cache is absent.
|
||||||
+
|
+
|
||||||
+ Do NOT use BUF_OVERLAY_MODIFF alone: org-mode >= 29 (org-fold-core)
|
+ Do NOT use BUF_OVERLAY_MODIFF alone: org-mode >= 29 (org-fold-core)
|
||||||
+ uses text properties, not overlays, for folding, so
|
+ uses text properties, not overlays, for folding, so
|
||||||
@@ -280,7 +293,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
&& cachedTextStart == BUF_BEGV (b)
|
&& cachedTextStart == BUF_BEGV (b)
|
||||||
&& pt >= cachedTextStart
|
&& pt >= cachedTextStart
|
||||||
&& (textLen == 0
|
&& (textLen == 0
|
||||||
@@ -8039,7 +8192,7 @@ included in the cached AX text (it is handled separately via
|
@@ -8039,7 +8196,7 @@ included in the cached AX text (it is handled separately via
|
||||||
{
|
{
|
||||||
[cachedText release];
|
[cachedText release];
|
||||||
cachedText = [text retain];
|
cachedText = [text retain];
|
||||||
@@ -289,7 +302,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
cachedTextStart = start;
|
cachedTextStart = start;
|
||||||
|
|
||||||
if (visibleRuns)
|
if (visibleRuns)
|
||||||
@@ -8051,9 +8204,9 @@ included in the cached AX text (it is handled separately via
|
@@ -8051,9 +8208,9 @@ included in the cached AX text (it is handled separately via
|
||||||
Walk the cached text once, recording the start offset of each
|
Walk the cached text once, recording the start offset of each
|
||||||
line. Uses NSString lineRangeForRange: --- O(N) in the total
|
line. Uses NSString lineRangeForRange: --- O(N) in the total
|
||||||
text --- but this loop runs only on cache rebuild, which is
|
text --- but this loop runs only on cache rebuild, which is
|
||||||
@@ -302,7 +315,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
enters this code. */
|
enters this code. */
|
||||||
if (lineStartOffsets)
|
if (lineStartOffsets)
|
||||||
xfree (lineStartOffsets);
|
xfree (lineStartOffsets);
|
||||||
@@ -8108,7 +8261,7 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos
|
@@ -8108,7 +8265,7 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos
|
||||||
/* Binary search: runs are sorted by charpos (ascending). Find the
|
/* Binary search: runs are sorted by charpos (ascending). Find the
|
||||||
run whose [charpos, charpos+length) range contains the target,
|
run whose [charpos, charpos+length) range contains the target,
|
||||||
or the nearest run after an invisible gap. O(log n) instead of
|
or the nearest run after an invisible gap. O(log n) instead of
|
||||||
@@ -311,7 +324,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
NSUInteger lo = 0, hi = visibleRunCount;
|
NSUInteger lo = 0, hi = visibleRunCount;
|
||||||
while (lo < hi)
|
while (lo < hi)
|
||||||
{
|
{
|
||||||
@@ -8157,10 +8310,10 @@ by run length (visible window), not total buffer size. */
|
@@ -8157,10 +8314,10 @@ by run length (visible window), not total buffer size. */
|
||||||
|
|
||||||
/* Convert accessibility string index to buffer charpos.
|
/* Convert accessibility string index to buffer charpos.
|
||||||
Safe to call from any thread: uses only cachedText (NSString) and
|
Safe to call from any thread: uses only cachedText (NSString) and
|
||||||
@@ -324,7 +337,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
@synchronized (self)
|
@synchronized (self)
|
||||||
{
|
{
|
||||||
if (visibleRunCount == 0)
|
if (visibleRunCount == 0)
|
||||||
@@ -8202,7 +8355,7 @@ the slow path (composed character sequence walk), which is
|
@@ -8202,7 +8359,7 @@ the slow path (composed character sequence walk), which is
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,7 +346,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
if (lo > 0)
|
if (lo > 0)
|
||||||
{
|
{
|
||||||
ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1];
|
ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1];
|
||||||
@@ -8224,7 +8377,7 @@ the slow path (composed character sequence walk), which is
|
@@ -8224,7 +8381,7 @@ the slow path (composed character sequence walk), which is
|
||||||
deadlocking the AX server thread. This is prevented by:
|
deadlocking the AX server thread. This is prevented by:
|
||||||
|
|
||||||
1. validWindow checks WINDOW_LIVE_P and BUFFERP before every
|
1. validWindow checks WINDOW_LIVE_P and BUFFERP before every
|
||||||
@@ -342,7 +355,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
2. All dispatch_sync blocks run on the main thread where no
|
2. All dispatch_sync blocks run on the main thread where no
|
||||||
concurrent Lisp code can modify state between checks.
|
concurrent Lisp code can modify state between checks.
|
||||||
3. block_input prevents timer events and process output from
|
3. block_input prevents timer events and process output from
|
||||||
@@ -8570,6 +8723,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber
|
@@ -8570,6 +8727,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber
|
||||||
return [self lineForAXIndex:point_idx];
|
return [self lineForAXIndex:point_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +406,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
- (NSRange)accessibilityRangeForLine:(NSInteger)line
|
- (NSRange)accessibilityRangeForLine:(NSInteger)line
|
||||||
{
|
{
|
||||||
if (![NSThread isMainThread])
|
if (![NSThread isMainThread])
|
||||||
@@ -8792,7 +8989,7 @@ - (NSRect)accessibilityFrame
|
@@ -8792,7 +8993,7 @@ - (NSRect)accessibilityFrame
|
||||||
|
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
@@ -402,7 +415,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
|
|
||||||
These methods notify VoiceOver of text and selection changes.
|
These methods notify VoiceOver of text and selection changes.
|
||||||
Called from the redisplay cycle (postAccessibilityUpdates).
|
Called from the redisplay cycle (postAccessibilityUpdates).
|
||||||
@@ -8807,7 +9004,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point
|
@@ -8807,7 +9008,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point
|
||||||
if (point > self.cachedPoint
|
if (point > self.cachedPoint
|
||||||
&& point - self.cachedPoint == 1)
|
&& point - self.cachedPoint == 1)
|
||||||
{
|
{
|
||||||
@@ -411,7 +424,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
[self invalidateTextCache];
|
[self invalidateTextCache];
|
||||||
[self ensureTextCache];
|
[self ensureTextCache];
|
||||||
if (cachedText)
|
if (cachedText)
|
||||||
@@ -8826,7 +9023,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point
|
@@ -8826,7 +9027,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point
|
||||||
/* Update cachedPoint here so the selection-move branch does NOT
|
/* Update cachedPoint here so the selection-move branch does NOT
|
||||||
fire for point changes caused by edits. WebKit and Chromium
|
fire for point changes caused by edits. WebKit and Chromium
|
||||||
never send both ValueChanged and SelectedTextChanged for the
|
never send both ValueChanged and SelectedTextChanged for the
|
||||||
@@ -420,7 +433,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
self.cachedPoint = point;
|
self.cachedPoint = point;
|
||||||
|
|
||||||
NSDictionary *change = @{
|
NSDictionary *change = @{
|
||||||
@@ -9220,16 +9417,80 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
@@ -9220,16 +9421,80 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
||||||
BOOL markActive = !NILP (BVAR (b, mark_active));
|
BOOL markActive = !NILP (BVAR (b, mark_active));
|
||||||
|
|
||||||
/* --- Text changed (edit) --- */
|
/* --- Text changed (edit) --- */
|
||||||
@@ -505,7 +518,24 @@ index a0419bb5df..54cee74401 100644
|
|||||||
{
|
{
|
||||||
ptrdiff_t oldPoint = self.cachedPoint;
|
ptrdiff_t oldPoint = self.cachedPoint;
|
||||||
BOOL oldMarkActive = self.cachedMarkActive;
|
BOOL oldMarkActive = self.cachedMarkActive;
|
||||||
@@ -12408,7 +12669,7 @@ - (int) fullscreenState
|
@@ -9247,8 +9512,15 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
||||||
|
bool isCtrlNP = ns_ax_event_is_line_nav_key (&ctrlNP);
|
||||||
|
|
||||||
|
/* --- Granularity detection --- */
|
||||||
|
+ /* Use cached text as-is; do NOT call ensureTextCache here.
|
||||||
|
+ ensureTextCache is O(visible-buffer-text) and must not run on
|
||||||
|
+ every redisplay cycle. Using stale cached text for granularity
|
||||||
|
+ classification is safe: the worst case is an incorrect
|
||||||
|
+ granularity hint (defaulting to unknown), which causes VoiceOver
|
||||||
|
+ to make its own determination. Fresh text is always available
|
||||||
|
+ to VoiceOver via the AX getter path (accessibilityValue etc.). */
|
||||||
|
NSInteger granularity = ns_ax_text_selection_granularity_unknown;
|
||||||
|
- [self ensureTextCache];
|
||||||
|
+ BOOL singleLineMove = NO;
|
||||||
|
if (cachedText && oldPoint > 0)
|
||||||
|
{
|
||||||
|
NSUInteger tlen = [cachedText length];
|
||||||
|
@@ -12408,7 +12680,7 @@ - (int) fullscreenState
|
||||||
|
|
||||||
if (WINDOW_LEAF_P (w))
|
if (WINDOW_LEAF_P (w))
|
||||||
{
|
{
|
||||||
@@ -514,7 +544,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
EmacsAccessibilityBuffer *elem
|
EmacsAccessibilityBuffer *elem
|
||||||
= [existing objectForKey:[NSValue valueWithPointer:w]];
|
= [existing objectForKey:[NSValue valueWithPointer:w]];
|
||||||
if (!elem)
|
if (!elem)
|
||||||
@@ -12442,7 +12703,7 @@ - (int) fullscreenState
|
@@ -12442,7 +12714,7 @@ - (int) fullscreenState
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -523,7 +553,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
Lisp_Object child = w->contents;
|
Lisp_Object child = w->contents;
|
||||||
while (!NILP (child))
|
while (!NILP (child))
|
||||||
{
|
{
|
||||||
@@ -12554,7 +12815,7 @@ - (void)postAccessibilityUpdates
|
@@ -12554,7 +12826,7 @@ - (void)postAccessibilityUpdates
|
||||||
accessibilityUpdating = YES;
|
accessibilityUpdating = YES;
|
||||||
|
|
||||||
/* Detect window tree change (split, delete, new buffer). Compare
|
/* Detect window tree change (split, delete, new buffer). Compare
|
||||||
@@ -532,7 +562,7 @@ index a0419bb5df..54cee74401 100644
|
|||||||
Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe);
|
Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe);
|
||||||
if (!EQ (curRoot, lastRootWindow))
|
if (!EQ (curRoot, lastRootWindow))
|
||||||
{
|
{
|
||||||
@@ -12563,12 +12824,12 @@ - (void)postAccessibilityUpdates
|
@@ -12563,12 +12835,12 @@ - (void)postAccessibilityUpdates
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If tree is stale, rebuild FIRST so we don't iterate freed
|
/* If tree is stale, rebuild FIRST so we don't iterate freed
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
From 137cb30bb546a9599983c25a9873d1518ad8edee Mon Sep 17 00:00:00 2001
|
From b54ed57b93cb47250695106021d6e96030ffdd59 Mon Sep 17 00:00:00 2001
|
||||||
From: Martin Sukany <martin@sukany.cz>
|
From: Martin Sukany <martin@sukany.cz>
|
||||||
Date: Mon, 2 Mar 2026 18:49:13 +0100
|
Date: Mon, 2 Mar 2026 18:49:13 +0100
|
||||||
Subject: [PATCH 9/9] ns: announce child frame completion candidates for
|
Subject: [PATCH 9/9] ns: announce child frame completion candidates for
|
||||||
@@ -37,8 +37,8 @@ Remove Zoom section (covered by patch 0000). Fix dangling paragraph.
|
|||||||
doc/emacs/macos.texi | 13 +-
|
doc/emacs/macos.texi | 13 +-
|
||||||
etc/NEWS | 25 +-
|
etc/NEWS | 25 +-
|
||||||
src/nsterm.h | 21 ++
|
src/nsterm.h | 21 ++
|
||||||
src/nsterm.m | 561 +++++++++++++++++++++++++++++++++++++------
|
src/nsterm.m | 560 +++++++++++++++++++++++++++++++++++++------
|
||||||
4 files changed, 529 insertions(+), 91 deletions(-)
|
4 files changed, 528 insertions(+), 91 deletions(-)
|
||||||
|
|
||||||
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
|
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
|
||||||
index 72ac3a9aa9..cf5ed0ff28 100644
|
index 72ac3a9aa9..cf5ed0ff28 100644
|
||||||
@@ -160,7 +160,7 @@ index a210ceba14..2edd7cd6e0 100644
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||||
index 54cee74401..6ba2229639 100644
|
index b9d3a0eb53..5e48710930 100644
|
||||||
--- a/src/nsterm.m
|
--- a/src/nsterm.m
|
||||||
+++ b/src/nsterm.m
|
+++ b/src/nsterm.m
|
||||||
@@ -1275,6 +1275,12 @@ If a completion candidate is selected (overlay or child frame),
|
@@ -1275,6 +1275,12 @@ If a completion candidate is selected (overlay or child frame),
|
||||||
@@ -309,7 +309,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
if (b != current_buffer)
|
if (b != current_buffer)
|
||||||
set_buffer_internal_1 (b);
|
set_buffer_internal_1 (b);
|
||||||
|
|
||||||
@@ -8605,6 +8726,11 @@ - (void)setAccessibilitySelectedTextRange:(NSRange)range
|
@@ -8609,6 +8730,11 @@ - (void)setAccessibilitySelectedTextRange:(NSRange)range
|
||||||
|
|
||||||
[self ensureTextCache];
|
[self ensureTextCache];
|
||||||
|
|
||||||
@@ -321,7 +321,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
specpdl_ref count = SPECPDL_INDEX ();
|
specpdl_ref count = SPECPDL_INDEX ();
|
||||||
record_unwind_current_buffer ();
|
record_unwind_current_buffer ();
|
||||||
/* Ensure block_input is always matched by unblock_input even if
|
/* Ensure block_input is always matched by unblock_input even if
|
||||||
@@ -9053,20 +9179,38 @@ - (void)postFocusedCursorNotification:(ptrdiff_t)point
|
@@ -9057,20 +9183,38 @@ - (void)postFocusedCursorNotification:(ptrdiff_t)point
|
||||||
&& granularity
|
&& granularity
|
||||||
== ns_ax_text_selection_granularity_character);
|
== ns_ax_text_selection_granularity_character);
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
ns_ax_post_notification_with_info (
|
ns_ax_post_notification_with_info (
|
||||||
self,
|
self,
|
||||||
NSAccessibilitySelectedTextChangedNotification,
|
NSAccessibilitySelectedTextChangedNotification,
|
||||||
@@ -9166,12 +9310,17 @@ user expectation ("w" jumps to next word and reads it). */
|
@@ -9170,12 +9314,17 @@ user expectation ("w" jumps to next word and reads it). */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
if (cachedText
|
if (cachedText
|
||||||
&& granularity == ns_ax_text_selection_granularity_line)
|
&& granularity == ns_ax_text_selection_granularity_line)
|
||||||
{
|
{
|
||||||
@@ -9236,6 +9385,11 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
|
@@ -9240,6 +9389,11 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
|
||||||
|
|
||||||
block_input ();
|
block_input ();
|
||||||
specpdl_ref count2 = SPECPDL_INDEX ();
|
specpdl_ref count2 = SPECPDL_INDEX ();
|
||||||
@@ -405,7 +405,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
record_unwind_protect_void (unblock_input);
|
record_unwind_protect_void (unblock_input);
|
||||||
record_unwind_current_buffer ();
|
record_unwind_current_buffer ();
|
||||||
if (b != current_buffer)
|
if (b != current_buffer)
|
||||||
@@ -9412,12 +9566,29 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
@@ -9416,12 +9570,29 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
||||||
if (!b)
|
if (!b)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
if (modiff != self.cachedModiff)
|
if (modiff != self.cachedModiff)
|
||||||
{
|
{
|
||||||
self.cachedModiff = modiff;
|
self.cachedModiff = modiff;
|
||||||
@@ -9431,6 +9602,7 @@ Text property changes (e.g. face updates from
|
@@ -9435,6 +9606,7 @@ Text property changes (e.g. face updates from
|
||||||
{
|
{
|
||||||
self.cachedCharsModiff = chars_modiff;
|
self.cachedCharsModiff = chars_modiff;
|
||||||
[self postTextChangedNotification:point];
|
[self postTextChangedNotification:point];
|
||||||
@@ -443,7 +443,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9453,37 +9625,44 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
@@ -9457,37 +9629,44 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
||||||
displayed in the minibuffer. In normal editing buffers,
|
displayed in the minibuffer. In normal editing buffers,
|
||||||
font-lock and other modes change BUF_OVERLAY_MODIFF on
|
font-lock and other modes change BUF_OVERLAY_MODIFF on
|
||||||
every redisplay, triggering O(overlays) work per keystroke.
|
every redisplay, triggering O(overlays) work per keystroke.
|
||||||
@@ -517,7 +517,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9497,7 +9676,18 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
@@ -9501,7 +9680,18 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
||||||
self.cachedPoint = point;
|
self.cachedPoint = point;
|
||||||
self.cachedMarkActive = markActive;
|
self.cachedMarkActive = markActive;
|
||||||
|
|
||||||
@@ -537,15 +537,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
NSInteger direction = ns_ax_text_selection_direction_discontiguous;
|
NSInteger direction = ns_ax_text_selection_direction_discontiguous;
|
||||||
if (point > oldPoint)
|
if (point > oldPoint)
|
||||||
direction = ns_ax_text_selection_direction_next;
|
direction = ns_ax_text_selection_direction_next;
|
||||||
@@ -9509,6 +9699,7 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
@@ -9534,7 +9724,18 @@ to VoiceOver via the AX getter path (accessibilityValue etc.). */
|
||||||
|
|
||||||
/* --- Granularity detection --- */
|
|
||||||
NSInteger granularity = ns_ax_text_selection_granularity_unknown;
|
|
||||||
+ BOOL singleLineMove = NO;
|
|
||||||
[self ensureTextCache];
|
|
||||||
if (cachedText && oldPoint > 0)
|
|
||||||
{
|
|
||||||
@@ -9523,7 +9714,18 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
|
||||||
NSRange newLine = [cachedText lineRangeForRange:
|
NSRange newLine = [cachedText lineRangeForRange:
|
||||||
NSMakeRange (newIdx, 0)];
|
NSMakeRange (newIdx, 0)];
|
||||||
if (oldLine.location != newLine.location)
|
if (oldLine.location != newLine.location)
|
||||||
@@ -565,7 +557,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSUInteger dist = (newIdx > oldIdx
|
NSUInteger dist = (newIdx > oldIdx
|
||||||
@@ -9545,38 +9747,23 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
|
@@ -9556,38 +9757,23 @@ to VoiceOver via the AX getter path (accessibilityValue etc.). */
|
||||||
granularity = ns_ax_text_selection_granularity_line;
|
granularity = ns_ax_text_selection_granularity_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +609,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
{
|
{
|
||||||
NSWindow *win = [self.emacsView window];
|
NSWindow *win = [self.emacsView window];
|
||||||
if (win)
|
if (win)
|
||||||
@@ -9735,6 +9922,13 @@ - (NSRect)accessibilityFrame
|
@@ -9746,6 +9932,13 @@ - (NSRect)accessibilityFrame
|
||||||
if (vis_start >= vis_end)
|
if (vis_start >= vis_end)
|
||||||
return @[];
|
return @[];
|
||||||
|
|
||||||
@@ -631,7 +623,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
block_input ();
|
block_input ();
|
||||||
specpdl_ref blk_count = SPECPDL_INDEX ();
|
specpdl_ref blk_count = SPECPDL_INDEX ();
|
||||||
record_unwind_protect_void (unblock_input);
|
record_unwind_protect_void (unblock_input);
|
||||||
@@ -10042,6 +10236,10 @@ - (void)dealloc
|
@@ -10053,6 +10246,10 @@ - (void)dealloc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[accessibilityElements release];
|
[accessibilityElements release];
|
||||||
@@ -642,7 +634,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
[[self menu] release];
|
[[self menu] release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -11491,6 +11689,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
|
@@ -11502,6 +11699,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
|
||||||
|
|
||||||
windowClosing = NO;
|
windowClosing = NO;
|
||||||
processingCompose = NO;
|
processingCompose = NO;
|
||||||
@@ -652,7 +644,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
scrollbarsNeedingUpdate = 0;
|
scrollbarsNeedingUpdate = 0;
|
||||||
fs_state = FULLSCREEN_NONE;
|
fs_state = FULLSCREEN_NONE;
|
||||||
fs_before_fs = next_maximized = -1;
|
fs_before_fs = next_maximized = -1;
|
||||||
@@ -12799,6 +13000,156 @@ - (id)accessibilityFocusedUIElement
|
@@ -12810,6 +13010,156 @@ - (id)accessibilityFocusedUIElement
|
||||||
The existing elements carry cached state (modiff, point) from the
|
The existing elements carry cached state (modiff, point) from the
|
||||||
previous redisplay cycle. Rebuilding first would create fresh
|
previous redisplay cycle. Rebuilding first would create fresh
|
||||||
elements with current values, making change detection impossible. */
|
elements with current values, making change detection impossible. */
|
||||||
@@ -809,7 +801,7 @@ index 54cee74401..6ba2229639 100644
|
|||||||
- (void)postAccessibilityUpdates
|
- (void)postAccessibilityUpdates
|
||||||
{
|
{
|
||||||
NSTRACE ("[EmacsView postAccessibilityUpdates]");
|
NSTRACE ("[EmacsView postAccessibilityUpdates]");
|
||||||
@@ -12809,11 +13160,69 @@ - (void)postAccessibilityUpdates
|
@@ -12820,11 +13170,69 @@ - (void)postAccessibilityUpdates
|
||||||
|
|
||||||
/* Re-entrance guard: VoiceOver callbacks during notification posting
|
/* Re-entrance guard: VoiceOver callbacks during notification posting
|
||||||
can trigger redisplay, which calls ns_update_end, which calls us
|
can trigger redisplay, which calls ns_update_end, which calls us
|
||||||
|
|||||||
Reference in New Issue
Block a user