Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||||
index 7c1ee4c..8bf21f6 100644
|
index 7c1ee4c..4abeafe 100644
|
||||||
--- a/src/nsterm.h
|
--- a/src/nsterm.h
|
||||||
+++ b/src/nsterm.h
|
+++ b/src/nsterm.h
|
||||||
@@ -453,6 +453,40 @@ enum ns_return_frame_mode
|
@@ -453,6 +453,40 @@ enum ns_return_frame_mode
|
||||||
@@ -43,20 +43,22 @@ index 7c1ee4c..8bf21f6 100644
|
|||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
|
|
||||||
The main Emacs view
|
The main Emacs view
|
||||||
@@ -471,6 +505,12 @@ enum ns_return_frame_mode
|
@@ -471,6 +505,14 @@ enum ns_return_frame_mode
|
||||||
#ifdef NS_IMPL_COCOA
|
#ifdef NS_IMPL_COCOA
|
||||||
char *old_title;
|
char *old_title;
|
||||||
BOOL maximizing_resize;
|
BOOL maximizing_resize;
|
||||||
+ NSMutableArray *accessibilityElements;
|
+ NSMutableArray *accessibilityElements;
|
||||||
+ Lisp_Object lastSelectedWindow;
|
+ Lisp_Object lastSelectedWindow;
|
||||||
|
+ Lisp_Object lastRootWindow;
|
||||||
+ BOOL accessibilityTreeValid;
|
+ BOOL accessibilityTreeValid;
|
||||||
|
+ BOOL accessibilityUpdating;
|
||||||
+ @public
|
+ @public
|
||||||
+ NSRect lastAccessibilityCursorRect;
|
+ NSRect lastAccessibilityCursorRect;
|
||||||
+ @protected
|
+ @protected
|
||||||
#endif
|
#endif
|
||||||
BOOL font_panel_active;
|
BOOL font_panel_active;
|
||||||
NSFont *font_panel_result;
|
NSFont *font_panel_result;
|
||||||
@@ -528,6 +568,13 @@ enum ns_return_frame_mode
|
@@ -528,6 +570,13 @@ enum ns_return_frame_mode
|
||||||
- (void)windowWillExitFullScreen;
|
- (void)windowWillExitFullScreen;
|
||||||
- (void)windowDidExitFullScreen;
|
- (void)windowDidExitFullScreen;
|
||||||
- (void)windowDidBecomeKey;
|
- (void)windowDidBecomeKey;
|
||||||
@@ -71,7 +73,7 @@ index 7c1ee4c..8bf21f6 100644
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||||
index 932d209..6543e3b 100644
|
index 932d209..e830f54 100644
|
||||||
--- a/src/nsterm.m
|
--- a/src/nsterm.m
|
||||||
+++ b/src/nsterm.m
|
+++ b/src/nsterm.m
|
||||||
@@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f)
|
@@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f)
|
||||||
@@ -124,7 +126,7 @@ index 932d209..6543e3b 100644
|
|||||||
ns_focus (f, NULL, 0);
|
ns_focus (f, NULL, 0);
|
||||||
|
|
||||||
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
||||||
@@ -6847,6 +6883,717 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
@@ -6847,6 +6883,756 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -759,13 +761,52 @@ index 932d209..6543e3b 100644
|
|||||||
+ kAXTextStateChangeTypeSelectionMove = 1. */
|
+ kAXTextStateChangeTypeSelectionMove = 1. */
|
||||||
+ if (point != self.cachedPoint || markActive != self.cachedMarkActive)
|
+ if (point != self.cachedPoint || markActive != self.cachedMarkActive)
|
||||||
+ {
|
+ {
|
||||||
|
+ ptrdiff_t oldPoint = self.cachedPoint;
|
||||||
+ self.cachedPoint = point;
|
+ self.cachedPoint = point;
|
||||||
+ self.cachedMarkActive = markActive;
|
+ self.cachedMarkActive = markActive;
|
||||||
+
|
+
|
||||||
|
+ /* Compute direction: 2=Previous, 3=Next, 4=Discontiguous. */
|
||||||
|
+ NSInteger direction = 4;
|
||||||
|
+ if (point > oldPoint)
|
||||||
|
+ direction = 3;
|
||||||
|
+ else if (point < oldPoint)
|
||||||
|
+ direction = 2;
|
||||||
|
+
|
||||||
|
+ /* Compute granularity from movement distance.
|
||||||
|
+ Check if we crossed a newline → line movement (2).
|
||||||
|
+ Otherwise single char (0) or discontiguous (5=unknown). */
|
||||||
|
+ NSInteger granularity = 5;
|
||||||
|
+ [self ensureTextCache];
|
||||||
|
+ if (cachedText && oldPoint > 0)
|
||||||
|
+ {
|
||||||
|
+ ptrdiff_t delta = point - oldPoint;
|
||||||
|
+ if (delta == 1 || delta == -1)
|
||||||
|
+ granularity = 0; /* Character. */
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Check for line crossing by looking for newlines
|
||||||
|
+ between old and new position. */
|
||||||
|
+ NSUInteger lo = (NSUInteger)
|
||||||
|
+ (MIN (oldPoint, point) - cachedTextStart);
|
||||||
|
+ NSUInteger hi = (NSUInteger)
|
||||||
|
+ (MAX (oldPoint, point) - cachedTextStart);
|
||||||
|
+ NSUInteger tlen = [cachedText length];
|
||||||
|
+ if (lo < tlen && hi <= tlen)
|
||||||
|
+ {
|
||||||
|
+ NSRange searchRange = NSMakeRange (lo, hi - lo);
|
||||||
|
+ NSRange nl = [cachedText rangeOfString:@"\n"
|
||||||
|
+ options:0
|
||||||
|
+ range:searchRange];
|
||||||
|
+ if (nl.location != NSNotFound)
|
||||||
|
+ granularity = 2; /* Line. */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ NSDictionary *moveInfo = @{
|
+ NSDictionary *moveInfo = @{
|
||||||
+ @"AXTextStateChangeType": @1,
|
+ @"AXTextStateChangeType": @1,
|
||||||
+ @"AXTextSelectionDirection": @4,
|
+ @"AXTextSelectionDirection": @(direction),
|
||||||
+ @"AXTextSelectionGranularity": @3
|
+ @"AXTextSelectionGranularity": @(granularity)
|
||||||
+ };
|
+ };
|
||||||
+ NSAccessibilityPostNotificationWithUserInfo (
|
+ NSAccessibilityPostNotificationWithUserInfo (
|
||||||
+ self,
|
+ self,
|
||||||
@@ -842,7 +883,7 @@ index 932d209..6543e3b 100644
|
|||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
|
|
||||||
EmacsView implementation
|
EmacsView implementation
|
||||||
@@ -6889,6 +7636,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
@@ -6889,6 +7675,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
||||||
[layer release];
|
[layer release];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -850,7 +891,7 @@ index 932d209..6543e3b 100644
|
|||||||
[[self menu] release];
|
[[self menu] release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -8237,6 +8985,18 @@ ns_in_echo_area (void)
|
@@ -8237,6 +9024,18 @@ ns_in_echo_area (void)
|
||||||
XSETFRAME (event.frame_or_window, emacsframe);
|
XSETFRAME (event.frame_or_window, emacsframe);
|
||||||
kbd_buffer_store_event (&event);
|
kbd_buffer_store_event (&event);
|
||||||
ns_send_appdefined (-1); // Kick main loop
|
ns_send_appdefined (-1); // Kick main loop
|
||||||
@@ -869,7 +910,7 @@ index 932d209..6543e3b 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -9474,6 +10234,259 @@ ns_in_echo_area (void)
|
@@ -9474,6 +10273,290 @@ ns_in_echo_area (void)
|
||||||
return fs_state;
|
return fs_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,37 +1069,68 @@ index 932d209..6543e3b 100644
|
|||||||
+ if (!emacsframe)
|
+ if (!emacsframe)
|
||||||
+ return;
|
+ return;
|
||||||
+
|
+
|
||||||
|
+ /* Re-entrance guard: VoiceOver callbacks during notification posting
|
||||||
|
+ can trigger redisplay, which calls ns_update_end, which calls us
|
||||||
|
+ again. Prevent infinite recursion. */
|
||||||
|
+ if (accessibilityUpdating)
|
||||||
|
+ return;
|
||||||
|
+ accessibilityUpdating = YES;
|
||||||
|
+
|
||||||
|
+ /* Detect window tree change (split, delete, new buffer). Compare
|
||||||
|
+ FRAME_ROOT_WINDOW — if it changed, the tree structure changed. */
|
||||||
|
+ Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe);
|
||||||
|
+ if (!EQ (curRoot, lastRootWindow))
|
||||||
|
+ {
|
||||||
|
+ lastRootWindow = curRoot;
|
||||||
|
+ accessibilityTreeValid = NO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If tree is stale, rebuild FIRST so we don't iterate freed
|
||||||
|
+ window pointers. Skip notifications for this cycle — the
|
||||||
|
+ freshly-built elements have no previous state to diff against. */
|
||||||
|
+ if (!accessibilityTreeValid)
|
||||||
|
+ {
|
||||||
|
+ [self rebuildAccessibilityTree];
|
||||||
|
+
|
||||||
|
+ /* Post focus change so VoiceOver picks up the new tree. */
|
||||||
|
+ id focused = [self accessibilityFocusedUIElement];
|
||||||
|
+ if (focused && focused != self)
|
||||||
|
+ NSAccessibilityPostNotification (focused,
|
||||||
|
+ NSAccessibilityFocusedUIElementChangedNotification);
|
||||||
|
+
|
||||||
|
+ lastSelectedWindow = emacsframe->selected_window;
|
||||||
|
+ accessibilityUpdating = NO;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ /* Post per-buffer notifications using EXISTING elements that have
|
+ /* Post per-buffer notifications using EXISTING elements that have
|
||||||
+ cached state from the previous cycle. */
|
+ cached state from the previous cycle. Validate each window
|
||||||
|
+ pointer before use. */
|
||||||
+ for (EmacsAccessibilityElement *elem in accessibilityElements)
|
+ for (EmacsAccessibilityElement *elem in accessibilityElements)
|
||||||
+ {
|
+ {
|
||||||
+ if ([elem isKindOfClass:[EmacsAccessibilityBuffer class]])
|
+ if ([elem isKindOfClass:[EmacsAccessibilityBuffer class]])
|
||||||
+ {
|
+ {
|
||||||
+ struct window *w = elem.emacsWindow;
|
+ struct window *w = elem.emacsWindow;
|
||||||
+ if (w && WINDOW_LEAF_P (w))
|
+ if (w && WINDOW_LEAF_P (w)
|
||||||
|
+ && BUFFERP (w->contents) && XBUFFER (w->contents))
|
||||||
+ [(EmacsAccessibilityBuffer *) elem
|
+ [(EmacsAccessibilityBuffer *) elem
|
||||||
+ postAccessibilityNotificationsForFrame:emacsframe];
|
+ postAccessibilityNotificationsForFrame:emacsframe];
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ /* Check for window switch (C-x o) before rebuild. */
|
+ /* Check for window switch (C-x o). */
|
||||||
+ Lisp_Object curSel = emacsframe->selected_window;
|
+ Lisp_Object curSel = emacsframe->selected_window;
|
||||||
+ BOOL windowSwitched = !EQ (curSel, lastSelectedWindow);
|
+ BOOL windowSwitched = !EQ (curSel, lastSelectedWindow);
|
||||||
+ if (windowSwitched)
|
+ if (windowSwitched)
|
||||||
+ lastSelectedWindow = curSel;
|
|
||||||
+
|
|
||||||
+ /* Rebuild tree only if window configuration changed. */
|
|
||||||
+ if (!accessibilityTreeValid)
|
|
||||||
+ [self rebuildAccessibilityTree];
|
|
||||||
+
|
|
||||||
+ /* Post focus change AFTER rebuild so the new element exists. */
|
|
||||||
+ if (windowSwitched)
|
|
||||||
+ {
|
+ {
|
||||||
|
+ lastSelectedWindow = curSel;
|
||||||
+ id focused = [self accessibilityFocusedUIElement];
|
+ id focused = [self accessibilityFocusedUIElement];
|
||||||
+ if (focused && focused != self)
|
+ if (focused && focused != self)
|
||||||
+ NSAccessibilityPostNotification (focused,
|
+ NSAccessibilityPostNotification (focused,
|
||||||
+ NSAccessibilityFocusedUIElementChangedNotification);
|
+ NSAccessibilityFocusedUIElementChangedNotification);
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
|
+ accessibilityUpdating = NO;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+/* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ----
|
+/* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ----
|
||||||
@@ -1129,7 +1201,7 @@ index 932d209..6543e3b 100644
|
|||||||
@end /* EmacsView */
|
@end /* EmacsView */
|
||||||
|
|
||||||
|
|
||||||
@@ -9941,6 +10954,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
|
@@ -9941,6 +11024,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
|
||||||
|
|
||||||
return [super accessibilityAttributeValue:attribute];
|
return [super accessibilityAttributeValue:attribute];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user