patches: fix B1 (live window ref), B2 (matrix guard), B3 (invisibility-spec), H1 (thread safety), H4 (main thread assert)
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
From 4626c5d0688db9d878120b120cb19e12fa2f3a94 Mon Sep 17 00:00:00 2001
|
||||
From 1caa0476b3109ad583715c2f8a90c943780ffcb9 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Sukany <martin@sukany.cz>
|
||||
Date: Fri, 27 Feb 2026 09:39:39 +0100
|
||||
Date: Fri, 27 Feb 2026 09:57:00 +0100
|
||||
Subject: [PATCH] ns: implement VoiceOver accessibility (AXBoundsForRange, line
|
||||
nav, completions)
|
||||
|
||||
---
|
||||
src/nsterm.h | 71 ++
|
||||
src/nsterm.m | 2195 ++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 2126 insertions(+), 140 deletions(-)
|
||||
src/nsterm.h | 73 ++
|
||||
src/nsterm.m | 2249 +++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 2187 insertions(+), 135 deletions(-)
|
||||
|
||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||
index 7c1ee4c..22828f2 100644
|
||||
index 7c1ee4c..717a838 100644
|
||||
--- a/src/nsterm.h
|
||||
+++ b/src/nsterm.h
|
||||
@@ -453,6 +453,62 @@ enum ns_return_frame_mode
|
||||
@@ -453,6 +453,64 @@ enum ns_return_frame_mode
|
||||
@end
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ index 7c1ee4c..22828f2 100644
|
||||
+/* Base class for virtual accessibility elements attached to EmacsView. */
|
||||
+@interface EmacsAccessibilityElement : NSAccessibilityElement
|
||||
+@property (nonatomic, unsafe_unretained) EmacsView *emacsView;
|
||||
+@property (nonatomic, assign) struct window *emacsWindow;
|
||||
+/* Lisp window object — safe across GC cycles. NULL_LISP when unset. */
|
||||
+@property (nonatomic, assign) Lisp_Object lispWindow;
|
||||
+- (struct window *)validWindow; /* Returns live window or NULL. */
|
||||
+- (NSRect)screenRectFromEmacsX:(int)x y:(int)y width:(int)w height:(int)h;
|
||||
+@end
|
||||
+
|
||||
@@ -76,7 +78,7 @@ index 7c1ee4c..22828f2 100644
|
||||
/* ==========================================================================
|
||||
|
||||
The main Emacs view
|
||||
@@ -471,6 +527,14 @@ enum ns_return_frame_mode
|
||||
@@ -471,6 +529,14 @@ enum ns_return_frame_mode
|
||||
#ifdef NS_IMPL_COCOA
|
||||
char *old_title;
|
||||
BOOL maximizing_resize;
|
||||
@@ -91,7 +93,7 @@ index 7c1ee4c..22828f2 100644
|
||||
#endif
|
||||
BOOL font_panel_active;
|
||||
NSFont *font_panel_result;
|
||||
@@ -528,6 +592,13 @@ enum ns_return_frame_mode
|
||||
@@ -528,6 +594,13 @@ enum ns_return_frame_mode
|
||||
- (void)windowWillExitFullScreen;
|
||||
- (void)windowDidExitFullScreen;
|
||||
- (void)windowDidBecomeKey;
|
||||
@@ -106,10 +108,18 @@ index 7c1ee4c..22828f2 100644
|
||||
|
||||
|
||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||
index 932d209..06ee636 100644
|
||||
index 932d209..220dccf 100644
|
||||
--- a/src/nsterm.m
|
||||
+++ b/src/nsterm.m
|
||||
@@ -1104,6 +1104,11 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
@@ -46,6 +46,7 @@ Updated by Christian Limpach (chris@nice.ch)
|
||||
#include "blockinput.h"
|
||||
#include "sysselect.h"
|
||||
#include "nsterm.h"
|
||||
+#include "intervals.h"
|
||||
#include "systime.h"
|
||||
#include "character.h"
|
||||
#include "xwidget.h"
|
||||
@@ -1104,6 +1105,11 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
||||
|
||||
unblock_input ();
|
||||
ns_updating_frame = NULL;
|
||||
@@ -121,7 +131,7 @@ index 932d209..06ee636 100644
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3232,6 +3237,37 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
|
||||
@@ -3232,6 +3238,37 @@ 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));
|
||||
|
||||
@@ -159,7 +169,7 @@ index 932d209..06ee636 100644
|
||||
ns_focus (f, NULL, 0);
|
||||
|
||||
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
||||
@@ -6849,216 +6885,1781 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
|
||||
@@ -6849,207 +6886,1829 @@ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
|
||||
|
||||
/* ==========================================================================
|
||||
|
||||
@@ -227,16 +237,14 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+ while (pos < zv)
|
||||
+ {
|
||||
+ /* Check invisible property (text properties + overlays). */
|
||||
+ /* Check invisible property (text properties + overlays).
|
||||
+ Use TEXT_PROP_MEANS_INVISIBLE which respects buffer-invisibility-spec,
|
||||
+ matching the logic in xdisp.c. This correctly handles org-mode,
|
||||
+ outline-mode, hideshow and any mode using spec-controlled
|
||||
+ invisibility (not just `invisible t'). */
|
||||
+ Lisp_Object invis = Fget_char_property (make_fixnum (pos),
|
||||
+ Qinvisible, Qnil);
|
||||
+ /* Check if invisible property means truly invisible.
|
||||
+ TEXT_PROP_MEANS_INVISIBLE is defined only in xdisp.c,
|
||||
+ so we replicate: EQ(invis, Qt), or invis is on the
|
||||
+ buffer's invisibility-spec list. Simplified: any
|
||||
+ non-nil invisible property hides the text. This matches
|
||||
+ the common case (invisible t) and org-mode/dired usage. */
|
||||
+ if (!NILP (invis))
|
||||
+ if (TEXT_PROP_MEANS_INVISIBLE (invis))
|
||||
+ {
|
||||
+ /* Skip to the next position where invisible changes. */
|
||||
+ Lisp_Object next = Fnext_single_char_property_change (
|
||||
@@ -730,8 +738,34 @@ index 932d209..06ee636 100644
|
||||
+@implementation EmacsAccessibilityElement
|
||||
|
||||
- return Qnil;
|
||||
+- (NSRect)screenRectFromEmacsX:(int)x y:(int)y width:(int)ew height:(int)eh
|
||||
+- (instancetype)init
|
||||
+{
|
||||
+ self = [super init];
|
||||
+ if (self)
|
||||
+ self.lispWindow = Qnil;
|
||||
+ return self;
|
||||
}
|
||||
|
||||
-- (BOOL)acceptsFirstResponder
|
||||
+/* Return the associated Emacs window if it is still live, else NULL.
|
||||
+ Use this instead of storing a raw struct window * which can become a
|
||||
+ dangling pointer after delete-window or kill-buffer. */
|
||||
+- (struct window *)validWindow
|
||||
{
|
||||
- NSTRACE ("[EmacsView acceptsFirstResponder]");
|
||||
- return YES;
|
||||
+ if (NILP (self.lispWindow) || !WINDOW_LIVE_P (self.lispWindow))
|
||||
+ return NULL;
|
||||
+ return XWINDOW (self.lispWindow);
|
||||
}
|
||||
|
||||
-/* Tell NS we want to accept clicks that activate the window */
|
||||
-- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
+- (NSRect)screenRectFromEmacsX:(int)x y:(int)y width:(int)ew height:(int)eh
|
||||
{
|
||||
- NSTRACE_MSG ("First mouse event: type=%ld, clickCount=%ld",
|
||||
- [theEvent type], [theEvent clickCount]);
|
||||
- return ns_click_through;
|
||||
+ EmacsView *view = self.emacsView;
|
||||
+ if (!view || ![view window])
|
||||
+ return NSZeroRect;
|
||||
@@ -740,39 +774,25 @@ index 932d209..06ee636 100644
|
||||
+ NSRect winRect = [view convertRect:r toView:nil];
|
||||
+ return [[view window] convertRectToScreen:winRect];
|
||||
}
|
||||
|
||||
-- (BOOL)acceptsFirstResponder
|
||||
-- (void)resetCursorRects
|
||||
+
|
||||
+- (BOOL)isAccessibilityElement
|
||||
{
|
||||
- NSTRACE ("[EmacsView acceptsFirstResponder]");
|
||||
return YES;
|
||||
}
|
||||
|
||||
-/* Tell NS we want to accept clicks that activate the window */
|
||||
-- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
+/* ---- Hierarchy plumbing (required for VoiceOver to find us) ---- */
|
||||
+
|
||||
+- (id)accessibilityParent
|
||||
{
|
||||
- NSTRACE_MSG ("First mouse event: type=%ld, clickCount=%ld",
|
||||
- [theEvent type], [theEvent clickCount]);
|
||||
- return ns_click_through;
|
||||
+ return NSAccessibilityUnignoredAncestor (self.emacsView);
|
||||
}
|
||||
-- (void)resetCursorRects
|
||||
-{
|
||||
- NSRect visible = [self visibleRect];
|
||||
- NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
|
||||
- NSTRACE ("[EmacsView resetCursorRects]");
|
||||
-
|
||||
+ return YES;
|
||||
+}
|
||||
|
||||
- if (currentCursor == nil)
|
||||
- currentCursor = [NSCursor arrowCursor];
|
||||
+/* ---- Hierarchy plumbing (required for VoiceOver to find us) ---- */
|
||||
|
||||
- if (!NSIsEmptyRect (visible))
|
||||
- [self addCursorRect: visible cursor: currentCursor];
|
||||
+- (id)accessibilityWindow
|
||||
+- (id)accessibilityParent
|
||||
+{
|
||||
+ return [self.emacsView window];
|
||||
+ return NSAccessibilityUnignoredAncestor (self.emacsView);
|
||||
+}
|
||||
|
||||
-#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||
@@ -781,17 +801,19 @@ index 932d209..06ee636 100644
|
||||
-#endif
|
||||
- [currentCursor setOnMouseEntered: YES];
|
||||
-#endif
|
||||
+- (id)accessibilityWindow
|
||||
+{
|
||||
+ return [self.emacsView window];
|
||||
+}
|
||||
+
|
||||
+- (id)accessibilityTopLevelUIElement
|
||||
+{
|
||||
+ return [self.emacsView window];
|
||||
}
|
||||
|
||||
+}
|
||||
+
|
||||
+@end
|
||||
|
||||
|
||||
-/*****************************************************************************/
|
||||
-/* Keyboard handling. */
|
||||
-#define NS_KEYLOG 0
|
||||
+
|
||||
+
|
||||
+@implementation EmacsAccessibilityBuffer
|
||||
+@synthesize cachedText;
|
||||
+@synthesize cachedTextModiff;
|
||||
@@ -803,8 +825,7 @@ index 932d209..06ee636 100644
|
||||
+@synthesize cachedCompletionOverlayStart;
|
||||
+@synthesize cachedCompletionOverlayEnd;
|
||||
+@synthesize cachedCompletionPoint;
|
||||
|
||||
-- (void)keyDown: (NSEvent *)theEvent
|
||||
+
|
||||
+- (void)dealloc
|
||||
+{
|
||||
+ [cachedText release];
|
||||
@@ -830,7 +851,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (void)ensureTextCache
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return;
|
||||
+
|
||||
@@ -868,7 +889,7 @@ index 932d209..06ee636 100644
|
||||
+/* Convert buffer charpos to accessibility string index. */
|
||||
+- (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ struct buffer *b = (w && WINDOW_LEAF_P (w)) ? XBUFFER (w->contents) : NULL;
|
||||
+
|
||||
+ for (NSUInteger i = 0; i < visibleRunCount; i++)
|
||||
@@ -901,7 +922,7 @@ index 932d209..06ee636 100644
|
||||
+/* Convert accessibility string index to buffer charpos. */
|
||||
+- (ptrdiff_t)charposForAccessibilityIndex:(NSUInteger)ax_idx
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ struct buffer *b = (w && WINDOW_LEAF_P (w)) ? XBUFFER (w->contents) : NULL;
|
||||
+
|
||||
+ for (NSUInteger i = 0; i < visibleRunCount; i++)
|
||||
@@ -950,7 +971,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSString *)accessibilityRoleDescription
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (w && MINI_WINDOW_P (w))
|
||||
+ return @"minibuffer";
|
||||
+ return @"editor";
|
||||
@@ -958,7 +979,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSString *)accessibilityLabel
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (w && WINDOW_LEAF_P (w))
|
||||
+ {
|
||||
+ if (MINI_WINDOW_P (w))
|
||||
@@ -977,7 +998,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (BOOL)isAccessibilityFocused
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w)
|
||||
+ return NO;
|
||||
+ EmacsView *view = self.emacsView;
|
||||
@@ -989,6 +1010,14 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (id)accessibilityValue
|
||||
+{
|
||||
+ /* AX getters can be called from any thread by the AT subsystem.
|
||||
+ Dispatch to main thread where Emacs buffer state is consistent. */
|
||||
+ if (![NSThread isMainThread])
|
||||
+ {
|
||||
+ __block id result;
|
||||
+ dispatch_sync (dispatch_get_main_queue (), ^{ result = [self accessibilityValue]; });
|
||||
+ return result;
|
||||
+ }
|
||||
+ [self ensureTextCache];
|
||||
+ return cachedText ? cachedText : @"";
|
||||
+}
|
||||
@@ -1001,7 +1030,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSString *)accessibilitySelectedText
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return @"";
|
||||
+
|
||||
@@ -1019,7 +1048,13 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSRange)accessibilitySelectedTextRange
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ if (![NSThread isMainThread])
|
||||
+ {
|
||||
+ __block NSRange result;
|
||||
+ dispatch_sync (dispatch_get_main_queue (), ^{ result = [self accessibilitySelectedTextRange]; });
|
||||
+ return result;
|
||||
+ }
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return NSMakeRange (0, 0);
|
||||
+
|
||||
@@ -1045,7 +1080,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (void)setAccessibilitySelectedTextRange:(NSRange)range
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return;
|
||||
+
|
||||
@@ -1104,7 +1139,7 @@ index 932d209..06ee636 100644
|
||||
+ if (!flag)
|
||||
+ return;
|
||||
+
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return;
|
||||
+
|
||||
@@ -1132,7 +1167,13 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSInteger)accessibilityInsertionPointLineNumber
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ if (![NSThread isMainThread])
|
||||
+ {
|
||||
+ __block NSInteger result;
|
||||
+ dispatch_sync (dispatch_get_main_queue (), ^{ result = [self accessibilityInsertionPointLineNumber]; });
|
||||
+ return result;
|
||||
+ }
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return 0;
|
||||
+
|
||||
@@ -1246,7 +1287,13 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSRect)accessibilityFrameForRange:(NSRange)range
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ if (![NSThread isMainThread])
|
||||
+ {
|
||||
+ __block NSRect result;
|
||||
+ dispatch_sync (dispatch_get_main_queue (), ^{ result = [self accessibilityFrameForRange:range]; });
|
||||
+ return result;
|
||||
+ }
|
||||
+ struct window *w = [self validWindow];
|
||||
+ EmacsView *view = self.emacsView;
|
||||
+ if (!w || !view)
|
||||
+ return NSZeroRect;
|
||||
@@ -1261,8 +1308,14 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSRange)accessibilityRangeForPosition:(NSPoint)screenPoint
|
||||
+{
|
||||
+ if (![NSThread isMainThread])
|
||||
+ {
|
||||
+ __block NSRange result;
|
||||
+ dispatch_sync (dispatch_get_main_queue (), ^{ result = [self accessibilityRangeForPosition:screenPoint]; });
|
||||
+ return result;
|
||||
+ }
|
||||
+ /* Hit test: convert screen point to buffer character index. */
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ EmacsView *view = self.emacsView;
|
||||
+ if (!w || !view || !w->current_matrix)
|
||||
+ return NSMakeRange (0, 0);
|
||||
@@ -1278,6 +1331,10 @@ index 932d209..06ee636 100644
|
||||
+ if (x < 0 || y < 0 || x >= w->pixel_width || y >= w->pixel_height)
|
||||
+ return NSMakeRange (0, 0);
|
||||
+
|
||||
+ /* Block input to prevent concurrent redisplay from modifying the
|
||||
+ glyph matrix while we traverse it. */
|
||||
+ block_input ();
|
||||
+
|
||||
+ /* Find the glyph row at this y coordinate. */
|
||||
+ struct glyph_matrix *matrix = w->current_matrix;
|
||||
+ struct glyph_row *hit_row = NULL;
|
||||
@@ -1297,7 +1354,10 @@ index 932d209..06ee636 100644
|
||||
+ }
|
||||
+
|
||||
+ if (!hit_row)
|
||||
+ return NSMakeRange (0, 0);
|
||||
+ {
|
||||
+ unblock_input ();
|
||||
+ return NSMakeRange (0, 0);
|
||||
+ }
|
||||
+
|
||||
+ /* Find the glyph at this x coordinate within the row. */
|
||||
+ struct glyph *glyph = hit_row->glyphs[TEXT_AREA];
|
||||
@@ -1324,6 +1384,8 @@ index 932d209..06ee636 100644
|
||||
+ NSUInteger ax_idx = [self accessibilityIndexForCharpos:best_charpos];
|
||||
+ if (cachedText && ax_idx > [cachedText length])
|
||||
+ ax_idx = [cachedText length];
|
||||
+
|
||||
+ unblock_input ();
|
||||
+ return NSMakeRange (ax_idx, 1);
|
||||
+}
|
||||
+
|
||||
@@ -1338,7 +1400,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSRect)accessibilityFrame
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w)
|
||||
+ return NSZeroRect;
|
||||
+
|
||||
@@ -1366,7 +1428,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (void)postAccessibilityNotificationsForFrame:(struct frame *)f
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return;
|
||||
+
|
||||
@@ -1812,7 +1874,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSString *)accessibilityLabel
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (w && WINDOW_LEAF_P (w))
|
||||
+ {
|
||||
+ struct buffer *b = XBUFFER (w->contents);
|
||||
@@ -1831,7 +1893,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (id)accessibilityValue
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w)
|
||||
+ return @"";
|
||||
+ return ns_ax_mode_line_text (w);
|
||||
@@ -1839,7 +1901,7 @@ index 932d209..06ee636 100644
|
||||
+
|
||||
+- (NSRect)accessibilityFrame
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ struct window *w = [self validWindow];
|
||||
+ if (!w || !w->current_matrix)
|
||||
+ return NSZeroRect;
|
||||
+
|
||||
@@ -2069,19 +2131,10 @@ index 932d209..06ee636 100644
|
||||
+#endif
|
||||
+ [currentCursor setOnMouseEntered: YES];
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*****************************************************************************/
|
||||
+/* Keyboard handling. */
|
||||
+#define NS_KEYLOG 0
|
||||
+
|
||||
+- (void)keyDown: (NSEvent *)theEvent
|
||||
{
|
||||
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
|
||||
int code;
|
||||
@@ -8237,6 +9838,28 @@ - (void)windowDidBecomeKey /* for direct calls */
|
||||
}
|
||||
|
||||
|
||||
@@ -8237,6 +9896,28 @@ - (void)windowDidBecomeKey /* for direct calls */
|
||||
XSETFRAME (event.frame_or_window, emacsframe);
|
||||
kbd_buffer_store_event (&event);
|
||||
ns_send_appdefined (-1); // Kick main loop
|
||||
@@ -2110,7 +2163,7 @@ index 932d209..06ee636 100644
|
||||
}
|
||||
|
||||
|
||||
@@ -9474,6 +11097,298 @@ - (int) fullscreenState
|
||||
@@ -9474,6 +11155,304 @@ - (int) fullscreenState
|
||||
return fs_state;
|
||||
}
|
||||
|
||||
@@ -2147,7 +2200,7 @@ index 932d209..06ee636 100644
|
||||
+ {
|
||||
+ [elem retain];
|
||||
+ }
|
||||
+ elem.emacsWindow = w;
|
||||
+ elem.lispWindow = window;
|
||||
+ [elements addObject:elem];
|
||||
+ [elem release];
|
||||
+
|
||||
@@ -2157,7 +2210,7 @@ index 932d209..06ee636 100644
|
||||
+ EmacsAccessibilityModeLine *ml
|
||||
+ = [[EmacsAccessibilityModeLine alloc] init];
|
||||
+ ml.emacsView = view;
|
||||
+ ml.emacsWindow = w;
|
||||
+ ml.lispWindow = window;
|
||||
+ [elements addObject:ml];
|
||||
+ [ml release];
|
||||
+ }
|
||||
@@ -2186,10 +2239,10 @@ index 932d209..06ee636 100644
|
||||
+ for (EmacsAccessibilityElement *elem in accessibilityElements)
|
||||
+ {
|
||||
+ if ([elem isKindOfClass:[EmacsAccessibilityBuffer class]]
|
||||
+ && elem.emacsWindow)
|
||||
+ && !NILP (elem.lispWindow))
|
||||
+ [existing setObject:elem
|
||||
+ forKey:[NSValue valueWithPointer:
|
||||
+ elem.emacsWindow]];
|
||||
+ XWINDOW (elem.lispWindow)]];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@@ -2248,7 +2301,7 @@ index 932d209..06ee636 100644
|
||||
+ for (EmacsAccessibilityElement *elem in accessibilityElements)
|
||||
+ {
|
||||
+ if ([elem isKindOfClass:[EmacsAccessibilityBuffer class]]
|
||||
+ && elem.emacsWindow == sel)
|
||||
+ && EQ (elem.lispWindow, emacsframe->selected_window))
|
||||
+ return elem;
|
||||
+ }
|
||||
+ return self;
|
||||
@@ -2262,6 +2315,9 @@ index 932d209..06ee636 100644
|
||||
+ elements with current values, making change detection impossible. */
|
||||
+- (void)postAccessibilityUpdates
|
||||
+{
|
||||
+ NSCAssert ([NSThread isMainThread],
|
||||
+ @"postAccessibilityUpdates must be called on the main thread");
|
||||
+
|
||||
+ if (!emacsframe)
|
||||
+ return;
|
||||
+
|
||||
@@ -2271,6 +2327,7 @@ index 932d209..06ee636 100644
|
||||
+ if (accessibilityUpdating)
|
||||
+ return;
|
||||
+ accessibilityUpdating = YES;
|
||||
+ @try {
|
||||
+
|
||||
+ /* Detect window tree change (split, delete, new buffer). Compare
|
||||
+ FRAME_ROOT_WINDOW — if it changed, the tree structure changed. */
|
||||
@@ -2308,7 +2365,7 @@ index 932d209..06ee636 100644
|
||||
+ {
|
||||
+ if ([elem isKindOfClass:[EmacsAccessibilityBuffer class]])
|
||||
+ {
|
||||
+ struct window *w = elem.emacsWindow;
|
||||
+ struct window *w = [elem validWindow];
|
||||
+ if (w && WINDOW_LEAF_P (w)
|
||||
+ && BUFFERP (w->contents) && XBUFFER (w->contents))
|
||||
+ [(EmacsAccessibilityBuffer *) elem
|
||||
@@ -2338,7 +2395,9 @@ index 932d209..06ee636 100644
|
||||
+ NSAccessibilityFocusedUIElementChangedNotification);
|
||||
+ }
|
||||
+
|
||||
+ accessibilityUpdating = NO;
|
||||
+ } @finally {
|
||||
+ accessibilityUpdating = NO;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ----
|
||||
|
||||
Reference in New Issue
Block a user