diff --git a/config.el b/config.el index c7c1191..872d05b 100644 --- a/config.el +++ b/config.el @@ -265,7 +265,7 @@ ;; Visual: hide markup, pretty entities, compact tags (setq org-startup-indented nil ; conflicts with org-modern star display - org-startup-folded t ; show only headings on open + org-startup-folded 'content ; show all headings, hide body text org-hide-emphasis-markers t org-pretty-entities t org-ellipsis " ▾" @@ -632,11 +632,14 @@ Skip for beamer exports — beamer uses adjustbox on plain tabular." (after! corfu (setq corfu-auto t corfu-auto-delay 2.0 - corfu-auto-prefix 2 + corfu-auto-prefix 3 ; need 3+ chars before popup corfu-cycle t corfu-preselect 'prompt corfu-quit-no-match 'separator corfu-preview-current nil) + ;; Re-set delay after global-corfu-mode to override Doom defaults + (add-hook 'global-corfu-mode-hook + (lambda () (setq corfu-auto-delay 2.0))) (global-corfu-mode)) (use-package! cape @@ -902,6 +905,12 @@ Skip for beamer exports — beamer uses adjustbox on plain tabular." "RET" #'dired-find-alternate-file "^" #'dired-up-directory)) +;; Disable hl-line-mode — its text property changes bump BUF_MODIFF +;; on every cursor movement, which blocks VoiceOver's +;; SelectedTextChanged notification in read-only buffers (dired, etc.) +(global-hl-line-mode -1) +(remove-hook 'dired-mode-hook #'hl-line-mode) + ;; Dirvish — modern dired replacement (use-package! dirvish :init (dirvish-override-dired-mode) diff --git a/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch b/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch index 2b89fb0..d698d82 100644 --- a/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch +++ b/patches/0007-ns-announce-overlay-completion-candidates-for-VoiceO.patch @@ -1,4 +1,4 @@ -From 7d5fe56a0e86aee931787eda2e4988a6b4815291 Mon Sep 17 00:00:00 2001 +From 8157451dedda9b43de47f82d1deb85c9d2853a35 Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 28 Feb 2026 14:46:25 +0100 Subject: [PATCH 1/2] ns: announce overlay completion candidates for VoiceOver @@ -52,8 +52,8 @@ Independent overlay branch, BUF_CHARS_MODIFF gating, candidate announcement with overlay Zoom rect storage. --- src/nsterm.h | 3 + - src/nsterm.m | 335 +++++++++++++++++++++++++++++++++++++++++++++------ - 2 files changed, 300 insertions(+), 38 deletions(-) + src/nsterm.m | 319 +++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 286 insertions(+), 36 deletions(-) diff --git a/src/nsterm.h b/src/nsterm.h index 51c30ca..5c15639 100644 @@ -77,7 +77,7 @@ index 51c30ca..5c15639 100644 BOOL font_panel_active; NSFont *font_panel_result; diff --git a/src/nsterm.m b/src/nsterm.m -index 1780194..6efeb1d 100644 +index 1780194..d13c5c7 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3258,7 +3258,12 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, @@ -403,34 +403,26 @@ index 1780194..6efeb1d 100644 self.cachedPoint = point; NSDictionary *change = @{ -@@ -8789,16 +8938,126 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, +@@ -8789,14 +8938,112 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, BOOL markActive = !NILP (BVAR (b, mark_active)); /* --- Text changed (edit) --- */ + ptrdiff_t chars_modiff = BUF_CHARS_MODIFF (b); -+ BOOL textDidChange = NO; if (modiff != self.cachedModiff) { self.cachedModiff = modiff; - [self postTextChangedNotification:point]; + /* Only post ValueChanged when actual characters changed. -+ Text property changes (e.g. face updates from hl-line-mode, ++ Text property changes (e.g. face updates from + vertico--prompt-selection) bump BUF_MODIFF but not + BUF_CHARS_MODIFF. Posting ValueChanged for property-only + changes causes VoiceOver to say "new line" when the diff -+ is non-empty due to overlay content changes. -+ -+ Use textDidChange to avoid blocking the cursor-move branch -+ below: property-only changes must not prevent -+ SelectedTextChanged from firing when point also moved -+ (e.g. hl-line-mode updates face properties on every cursor -+ movement in dired and other read-only buffers). */ ++ is non-empty due to overlay content changes. */ + if (chars_modiff != self.cachedCharsModiff) + { + self.cachedCharsModiff = chars_modiff; + self.emacsView->overlayZoomActive = NO; + [self postTextChangedNotification:point]; -+ textDidChange = YES; + } + } + @@ -522,19 +514,11 @@ index 1780194..6efeb1d 100644 /* --- Cursor moved or selection changed --- - Use 'else if' — edits and selection moves are mutually exclusive -- per the WebKit/Chromium pattern. */ -- else if (point != self.cachedPoint || markActive != self.cachedMarkActive) -+ Skip when ValueChanged was already posted (edits and selection -+ moves are mutually exclusive per the WebKit/Chromium pattern). -+ But DO fire when only text properties changed (BUF_MODIFF bumped -+ without BUF_CHARS_MODIFF) --- hl-line-mode and similar packages -+ update face properties on every cursor movement. */ -+ if (!textDidChange -+ && (point != self.cachedPoint || markActive != self.cachedMarkActive)) ++ Use 'else if' --- edits and selection moves are mutually exclusive + per the WebKit/Chromium pattern. */ + else if (point != self.cachedPoint || markActive != self.cachedMarkActive) { - ptrdiff_t oldPoint = self.cachedPoint; - BOOL oldMarkActive = self.cachedMarkActive; -@@ -8966,7 +9225,7 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, +@@ -8966,7 +9213,7 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem, /* =================================================================== @@ -543,7 +527,7 @@ index 1780194..6efeb1d 100644 =================================================================== */ /* Scan visible range of window W for interactive spans. -@@ -9157,7 +9416,7 @@ ns_ax_scan_interactive_spans (struct window *w, +@@ -9157,7 +9404,7 @@ ns_ax_scan_interactive_spans (struct window *w, - (BOOL) isAccessibilityFocused { /* Read the cached point stored by EmacsAccessibilityBuffer on the main @@ -552,7 +536,7 @@ index 1780194..6efeb1d 100644 EmacsAccessibilityBuffer *pb = self.parentBuffer; if (!pb) return NO; -@@ -9174,7 +9433,7 @@ ns_ax_scan_interactive_spans (struct window *w, +@@ -9174,7 +9421,7 @@ ns_ax_scan_interactive_spans (struct window *w, dispatch_async (dispatch_get_main_queue (), ^{ /* lwin is a Lisp_Object captured by value. This is GC-safe because Lisp_Objects are tagged integers/pointers that @@ -561,7 +545,7 @@ index 1780194..6efeb1d 100644 Emacs. The WINDOW_LIVE_P check below guards against the window being deleted between capture and execution. */ if (!WINDOWP (lwin) || NILP (Fwindow_live_p (lwin))) -@@ -9200,7 +9459,7 @@ ns_ax_scan_interactive_spans (struct window *w, +@@ -9200,7 +9447,7 @@ ns_ax_scan_interactive_spans (struct window *w, @end @@ -570,7 +554,7 @@ index 1780194..6efeb1d 100644 Methods are kept here (same .m file) so they access the ivars declared in the @interface ivar block. */ @implementation EmacsAccessibilityBuffer (InteractiveSpans) -@@ -10520,13 +10779,13 @@ ns_in_echo_area (void) +@@ -10520,13 +10767,13 @@ ns_in_echo_area (void) if (old_title == 0) { char *t = strdup ([[[self window] title] UTF8String]); @@ -586,7 +570,7 @@ index 1780194..6efeb1d 100644 [window setTitle: [NSString stringWithUTF8String: size_title]]; [window display]; xfree (size_title); -@@ -11922,7 +12181,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, +@@ -11922,7 +12169,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, if (WINDOW_LEAF_P (w)) { @@ -595,7 +579,7 @@ index 1780194..6efeb1d 100644 EmacsAccessibilityBuffer *elem = [existing objectForKey:[NSValue valueWithPointer:w]]; if (!elem) -@@ -11956,7 +12215,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, +@@ -11956,7 +12203,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, } else { @@ -604,7 +588,7 @@ index 1780194..6efeb1d 100644 Lisp_Object child = w->contents; while (!NILP (child)) { -@@ -12068,7 +12327,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, +@@ -12068,7 +12315,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, accessibilityUpdating = YES; /* Detect window tree change (split, delete, new buffer). Compare @@ -613,7 +597,7 @@ index 1780194..6efeb1d 100644 Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe); if (!EQ (curRoot, lastRootWindow)) { -@@ -12077,12 +12336,12 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, +@@ -12077,12 +12324,12 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, } /* If tree is stale, rebuild FIRST so we don't iterate freed