From 8a48e724930c6f89cde15cfaeff49403f06b41fd Mon Sep 17 00:00:00 2001 From: Daneel Date: Sat, 28 Feb 2026 14:44:37 +0100 Subject: [PATCH] patches: add 0009 fix Fequal face comparison in overlay detection --- ...9-ns-fix-overlay-candidate-detection.patch | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 patches/0009-ns-fix-overlay-candidate-detection.patch diff --git a/patches/0009-ns-fix-overlay-candidate-detection.patch b/patches/0009-ns-fix-overlay-candidate-detection.patch new file mode 100644 index 0000000..72a7411 --- /dev/null +++ b/patches/0009-ns-fix-overlay-candidate-detection.patch @@ -0,0 +1,152 @@ +From 2e5505f044e403ccaef8c43bdc66480c71dcf05a Mon Sep 17 00:00:00 2001 +From: Martin Sukany +Date: Sat, 28 Feb 2026 14:44:37 +0100 +Subject: [PATCH] ns: fix overlay candidate detection (Fequal face comparison) + +The previous ns_ax_selected_overlay_text matched ANY non-nil face, +but all Vertico lines have faces. Fix: collect line boundaries, +compare each line's face against the first line's face via Fequal, +return the line with a DIFFERENT face (the selected candidate). + +Also fix duplicate 'NSString *candidate' declaration. + +* src/nsterm.m (ns_ax_selected_overlay_text): Rewrite to compare +faces line-by-line via Fequal instead of matching first non-nil face. +--- + src/nsterm.m | 94 +++++++++++++++++++++++++++------------------------- + 1 file changed, 48 insertions(+), 46 deletions(-) + +diff --git a/src/nsterm.m b/src/nsterm.m +index 43d30f9..35edd39 100644 +--- a/src/nsterm.m ++++ b/src/nsterm.m +@@ -6916,12 +6916,12 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) + #define NS_AX_TEXT_CAP 100000 + + /* Extract the currently selected candidate text from overlay display +- strings in window W. Completion frameworks (Vertico, Ivy, Icomplete) +- highlight the current candidate by applying a face property to a +- portion of the overlay's before-string or after-string. We find +- that highlighted portion and return it as an NSString. ++ strings. Completion frameworks (Vertico, Ivy, Icomplete) highlight ++ the current candidate with a distinct face. We find the line whose ++ face DIFFERS from the first line's face (the "normal" candidate ++ face) — that is the selected candidate. + +- Returns nil if no highlighted overlay text is found. */ ++ Returns nil if no distinctly-faced line is found. */ + static NSString * + ns_ax_selected_overlay_text (struct buffer *b, + ptrdiff_t beg, ptrdiff_t end) +@@ -6942,57 +6942,60 @@ ns_ax_selected_overlay_text (struct buffer *b, + continue; + + Lisp_Object str = strings[s]; +- ptrdiff_t len = SCHARS (str); +- ptrdiff_t pos = 0; ++ ptrdiff_t slen = SCHARS (str); ++ if (slen == 0) ++ continue; ++ ++ /* Collect line boundaries. */ ++ ptrdiff_t line_starts[512]; ++ ptrdiff_t line_ends[512]; ++ int nlines = 0; ++ ptrdiff_t lstart = 0; + +- while (pos < len) ++ for (ptrdiff_t i = 0; i <= slen && nlines < 512; i++) + { +- Lisp_Object face +- = Fget_text_property (make_fixnum (pos), +- Qface, str); +- if (!NILP (face)) ++ bool is_nl = false; ++ if (i < slen) ++ { ++ Lisp_Object ch = Faref (str, make_fixnum (i)); ++ is_nl = (FIXNUMP (ch) && XFIXNUM (ch) == '\n'); ++ } ++ if (is_nl || i == slen) + { +- /* Found highlighted text. Extract the full line +- containing this position. */ +- ptrdiff_t line_start = pos; +- while (line_start > 0) ++ if (i > lstart) + { +- /* Check character before line_start. */ +- Lisp_Object ch +- = Faref (str, make_fixnum (line_start - 1)); +- if (FIXNUMP (ch) && XFIXNUM (ch) == '\n') +- break; +- line_start--; ++ line_starts[nlines] = lstart; ++ line_ends[nlines] = i; ++ nlines++; + } ++ lstart = i + 1; ++ } ++ } + +- ptrdiff_t line_end = pos; +- while (line_end < len) +- { +- Lisp_Object ch +- = Faref (str, make_fixnum (line_end)); +- if (FIXNUMP (ch) && XFIXNUM (ch) == '\n') +- break; +- line_end++; +- } ++ if (nlines < 2) ++ continue; + ++ /* Get the face of the first line (the "normal" face). */ ++ Lisp_Object normal_face ++ = Fget_text_property (make_fixnum (line_starts[0]), ++ Qface, str); ++ ++ /* Find the first line with a DIFFERENT face. */ ++ for (int li = 0; li < nlines; li++) ++ { ++ Lisp_Object line_face ++ = Fget_text_property (make_fixnum (line_starts[li]), ++ Qface, str); ++ if (NILP (Fequal (line_face, normal_face))) ++ { + Lisp_Object line +- = Fsubstring_no_properties (str, +- make_fixnum (line_start), +- make_fixnum (line_end)); ++ = Fsubstring_no_properties ( ++ str, ++ make_fixnum (line_starts[li]), ++ make_fixnum (line_ends[li])); + if (SCHARS (line) > 0) + return [NSString stringWithLispString:line]; + } +- +- /* Skip to next face change. */ +- Lisp_Object next +- = Fnext_single_property_change (make_fixnum (pos), +- Qface, str, +- make_fixnum (len)); +- ptrdiff_t npos +- = FIXNUMP (next) ? XFIXNUM (next) : len; +- if (npos <= pos) +- break; +- pos = npos; + } + } + } +@@ -8956,7 +8959,6 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, + properties. Completion frameworks highlight the current + candidate with a text face (e.g. vertico-current, + icomplete-selected-match). */ +- NSString *candidate + NSString *candidate + = ns_ax_selected_overlay_text (b, BUF_BEGV (b), BUF_ZV (b)); + if (candidate) +-- +2.43.0 +