- Merge 3 separate (after! mu4e) blocks into one
- Fix key conflict: bookmark Today was ?t, same as maildir Trash
New: Today=?d, Trash shortcut=?T (uppercase)
- Remove duplicate mu4e-view-mode-hook (gnus-article-prepare-hook suffices)
- Move sendmail + message-cite settings into the single block
- Add inline comments explaining gnus-cite-* vs message-cited-text-*
duplication (separate face systems, same visual intent)
- Minor: group settings with section comments for readability
Move file-scope statics (lastChildFrameBuffer/Modiff/Candidate) and
ns_ax_reset_accessibility_updating before announceChildFrameCompletion.
Using them before their declaration was a forward reference (UB in C).
Remove two spurious blank lines at start of announceChildFrameCompletion
method body.
New patch 0009 fixes HIGH severity issues from Opus review:
- Announcement coalescing (50ms debounce)
- cachedText retain+autorelease in accessibilityValue
- EmacsView dealloc: nil out emacsView on all AX elements
- Nil guards on protocol methods + overlayZoomActive
0007 updated: revert accidental em-dash→triple-dash, add overlayZoomActive nil guards
0008 updated: specpdl exception safety for accessibilityUpdating, lastChildFrameBuffer staticpro
Series now 9 patches total (0001-0006 unchanged, 0007-0009 new/updated).
BLOCKER #1: accessibilityUpdating flag exception safety.
A Lisp signal (longjmp) during postAccessibilityUpdates left
the re-entrance flag permanently YES, suppressing all future
AX notifications → VoiceOver goes silent randomly.
Fix: specpdl unwind protection (record_unwind_protect_ptr)
resets the flag on any longjmp. All 3 exit points use unbind_to.
BLOCKER #2: static struct buffer *lastBuffer dangling pointer.
Raw C pointer to buffer struct has no GC protection. After
kill-buffer, the pointer dangles.
Fix: file-scope Lisp_Object lastChildFrameBuffer with staticpro.
EQ comparison instead of pointer equality.
Also: revert accidental em-dash → triple-dash in title bar (0007),
fix README factual error (BUF_OVERLAY_MODIFF cache key).
hl-line-mode (and similar) bumps BUF_MODIFF via text property
changes on every cursor movement. The else-if structure caused
the modiff branch to fire (skipping ValueChanged correctly) but
also blocked the cursor-move branch (SelectedTextChanged).
Fix: use textDidChange flag to decouple the two branches.
ValueChanged and SelectedTextChanged remain mutually exclusive
for real edits, but SelectedTextChanged now fires when only
text properties changed.
- childFrameCompletionActive flag: set by child frame handler,
cleared when no child frame visible on parent's next cycle
- Posts FocusedUIElementChanged on parent buffer element to
restore VoiceOver character echo after corfu closes
- corfu-auto-delay: 1.0 → 2.0 (reduce popup noise)
Child frames cause VoiceOver to announce 'X window' and break
focus tracking. corfu-terminal renders via overlays, which the
VoiceOver overlay completion patch (0007) handles automatically.
Fbuffer_substring_no_properties operates on current_buffer, not the
passed buffer. Added set_buffer_internal_1 + record_unwind_current_buffer
with unbind_to on every return path.
Added: child frame buffer scanning for Corfu/Company-box.
Fixed: Zoom rect at text area left edge (not window center).
Added: 'selection' face match for company-tooltip-selection.
Zoom rect now at text area left edge (WINDOW_TEXT_TO_FRAME_PIXEL_X)
with cursor-width (FRAME_COLUMN_WIDTH) instead of full window width.
Face matching adds 'selection' (company-tooltip-selection).
Zoom now tracks the selected candidate row via overlayZoomRect
instead of always pointing at the text cursor. Returns to cursor
on typing (chars_modiff change).
Previous two-reference algorithm failed because:
- Vertico's cursor-space line (face=nil) confused the reference
- Count overlay processed before candidates overlay
- Group titles have distinct faces too
New approach: ns_ax_face_is_selected checks if face symbol name
contains 'current' or 'selected'. Works for all major frameworks
(Vertico, Icomplete, Ivy) without framework-specific code.
Key changes from previous version:
- Remove overlay text from ns_ax_buffer_text (was causing spurious
'new line' announcements via VoiceOver text diff)
- Do NOT invalidate text cache on overlay change
- Two-reference face detection (handles selected at any position)
- SDATA scan instead of per-char Faref for newline detection
- Zoom tracking via UAZoomChangeFocus for selected candidate row
- Deduplication via cachedCompletionAnnouncement
- Appends overlay before-string/after-string to AX text
- Detects BUF_OVERLAY_MODIFF changes
- Finds highlighted candidate via face text property
- Announces selected candidate via AnnouncementRequested
(fixes 'new line' instead of reading candidate)
- Appends overlay before-string/after-string to AX text
- Detects BUF_OVERLAY_MODIFF changes
- Finds highlighted candidate via face text property
- Announces selected candidate via AnnouncementRequested
(fixes 'new line' instead of reading candidate)
Vertico default renders candidates via overlay before-string which
is invisible to the nsterm.m AX text extraction. vertico-buffer-mode
renders in a real buffer window that the accessibility layer handles.
- Start from today (no past days visible)
- Show 7 days forward
- Skip done/cancelled items
- No duplicate: skip scheduled if deadline already shown
- Suppress early deadline warning if scheduled date exists
- Priority-based sorting within groups (A > B > C)
- Overdue deadlines at top
- Due today / scheduled today separated
- Due soon (upcoming deadlines) in own group
- No duplicates (items match first group only)
- Kyndryl/ZTJ groups by tag without deadline overlap