patches: pre-upstream review fixes (all blockers + nits)

- 0000: fix double blank line before #ifdef, remove extra block scope braces
- 0001: spell out 'AT' -> 'assistive technology'; fix stub comment
- 0002: revert unrelated em-dash->triple-dash in windowWillResize strings
- 0003-0005: renumber from [PATCH N/9] to [PATCH N/8]
- 0006: remove 'Block-style cursors' from Known Limitations; fix @xref note
- 0007: remove spurious ns_ax_face_is_selected ChangeLog entry
- 0008: refactor goto skip_overlay_scan to nested if; remove spurious blank line
- All: renumber series (0000=[PATCH 1/1], 0001-0008=[PATCH 1/8]-[PATCH 8/8])
This commit is contained in:
2026-03-05 02:08:55 +01:00
parent abc518a60a
commit d4952ae9e9
11 changed files with 657 additions and 92 deletions

View File

@@ -1,7 +1,7 @@
From 2bce9ba4ad500eabad619e684ba319b58f9b1fca Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:53 +0100
Subject: [PATCH 1/9] ns: integrate with macOS Zoom for cursor tracking
Subject: [PATCH 1/1] 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. Also track completion candidates so
@@ -86,11 +86,10 @@ index 932d209f56..6333a7253a 100644
#endif
static EmacsMenu *dockMenu;
@@ -1081,6 +1086,293 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
@@ -1081,6 +1086,292 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
}
+
+#ifdef NS_IMPL_COCOA
+#if defined (MAC_OS_X_VERSION_MIN_REQUIRED) \
+ && MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
@@ -422,7 +421,7 @@ index 932d209f56..6333a7253a 100644
}
static void
@@ -3232,6 +3559,45 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -3232,6 +3559,43 @@ 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));
@@ -436,10 +435,9 @@ index 932d209f56..6333a7253a 100644
+ -> 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)
+ {
+ EmacsView *view = FRAME_NS_VIEW (f);
+ if (view && on_p && active_p)
+ {
+ view->lastCursorRect = r;
+ view->zoomCursorUpdated = YES;
+
@@ -461,8 +459,7 @@ index 932d209f56..6333a7253a 100644
+ kUAZoomFocusTypeInsertionPoint);
+ }
+#endif
+ }
+ }
+ }
+#endif /* NS_IMPL_COCOA */
+
ns_focus (f, NULL, 0);

View File

@@ -1,7 +1,7 @@
From 573beced02b3f9b70ba82694d8e4790cfeee9563 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:53 +0100
Subject: [PATCH 2/9] ns: add accessibility base classes and helpers
Subject: [PATCH 1/8] ns: add accessibility base classes and helpers
Add the foundation for macOS VoiceOver accessibility in the NS (Cocoa)
port. No existing code paths are modified.
@@ -26,7 +26,7 @@ rect via glyph matrix.
(EmacsAccessibilityElement): Implement base class.
(syms_of_nsterm): Register accessibility DEFSYMs. Add DEFVAR_BOOL
ns-accessibility-enabled with corrected doc: initial value is nil,
set non-nil automatically when an AT is detected at startup.
set non-nil automatically when an assistive technology (AT) is detected at startup.
---
src/nsterm.h | 131 +++++++++++++++
src/nsterm.m | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -633,7 +633,7 @@ index 6333a7253a..9c53001e37 100644
+
+- (void)invalidateInteractiveSpans
+{
+ /* Stub: full implementation added in patch 0004. */
+ /* Stub: full implementation in the following patch. */
+}
+
+@end

View File

@@ -1,7 +1,7 @@
From 64859d37421bdaabe2ec416285b6f1847da0737c Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:54 +0100
Subject: [PATCH 3/9] ns: implement buffer accessibility element
Subject: [PATCH 2/8] ns: implement buffer accessibility element
Implement the NSAccessibility text protocol for Emacs buffer windows.
@@ -1176,15 +1176,13 @@ index 9c53001e37..e4b3fb17a0 100644
if (old_title == 0)
{
char *t = strdup ([[[self window] title] UTF8String]);
- char *pos = strstr (t, " — ");
+ char *pos = strstr (t, " --- ");
char *pos = strstr (t, " — ");
if (pos)
*pos = '\0';
old_title = t;
}
size_title = xmalloc (strlen (old_title) + 40);
- esprintf (size_title, "%s — (%d × %d)", old_title, cols, rows);
+ esprintf (size_title, "%s --- (%d × %d)", old_title, cols, rows);
esprintf (size_title, "%s — (%d × %d)", old_title, cols, rows);
[window setTitle: [NSString stringWithUTF8String: size_title]];
[window display];
xfree (size_title);

