patches: fix 0008 — forward reference + blank lines (maintainer review)

Move file-scope statics (lastChildFrameBuffer/Modiff/Candidate) and
ns_ax_reset_accessibility_updating before announceChildFrameCompletion.
Using them before their declaration was a forward reference (UB in C).

Remove two spurious blank lines at start of announceChildFrameCompletion
method body.
This commit is contained in:
2026-02-28 19:26:55 +01:00
parent 98b3d04597
commit c82ef86eaf

View File

@@ -1,8 +1,7 @@
From 8564e4989f5f358092bd1494c3894a42974ee6e1 Mon Sep 17 00:00:00 2001 From 846e2fa3f856138127bdc7a475e066003cc76904 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 16:01:29 +0100 Date: Sat, 28 Feb 2026 16:01:29 +0100
Subject: [PATCH 2/2] ns: announce child frame completion candidates for Subject: [PATCH] ns: announce child frame completion candidates for VoiceOver
VoiceOver
Completion frameworks such as Corfu, Company-box, and similar Completion frameworks such as Corfu, Company-box, and similar
render candidates in a child frame rather than as overlay strings render candidates in a child frame rather than as overlay strings
@@ -43,8 +42,8 @@ childFrameCompletionActive flag.
refocus parent buffer element when child frame closes. refocus parent buffer element when child frame closes.
--- ---
src/nsterm.h | 2 + src/nsterm.h | 2 +
src/nsterm.m | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/nsterm.m | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 278 insertions(+), 3 deletions(-) 2 files changed, 276 insertions(+), 3 deletions(-)
diff --git a/src/nsterm.h b/src/nsterm.h diff --git a/src/nsterm.h b/src/nsterm.h
index 5c15639..8b34300 100644 index 5c15639..8b34300 100644
@@ -67,7 +66,7 @@ index 5c15639..8b34300 100644
@end @end
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 143e784..da1a319 100644 index 143e784..37918a4 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -7066,6 +7066,110 @@ ns_ax_selected_overlay_text (struct buffer *b, @@ -7066,6 +7066,110 @@ ns_ax_selected_overlay_text (struct buffer *b,
@@ -181,11 +180,29 @@ index 143e784..da1a319 100644
/* Build accessibility text for window W, skipping invisible text. /* Build accessibility text for window W, skipping invisible text.
Populates *OUT_START with the buffer start charpos. Populates *OUT_START with the buffer start charpos.
Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS
@@ -12311,6 +12415,122 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12311,6 +12415,120 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
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. */
+ +
+/* Child frame completion dedup state. File-scope so that
+ lastChildFrameBuffer can be staticpro'd against GC. */
+static Lisp_Object lastChildFrameBuffer;
+static EMACS_INT lastChildFrameModiff;
+static char *lastChildFrameCandidate;
+
+/* Reset the re-entrance guard when unwinding past
+ postAccessibilityUpdates due to a Lisp signal (longjmp).
+ Without this, a signal during Lisp calls (e.g. Fget_char_property
+ in overlay or child frame scanning) would leave
+ accessibilityUpdating = YES permanently, suppressing all future
+ accessibility notifications. */
+static void
+ns_ax_reset_accessibility_updating (void *view)
+{
+ ((EmacsView *)view)->accessibilityUpdating = NO;
+}
+
+/* Announce the selected candidate in a child frame completion popup. +/* Announce the selected candidate in a child frame completion popup.
+ Handles Corfu, Company-box, and similar frameworks that render + Handles Corfu, Company-box, and similar frameworks that render
+ candidates in a separate child frame rather than as overlay strings + candidates in a separate child frame rather than as overlay strings
@@ -194,8 +211,6 @@ index 143e784..da1a319 100644
+ after the parent's draw_window_cursor. */ + after the parent's draw_window_cursor. */
+- (void)announceChildFrameCompletion +- (void)announceChildFrameCompletion
+{ +{
+
+
+ /* Validate frame state --- child frames may be partially + /* Validate frame state --- child frames may be partially
+ initialized during creation. */ + initialized during creation. */
+ if (!WINDOWP (emacsframe->selected_window)) + if (!WINDOWP (emacsframe->selected_window))
@@ -282,29 +297,11 @@ index 143e784..da1a319 100644
+ kUAZoomFocusTypeInsertionPoint); + kUAZoomFocusTypeInsertionPoint);
+ } + }
+} +}
+
+/* Child frame completion dedup state. File-scope so that
+ lastChildFrameBuffer can be staticpro'd against GC. */
+static Lisp_Object lastChildFrameBuffer;
+static EMACS_INT lastChildFrameModiff;
+static char *lastChildFrameCandidate;
+
+/* Reset the re-entrance guard when unwinding past
+ postAccessibilityUpdates due to a Lisp signal (longjmp).
+ Without this, a signal during Lisp calls (e.g. Fget_char_property
+ in overlay or child frame scanning) would leave
+ accessibilityUpdating = YES permanently, suppressing all future
+ accessibility notifications. */
+static void
+ns_ax_reset_accessibility_updating (void *view)
+{
+ ((EmacsView *)view)->accessibilityUpdating = NO;
+}
+ +
- (void)postAccessibilityUpdates - (void)postAccessibilityUpdates
{ {
NSTRACE ("[EmacsView postAccessibilityUpdates]"); NSTRACE ("[EmacsView postAccessibilityUpdates]");
@@ -12321,10 +12541,60 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12321,10 +12539,60 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
/* 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
@@ -366,7 +363,7 @@ index 143e784..da1a319 100644
/* Detect window tree change (split, delete, new buffer). Compare /* Detect window tree change (split, delete, new buffer). Compare
FRAME_ROOT_WINDOW --- if it changed, the tree structure changed. */ FRAME_ROOT_WINDOW --- if it changed, the tree structure changed. */
@@ -12355,7 +12625,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12355,7 +12623,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
NSAccessibilityFocusedUIElementChangedNotification); NSAccessibilityFocusedUIElementChangedNotification);
lastSelectedWindow = emacsframe->selected_window; lastSelectedWindow = emacsframe->selected_window;
@@ -375,7 +372,7 @@ index 143e784..da1a319 100644
return; return;
} }
@@ -12399,7 +12669,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12399,7 +12667,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
NSAccessibilityFocusedUIElementChangedNotification); NSAccessibilityFocusedUIElementChangedNotification);
} }
@@ -384,7 +381,7 @@ index 143e784..da1a319 100644
} }
/* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ---- /* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ----
@@ -14341,6 +14611,9 @@ syms_of_nsterm (void) @@ -14341,6 +14609,9 @@ syms_of_nsterm (void)
DEFSYM (Qns_ax_completion, "completion"); DEFSYM (Qns_ax_completion, "completion");
DEFSYM (Qns_ax_completions_highlight, "completions-highlight"); DEFSYM (Qns_ax_completions_highlight, "completions-highlight");
DEFSYM (Qns_ax_backtab, "backtab"); DEFSYM (Qns_ax_backtab, "backtab");