patches: review pass 3 - move block_input to origin patches

block_input protection moved from P0008 to their respective origin
patches for independent compilability (GNU Emacs requirement):
- P0001 (ns_ax_buffer_text): now has block_input + record_unwind
- P0003 (postCompletionAnnouncementForBuffer): now has block_input
- P0004 (ns_ax_scan_interactive_spans): now has block_input

P0008 now only adds its own new functionality (child frame completion
announcements, echo area announcements) without duplicating block_input
from earlier patches.

All 9 patches apply cleanly with git am on Linux git 2.43.0.
This commit is contained in:
2026-03-02 18:55:33 +01:00
parent 6176087cfb
commit 6fd28e19a8
9 changed files with 97 additions and 105 deletions

View File

@@ -1,7 +1,7 @@
From cc35459697126cf2fe7d152978170fa1e152b11d Mon Sep 17 00:00:00 2001 From d71de5bc8af58083ee024fd7117d06bf7e6cc0d0 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 22:39:35 +0100 Date: Sat, 28 Feb 2026 22:39:35 +0100
Subject: [PATCH 1/9] ns: integrate with macOS Zoom for cursor tracking Subject: [PATCH 0/8] ns: integrate with macOS Zoom for cursor tracking
Inform macOS Zoom of the text cursor position so the zoomed viewport Inform macOS Zoom of the text cursor position so the zoomed viewport
follows keyboard focus in Emacs. Also track completion candidates so follows keyboard focus in Emacs. Also track completion candidates so

View File

@@ -1,7 +1,7 @@
From 3658dbc6fed51b2d34ab8c06707eaca1ee1a78d4 Mon Sep 17 00:00:00 2001 From 07aa615d046f1af0d02e22f834a2728a75943d18 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 2/9] ns: add accessibility base classes and text extraction Subject: [PATCH 1/8] ns: add accessibility base classes and text extraction
Add the foundation for macOS VoiceOver accessibility in the NS (Cocoa) Add the foundation for macOS VoiceOver accessibility in the NS (Cocoa)
port. No existing code paths are modified. port. No existing code paths are modified.
@@ -29,8 +29,8 @@ ns-accessibility-enabled with corrected doc: initial value is nil,
set non-nil automatically when an AT is detected at startup. set non-nil automatically when an AT is detected at startup.
--- ---
src/nsterm.h | 131 +++++++++++++++ src/nsterm.h | 131 +++++++++++++++
src/nsterm.m | 452 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/nsterm.m | 454 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 583 insertions(+) 2 files changed, 585 insertions(+)
diff --git a/src/nsterm.h b/src/nsterm.h diff --git a/src/nsterm.h b/src/nsterm.h
index ea6e7ba4f5..5746e9e9bd 100644 index ea6e7ba4f5..5746e9e9bd 100644
@@ -189,7 +189,7 @@ index ea6e7ba4f5..5746e9e9bd 100644
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 88c9251c18..8b6f12517d 100644 index 88c9251c18..9d36de66f9 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -46,6 +46,7 @@ Updated by Christian Limpach (chris@nice.ch) @@ -46,6 +46,7 @@ Updated by Christian Limpach (chris@nice.ch)
@@ -200,7 +200,7 @@ index 88c9251c18..8b6f12517d 100644
#include "systime.h" #include "systime.h"
#include "character.h" #include "character.h"
#include "xwidget.h" #include "xwidget.h"
@@ -7201,6 +7202,430 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg @@ -7201,6 +7202,432 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
} }
#endif #endif
@@ -249,6 +249,8 @@ index 88c9251c18..8b6f12517d 100644
+ +
+ specpdl_ref count = SPECPDL_INDEX (); + specpdl_ref count = SPECPDL_INDEX ();
+ record_unwind_current_buffer (); + record_unwind_current_buffer ();
+ record_unwind_protect_void (unblock_input);
+ block_input ();
+ if (b != current_buffer) + if (b != current_buffer)
+ set_buffer_internal_1 (b); + set_buffer_internal_1 (b);
+ +
@@ -631,7 +633,7 @@ index 88c9251c18..8b6f12517d 100644
/* ========================================================================== /* ==========================================================================
EmacsView implementation EmacsView implementation
@@ -11657,6 +12082,24 @@ Convert an X font name (XLFD) to an NS font name. @@ -11657,6 +12084,24 @@ Convert an X font name (XLFD) to an NS font name.
DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic"); DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic");
DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion"); DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion");
@@ -656,7 +658,7 @@ index 88c9251c18..8b6f12517d 100644
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier)); Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
@@ -11805,6 +12248,15 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with @@ -11805,6 +12250,15 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with
This variable is ignored on Mac OS X < 10.7 and GNUstep. */); This variable is ignored on Mac OS X < 10.7 and GNUstep. */);
ns_use_srgb_colorspace = YES; ns_use_srgb_colorspace = YES;

