v7 patch: fix Zoom snapping to old window on C-x o

Guard accessibility notifications with on_p && active_p so they only
fire when drawing the cursor in the selected window. Without this,
ns_draw_window_cursor is called for both old and new windows during
redisplay, and UAZoomChangeFocus fires for the old window last.
This commit is contained in:
2026-02-25 20:10:12 +01:00
parent 15a7c927f4
commit d0cd1f103b

View File

@@ -1,5 +1,5 @@
From: Martin Sukany <martin@sukany.cz>
Date: Tue, 25 Feb 2026 19:20:00 +0100
Date: Tue, 25 Feb 2026 20:10:00 +0100
Subject: [PATCH] ns: implement macOS Zoom cursor tracking and VoiceOver
support via UAZoomChangeFocus + NSAccessibility
@@ -19,12 +19,10 @@ Add cursor tracking and screen reader support for macOS accessibility:
movement), FocusedUIElementChanged (window focus).
Ref: https://developer.apple.com/documentation/appkit/nsaccessibilityprotocol
accessibilityFrame returns the view's frame (standard behavior) so
VoiceOver draws its focus ring around the text area. Cursor position
is exposed via accessibilityBoundsForRange: only.
Both mechanisms are needed: UAZoomChangeFocus serves Zoom; NSAccessibility
serves VoiceOver. Same dual pattern used by iTerm2.
Accessibility notifications are only posted when drawing the cursor in
the active (selected) window (on_p && active_p guard). Without this,
C-x o (other-window) triggers UAZoomChangeFocus for the old window
last, snapping Zoom back to it.
---
diff --git a/src/nsterm.h b/src/nsterm.h
index 7c1ee4c..6c1ff34 100644
@@ -41,10 +39,10 @@ index 7c1ee4c..6c1ff34 100644
/* AppKit-side interface. */
diff --git a/src/nsterm.m b/src/nsterm.m
index 932d209..2576c96 100644
index 932d209..e6b1699 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3232,6 +3232,72 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -3232,6 +3232,77 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
/* Prevent the cursor from being drawn outside the text area. */
r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
@@ -75,7 +73,12 @@ index 932d209..2576c96 100644
+ serves macOS Zoom's "Follow keyboard focus" feature. */
+ {
+ EmacsView *view = FRAME_NS_VIEW (f);
+ if (view)
+ /* Only notify AT when drawing the cursor in the active
+ (selected) window. ns_draw_window_cursor is called for
+ all windows during redisplay (to draw or erase cursors);
+ without this guard, C-x o triggers UAZoomChangeFocus for
+ the old window last, snapping Zoom back to it. */
+ if (view && on_p && active_p)
+ {
+ /* Store cursor rect for accessibilityBoundsForRange: queries. */
+ view->lastAccessibilityCursorRect = r;
@@ -117,7 +120,7 @@ index 932d209..2576c96 100644
ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -8237,6 +8303,15 @@ - (void)windowDidBecomeKey /* for direct calls */
@@ -8237,6 +8308,15 @@ - (void)windowDidBecomeKey /* for direct calls */
XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop
@@ -133,7 +136,7 @@ index 932d209..2576c96 100644
}
@@ -9474,6 +9549,310 @@ - (int) fullscreenState
@@ -9474,6 +9554,310 @@ - (int) fullscreenState
return fs_state;
}