patches: add Zoom completion tracking (overlay + child frame)

Zoom patch 0000 now tracks completion candidates:
- Overlay: Vertico, Icomplete, Ivy (face heuristic on before-string)
- Child frame: Corfu, Company-box (scan buffer text for selected face)
Also fixes duplicate lastCursorRect ivar when applied with VoiceOver.
This commit is contained in:
2026-03-01 03:38:58 +01:00
parent 9110eee881
commit b283068f82
9 changed files with 340 additions and 86 deletions

View File

@@ -1,4 +1,4 @@
From f10036eeadf681cd87bbec7ec0581b572053c38a Mon Sep 17 00:00:00 2001
From be594f584a94e6fccd649be029c1af30242a12ee 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/9] ns: integrate accessibility with EmacsView and redisplay
@@ -23,14 +23,14 @@ block cursor, org-mode folded headings, indirect buffers.
Known limitations documented in patch 6 Texinfo node.
---
etc/NEWS | 13 ++
src/nsterm.m | 369 +++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 374 insertions(+), 8 deletions(-)
src/nsterm.m | 376 +++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 376 insertions(+), 13 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index f10d17e..f48d05b 100644
index 80661a9..2b1f9e6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -4397,6 +4397,19 @@ allowing Emacs users access to speech recognition utilities.
@@ -4400,6 +4400,19 @@ allowing Emacs users access to speech recognition utilities.
Note: Accepting this permission allows the use of system APIs, which may
send user data to Apple's speech recognition servers.
@@ -51,20 +51,28 @@ index f10d17e..f48d05b 100644
** Re-introduced dictation, lost in Emacs v30 (macOS).
We lost macOS dictation in v30 when migrating to NSTextInputClient.
diff --git a/src/nsterm.m b/src/nsterm.m
index 907ce47..d813274 100644
index 86bb7b6..2e8ae20 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1133,6 +1133,9 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
@@ -1343,13 +1343,16 @@ so the visual offset is (ov_line + 1) * line_h from
}
if (view)
view->zoomCursorUpdated = NO;
#endif
-#endif
/* Track completion candidates for Zoom (overlay and child frame).
Runs after cursor tracking so the selected candidate overrides
the default cursor position. */
if (view)
ns_zoom_track_completion (f, view);
+#endif
+
+ /* Post accessibility notifications after each redisplay cycle. */
+ [view postAccessibilityUpdates];
#endif /* NS_IMPL_COCOA */
}
@@ -3263,11 +3266,11 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -3480,15 +3483,12 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
#ifdef NS_IMPL_COCOA
@@ -73,15 +81,20 @@ index 907ce47..d813274 100644
- element to keep the zoomed viewport centered on the cursor.
-
- Coordinate conversion:
+ /* Store cursor rect and inform macOS Zoom / VoiceOver.
+ lastCursorRect is used by:
+ - Zoom: UAZoomChangeFocus below (unconditional when active)
+ - VoiceOver: accessibilityBoundsForRange: fallback
- EmacsView pixels (AppKit, flipped, top-left origin)
- -> NSWindow (convertRect:toView:nil)
- -> NSScreen (convertRectToScreen:)
- -> CGRect with y-flip for CoreGraphics top-left origin. */
+ /* Store cursor rect for Zoom and VoiceOver bounds queries.
+ Zoom: UAZoomChangeFocus below.
+ VoiceOver: accessibilityBoundsForRange: fallback.
+ Coordinate conversion for Zoom:
EmacsView pixels (AppKit, flipped, top-left origin)
-> NSWindow (convertRect:toView:nil)
-> NSScreen (convertRectToScreen:)
@@ -7349,7 +7352,6 @@ - (id)accessibilityTopLevelUIElement
+ EmacsView (AppKit, flipped) -> NSWindow -> NSScreen
+ -> CGRect with y-flip for CoreGraphics top-left origin. */
{
EmacsView *view = FRAME_NS_VIEW (f);
if (view && on_p && active_p)
@@ -7566,7 +7566,6 @@ - (id)accessibilityTopLevelUIElement
@@ -89,7 +102,7 @@ index 907ce47..d813274 100644
static BOOL
ns_ax_find_completion_overlay_range (struct buffer *b, ptrdiff_t point,
ptrdiff_t *out_start,
@@ -8444,7 +8446,6 @@ - (NSRect)accessibilityFrame
@@ -8661,7 +8660,6 @@ - (NSRect)accessibilityFrame
@end
@@ -97,7 +110,7 @@ index 907ce47..d813274 100644
/* ===================================================================
EmacsAccessibilityBuffer (Notifications) — AX event dispatch
@@ -8989,7 +8990,6 @@ - (NSRect)accessibilityFrame
@@ -9206,7 +9204,6 @@ - (NSRect)accessibilityFrame
@end
@@ -105,7 +118,7 @@ index 907ce47..d813274 100644
/* ===================================================================
EmacsAccessibilityInteractiveSpan — helpers and implementation
=================================================================== */
@@ -9319,6 +9319,7 @@ - (void)dealloc
@@ -9536,6 +9533,7 @@ - (void)dealloc
[layer release];
#endif
@@ -113,7 +126,7 @@ index 907ce47..d813274 100644
[[self menu] release];
[super dealloc];
}
@@ -10667,6 +10668,32 @@ - (void)windowDidBecomeKey /* for direct calls */
@@ -10884,6 +10882,32 @@ - (void)windowDidBecomeKey /* for direct calls */
XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop
@@ -146,7 +159,7 @@ index 907ce47..d813274 100644
}
@@ -11904,6 +11931,332 @@ - (int) fullscreenState
@@ -12121,6 +12145,332 @@ - (int) fullscreenState
return fs_state;
}