patches: comprehensive review fixes — B1/W1-4/M1-4

B1: setAccessibilityFocused: on EmacsAccessibilityBuffer now checks
    ![NSThread isMainThread] and dispatches to main via dispatch_async.
    Prevents data race + AppKit thread violation from AX server thread.

W1: accessibilityInsertionPointLineNumber and accessibilityLineForIndex:
    now use lineRangeForRange iteration — O(lines) instead of O(chars).

W2: ns_ax_scan_interactive_spans skips non-interactive regions using
    Fnext_single_property_change for each scannable property and
    Fnext_single_char_property_change for keymap overlays.

W3: ns_ax_event_is_line_nav_key inspects Vthis_command against known
    navigation command symbols (next-line, previous-line, evil variants,
    dired variants) instead of raw key codes. Tab/backtab fallback
    retained via last_command_event.

W4: DEFSYM symbols renamed with ns_ax_ prefix (Qns_ax_button, etc.)
    to avoid linker collisions with other Emacs source files.
    Lisp symbol strings unchanged.

M3: Removed dead enum values (CheckBox, TextField, PopUpButton) and
    corresponding dead switch cases.

M4: Improved accessibilityStyleRangeForIndex: comment documenting the
    line-granularity simplification.

README: Updated stats, KNOWN LIMITATIONS, DEFSYM docs, test numbering.
This commit is contained in:
2026-02-27 16:14:47 +01:00
parent a6a3aca678
commit 936c251f11
2 changed files with 163 additions and 103 deletions

View File

@@ -3,7 +3,7 @@ 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 (+2588 ins, -140 del, +2448 net)
src/nsterm.m (+2638 ins, -140 del, +2498 net)
OVERVIEW
@@ -36,8 +36,6 @@ OVERVIEW
also covers completion announcements for the *Completions* buffer and
Tab-navigable interactive spans for buttons, links, checkboxes,
Org-mode links, completion candidates, and keymap overlays.
(EmacsAXSpanTypeCheckBox is reserved for future use but not
currently scanned.)
ARCHITECTURE
@@ -367,10 +365,10 @@ INTERACTIVE SPANS
column-adjacent completion candidates from being merged into one span
when their mouse-face regions share padding whitespace.
All property symbols (Qwidget, Qbutton, Qfollow_link, Qorg_link,
Qcompletion__string, Qcompletion, Qcompletions_highlight, Qbacktab,
Qcompletion_list_mode) are registered with DEFSYM in syms_of_nsterm
and referenced directly -- no repeated intern() calls.
All property symbols are registered with DEFSYM in syms_of_nsterm
using ns_ax_ prefixed C variable names (e.g., Qns_ax_button for
"button") to avoid collisions with other Emacs source files.
Referenced directly -- no repeated intern() calls.
Each span is allocated, configured, added to the spans array, then
released (the array retains it). The function returns an autoreleased
@@ -505,8 +503,8 @@ 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 is O(n) in the visible buffer range. Every
character position is visited to find property boundaries. For
- 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.
@@ -516,6 +514,12 @@ KNOWN LIMITATIONS
Mode lines with icon fonts (e.g. doom-modeline with nerd-font)
produce incomplete or garbled accessibility text.
- Line counting (accessibilityInsertionPointLineNumber,
accessibilityLineForIndex:) uses O(lines) iteration via
lineRangeForRange. For buffers with tens of thousands of visible
lines this is acceptable but not optimal. A line-number cache
keyed on cachedTextModiff could reduce this to O(1).
- Buffers larger than NS_AX_TEXT_CAP (100,000 UTF-16 units) are
truncated. The truncation is silent; AT tools navigating past the
truncation boundary may behave unexpectedly.
@@ -527,11 +531,11 @@ KNOWN LIMITATIONS
has a different accessibility model and requires separate work.
- Line navigation detection (ns_ax_event_is_line_nav_key) checks
raw key codes (C-n = 14, C-p = 16, Tab = 9, backtab symbol).
Users who remap keys to navigation commands (e.g. C-j -> next-line)
will not get forced line-granularity announcements for those
bindings. A future improvement would inspect Vthis_command
against known navigation command symbols instead.
Vthis_command against known navigation command symbols
(next-line, previous-line, evil-next-line, etc.) and falls back
to raw key codes for Tab/backtab. Custom navigation commands
not in the recognized list will not get forced line-granularity
announcements.
- UAZoomChangeFocus always uses kUAZoomFocusTypeInsertionPoint
regardless of cursor style (box, bar, hbar). This is cosmetically
@@ -600,9 +604,9 @@ TESTING CHECKLIST
C-x o to switch windows. Emacs must not hang.
Stress test:
26. Open a large file (>5000 lines). Navigate with C-v / M-v.
25. Open a large file (>5000 lines). Navigate with C-v / M-v.
Verify no significant lag in VoiceOver speech response.
27. Open an org-mode file with many folded sections. Verify that
26. Open an org-mode file with many folded sections. Verify that
folded (invisible) text is not announced during navigation.
-- end of README --