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 6f8d678..43ce26e 100644 --- a/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch +++ b/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch @@ -73,7 +73,7 @@ index 7c1ee4c..4abeafe 100644 diff --git a/src/nsterm.m b/src/nsterm.m -index 932d209..792f7c5 100644 +index 932d209..5252e6d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f) @@ -126,7 +126,7 @@ index 932d209..792f7c5 100644 ns_focus (f, NULL, 0); NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; -@@ -6847,6 +6883,756 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) +@@ -6847,6 +6883,764 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) } #endif @@ -743,6 +743,11 @@ index 932d209..792f7c5 100644 + } + + self.cachedModiff = modiff; ++ /* Update cachedPoint here so the selection-move branch below ++ does NOT fire for point changes caused by edits. WebKit and ++ Chromium never send both ValueChanged and SelectedTextChanged ++ for the same user action — they are mutually exclusive. */ ++ self.cachedPoint = point; + + NSDictionary *change = @{ + @"AXTextEditType": @3, @@ -758,8 +763,11 @@ index 932d209..792f7c5 100644 + } + + /* --- Cursor moved or selection changed → line reading --- -+ kAXTextStateChangeTypeSelectionMove = 2. */ -+ if (point != self.cachedPoint || markActive != self.cachedMarkActive) ++ kAXTextStateChangeTypeSelectionMove = 2. ++ Use 'else if' — edits and selection moves are mutually exclusive ++ per the WebKit/Chromium pattern. VoiceOver gets confused if ++ both notifications arrive in the same runloop iteration. */ ++ else if (point != self.cachedPoint || markActive != self.cachedMarkActive) + { + ptrdiff_t oldPoint = self.cachedPoint; + self.cachedPoint = point; @@ -883,7 +891,7 @@ index 932d209..792f7c5 100644 /* ========================================================================== EmacsView implementation -@@ -6889,6 +7675,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) +@@ -6889,6 +7683,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) [layer release]; #endif @@ -891,7 +899,7 @@ index 932d209..792f7c5 100644 [[self menu] release]; [super dealloc]; } -@@ -8237,6 +9024,18 @@ ns_in_echo_area (void) +@@ -8237,6 +9032,18 @@ ns_in_echo_area (void) XSETFRAME (event.frame_or_window, emacsframe); kbd_buffer_store_event (&event); ns_send_appdefined (-1); // Kick main loop @@ -910,7 +918,7 @@ index 932d209..792f7c5 100644 } -@@ -9474,6 +10273,290 @@ ns_in_echo_area (void) +@@ -9474,6 +10281,290 @@ ns_in_echo_area (void) return fs_state; } @@ -1201,7 +1209,7 @@ index 932d209..792f7c5 100644 @end /* EmacsView */ -@@ -9941,6 +11024,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) +@@ -9941,6 +11032,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) return [super accessibilityAttributeValue:attribute]; }