diff --git a/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch b/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch index a053047..39bb8bf 100644 --- a/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch +++ b/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch @@ -1,13 +1,13 @@ -From f88649b2e09520d4c6e7ebc041e9e1a6e7ed616b Mon Sep 17 00:00:00 2001 +From 442f21965862e63ddd0234777918b999b97c8f9c Mon Sep 17 00:00:00 2001 From: Daneel -Date: Thu, 26 Feb 2026 18:24:58 +0100 +Date: Thu, 26 Feb 2026 18:36:53 +0100 Subject: [PATCH] ns: implement AXBoundsForRange and VoiceOver interaction fixes --- nsterm.h | 71 ++ - nsterm.m | 2126 ++++++++++++++++++++++++++++++++++++++++++++++++++---- - 2 files changed, 2051 insertions(+), 146 deletions(-) + nsterm.m | 2168 ++++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 2096 insertions(+), 143 deletions(-) diff --git a/src/nsterm.h b/src/nsterm.h index 7c1ee4c..22828f2 100644 @@ -106,7 +106,7 @@ index 7c1ee4c..22828f2 100644 diff --git a/src/nsterm.m b/src/nsterm.m -index 932d209..add827f 100644 +index 932d209..b7f0614 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f) @@ -159,7 +159,7 @@ index 932d209..add827f 100644 ns_focus (f, NULL, 0); NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; -@@ -6849,220 +6885,1696 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) +@@ -6849,219 +6885,1743 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) /* ========================================================================== @@ -538,11 +538,6 @@ index 932d209..add827f 100644 } - [NSApp stop: self]; --} -- --- (void) noteUserCancelledSelection --{ -- font_panel_active = NO; + if (!found) + { + for (ptrdiff_t scan = begv; scan < zv; scan++) @@ -580,17 +575,31 @@ index 932d209..add827f 100644 + } + } + } ++ ++ if (!found) ++ return NO; ++ ++ *out_start = best_start; ++ *out_end = best_end; ++ return YES; + } + +-- (void) noteUserCancelledSelection ++static bool ++ns_ax_command_is_basic_line_move (void) + { +- font_panel_active = NO; ++ if (!SYMBOLP (real_this_command)) ++ return false; - if (font_panel_result) - [font_panel_result release]; - font_panel_result = nil; -+ if (!found) -+ return NO; - +- - [NSApp stop: self]; -+ *out_start = best_start; -+ *out_end = best_end; -+ return YES; ++ Lisp_Object next = intern ("next-line"); ++ Lisp_Object prev = intern ("previous-line"); ++ return EQ (real_this_command, next) || EQ (real_this_command, prev); } -#endif @@ -786,7 +795,6 @@ index 932d209..add827f 100644 { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe); - int code; -- unsigned fnKeysym = 0; + [cachedText release]; + cachedText = nil; + if (visibleRuns) @@ -1450,6 +1458,43 @@ index 932d209..add827f 100644 + NSAccessibilitySelectedTextChangedNotification, + moveInfo); + ++ /* C-n/C-p (`next-line' / `previous-line') can diverge from ++ arrow-down/up command paths in some major modes (completion list, ++ Dired, etc.). Emit an explicit line announcement for this basic ++ line-motion path so VoiceOver tracks the Emacs point reliably. */ ++ if ([self isAccessibilityFocused] ++ && cachedText ++ && ns_ax_command_is_basic_line_move () ++ && (direction == ns_ax_text_selection_direction_next ++ || direction == ns_ax_text_selection_direction_previous)) ++ { ++ NSUInteger point_idx = [self accessibilityIndexForCharpos:point]; ++ if (point_idx <= [cachedText length]) ++ { ++ NSInteger lineNum = [self accessibilityLineForIndex:point_idx]; ++ NSRange lineRange = [self accessibilityRangeForLine:lineNum]; ++ if (lineRange.location != NSNotFound ++ && lineRange.length > 0 ++ && lineRange.location + lineRange.length <= [cachedText length]) ++ { ++ NSString *lineText = [cachedText substringWithRange:lineRange]; ++ lineText = [lineText stringByTrimmingCharactersInSet: ++ [NSCharacterSet whitespaceAndNewlineCharacterSet]]; ++ if ([lineText length] > 0) ++ { ++ NSDictionary *annInfo = @{ ++ NSAccessibilityAnnouncementKey: lineText, ++ NSAccessibilityPriorityKey: @(NSAccessibilityPriorityHigh) ++ }; ++ NSAccessibilityPostNotificationWithUserInfo ( ++ NSApp, ++ NSAccessibilityAnnouncementRequestedNotification, ++ annInfo); ++ } ++ } ++ } ++ } ++ + /* --- Completions announcement --- + When point changes in a non-focused buffer (e.g. *Completions* + while the minibuffer has keyboard focus), VoiceOver won't read @@ -1998,11 +2043,10 @@ index 932d209..add827f 100644 +{ + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe); + int code; -+ unsigned fnKeysym = 0; + unsigned fnKeysym = 0; static NSMutableArray *nsEvArray; unsigned int flags = [theEvent modifierFlags]; - -@@ -8237,6 +9749,28 @@ ns_in_echo_area (void) +@@ -8237,6 +9797,28 @@ ns_in_echo_area (void) XSETFRAME (event.frame_or_window, emacsframe); kbd_buffer_store_event (&event); ns_send_appdefined (-1); // Kick main loop @@ -2031,7 +2075,7 @@ index 932d209..add827f 100644 } -@@ -9474,6 +11008,298 @@ ns_in_echo_area (void) +@@ -9474,6 +11056,298 @@ ns_in_echo_area (void) return fs_state; } @@ -2330,7 +2374,7 @@ index 932d209..add827f 100644 @end /* EmacsView */ -@@ -9941,6 +11767,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) +@@ -9941,6 +11815,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) return [super accessibilityAttributeValue:attribute]; }