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> 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 Subject: [PATCH] ns: implement macOS Zoom cursor tracking and VoiceOver
support via UAZoomChangeFocus + NSAccessibility support via UAZoomChangeFocus + NSAccessibility
@@ -19,12 +19,10 @@ Add cursor tracking and screen reader support for macOS accessibility:
movement), FocusedUIElementChanged (window focus). movement), FocusedUIElementChanged (window focus).
Ref: https://developer.apple.com/documentation/appkit/nsaccessibilityprotocol Ref: https://developer.apple.com/documentation/appkit/nsaccessibilityprotocol
accessibilityFrame returns the view's frame (standard behavior) so Accessibility notifications are only posted when drawing the cursor in
VoiceOver draws its focus ring around the text area. Cursor position the active (selected) window (on_p && active_p guard). Without this,
is exposed via accessibilityBoundsForRange: only. C-x o (other-window) triggers UAZoomChangeFocus for the old window
last, snapping Zoom back to it.
Both mechanisms are needed: UAZoomChangeFocus serves Zoom; NSAccessibility
serves VoiceOver. Same dual pattern used by iTerm2.
--- ---
diff --git a/src/nsterm.h b/src/nsterm.h diff --git a/src/nsterm.h b/src/nsterm.h
index 7c1ee4c..6c1ff34 100644 index 7c1ee4c..6c1ff34 100644
@@ -41,10 +39,10 @@ index 7c1ee4c..6c1ff34 100644
/* AppKit-side interface. */ /* AppKit-side interface. */
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index 932d209..2576c96 100644 index 932d209..e6b1699 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/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. */ /* Prevent the cursor from being drawn outside the text area. */
r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, 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. */ + serves macOS Zoom's "Follow keyboard focus" feature. */
+ { + {
+ EmacsView *view = FRAME_NS_VIEW (f); + 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. */ + /* Store cursor rect for accessibilityBoundsForRange: queries. */
+ view->lastAccessibilityCursorRect = r; + view->lastAccessibilityCursorRect = r;
@@ -117,7 +120,7 @@ index 932d209..2576c96 100644
ns_focus (f, NULL, 0); ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; 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); XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event); kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop 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; return fs_state;
} }