View File

@@ -1,7 +1,7 @@
From 11aa323081fd9117381413b6d8e477659d6afc29 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:55 +0100
Subject: [PATCH 4/9] ns: add AX notifications and mode-line element
Subject: [PATCH 3/8] ns: add AX notifications and mode-line element
Add VoiceOver notification dispatch and mode-line readout.

View File

@@ -1,7 +1,7 @@
From 9d99df6f95ac2011a1a9f3de448f2f0ec4c27145 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:55 +0100
Subject: [PATCH 5/9] ns: add interactive span elements for Tab
Subject: [PATCH 4/8] ns: add interactive span elements for Tab
* src/nsterm.m (ns_ax_scan_interactive_spans): New function; scans the
visible portion of a buffer for interactive text properties

View File

@@ -1,7 +1,7 @@
From cba3eda4d3c50dcd77c73353c6a8d2713bfcb8ae Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:55 +0100
Subject: [PATCH 6/9] ns: wire accessibility into EmacsView and redisplay
Subject: [PATCH 5/8] ns: wire accessibility into EmacsView and redisplay
Wire the accessibility element tree into EmacsView and hook it into
the redisplay cycle.

View File

@@ -1,13 +1,12 @@
From a1ea69133e5a5c04076901dce47cd54683c4ca2e Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:55 +0100
Subject: [PATCH 7/9] doc: add VoiceOver section to macOS appendix
Subject: [PATCH 6/8] doc: add VoiceOver section to macOS appendix
* doc/emacs/macos.texi (VoiceOver Accessibility): New node between
'Mac / GNUstep Events' and 'GNUstep Support'. Document screen reader
usage, keyboard navigation, completion announcements, ns-accessibility-
enabled, and known limitations. Use @xref for cross-reference at
sentence start. Correct description of ns-accessibility-enabled
enabled, and known limitations. Correct description of ns-accessibility-enabled
default: initial value is nil, set automatically at startup.
---
doc/emacs/macos.texi | 77 ++++++++++++++++++++++++++++++++++++++++++++
@@ -26,7 +25,7 @@ index 6bd334f48e..72ac3a9aa9 100644
* GNUstep Support:: Details on status of GNUstep support.
@end menu
@@ -272,6 +273,82 @@ and return the result as a string. You can also use the Lisp function
@@ -272,6 +273,78 @@ and return the result as a string. You can also use the Lisp function
services and receive the results back. Note that you may need to
restart Emacs to access newly-available services.
@@ -96,10 +95,6 @@ index 6bd334f48e..72ac3a9aa9 100644
+Right-to-left (bidi) text is exposed correctly as buffer content,
+but @code{accessibilityRangeForPosition} hit-testing assumes
+left-to-right glyph layout.
+@item
+Block-style cursors are handled correctly: character navigation
+announces the character at the cursor position, not the character
+before it.
+@end itemize
+
+ This support is available only on the Cocoa build. GNUstep has a

View File

@@ -1,14 +1,12 @@
From b6bc1d102334e32dbc3e284d9e65b0f304c3e694 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:56 +0100
Subject: [PATCH 8/9] ns: announce overlay completions to VoiceOver
Subject: [PATCH 7/8] ns: announce overlay completions to VoiceOver
Completion frameworks such as Vertico, Ivy, and Icomplete render
candidates via overlay before-string/after-string properties. Without
this change VoiceOver cannot read overlay-based completion UIs.
* src/nsterm.m (ns_ax_face_is_selected): New static function; matches
'current', 'selected', 'selection' in face symbol names.
(ns_ax_selected_overlay_text): New function; scan overlay strings in
the window for a line with a selected face; return its text.
(ensureTextCache): Switch cache-validity counter from BUF_CHARS_MODIFF

View File

