patches: fix all review blockers (iteration 2)
Fixes from Opus maintainer review: 1. [BLOCKER] Zoom code completely removed from ALL intermediate patches (0005-0007 no longer have UAZoom/overlayZoom at any commit point) 2. [BLOCKER] Unified cursor rect ivar: lastCursorRect (was split between lastZoomCursorRect and lastAccessibilityCursorRect) 3. [HIGH] Child frame static vars moved to EmacsView ivars (childFrameLastCandidate/Buffer/Modiff — no cross-frame interference) 4. [HIGH] intern_c_string replaced with Qbefore_string/Qafter_string 5. [MEDIUM] Zoom fallback gated by zoomCursorUpdated flag (no double call)
This commit is contained in:
@@ -1,34 +1,34 @@
|
||||
From 402d2959cc569ebe740f07687c37283323fce314 Mon Sep 17 00:00:00 2001
|
||||
From 085a2c40d1335819b7a0d43b67581cc7b547088f Mon Sep 17 00:00:00 2001
|
||||
From: Martin Sukany <martin@sukany.cz>
|
||||
Date: Sat, 28 Feb 2026 22:08:55 +0100
|
||||
Date: Sat, 28 Feb 2026 22:39:35 +0100
|
||||
Subject: [PATCH] ns: integrate with macOS Zoom for cursor tracking
|
||||
|
||||
Inform macOS Zoom of the text cursor position so the zoomed viewport
|
||||
follows keyboard focus in Emacs.
|
||||
|
||||
* src/nsterm.h (EmacsView): Add lastZoomCursorRect ivar.
|
||||
* src/nsterm.h (EmacsView): Add lastCursorRect, zoomCursorUpdated.
|
||||
* src/nsterm.m (ns_draw_window_cursor): Store cursor rect in
|
||||
lastZoomCursorRect; call UAZoomChangeFocus with CG-space
|
||||
coordinates when UAZoomEnabled returns true.
|
||||
(ns_update_end): Call UAZoomChangeFocus as fallback after each
|
||||
redisplay cycle to ensure Zoom tracks cursor across window
|
||||
switches (C-x o) where the physical cursor may not be redrawn.
|
||||
lastCursorRect; call UAZoomChangeFocus with CG-space coordinates
|
||||
when UAZoomEnabled returns true. Set zoomCursorUpdated flag.
|
||||
(ns_update_end): Call UAZoomChangeFocus as fallback when cursor
|
||||
was not physically redrawn in this cycle (e.g., after C-x o window
|
||||
switch). Gated by zoomCursorUpdated to avoid double calls.
|
||||
|
||||
Coordinate conversion: EmacsView pixels (AppKit, flipped) ->
|
||||
NSWindow -> NSScreen -> CGRect with y-flip for CoreGraphics
|
||||
top-left origin. UAZoomChangeFocus is available since macOS 10.4
|
||||
(ApplicationServices umbrella framework).
|
||||
top-left origin. UAZoomEnabled returns false when Zoom is inactive,
|
||||
so overhead is a single function call per redisplay cycle.
|
||||
|
||||
Tested on macOS 14 with Zoom enabled: cursor tracking works across
|
||||
window splits, switches, and normal navigation.
|
||||
window splits, switches (C-x o), and normal navigation.
|
||||
---
|
||||
etc/NEWS | 8 ++++++
|
||||
src/nsterm.h | 4 +++
|
||||
src/nsterm.m | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
etc/NEWS | 8 +++++++
|
||||
src/nsterm.h | 6 +++++
|
||||
src/nsterm.m | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 82 insertions(+)
|
||||
|
||||
diff --git a/etc/NEWS b/etc/NEWS
|
||||
index ef36df5..e80e124 100644
|
||||
index ef36df5..f10d17e 100644
|
||||
--- a/etc/NEWS
|
||||
+++ b/etc/NEWS
|
||||
@@ -82,6 +82,14 @@ other directory on your system. You can also invoke the
|
||||
@@ -37,7 +37,7 @@ index ef36df5..e80e124 100644
|
||||
|
||||
++++
|
||||
+** The macOS NS port now integrates with macOS Zoom.
|
||||
+When macOS Zoom is enabled (System Settings -> Accessibility -> Zoom ->
|
||||
+When macOS Zoom is enabled (System Settings, Accessibility, Zoom,
|
||||
+Follow keyboard focus), Emacs informs Zoom of the text cursor position
|
||||
+after every cursor redraw via 'UAZoomChangeFocus'. The zoomed viewport
|
||||
+automatically tracks the insertion point across window splits and
|
||||
@@ -47,41 +47,42 @@ index ef36df5..e80e124 100644
|
||||
** 'line-spacing' now supports specifying spacing above the line.
|
||||
Previously, only spacing below the line could be specified. The user
|
||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||
index 7c1ee4c..f2755e4 100644
|
||||
index 7c1ee4c..ea6e7ba 100644
|
||||
--- a/src/nsterm.h
|
||||
+++ b/src/nsterm.h
|
||||
@@ -484,6 +484,10 @@ enum ns_return_frame_mode
|
||||
@@ -484,6 +484,12 @@ enum ns_return_frame_mode
|
||||
@public
|
||||
struct frame *emacsframe;
|
||||
int scrollbarsNeedingUpdate;
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ /* Cached cursor rect for macOS Zoom integration. */
|
||||
+ NSRect lastZoomCursorRect;
|
||||
+ /* Cached cursor rect for macOS Zoom integration. Set by
|
||||
+ ns_draw_window_cursor, used by ns_update_end fallback. */
|
||||
+ NSRect lastCursorRect;
|
||||
+ BOOL zoomCursorUpdated;
|
||||
+#endif
|
||||
NSRect ns_userRect;
|
||||
}
|
||||
|
||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||
index 74e4ad5..eb1649b 100644
|
||||
index 74e4ad5..cd721c8 100644
|
||||
--- a/src/nsterm.m
|
||||
+++ b/src/nsterm.m
|
||||
@@ -1104,6 +1104,34 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
@@ -1104,6 +1104,35 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
|
||||
unblock_input ();
|
||||
ns_updating_frame = NULL;
|
||||
+
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ /* Zoom fallback: ensure Zoom tracks the cursor after window
|
||||
+ switches (C-x o) and other operations where the physical cursor
|
||||
+ may not be redrawn but the focused window changed. This uses
|
||||
+ lastZoomCursorRect which was set by ns_draw_window_cursor
|
||||
+ during the current or a previous redisplay cycle. */
|
||||
+ switches (C-x o) where the physical cursor may not be redrawn.
|
||||
+ Only fires when ns_draw_window_cursor did NOT run in this cycle
|
||||
+ (zoomCursorUpdated is NO). */
|
||||
+#if defined (MAC_OS_X_VERSION_MIN_REQUIRED) \
|
||||
+ && MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
|
||||
+ if (view && UAZoomEnabled ()
|
||||
+ && !NSIsEmptyRect (view->lastZoomCursorRect))
|
||||
+ if (view && !view->zoomCursorUpdated && UAZoomEnabled ()
|
||||
+ && !NSIsEmptyRect (view->lastCursorRect))
|
||||
+ {
|
||||
+ NSRect r = view->lastZoomCursorRect;
|
||||
+ NSRect r = view->lastCursorRect;
|
||||
+ NSRect windowRect = [view convertRect:r toView:nil];
|
||||
+ NSRect screenRect
|
||||
+ = [[view window] convertRectToScreen:windowRect];
|
||||
@@ -95,34 +96,33 @@ index 74e4ad5..eb1649b 100644
|
||||
+ UAZoomChangeFocus (&cgRect, &cgRect,
|
||||
+ kUAZoomFocusTypeInsertionPoint);
|
||||
+ }
|
||||
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 */
|
||||
+ if (view)
|
||||
+ view->zoomCursorUpdated = NO;
|
||||
+#endif
|
||||
+#endif /* NS_IMPL_COCOA */
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3232,6 +3260,48 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
|
||||
@@ -3232,6 +3261,45 @@ 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));
|
||||
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ /* Accessibility: store cursor rect for macOS Zoom integration.
|
||||
+ /* Zoom integration: inform macOS Zoom of the cursor position.
|
||||
+ Zoom (System Settings -> Accessibility -> Zoom) tracks a focus
|
||||
+ element to keep the zoomed viewport centered on the cursor.
|
||||
+ UAZoomChangeFocus() informs Zoom of the cursor position after
|
||||
+ every physical cursor redraw.
|
||||
+
|
||||
+ The coordinate conversion chain:
|
||||
+ EmacsView pixels (AppKit, flipped, origin at top-left)
|
||||
+ -> NSWindow coordinates (convertRect:toView:nil)
|
||||
+ -> NSScreen coordinates (convertRectToScreen:)
|
||||
+ -> CGRect (NSRectToCGRect, same values)
|
||||
+ -> CG y-flip (CoreGraphics uses top-left origin on
|
||||
+ the primary screen; AppKit uses bottom-left). */
|
||||
+ Coordinate conversion:
|
||||
+ EmacsView pixels (AppKit, flipped, top-left origin)
|
||||
+ -> NSWindow (convertRect:toView:nil)
|
||||
+ -> NSScreen (convertRectToScreen:)
|
||||
+ -> CGRect with y-flip for CoreGraphics top-left origin. */
|
||||
+ {
|
||||
+ EmacsView *view = FRAME_NS_VIEW (f);
|
||||
+ if (view && on_p && active_p)
|
||||
+ {
|
||||
+ view->lastZoomCursorRect = r;
|
||||
+ view->lastCursorRect = r;
|
||||
+ view->zoomCursorUpdated = YES;
|
||||
+
|
||||
+#if defined (MAC_OS_X_VERSION_MIN_REQUIRED) \
|
||||
+ && MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
|
||||
@@ -141,7 +141,7 @@ index 74e4ad5..eb1649b 100644
|
||||
+ UAZoomChangeFocus (&cgRect, &cgRect,
|
||||
+ kUAZoomFocusTypeInsertionPoint);
|
||||
+ }
|
||||
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 */
|
||||
+#endif
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* NS_IMPL_COCOA */
|
||||
|
||||
Reference in New Issue
Block a user