- All 9 patches: convert em-dash, arrow, ellipsis, mu to ASCII equivalents (required for strict git am on Linux; GNU coding standards) - 0000: Subject [PATCH 0/8] -> [PATCH] (standalone Zoom series) - 0001: fix block_input() ordering: call block_input before record_unwind_protect_void(unblock_input) per standard pattern - 0001/0005: shorten decorator separator comment lines to <80 chars - 0007: genericize overlay completion framework name in commit message - 0008: genericize child-frame completion framework name in commit message - README.txt: fix stale 'default t' to 'default nil' with auto-detection note - TESTING.txt: fix stale 'defaults to t' to 'defaults to nil'
130 lines
4.4 KiB
Plaintext
130 lines
4.4 KiB
Plaintext
EMACS NS ACCESSIBILITY PATCHES
|
|
================================
|
|
author: Martin Sukany <martin@sukany.cz>
|
|
|
|
This directory contains two independent patch sets for the Emacs NS
|
|
(Cocoa) port:
|
|
|
|
A. Standalone Zoom patch (0000)
|
|
B. VoiceOver accessibility patch series (0001-0008)
|
|
|
|
Each can be applied independently. They do not depend on each other.
|
|
|
|
|
|
PATCH A: ZOOM CURSOR TRACKING (0000)
|
|
-------------------------------------
|
|
|
|
0000 ns: integrate with macOS Zoom for cursor tracking
|
|
|
|
A minimal patch that informs macOS Zoom of the text cursor position
|
|
after every physical cursor redraw. When Zoom is enabled (System
|
|
Settings -> Accessibility -> Zoom -> Follow keyboard focus), the
|
|
zoomed viewport automatically tracks the Emacs insertion point.
|
|
|
|
Files modified:
|
|
src/nsterm.h (+4 lines: lastZoomCursorRect ivar)
|
|
src/nsterm.m (+66 lines: cursor store + UAZoomChangeFocus)
|
|
etc/NEWS (+8 lines)
|
|
|
|
Implementation:
|
|
ns_draw_window_cursor stores the cursor rect in
|
|
view->lastZoomCursorRect and calls UAZoomChangeFocus() with
|
|
CG-space coordinates. A fallback call in ns_update_end ensures
|
|
Zoom tracks the cursor even after window switches (C-x o) where
|
|
the physical cursor may not be redrawn.
|
|
|
|
Coordinate conversion: EmacsView pixels (AppKit, flipped) ->
|
|
NSWindow -> NSScreen -> CGRect with y-flip for CoreGraphics
|
|
top-left origin.
|
|
|
|
No user option is needed: UAZoomEnabled() returns false when Zoom
|
|
is not active, so the overhead is a single function call per
|
|
redisplay cycle.
|
|
|
|
|
|
PATCH B: VOICEOVER ACCESSIBILITY (0001-0008)
|
|
----------------------------------------------
|
|
|
|
0001 ns: add accessibility base classes and text extraction
|
|
0002 ns: implement buffer accessibility element (core protocol)
|
|
0003 ns: add buffer notification dispatch and mode-line element
|
|
0004 ns: add interactive span elements for Tab navigation
|
|
0005 ns: integrate accessibility with EmacsView and redisplay
|
|
0006 doc: add VoiceOver accessibility section to macOS appendix
|
|
0007 ns: announce overlay completion candidates for VoiceOver
|
|
0008 ns: announce child frame completion candidates for VoiceOver
|
|
|
|
Files modified:
|
|
src/nsterm.h (~120 lines: class declarations, ivars)
|
|
src/nsterm.m (~3400 lines: implementation)
|
|
doc/emacs/macos.texi (~50 lines: documentation)
|
|
etc/NEWS (~8 lines)
|
|
|
|
This patch series adds comprehensive VoiceOver accessibility support
|
|
to the NS port. Before this patch, Emacs exposed only a minimal,
|
|
largely broken accessibility interface: EmacsView identified itself
|
|
as a generic NSAccessibilityGroup with no text content, no cursor
|
|
tracking, and no notifications.
|
|
|
|
|
|
ARCHITECTURE
|
|
------------
|
|
|
|
Virtual element tree above EmacsView:
|
|
|
|
EmacsAccessibilityElement (base)
|
|
+-- EmacsAccessibilityBuffer (AXTextArea; one per window)
|
|
+-- EmacsAccessibilityModeLine (AXStaticText; mode line)
|
|
+-- EmacsAccessibilityInteractiveSpan (AXButton/Link; Tab nav)
|
|
|
|
Each buffer element maintains a text cache with visible-run mapping
|
|
(O(log n) index lookup) and a precomputed line index (O(log L) line
|
|
queries). Notifications are posted asynchronously via dispatch_async
|
|
to prevent VoiceOver deadlocks.
|
|
|
|
Full details in the commit messages of each patch.
|
|
|
|
|
|
PERFORMANCE
|
|
-----------
|
|
|
|
ns-accessibility-enabled (DEFVAR_BOOL, default t):
|
|
When nil, no virtual elements are built, no notifications are
|
|
posted, and ns_draw_window_cursor skips the cursor rect store.
|
|
Zero overhead for users who do not use assistive technology.
|
|
|
|
When enabled:
|
|
- Text cache rebuilds only on BUF_MODIFF change (not per-keystroke)
|
|
- Index lookups are O(log n) via binary search on visible runs
|
|
- Line queries are O(log L) via precomputed lineStartOffsets
|
|
- Interactive span scan runs only when dirty flag is set
|
|
- No character cap: full buffer exposed, but cache is lazy
|
|
|
|
|
|
THREADING MODEL
|
|
---------------
|
|
|
|
Main thread: all Lisp calls, buffer mutations, notification posting.
|
|
AX thread: VoiceOver queries dispatch_sync to main thread.
|
|
Async notifications: dispatch_async prevents deadlock (same pattern
|
|
as WebKit's AXObjectCacheMac).
|
|
|
|
|
|
KNOWN LIMITATIONS
|
|
-----------------
|
|
|
|
- Mode line: CHAR_GLYPH only (icon fonts produce incomplete text)
|
|
- Overlay face matching: string containment ("current", "selected")
|
|
- GNUstep excluded (#ifdef NS_IMPL_COCOA)
|
|
- No multi-frame coordination
|
|
- Child frame static lastCandidate leaks at exit (minor)
|
|
|
|
|
|
TESTING
|
|
-------
|
|
|
|
See TESTING.txt for the full test matrix and results.
|
|
|
|
|
|
-- end of README --
|