@@ -1,7 +1,7 @@
From a6b1def9a83e23cc0e3325d795ac22b46eb16a5d Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Wed, 4 Mar 2026 15:23:56 +0100
Subject: [PATCH 9/9] ns: announce child frame completions to VoiceOver
Subject: [PATCH 8/8] ns: announce child frame completions to VoiceOver
Child frame popups (Corfu, Company-mode child frames) render completion
candidates in a separate frame whose buffer is not accessible via the
@@ -438,7 +438,7 @@ index 209b8a0a1d..13696786ab 100644
}
}
@@ -9437,41 +9609,49 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
@@ -9437,41 +9609,48 @@ frameworks like Vertico bump BOTH BUF_MODIFF (via text property
displayed in the minibuffer. In normal editing buffers,
font-lock and other modes change BUF_OVERLAY_MODIFF on
every redisplay, triggering O(overlays) work per keystroke.
@@ -452,68 +452,40 @@ index 209b8a0a1d..13696786ab 100644
+ echo produced by postTextChangedNotification, making typed
+ characters inaudible. VoiceOver should read the overlay
+ candidate only when the user navigates (C-n/C-p), not types. */
+ if (!MINI_WINDOW_P (w) || didTextChange)
+ goto skip_overlay_scan;
+
+ int selected_line = -1;
+ NSString *candidate
+ = ns_ax_selected_overlay_text (b, BUF_BEGV (b), BUF_ZV (b),
+ &selected_line);
+ if (candidate)
+ if (MINI_WINDOW_P (w) && !didTextChange)
{
- int selected_line = -1;
- NSString *candidate
- = ns_ax_selected_overlay_text (b, BUF_BEGV (b), BUF_ZV (b),
- &selected_line);
- if (candidate)
+ /* Deduplicate: only announce when the candidate changed. */
+ if (![candidate isEqualToString:
+ self.cachedCompletionAnnouncement])
int selected_line = -1;
NSString *candidate
= ns_ax_selected_overlay_text (b, BUF_BEGV (b), BUF_ZV (b),
&selected_line);
if (candidate)
{
- /* Deduplicate: only announce when the candidate changed. */
- if (![candidate isEqualToString:
- self.cachedCompletionAnnouncement])
- {
- self.cachedCompletionAnnouncement = candidate;
-
- /* Announce the candidate text directly via NSApp.
- Do NOT post SelectedTextChanged --- that would cause
- VoiceOver to read the AX text at the cursor position
- (the minibuffer input line), not the overlay candidate.
- AnnouncementRequested with High priority interrupts
- any current speech and announces our text. */
- NSDictionary *annInfo = @{
- NSAccessibilityAnnouncementKey: candidate,
- NSAccessibilityPriorityKey:
- @(NSAccessibilityPriorityHigh)
- };
- ns_ax_post_notification_with_info (
- NSApp,
- NSAccessibilityAnnouncementRequestedNotification,
- annInfo);
- }
+ self.cachedCompletionAnnouncement = candidate;
+
+ /* Announce the candidate text directly via NSApp.
+ Do NOT post SelectedTextChanged --- that would cause
+ VoiceOver to read the AX text at the cursor position
+ (the minibuffer input line), not the overlay candidate.
+ AnnouncementRequested with High priority interrupts
+ any current speech and announces our text. */
+ NSDictionary *annInfo = @{
+ NSAccessibilityAnnouncementKey: candidate,
+ NSAccessibilityPriorityKey:
+ @(NSAccessibilityPriorityHigh)
+ };
+ ns_ax_post_notification_with_info (
+ NSApp,
+ NSAccessibilityAnnouncementRequestedNotification,
+ annInfo);
/* Deduplicate: only announce when the candidate changed. */
if (![candidate isEqualToString:
self.cachedCompletionAnnouncement])
{
self.cachedCompletionAnnouncement = candidate;
/* Announce the candidate text directly via NSApp.
Do NOT post SelectedTextChanged --- that would cause
VoiceOver to read the AX text at the cursor position
(the minibuffer input line), not the overlay candidate.
AnnouncementRequested with High priority interrupts
any current speech and announces our text. */
NSDictionary *annInfo = @{
NSAccessibilityAnnouncementKey: candidate,
NSAccessibilityPriorityKey:
@(NSAccessibilityPriorityHigh)
};
ns_ax_post_notification_with_info (
NSApp,
NSAccessibilityAnnouncementRequestedNotification,
annInfo);
}
}
}
}
+ skip_overlay_scan:
/* --- Cursor moved or selection changed ---
Independent check from the overlay branch above. */
if (point != self.cachedPoint || markActive != self.cachedMarkActive)
@@ -652,7 +624,7 @@ index 209b8a0a1d..13696786ab 100644
scrollbarsNeedingUpdate = 0;
fs_state = FULLSCREEN_NONE;
fs_before_fs = next_maximized = -1;
@@ -12789,6 +12991,156 @@ - (id)accessibilityFocusedUIElement
@@ -12789,6 +12991,155 @@ - (id)accessibilityFocusedUIElement
The existing elements carry cached state (modiff, point) from the
previous redisplay cycle. Rebuilding first would create fresh
elements with current values, making change detection impossible. */
@@ -720,7 +692,6 @@ index 209b8a0a1d..13696786ab 100644
+ in the minibuffer. */
+- (void)announceChildFrameCompletion
+{
+
+ /* Validate frame state --- child frames may be partially
+ initialized during creation. */
+ if (!WINDOWP (emacsframe->selected_window))