View File

@@ -1,7 +1,7 @@
From 5491457834dc7a35eaca62b22baa607ce73f102b Mon Sep 17 00:00:00 2001 From 885981f0f365c58167cc6ea8e7cff65f14e1f57f Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 3/9] ns: implement buffer accessibility element (core Subject: [PATCH 2/8] ns: implement buffer accessibility element (core
protocol) protocol)
Implement the NSAccessibility text protocol for Emacs buffer windows. Implement the NSAccessibility text protocol for Emacs buffer windows.
@@ -27,10 +27,10 @@ loop is safe: it runs only on actual character modifications.
1 file changed, 1115 insertions(+) 1 file changed, 1115 insertions(+)
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 8b6f12517d..13b8357286 100644 index 9d36de66f9..6256dbc22e 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -7623,6 +7623,1121 @@ - (id)accessibilityTopLevelUIElement @@ -7625,6 +7625,1121 @@ - (id)accessibilityTopLevelUIElement
@end @end

View File

@@ -1,7 +1,7 @@
From ab845beb9112989f85fe3f5b344e5a26ec1b5421 Mon Sep 17 00:00:00 2001 From af4a3c4333452107c9299950ff947af53ab1b705 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 4/9] ns: add buffer notification dispatch and mode-line Subject: [PATCH 3/8] ns: add buffer notification dispatch and mode-line
element element
Add VoiceOver notification dispatch and mode-line readout. Add VoiceOver notification dispatch and mode-line readout.
@@ -22,14 +22,14 @@ detects text edit, cursor/mark change, or overlay change.
(EmacsAccessibilityModeLine): Implement AXStaticText element for the (EmacsAccessibilityModeLine): Implement AXStaticText element for the
mode line. mode line.
--- ---
src/nsterm.m | 604 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/nsterm.m | 606 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 604 insertions(+) 1 file changed, 606 insertions(+)
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 13b8357286..cbf29694dd 100644 index 6256dbc22e..9e0e317237 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -8738,6 +8738,610 @@ - (NSRect)accessibilityFrame @@ -8740,6 +8740,612 @@ - (NSRect)accessibilityFrame
@end @end
@@ -281,7 +281,9 @@ index 13b8357286..cbf29694dd 100644
+ ptrdiff_t currentOverlayStart = 0; + ptrdiff_t currentOverlayStart = 0;
+ ptrdiff_t currentOverlayEnd = 0; + ptrdiff_t currentOverlayEnd = 0;
+ +
+ block_input ();
+ specpdl_ref count2 = SPECPDL_INDEX (); + specpdl_ref count2 = SPECPDL_INDEX ();
+ record_unwind_protect_void (unblock_input);
+ record_unwind_current_buffer (); + record_unwind_current_buffer ();
+ if (b != current_buffer) + if (b != current_buffer)
+ set_buffer_internal_1 (b); + set_buffer_internal_1 (b);

View File

@@ -1,7 +1,7 @@
From e3c3878e65d8273e5fca97e942fe97ff3c5c113f Mon Sep 17 00:00:00 2001 From 589f1536255d1ad28552d8047387fbf3e9288235 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 5/9] ns: add interactive span elements for Tab navigation Subject: [PATCH 4/8] ns: add interactive span elements for Tab navigation
* src/nsterm.m (ns_ax_scan_interactive_spans): New function; scans the * src/nsterm.m (ns_ax_scan_interactive_spans): New function; scans the
visible portion of a buffer for interactive text properties visible portion of a buffer for interactive text properties
@@ -14,14 +14,14 @@ elements with an AXPress action that sends a synthetic TAB keystroke.
(accessibilityChildrenInNavigationOrder): Return cached span array, (accessibilityChildrenInNavigationOrder): Return cached span array,
rebuilding lazily when interactiveSpansDirty is set. rebuilding lazily when interactiveSpansDirty is set.
--- ---
src/nsterm.m | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/nsterm.m | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 287 insertions(+) 1 file changed, 291 insertions(+)
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index cbf29694dd..e8bbc1ffe1 100644 index 9e0e317237..b460beb00c 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -9342,6 +9342,293 @@ - (NSRect)accessibilityFrame @@ -9346,6 +9346,297 @@ - (NSRect)accessibilityFrame
@end @end
@@ -57,6 +57,10 @@ index cbf29694dd..e8bbc1ffe1 100644
+ if (vis_start >= vis_end) + if (vis_start >= vis_end)
+ return @[]; + return @[];
+ +
+ block_input ();
+ specpdl_ref blk_count = SPECPDL_INDEX ();
+ record_unwind_protect_void (unblock_input);
+
+ /* Symbols are interned once at startup via DEFSYM in syms_of_nsterm; + /* Symbols are interned once at startup via DEFSYM in syms_of_nsterm;
+ reference them directly here (GC-safe, no repeated obarray lookup). */ + reference them directly here (GC-safe, no repeated obarray lookup). */
+ +

