patches: address all maintainer review issues
- Issue 1: Add explicit ApplicationServices import for UAZoomEnabled/ UAZoomChangeFocus (was implicit via Carbon.h, now explicit) - Issue 2: Rename FOR_EACH_FRAME variable 'frames' -> 'frame' (plural was misleading; matches Emacs convention) - Issue 3: Move unblock_input before ObjC calls in postCompletionAnnouncementForBuffer: to avoid holding block_input during @synchronized operations - Issue 4: Fix DEFVAR_BOOL doc and Texinfo: initial value is nil, not t; auto-detection sets it at startup - Issue 5: Replace magic 10000 with NS_AX_MAX_COMPLETION_BUFFER_CHARS constant with explanatory comment - Issue 6: Add comment to lineStartOffsets loop explaining it is gated on BUF_CHARS_MODIFF and never runs on the hot path - Issue 8: Rewrite all 9 commit messages to GNU ChangeLog format with '* file (symbol): description' entries - Issue 9: Break 81-char @interface line in nsterm.h - Issue 10: Add WINDOWP/BUFFERP guards before dereferencing cf->selected_window and cw->contents in ns_zoom_find_child_frame_candidate - Issue 11: Fix @pxref -> @xref at sentence start in macos.texi
This commit is contained in:
@@ -1,53 +1,30 @@
|
||||
From fb4d1411fcc4a18cefae80dbed856fda8fe8c85e Mon Sep 17 00:00:00 2001
|
||||
From 2f655a0fa3071046169011ecdc97f0a3f7c1105c Mon Sep 17 00:00:00 2001
|
||||
From: Martin Sukany <martin@sukany.cz>
|
||||
Date: Sat, 28 Feb 2026 16:01:29 +0100
|
||||
Subject: [PATCH 8/8] ns: announce child frame completion candidates for
|
||||
VoiceOver
|
||||
|
||||
Completion frameworks such as Corfu, Company-box, and similar
|
||||
render candidates in a child frame rather than as overlay strings
|
||||
in the minibuffer. This patch extends the overlay announcement
|
||||
support (patch 7/8) to handle child frame popups.
|
||||
Completion frameworks such as Corfu and Company-box render candidates
|
||||
in a child frame. This extends the overlay announcement support to
|
||||
handle child frame popups.
|
||||
|
||||
Detect child frames via FRAME_PARENT_FRAME in postAccessibilityUpdates.
|
||||
Scan the child frame buffer text line by line using Fget_char_property
|
||||
(which checks both text properties and overlay face properties) to
|
||||
find the selected candidate. Reuse ns_ax_face_is_selected from
|
||||
the overlay patch to identify "current", "selected", and
|
||||
"selection" faces.
|
||||
|
||||
Safety:
|
||||
- record_unwind_current_buffer / set_buffer_internal_1 to switch to
|
||||
the child frame buffer for Fbuffer_substring_no_properties.
|
||||
- Re-entrance guard (accessibilityUpdating) before child frame dispatch.
|
||||
- BUF_MODIFF gating prevents redundant scans.
|
||||
- WINDOWP, BUFFERP validation for partially initialized frames.
|
||||
- Buffer size limit (10000 chars) skips non-completion child frames.
|
||||
|
||||
When the child frame closes, post FocusedUIElementChangedNotification
|
||||
on the parent buffer element to restore VoiceOver's character echo
|
||||
and cursor tracking. The flag childFrameCompletionActive is set by
|
||||
the child frame handler and cleared on the parent's next accessibility
|
||||
cycle when no child frame is visible (via FOR_EACH_FRAME).
|
||||
|
||||
Announce via AnnouncementRequested to NSApp with High priority.
|
||||
independently --- its ns_update_end runs after the parent's
|
||||
|
||||
* src/nsterm.h (EmacsView): Add announceChildFrameCompletion,
|
||||
childFrameCompletionActive flag.
|
||||
* src/nsterm.m (ns_ax_selected_child_frame_text): New function.
|
||||
(EmacsView announceChildFrameCompletion): New method, set parent flag.
|
||||
(EmacsView postAccessibilityUpdates): Dispatch to child frame handler,
|
||||
refocus parent buffer element when child frame closes.
|
||||
* src/nsterm.m (ns_ax_selected_child_frame_text): New function; scan
|
||||
a child frame buffer line by line using Fget_char_property to find the
|
||||
selected candidate; uses record_unwind_current_buffer for safety.
|
||||
(EmacsView announceChildFrameCompletion): New method.
|
||||
(EmacsView postAccessibilityUpdates): Detect child frames via
|
||||
FRAME_PARENT_FRAME; call announceChildFrameCompletion. Post
|
||||
NSAccessibilityFocusedUIElementChangedNotification on the parent buffer
|
||||
element when a child frame completion closes.
|
||||
---
|
||||
doc/emacs/macos.texi | 6 -
|
||||
etc/NEWS | 4 +-
|
||||
src/nsterm.h | 5 +
|
||||
src/nsterm.m | 266 +++++++++++++++++++++++++++++++++++++++++--
|
||||
4 files changed, 263 insertions(+), 18 deletions(-)
|
||||
src/nsterm.m | 265 +++++++++++++++++++++++++++++++++++++++++--
|
||||
4 files changed, 262 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
|
||||
index 4825cf9..97777e2 100644
|
||||
index 6514dfc..f47929e 100644
|
||||
--- a/doc/emacs/macos.texi
|
||||
+++ b/doc/emacs/macos.texi
|
||||
@@ -278,7 +278,6 @@ restart Emacs to access newly-available services.
|
||||
@@ -86,10 +63,10 @@ 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 2102fb9..dd98d56 100644
|
||||
index 483fed3..8bf867a 100644
|
||||
--- a/src/nsterm.h
|
||||
+++ b/src/nsterm.h
|
||||
@@ -594,6 +594,10 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType)
|
||||
@@ -595,6 +595,10 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType)
|
||||
Lisp_Object lastRootWindow;
|
||||
BOOL accessibilityTreeValid;
|
||||
BOOL accessibilityUpdating;
|
||||
@@ -100,7 +77,7 @@ index 2102fb9..dd98d56 100644
|
||||
#endif
|
||||
BOOL font_panel_active;
|
||||
NSFont *font_panel_result;
|
||||
@@ -663,6 +667,7 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType)
|
||||
@@ -664,6 +668,7 @@ typedef NS_ENUM (NSInteger, EmacsAXSpanType)
|
||||
- (void)rebuildAccessibilityTree;
|
||||
- (void)invalidateAccessibilityTree;
|
||||
- (void)postAccessibilityUpdates;
|
||||
@@ -109,10 +86,10 @@ index 2102fb9..dd98d56 100644
|
||||
@end
|
||||
|
||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||
index a3104d0..6e8a226 100644
|
||||
index 20ba0b9..f911d93 100644
|
||||
--- a/src/nsterm.m
|
||||
+++ b/src/nsterm.m
|
||||
@@ -7398,6 +7398,112 @@ visual line index for Zoom (skip whitespace-only lines
|
||||
@@ -7415,6 +7415,112 @@ visual line index for Zoom (skip whitespace-only lines
|
||||
|
||||
return nil;
|
||||
}
|
||||
@@ -225,7 +202,7 @@ index a3104d0..6e8a226 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
|
||||
@@ -8142,16 +8248,25 @@ - (void)ensureTextCache
|
||||
@@ -8159,16 +8265,25 @@ - (void)ensureTextCache
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
@@ -259,7 +236,7 @@ index a3104d0..6e8a226 100644
|
||||
&& cachedTextStart == BUF_BEGV (b)
|
||||
&& pt >= cachedTextStart
|
||||
&& (textLen == 0
|
||||
@@ -8167,7 +8282,7 @@ included in the cached AX text (it is handled separately via
|
||||
@@ -8184,7 +8299,7 @@ included in the cached AX text (it is handled separately via
|
||||
{
|
||||
[cachedText release];
|
||||
cachedText = [text retain];
|
||||
@@ -268,7 +245,7 @@ index a3104d0..6e8a226 100644
|
||||
cachedTextStart = start;
|
||||
|
||||
if (visibleRuns)
|
||||
@@ -9154,6 +9269,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
|
||||
@@ -9175,6 +9290,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
|
||||
ptrdiff_t currentOverlayStart = 0;
|
||||
ptrdiff_t currentOverlayEnd = 0;
|
||||
|
||||
@@ -276,15 +253,7 @@ index a3104d0..6e8a226 100644
|
||||
specpdl_ref count2 = SPECPDL_INDEX ();
|
||||
record_unwind_current_buffer ();
|
||||
if (b != current_buffer)
|
||||
@@ -9312,6 +9428,7 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
|
||||
self.cachedCompletionOverlayEnd = 0;
|
||||
self.cachedCompletionPoint = 0;
|
||||
}
|
||||
+ unblock_input ();
|
||||
}
|
||||
|
||||
/* ---- Notification dispatch (main entry point) ---- */
|
||||
@@ -9908,6 +10025,10 @@ - (void)dealloc
|
||||
@@ -9930,6 +10046,10 @@ - (void)dealloc
|
||||
#endif
|
||||
|
||||
[accessibilityElements release];
|
||||
@@ -295,7 +264,7 @@ index a3104d0..6e8a226 100644
|
||||
[[self menu] release];
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -11357,6 +11478,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
|
||||
@@ -11379,6 +11499,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
|
||||
|
||||
windowClosing = NO;
|
||||
processingCompose = NO;
|
||||
@@ -305,7 +274,7 @@ index a3104d0..6e8a226 100644
|
||||
scrollbarsNeedingUpdate = 0;
|
||||
fs_state = FULLSCREEN_NONE;
|
||||
fs_before_fs = next_maximized = -1;
|
||||
@@ -12665,6 +12789,80 @@ - (id)accessibilityFocusedUIElement
|
||||
@@ -12687,6 +12810,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 +355,7 @@ index a3104d0..6e8a226 100644
|
||||
- (void)postAccessibilityUpdates
|
||||
{
|
||||
NSTRACE ("[EmacsView postAccessibilityUpdates]");
|
||||
@@ -12675,11 +12873,59 @@ - (void)postAccessibilityUpdates
|
||||
@@ -12697,11 +12894,59 @@ - (void)postAccessibilityUpdates
|
||||
|
||||
/* Re-entrance guard: VoiceOver callbacks during notification posting
|
||||
can trigger redisplay, which calls ns_update_end, which calls us
|
||||
|
||||
Reference in New Issue
Block a user