patches: fix review B1/W1-5 — unwind protection, dealloc leak, DEFSYM nav, lineRange, buffer validation, select-window

B1: setAccessibilitySelectedTextRange: — add record_unwind_protect_void(unblock_input)
    before block_input to prevent permanently blocked input if Fset_marker signals.
W1: EmacsAccessibilityInteractiveSpan — add -dealloc releasing spanLabel/spanValue
    (MRC copy properties leaked on every span rebuild cycle).
W2: ns_ax_event_is_line_nav_key — replace 8x intern_c_string with DEFSYM'd symbols
    (Qns_ax_next_line etc.) to avoid per-cursor-move obarray lookups.
W3: accessibilityRangeForLine: — rewrite from O(n chars) characterAtIndex loop to
    O(lines) lineRangeForRange, matching accessibilityLineForIndex: pattern.
W4: accessibilityChildrenInNavigationOrder — validate buffer before calling
    ns_ax_scan_interactive_spans to prevent Lisp signals in dispatch_sync context.
W5: EmacsAccessibilityBuffer setAccessibilityFocused: — add Fselect_window so
    VoiceOver focus actually switches the Emacs selected window, with proper
    unwind protection for block_input.
This commit is contained in:
2026-02-27 16:38:12 +01:00
parent 936c251f11
commit 765725aaef
2 changed files with 97 additions and 55 deletions

View File

@@ -2,8 +2,8 @@ EMACS NS VOICEOVER ACCESSIBILITY PATCH
========================================
patch: 0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch
author: Martin Sukany <martin@sukany.cz>
files: src/nsterm.h (+108 lines)
src/nsterm.m (+2638 ins, -140 del, +2498 net)
files: src/nsterm.h (+105 lines)
src/nsterm.m (+2844 ins, -149 del, +2695 net)
OVERVIEW
@@ -425,12 +425,15 @@ ZOOM INTEGRATION
KEY DESIGN DECISIONS
--------------------
1. DEFSYM instead of intern for property symbols.
1. DEFSYM instead of intern for all frequently-used symbols.
DEFSYM registers symbols at startup (syms_of_nsterm) and stores
them in C globals (e.g. Qcompletion__string). Using intern() at
every AX scan would perform an obarray lookup on each redisplay
cycle. DEFSYM symbols are also always reachable by the GC via
staticpro, eliminating any risk of premature collection.
them in C globals (e.g. Qns_ax_completion__string, Qns_ax_next_line).
This covers both property scanning symbols and line navigation
command symbols used in ns_ax_event_is_line_nav_key (hot path:
runs on every cursor movement). Using intern() would perform
obarray lookups on each redisplay cycle. DEFSYM symbols are
also always reachable by the GC via staticpro, eliminating any
risk of premature collection.
2. AnnouncementRequested for character moves, not SelectedTextChanged.
VoiceOver derives the speech character from SelectedTextChanged by
@@ -503,11 +506,12 @@ KNOWN LIMITATIONS
covers the common case, but overlay-only changes with a stationary
point would be missed. A future fix would compare overlay_modiff.
- Interactive span scan uses property-change jumps to skip
non-interactive regions, but still visits every property boundary. For
large visible buffers this scan runs on every redisplay cycle
whenever interactiveSpansDirty is set. An optimization would use
next_single_property_change to skip non-interactive regions in bulk.
- Interactive span scan uses Fnext_single_property_change across
multiple properties to skip non-interactive regions in bulk, but
still visits every property-change boundary. For buffers with
many overlapping text properties (e.g. heavily fontified source
code), the number of boundaries can be significant. The scan
runs on every redisplay cycle when interactiveSpansDirty is set.
- Mode line text is extracted from CHAR_GLYPH rows only. Image
glyphs, stretch glyphs, and composed glyphs are silently skipped.