Files
emacs-doom/patches/0006-doc-add-VoiceOver-accessibility-section-to-macOS-app.patch
Daneel 010630f33d patches: review pass 4 - fix BUF_MODIFF->BUF_CHARS_MODIFF in P0007
P0007 (announce overlay candidates) incorrectly changed ensureTextCache
to use BUF_MODIFF, causing O(buffer-size) AX text rebuilds on every
font-lock pass.  Reverted to BUF_CHARS_MODIFF throughout.

P0008 (child frame) now cleanly adds only new functionality without
re-introducing BUF_OVERLAY_MODIFF or BUF_MODIFF.

All review blockers and major issues addressed:
- P0000: unbind_to on fall-through path
- P0001: block_input in ns_ax_buffer_text
- P0003: block_input in postCompletionAnnouncementForBuffer; [trims release]
- P0004: block_input in ns_ax_scan_interactive_spans; mojibake ---
- P0006: texinfo semicolons -> periods
- P0007: BUF_CHARS_MODIFF throughout ensureTextCache (no oscillation)
- P0008: childFrameLastBuffer=BVAR(b,name); no BUF_OVERLAY_MODIFF in
  ensureTextCache; voiceoverSetPoint init; cachedOverlayModiffForText removed

git am passes all 9 patches on Linux git 2.43.0.
2026-03-02 19:36:23 +01:00

136 lines
5.4 KiB
Diff

From 7e419d0b59c4d4cbec800306a61eecaaa1921500 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 6/8] doc: add VoiceOver accessibility section to macOS
appendix
* doc/emacs/macos.texi (VoiceOver Accessibility): New node between
'Mac / GNUstep Events' and 'GNUstep Support'. Document screen reader
usage, keyboard navigation, completion announcements, ns-accessibility-
enabled, and known limitations. Use @xref for cross-reference at
sentence start. Correct description of ns-accessibility-enabled
default: initial value is nil, set automatically at startup.
---
doc/emacs/macos.texi | 76 ++++++++++++++++++++++++++++++++++++++++++++
src/nsterm.m | 10 ++++--
2 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index 6bd334f48e..8d4a7825d8 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -36,6 +36,7 @@ Support}), but we hope to improve it in the future.
* Mac / GNUstep Basics:: Basic Emacs usage under GNUstep or macOS.
* Mac / GNUstep Customization:: Customizations under GNUstep or macOS.
* Mac / GNUstep Events:: How window system events are handled.
+* VoiceOver Accessibility:: Screen reader support on macOS.
* GNUstep Support:: Details on status of GNUstep support.
@end menu
@@ -272,6 +273,81 @@ and return the result as a string. You can also use the Lisp function
services and receive the results back. Note that you may need to
restart Emacs to access newly-available services.
+@node VoiceOver Accessibility
+@section VoiceOver Accessibility (macOS)
+@cindex VoiceOver
+@cindex accessibility (macOS)
+@cindex screen reader (macOS)
+@cindex Zoom, cursor tracking (macOS)
+
+ When built with the Cocoa interface on macOS, Emacs exposes buffer
+content, cursor position, mode lines, and interactive elements to the
+macOS accessibility subsystem. This enables use with VoiceOver,
+Apple's built-in screen reader, and with other assistive technology
+such as macOS Zoom.
+
+ Toggle VoiceOver with @kbd{Cmd-F5} (or via System Settings,
+Accessibility, VoiceOver). When Emacs is focused, VoiceOver announces
+the buffer name and current line. Standard Emacs navigation produces
+speech feedback:
+
+@itemize @bullet
+@item
+Arrow keys read individual characters (left/right) or full lines
+(up/down).
+@item
+@kbd{M-f} and @kbd{M-b} announce words.
+@item
+@kbd{C-n} and @kbd{C-p} read the destination line.
+@item
+Shift-modified movement announces selected or deselected text.
+@item
+@key{TAB} and @kbd{S-@key{TAB}} navigate interactive elements
+(buttons, links, completion candidates) within a buffer.
+@end itemize
+
+ The @file{*Completions*} buffer announces each completion candidate
+as you navigate, even while keyboard focus remains in the minibuffer.
+
+ macOS Zoom (System Settings, Accessibility, Zoom) tracks the Emacs
+cursor automatically when set to follow keyboard focus. The cursor
+position is communicated via @code{UAZoomChangeFocus} and the
+@code{AXBoundsForRange} accessibility attribute.
+
+@vindex ns-accessibility-enabled
+ To disable the accessibility interface entirely (for instance, to
+eliminate overhead on systems where assistive technology is not in
+use), set @code{ns-accessibility-enabled} to @code{nil}. Emacs
+detects the presence of assistive technology at startup and sets this
+variable automatically; the initial value is @code{nil}.
+
+@subheading Known Limitations
+
+@itemize @bullet
+@item
+Very large buffers (tens of megabytes) may cause slow initial
+accessibility text extraction. Once cached, subsequent queries
+are fast.
+@item
+Mode-line text extraction handles only character glyphs. Mode lines
+using icon fonts (e.g., icon-based mode-lines)
+produce incomplete accessibility text.
+@item
+The accessibility virtual element tree is rebuilt automatically on
+window configuration changes (splits, deletions, new buffers).
+@item
+Right-to-left (bidi) text is exposed correctly as buffer content,
+but @code{accessibilityRangeForPosition} hit-testing assumes
+left-to-right glyph layout.
+@end itemize
+
+ This support is available only on the Cocoa build. GNUstep has a
+different accessibility model and is not yet supported.
+Block-style cursors are handled
+correctly: character navigation announces the character at the cursor
+position, not the character before it.
+
+
@node GNUstep Support
@section GNUstep Support
diff --git a/src/nsterm.m b/src/nsterm.m
index 95a5b378c1..8a1bfd9eb1 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -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,
doc: /* Non-nil enables Zoom cursor tracking and VoiceOver support.
-Emacs sets this automatically at startup when macOS Zoom is active or
-any assistive technology (VoiceOver, Switch Control, etc.) is connected,
-and updates it whenever that state changes. You can override manually:
+Emacs detects at startup whether macOS Zoom is active or an assistive
+technology (VoiceOver, Switch Control, etc.) is connected, and sets
+this variable accordingly. It updates automatically when accessibility
+state changes. The initial value is nil; it becomes non-nil only when
+an AT is detected.
+
+You can override the auto-detection:
(setq ns-accessibility-enabled t) ; always on
(setq ns-accessibility-enabled nil) ; always off
--
2.43.0