View File

@@ -1,7 +1,7 @@
From d020bfbad36ff87ac4fd1ec6b52f7f451435260a Mon Sep 17 00:00:00 2001 From 2892f6c1591e8cf269897d738367daf38ae85326 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 6/9] ns: integrate accessibility with EmacsView and redisplay Subject: [PATCH 5/8] ns: integrate accessibility with EmacsView and redisplay
Wire the accessibility element tree into EmacsView and hook it into Wire the accessibility element tree into EmacsView and hook it into
the redisplay cycle. the redisplay cycle.
@@ -51,7 +51,7 @@ index 4c149e41d6..7f917f93b2 100644
** Re-introduced dictation, lost in Emacs v30 (macOS). ** Re-introduced dictation, lost in Emacs v30 (macOS).
We lost macOS dictation in v30 when migrating to NSTextInputClient. We lost macOS dictation in v30 when migrating to NSTextInputClient.
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index e8bbc1ffe1..231ae95a17 100644 index b460beb00c..95a5b378c1 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -1275,7 +1275,7 @@ If a completion candidate is selected (overlay or child frame), @@ -1275,7 +1275,7 @@ If a completion candidate is selected (overlay or child frame),
@@ -149,7 +149,7 @@ index e8bbc1ffe1..231ae95a17 100644
- (void)antialiasThresholdDidChange:(NSNotification *)notification - (void)antialiasThresholdDidChange:(NSNotification *)notification
{ {
#ifdef NS_IMPL_COCOA #ifdef NS_IMPL_COCOA
@@ -7626,7 +7677,6 @@ - (id)accessibilityTopLevelUIElement @@ -7628,7 +7679,6 @@ - (id)accessibilityTopLevelUIElement
@@ -157,7 +157,7 @@ index e8bbc1ffe1..231ae95a17 100644
static BOOL static BOOL
ns_ax_find_completion_overlay_range (struct buffer *b, ptrdiff_t point, ns_ax_find_completion_overlay_range (struct buffer *b, ptrdiff_t point,
ptrdiff_t *out_start, ptrdiff_t *out_start,
@@ -8739,7 +8789,6 @@ - (NSRect)accessibilityFrame @@ -8741,7 +8791,6 @@ - (NSRect)accessibilityFrame
@end @end
@@ -165,7 +165,7 @@ index e8bbc1ffe1..231ae95a17 100644
/* =================================================================== /* ===================================================================
EmacsAccessibilityBuffer (Notifications) — AX event dispatch EmacsAccessibilityBuffer (Notifications) — AX event dispatch
@@ -9343,7 +9392,6 @@ - (NSRect)accessibilityFrame @@ -9347,7 +9396,6 @@ - (NSRect)accessibilityFrame
@end @end
@@ -173,7 +173,7 @@ index e8bbc1ffe1..231ae95a17 100644
/* =================================================================== /* ===================================================================
EmacsAccessibilityInteractiveSpan --- helpers and implementation EmacsAccessibilityInteractiveSpan --- helpers and implementation
=================================================================== */ =================================================================== */
@@ -9674,6 +9722,7 @@ - (void)dealloc @@ -9682,6 +9730,7 @@ - (void)dealloc
[layer release]; [layer release];
#endif #endif
@@ -181,7 +181,7 @@ index e8bbc1ffe1..231ae95a17 100644
[[self menu] release]; [[self menu] release];
[super dealloc]; [super dealloc];
} }
@@ -11022,6 +11071,32 @@ - (void)windowDidBecomeKey /* for direct calls */ @@ -11030,6 +11079,32 @@ - (void)windowDidBecomeKey /* for direct calls */
XSETFRAME (event.frame_or_window, emacsframe); XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event); kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop ns_send_appdefined (-1); // Kick main loop
@@ -214,7 +214,7 @@ index e8bbc1ffe1..231ae95a17 100644
} }
@@ -12259,6 +12334,332 @@ - (int) fullscreenState @@ -12267,6 +12342,332 @@ - (int) fullscreenState
return fs_state; return fs_state;
} }
@@ -547,7 +547,7 @@ index e8bbc1ffe1..231ae95a17 100644
@end /* EmacsView */ @end /* EmacsView */
@@ -14255,12 +14656,17 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with @@ -14263,12 +14664,17 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with
ns_use_srgb_colorspace = YES; ns_use_srgb_colorspace = YES;
DEFVAR_BOOL ("ns-accessibility-enabled", ns_accessibility_enabled, DEFVAR_BOOL ("ns-accessibility-enabled", ns_accessibility_enabled,

View File

@@ -1,7 +1,7 @@
From 8bc94f26137898cb050f176c244caa3d3a1c5946 Mon Sep 17 00:00:00 2001 From 09e78385e7ccaf3a74d333f741f408bd2baa88f3 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 7/9] doc: add VoiceOver accessibility section to macOS Subject: [PATCH 6/8] doc: add VoiceOver accessibility section to macOS
appendix appendix
* doc/emacs/macos.texi (VoiceOver Accessibility): New node between * doc/emacs/macos.texi (VoiceOver Accessibility): New node between
@@ -110,10 +110,10 @@ index 6bd334f48e..8d4a7825d8 100644
@section GNUstep Support @section GNUstep Support
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 231ae95a17..062066d4e5 100644 index 95a5b378c1..8a1bfd9eb1 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -14657,9 +14657,13 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with @@ -14665,9 +14665,13 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with
DEFVAR_BOOL ("ns-accessibility-enabled", ns_accessibility_enabled, DEFVAR_BOOL ("ns-accessibility-enabled", ns_accessibility_enabled,
doc: /* Non-nil enables Zoom cursor tracking and VoiceOver support. doc: /* Non-nil enables Zoom cursor tracking and VoiceOver support.

View File

@@ -1,7 +1,7 @@
From 1c8bbd32afe8d5686c8c875feb399a20ea656d72 Mon Sep 17 00:00:00 2001 From 92aec64d791200f54fcd756b5a07581a6c15d0cb Mon Sep 17 00:00:00 2001
From: Daneel <daneel@sukany.cz> From: Daneel <daneel@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 7/8] ns: announce overlay completion candidates for VoiceOver
Completion frameworks such as Vertico, Ivy, and Icomplete render Completion frameworks such as Vertico, Ivy, and Icomplete render
candidates via overlay before-string/after-string properties. Without candidates via overlay before-string/after-string properties. Without
@@ -34,7 +34,7 @@ index 5746e9e9bd..21a93bc799 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 062066d4e5..5e6ab11295 100644 index 8a1bfd9eb1..7fa28222b6 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)
@@ -193,7 +193,7 @@ index 062066d4e5..5e6ab11295 100644
static NSString * static NSString *
ns_ax_buffer_text (struct window *w, ptrdiff_t *out_start, ns_ax_buffer_text (struct window *w, ptrdiff_t *out_start,
ns_ax_visible_run **out_runs, NSUInteger *out_nruns) ns_ax_visible_run **out_runs, NSUInteger *out_nruns)
@@ -7338,7 +7481,7 @@ Accessibility virtual elements (macOS / Cocoa only) @@ -7340,7 +7483,7 @@ Accessibility virtual elements (macOS / Cocoa only)
/* Extract this visible run's text. Use /* Extract this visible run's text. Use
Fbuffer_substring_no_properties which correctly handles the Fbuffer_substring_no_properties which correctly handles the
@@ -202,7 +202,7 @@ index 062066d4e5..5e6ab11295 100644
include garbage bytes when the run spans the gap position. */ include garbage bytes when the run spans the gap position. */
Lisp_Object lstr = Fbuffer_substring_no_properties ( Lisp_Object lstr = Fbuffer_substring_no_properties (
make_fixnum (pos), make_fixnum (run_end)); make_fixnum (pos), make_fixnum (run_end));
@@ -7419,7 +7562,7 @@ Mode lines using icon fonts (e.g. nerd-font icons) @@ -7421,7 +7564,7 @@ Mode lines using icon fonts (e.g. nerd-font icons)
return NSZeroRect; return NSZeroRect;
/* charpos_start and charpos_len are already in buffer charpos /* charpos_start and charpos_len are already in buffer charpos
@@ -211,7 +211,7 @@ index 062066d4e5..5e6ab11295 100644
charposForAccessibilityIndex which handles invisible text. */ charposForAccessibilityIndex which handles invisible text. */
ptrdiff_t cp_start = charpos_start; ptrdiff_t cp_start = charpos_start;
ptrdiff_t cp_end = cp_start + charpos_len; ptrdiff_t cp_end = cp_start + charpos_len;
@@ -7894,6 +8037,7 @@ @implementation EmacsAccessibilityBuffer @@ -7896,6 +8039,7 @@ @implementation EmacsAccessibilityBuffer
@synthesize cachedOverlayModiff; @synthesize cachedOverlayModiff;
@synthesize cachedTextStart; @synthesize cachedTextStart;
@synthesize cachedModiff; @synthesize cachedModiff;
@@ -219,7 +219,7 @@ index 062066d4e5..5e6ab11295 100644
@synthesize cachedPoint; @synthesize cachedPoint;
@synthesize cachedMarkActive; @synthesize cachedMarkActive;
@synthesize cachedCompletionAnnouncement; @synthesize cachedCompletionAnnouncement;
@@ -7991,7 +8135,7 @@ - (void)ensureTextCache @@ -7993,7 +8137,7 @@ - (void)ensureTextCache
NSTRACE ("EmacsAccessibilityBuffer ensureTextCache"); NSTRACE ("EmacsAccessibilityBuffer ensureTextCache");
/* This method is only called from the main thread (AX getters /* This method is only called from the main thread (AX getters
dispatch_sync to main first). Reads of cachedText/cachedTextModiff dispatch_sync to main first). Reads of cachedText/cachedTextModiff
@@ -228,7 +228,7 @@ index 062066d4e5..5e6ab11295 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]);
@@ -8003,25 +8147,16 @@ - (void)ensureTextCache @@ -8005,25 +8149,16 @@ - (void)ensureTextCache
if (!b) if (!b)
return; return;
@@ -262,7 +262,7 @@ index 062066d4e5..5e6ab11295 100644
&& cachedTextStart == BUF_BEGV (b) && cachedTextStart == BUF_BEGV (b)
&& pt >= cachedTextStart && pt >= cachedTextStart
&& (textLen == 0 && (textLen == 0
@@ -8037,7 +8172,7 @@ included in the cached AX text (it is handled separately via @@ -8039,7 +8174,7 @@ included in the cached AX text (it is handled separately via
{ {
[cachedText release]; [cachedText release];
cachedText = [text retain]; cachedText = [text retain];
@@ -271,7 +271,7 @@ index 062066d4e5..5e6ab11295 100644
cachedTextStart = start; cachedTextStart = start;
if (visibleRuns) if (visibleRuns)
@@ -8106,7 +8241,7 @@ - (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos @@ -8108,7 +8243,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
@@ -280,7 +280,7 @@ index 062066d4e5..5e6ab11295 100644
NSUInteger lo = 0, hi = visibleRunCount; NSUInteger lo = 0, hi = visibleRunCount;
while (lo < hi) while (lo < hi)
{ {
@@ -8155,10 +8290,10 @@ by run length (visible window), not total buffer size. */ @@ -8157,10 +8292,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
@@ -293,7 +293,7 @@ index 062066d4e5..5e6ab11295 100644
@synchronized (self) @synchronized (self)
{ {
if (visibleRunCount == 0) if (visibleRunCount == 0)
@@ -8200,7 +8335,7 @@ the slow path (composed character sequence walk), which is @@ -8202,7 +8337,7 @@ the slow path (composed character sequence walk), which is
return cp; return cp;
} }
} }
@@ -302,7 +302,7 @@ index 062066d4e5..5e6ab11295 100644
if (lo > 0) if (lo > 0)
{ {
ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1]; ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1];
@@ -8222,7 +8357,7 @@ the slow path (composed character sequence walk), which is @@ -8224,7 +8359,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
@@ -311,7 +311,7 @@ index 062066d4e5..5e6ab11295 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
@@ -8568,6 +8703,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber @@ -8570,6 +8705,50 @@ - (NSInteger)accessibilityInsertionPointLineNumber
return [self lineForAXIndex:point_idx]; return [self lineForAXIndex:point_idx];
} }
@@ -362,7 +362,7 @@ index 062066d4e5..5e6ab11295 100644
- (NSRange)accessibilityRangeForLine:(NSInteger)line - (NSRange)accessibilityRangeForLine:(NSInteger)line
{ {
if (![NSThread isMainThread]) if (![NSThread isMainThread])
@@ -8790,7 +8969,7 @@ - (NSRect)accessibilityFrame @@ -8792,7 +8971,7 @@ - (NSRect)accessibilityFrame
/* =================================================================== /* ===================================================================
@@ -371,7 +371,7 @@ index 062066d4e5..5e6ab11295 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).
@@ -8805,7 +8984,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point @@ -8807,7 +8986,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point
if (point > self.cachedPoint if (point > self.cachedPoint
&& point - self.cachedPoint == 1) && point - self.cachedPoint == 1)
{ {
@@ -380,7 +380,7 @@ index 062066d4e5..5e6ab11295 100644
[self invalidateTextCache]; [self invalidateTextCache];
[self ensureTextCache]; [self ensureTextCache];
if (cachedText) if (cachedText)
@@ -8824,7 +9003,7 @@ - (void)postTextChangedNotification:(ptrdiff_t)point @@ -8826,7 +9005,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
@@ -389,7 +389,7 @@ index 062066d4e5..5e6ab11295 100644
self.cachedPoint = point; self.cachedPoint = point;
NSDictionary *change = @{ NSDictionary *change = @{
@@ -9216,16 +9395,83 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f @@ -9220,16 +9399,83 @@ - (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) --- */
@@ -477,7 +477,7 @@ index 062066d4e5..5e6ab11295 100644
{ {
ptrdiff_t oldPoint = self.cachedPoint; ptrdiff_t oldPoint = self.cachedPoint;
BOOL oldMarkActive = self.cachedMarkActive; BOOL oldMarkActive = self.cachedMarkActive;
@@ -12350,7 +12596,7 @@ - (int) fullscreenState @@ -12358,7 +12604,7 @@ - (int) fullscreenState
if (WINDOW_LEAF_P (w)) if (WINDOW_LEAF_P (w))
{ {
@@ -486,7 +486,7 @@ index 062066d4e5..5e6ab11295 100644
EmacsAccessibilityBuffer *elem EmacsAccessibilityBuffer *elem
= [existing objectForKey:[NSValue valueWithPointer:w]]; = [existing objectForKey:[NSValue valueWithPointer:w]];
if (!elem) if (!elem)
@@ -12384,7 +12630,7 @@ - (int) fullscreenState @@ -12392,7 +12638,7 @@ - (int) fullscreenState
} }
else else
{ {
@@ -495,7 +495,7 @@ index 062066d4e5..5e6ab11295 100644
Lisp_Object child = w->contents; Lisp_Object child = w->contents;
while (!NILP (child)) while (!NILP (child))
{ {
@@ -12496,7 +12742,7 @@ - (void)postAccessibilityUpdates @@ -12504,7 +12750,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
@@ -504,7 +504,7 @@ index 062066d4e5..5e6ab11295 100644
Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe); Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe);
if (!EQ (curRoot, lastRootWindow)) if (!EQ (curRoot, lastRootWindow))
{ {
@@ -12505,12 +12751,12 @@ - (void)postAccessibilityUpdates @@ -12513,12 +12759,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

View File

@@ -1,7 +1,7 @@
From 3daf00725fe434bfe5e820fd69e390697e9e6373 Mon Sep 17 00:00:00 2001 From a442640322cfb64956e28cc01442c75815718bb9 Mon Sep 17 00:00:00 2001
From: Daneel <daneel@sukany.cz> From: Daneel <daneel@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 8/8] ns: announce child frame completion candidates for
VoiceOver VoiceOver
Child frame popups (Corfu, Company-mode child frames) render completion Child frame popups (Corfu, Company-mode child frames) render completion
@@ -33,8 +33,8 @@ area announcements.
doc/emacs/macos.texi | 14 +- doc/emacs/macos.texi | 14 +-
etc/NEWS | 18 +- etc/NEWS | 18 +-
src/nsterm.h | 20 ++ src/nsterm.h | 20 ++
src/nsterm.m | 537 +++++++++++++++++++++++++++++++++++++++---- src/nsterm.m | 529 +++++++++++++++++++++++++++++++++++++++----
4 files changed, 538 insertions(+), 51 deletions(-) 4 files changed, 530 insertions(+), 51 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 8d4a7825d8..03a657f970 100644 index 8d4a7825d8..03a657f970 100644
@@ -149,7 +149,7 @@ index 21a93bc799..bdd40b8eb7 100644
@end @end
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 5e6ab11295..6e0575677e 100644 index 7fa28222b6..6e0575677e 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -1126,24 +1126,19 @@ Uses CFAbsoluteTimeGetCurrent() (~5 ns, a VDSO read) for timing. */ @@ -1126,24 +1126,19 @@ Uses CFAbsoluteTimeGetCurrent() (~5 ns, a VDSO read) for timing. */
@@ -313,16 +313,7 @@ index 5e6ab11295..6e0575677e 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
@@ -7441,6 +7548,8 @@ visual line index for Zoom (skip whitespace-only lines @@ -8149,16 +8256,32 @@ - (void)ensureTextCache
specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
+ record_unwind_protect_void (unblock_input);
+ block_input ();
if (b != current_buffer)
set_buffer_internal_1 (b);
@@ -8147,16 +8256,32 @@ - (void)ensureTextCache
if (!b) if (!b)
return; return;
@@ -363,7 +354,7 @@ index 5e6ab11295..6e0575677e 100644
&& cachedTextStart == BUF_BEGV (b) && cachedTextStart == BUF_BEGV (b)
&& pt >= cachedTextStart && pt >= cachedTextStart
&& (textLen == 0 && (textLen == 0
@@ -8172,7 +8297,7 @@ included in the cached AX text (it is handled separately via @@ -8174,7 +8297,7 @@ included in the cached AX text (it is handled separately via
{ {
[cachedText release]; [cachedText release];
cachedText = [text retain]; cachedText = [text retain];
@@ -372,7 +363,7 @@ index 5e6ab11295..6e0575677e 100644
cachedTextStart = start; cachedTextStart = start;
if (visibleRuns) if (visibleRuns)
@@ -8585,6 +8710,11 @@ - (void)setAccessibilitySelectedTextRange:(NSRange)range @@ -8587,6 +8710,11 @@ - (void)setAccessibilitySelectedTextRange:(NSRange)range
[self ensureTextCache]; [self ensureTextCache];
@@ -384,7 +375,7 @@ index 5e6ab11295..6e0575677e 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
@@ -9040,15 +9170,23 @@ - (void)postFocusedCursorNotification:(ptrdiff_t)point @@ -9042,15 +9170,23 @@ - (void)postFocusedCursorNotification:(ptrdiff_t)point
= @(ns_ax_text_state_change_selection_move); = @(ns_ax_text_state_change_selection_move);
moveInfo[@"AXTextSelectionDirection"] = @(direction); moveInfo[@"AXTextSelectionDirection"] = @(direction);
moveInfo[@"AXTextChangeElement"] = self; moveInfo[@"AXTextChangeElement"] = self;
@@ -414,7 +405,7 @@ index 5e6ab11295..6e0575677e 100644
NSAccessibilitySelectedTextChangedNotification, NSAccessibilitySelectedTextChangedNotification,
moveInfo); moveInfo);
@@ -9146,12 +9284,17 @@ user expectation ("w" jumps to next word and reads it). */ @@ -9148,12 +9284,17 @@ user expectation ("w" jumps to next word and reads it). */
} }
} }
@@ -437,22 +428,19 @@ index 5e6ab11295..6e0575677e 100644
if (cachedText if (cachedText
&& granularity == ns_ax_text_selection_granularity_line) && granularity == ns_ax_text_selection_granularity_line)
{ {
@@ -9214,7 +9357,14 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b @@ -9218,6 +9359,11 @@ - (void)postCompletionAnnouncementForBuffer:(struct buffer *)b
ptrdiff_t currentOverlayStart = 0;
ptrdiff_t currentOverlayEnd = 0;
+ block_input (); block_input ();
specpdl_ref count2 = SPECPDL_INDEX (); specpdl_ref count2 = SPECPDL_INDEX ();
+ /* Register unblock_input as an unwind action so that if any Lisp + /* Register unblock_input as an unwind action so that if any Lisp
+ call below signals (triggering a longjmp through unbind_to), + call below signals (triggering a longjmp through unbind_to),
+ block_input is always paired with an unblock_input. The + block_input is always paired with an unblock_input. The
+ unbind_to call at the end of the function unwinds this. + unbind_to call at the end of the function unwinds this.
+ record_unwind_protect_void plus unbind_to is idempotent. */ + record_unwind_protect_void plus unbind_to is idempotent. */
+ 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)
set_buffer_internal_1 (b); @@ -9394,12 +9540,29 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
@@ -9390,12 +9540,29 @@ - (void)postAccessibilityNotificationsForFrame:(struct frame *)f
if (!b) if (!b)
return; return;
@@ -482,7 +470,7 @@ index 5e6ab11295..6e0575677e 100644
if (modiff != self.cachedModiff) if (modiff != self.cachedModiff)
{ {
self.cachedModiff = modiff; self.cachedModiff = modiff;
@@ -9409,6 +9576,7 @@ Text property changes (e.g. face updates from @@ -9413,6 +9576,7 @@ Text property changes (e.g. face updates from
{ {
self.cachedCharsModiff = chars_modiff; self.cachedCharsModiff = chars_modiff;
[self postTextChangedNotification:point]; [self postTextChangedNotification:point];
@@ -490,7 +478,7 @@ index 5e6ab11295..6e0575677e 100644
} }
} }
@@ -9431,8 +9599,15 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property @@ -9435,8 +9599,15 @@ 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.
@@ -508,7 +496,7 @@ index 5e6ab11295..6e0575677e 100644
goto skip_overlay_scan; goto skip_overlay_scan;
int selected_line = -1; int selected_line = -1;
@@ -9478,7 +9653,18 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property @@ -9482,7 +9653,18 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
self.cachedPoint = point; self.cachedPoint = point;
self.cachedMarkActive = markActive; self.cachedMarkActive = markActive;
@@ -528,7 +516,7 @@ index 5e6ab11295..6e0575677e 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;
@@ -9526,6 +9712,58 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property @@ -9530,6 +9712,58 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
granularity = ns_ax_text_selection_granularity_line; granularity = ns_ax_text_selection_granularity_line;
} }
@@ -587,7 +575,7 @@ index 5e6ab11295..6e0575677e 100644
/* Post notifications for focused and non-focused elements. */ /* Post notifications for focused and non-focused elements. */
if ([self isAccessibilityFocused]) if ([self isAccessibilityFocused])
[self postFocusedCursorNotification:point [self postFocusedCursorNotification:point
@@ -9668,6 +9906,17 @@ - (NSRect)accessibilityFrame @@ -9672,6 +9906,13 @@ - (NSRect)accessibilityFrame
if (vis_start >= vis_end) if (vis_start >= vis_end)
return @[]; return @[];
@@ -598,14 +586,10 @@ index 5e6ab11295..6e0575677e 100644
+ that could modify buffer state (e.g. invalidate vis_end). + that could modify buffer state (e.g. invalidate vis_end).
+ record_unwind_protect_void guarantees unblock_input even if + record_unwind_protect_void guarantees unblock_input even if
+ a Lisp call signals. */ + a Lisp call signals. */
+ 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);
+ @@ -9796,6 +10037,7 @@ than O(chars). Fall back to pos+1 as safety net. */
/* Symbols are interned once at startup via DEFSYM in syms_of_nsterm;
reference them directly here (GC-safe, no repeated obarray lookup). */
@@ -9788,6 +10037,7 @@ than O(chars). Fall back to pos+1 as safety net. */
pos = span_end; pos = span_end;
} }
@@ -613,7 +597,7 @@ index 5e6ab11295..6e0575677e 100644
return [[spans copy] autorelease]; return [[spans copy] autorelease];
} }
@@ -9969,6 +10219,10 @@ - (void)dealloc @@ -9977,6 +10219,10 @@ - (void)dealloc
#endif #endif
[accessibilityElements release]; [accessibilityElements release];
@@ -624,7 +608,7 @@ index 5e6ab11295..6e0575677e 100644
[[self menu] release]; [[self menu] release];
[super dealloc]; [super dealloc];
} }
@@ -11418,6 +11672,10 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f @@ -11426,6 +11672,10 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
windowClosing = NO; windowClosing = NO;
processingCompose = NO; processingCompose = NO;
@@ -635,7 +619,7 @@ index 5e6ab11295..6e0575677e 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;
@@ -12726,6 +12984,154 @@ - (id)accessibilityFocusedUIElement @@ -12734,6 +12984,154 @@ - (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. */
@@ -790,7 +774,7 @@ index 5e6ab11295..6e0575677e 100644
- (void)postAccessibilityUpdates - (void)postAccessibilityUpdates
{ {
NSTRACE ("[EmacsView postAccessibilityUpdates]"); NSTRACE ("[EmacsView postAccessibilityUpdates]");
@@ -12736,11 +13142,64 @@ - (void)postAccessibilityUpdates @@ -12744,11 +13142,64 @@ - (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