patches: fix Corfu Zoom tracking — replace rate-limit with parent-frame guard
Root cause: the 50ms rate limit broke child-frame (Corfu) tracking. When the Corfu child frame redraws, its ns_update_end fires first and resets the rate-limit timer. When the parent frame's ns_update_end fires immediately after, the timer has not expired, so ns_zoom_track_completion returns early without scanning child frames. Zoom focus stays on the first candidate. Fix: remove the rate limit; add a FRAME_PARENT_FRAME(f) guard instead. Child frames have no completion children to scan; their parent's ns_update_end does the scan via FOR_EACH_FRAME. Returning early on child-frame calls avoids the redundant scan and leaves the timer problem moot. Overhead without the rate limit is ~40 Lisp evaluations per redisplay (~5-20 µs), acceptable given ns_zoom_enabled_p() already caches the UAZoomEnabled() IPC call.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
From d494967af08ec3e5bb94ff50126c2994505a6d85 Mon Sep 17 00:00:00 2001
|
||||
From aeab7e4db306049fb543f60cadcaaa346350f77b Mon Sep 17 00:00:00 2001
|
||||
From: Martin Sukany <martin@sukany.cz>
|
||||
Date: Sat, 28 Feb 2026 22:39:35 +0100
|
||||
Subject: [PATCH 1/9] ns: integrate with macOS Zoom for cursor tracking
|
||||
@@ -38,8 +38,8 @@ window splits, switches (C-x o), and completion frameworks.
|
||||
---
|
||||
etc/NEWS | 11 ++
|
||||
src/nsterm.h | 6 +
|
||||
src/nsterm.m | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 356 insertions(+)
|
||||
src/nsterm.m | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 353 insertions(+)
|
||||
|
||||
diff --git a/etc/NEWS b/etc/NEWS
|
||||
index ef36df5..80661a9 100644
|
||||
@@ -81,10 +81,10 @@ index 7c1ee4c..ea6e7ba 100644
|
||||
}
|
||||
|
||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||
index 74e4ad5..6527750 100644
|
||||
index 74e4ad5..5498d7a 100644
|
||||
--- a/src/nsterm.m
|
||||
+++ b/src/nsterm.m
|
||||
@@ -1081,6 +1081,271 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
@@ -1081,6 +1081,268 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
}
|
||||
|
||||
|
||||
@@ -268,18 +268,15 @@ index 74e4ad5..6527750 100644
|
||||
+ return;
|
||||
+ if (!WINDOWP (f->selected_window))
|
||||
+ return;
|
||||
+
|
||||
+ /* Rate-limit completion scan to 20 Hz (50 ms). UAZoomEnabled() is
|
||||
+ now cached so the main cost is the overlay/child-frame scan.
|
||||
+ 50 ms is imperceptible for completion navigation while preventing
|
||||
+ per-frame FOR_EACH_FRAME overhead. */
|
||||
+ {
|
||||
+ static CFAbsoluteTime last_check;
|
||||
+ CFAbsoluteTime now = CFAbsoluteTimeGetCurrent ();
|
||||
+ if (now - last_check < 0.05)
|
||||
+ return;
|
||||
+ last_check = now;
|
||||
+ }
|
||||
+ /* Child frames (e.g. the Corfu popup itself) have no children to
|
||||
+ scan for completion candidates; their parent frame's ns_update_end
|
||||
+ will scan them via FOR_EACH_FRAME. Return early to avoid a
|
||||
+ redundant O(frames) scan on every child-frame redisplay cycle.
|
||||
+ Note: the rate limit that was here caused corfu tracking to fail:
|
||||
+ the child frame's ns_update_end reset the timer, so the parent
|
||||
+ frame's subsequent ns_update_end returned early without scanning. */
|
||||
+ if (FRAME_PARENT_FRAME (f))
|
||||
+ return;
|
||||
+
|
||||
+ specpdl_ref count = SPECPDL_INDEX ();
|
||||
+ record_unwind_current_buffer ();
|
||||
@@ -356,7 +353,7 @@ index 74e4ad5..6527750 100644
|
||||
static void
|
||||
ns_update_end (struct frame *f)
|
||||
/* --------------------------------------------------------------------------
|
||||
@@ -1104,6 +1369,41 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
@@ -1104,6 +1366,41 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
|
||||
unblock_input ();
|
||||
ns_updating_frame = NULL;
|
||||
@@ -398,7 +395,7 @@ index 74e4ad5..6527750 100644
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3232,6 +3532,45 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
|
||||
@@ -3232,6 +3529,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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user