From 6703914305fbbfd1db592bf66208072c86adb811 Mon Sep 17 00:00:00 2001 From: Daneel Date: Sun, 1 Mar 2026 13:43:25 +0100 Subject: [PATCH] patches: fix fold/unfold AX cache regression (BUF_OVERLAY_MODIFF) --- ...d-frame-completion-candidates-for-Vo.patch | 58 ++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) 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 26a9e5f..f1557d0 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 17cd7eabf984a7de09ac277b4831836a44c4cf81 Mon Sep 17 00:00:00 2001 +From 1cbef245410db30407aa55f7d1290e879705a491 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 @@ -19,9 +19,9 @@ element when a child frame completion closes. --- doc/emacs/macos.texi | 6 - etc/NEWS | 4 +- - src/nsterm.h | 5 + - src/nsterm.m | 265 +++++++++++++++++++++++++++++++++++++++++-- - 4 files changed, 262 insertions(+), 18 deletions(-) + src/nsterm.h | 9 ++ + src/nsterm.m | 275 +++++++++++++++++++++++++++++++++++++++++-- + 4 files changed, 276 insertions(+), 18 deletions(-) diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi index 6514dfc..f47929e 100644 @@ -63,10 +63,21 @@ index 2b1f9e6..8a40850 100644 for the *Completions* buffer. The implementation uses a virtual accessibility tree with per-window elements, hybrid SelectedTextChanged diff --git a/src/nsterm.h b/src/nsterm.h -index 21a93bc..75c731f 100644 +index 21a93bc..bbce9fe 100644 --- a/src/nsterm.h +++ b/src/nsterm.h -@@ -596,6 +596,10 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType) +@@ -507,6 +507,10 @@ typedef struct ns_ax_visible_run + } + @property (nonatomic, retain) NSString *cachedText; + @property (nonatomic, assign) ptrdiff_t cachedTextModiff; ++/* Overlay modiff at last text cache rebuild. Tracked separately from ++ cachedOverlayModiff (which is used for completion announcements) so ++ that fold/unfold detection is independent of notification dispatch. */ ++@property (nonatomic, assign) ptrdiff_t cachedOverlayModiffForText; + @property (nonatomic, assign) ptrdiff_t cachedOverlayModiff; + @property (nonatomic, assign) ptrdiff_t cachedTextStart; + @property (nonatomic, assign) ptrdiff_t cachedModiff; +@@ -596,6 +600,10 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType) Lisp_Object lastRootWindow; BOOL accessibilityTreeValid; BOOL accessibilityUpdating; @@ -77,7 +88,7 @@ index 21a93bc..75c731f 100644 #endif BOOL font_panel_active; NSFont *font_panel_result; -@@ -665,6 +669,7 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType) +@@ -665,6 +673,7 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType) - (void)rebuildAccessibilityTree; - (void)invalidateAccessibilityTree; - (void)postAccessibilityUpdates; @@ -86,7 +97,7 @@ index 21a93bc..75c731f 100644 @end diff --git a/src/nsterm.m b/src/nsterm.m -index 8d44b5f..8d88273 100644 +index 8d44b5f..8548c68 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -7415,6 +7415,112 @@ visual line index for Zoom (skip whitespace-only lines @@ -202,7 +213,15 @@ index 8d44b5f..8d88273 100644 /* Build accessibility text for window W, skipping invisible text. Populates *OUT_START with the buffer start charpos. Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS -@@ -8159,16 +8265,25 @@ - (void)ensureTextCache +@@ -8046,6 +8152,7 @@ that remapped bindings (e.g., C-j -> next-line) are recognized. + @implementation EmacsAccessibilityBuffer + @synthesize cachedText; + @synthesize cachedTextModiff; ++@synthesize cachedOverlayModiffForText; + @synthesize cachedOverlayModiff; + @synthesize cachedTextStart; + @synthesize cachedModiff; +@@ -8159,16 +8266,33 @@ - (void)ensureTextCache if (!b) return; @@ -230,22 +249,31 @@ index 8d44b5f..8d88273 100644 + Including overlay_modiff would silently update cachedOverlayModiff + and prevent the notification dispatch from detecting changes. */ + ptrdiff_t chars_modiff = BUF_CHARS_MODIFF (b); ++ ptrdiff_t overlay_modiff = BUF_OVERLAY_MODIFF (b); + ptrdiff_t pt = BUF_PT (b); + NSUInteger textLen = cachedText ? [cachedText length] : 0; ++ /* Cache is valid when neither characters nor fold-state have changed. ++ BUF_CHARS_MODIFF guards against character edits and is not bumped ++ by font-lock (text-property changes), preserving the O(1) hot path. ++ BUF_OVERLAY_MODIFF covers fold/unfold in modes that use overlays ++ (org-mode, hideshow); text-property-based invisibility such as ++ outline-minor-mode without overlays is a known limitation. */ + if (cachedText && cachedTextModiff == chars_modiff ++ && cachedOverlayModiffForText == overlay_modiff && cachedTextStart == BUF_BEGV (b) && pt >= cachedTextStart && (textLen == 0 -@@ -8184,7 +8299,7 @@ included in the cached AX text (it is handled separately via +@@ -8184,7 +8308,8 @@ included in the cached AX text (it is handled separately via { [cachedText release]; cachedText = [text retain]; - cachedTextModiff = modiff; + cachedTextModiff = chars_modiff; ++ cachedOverlayModiffForText = overlay_modiff; cachedTextStart = start; if (visibleRuns) -@@ -9175,6 +9290,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b +@@ -9175,6 +9300,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b ptrdiff_t currentOverlayStart = 0; ptrdiff_t currentOverlayEnd = 0; @@ -253,7 +281,7 @@ index 8d44b5f..8d88273 100644 specpdl_ref count2 = SPECPDL_INDEX (); record_unwind_current_buffer (); if (b != current_buffer) -@@ -9931,6 +10047,10 @@ - (void)dealloc +@@ -9931,6 +10057,10 @@ - (void)dealloc #endif [accessibilityElements release]; @@ -264,7 +292,7 @@ index 8d44b5f..8d88273 100644 [[self menu] release]; [super dealloc]; } -@@ -11380,6 +11500,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f +@@ -11380,6 +11510,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f windowClosing = NO; processingCompose = NO; @@ -274,7 +302,7 @@ index 8d44b5f..8d88273 100644 scrollbarsNeedingUpdate = 0; fs_state = FULLSCREEN_NONE; fs_before_fs = next_maximized = -1; -@@ -12688,6 +12811,80 @@ - (id)accessibilityFocusedUIElement +@@ -12688,6 +12821,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. */ @@ -355,7 +383,7 @@ index 8d44b5f..8d88273 100644 - (void)postAccessibilityUpdates { NSTRACE ("[EmacsView postAccessibilityUpdates]"); -@@ -12698,11 +12895,59 @@ - (void)postAccessibilityUpdates +@@ -12698,11 +12905,59 @@ - (void)postAccessibilityUpdates /* Re-entrance guard: VoiceOver callbacks during notification posting can trigger redisplay, which calls ns_update_end, which calls us