Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
diff --git a/src/nsterm.h b/src/nsterm.h
|
||||
index 7c1ee4c..855d302 100644
|
||||
index 7c1ee4c..2e2c80f 100644
|
||||
--- a/src/nsterm.h
|
||||
+++ b/src/nsterm.h
|
||||
@@ -453,6 +453,57 @@ enum ns_return_frame_mode
|
||||
@@ -453,6 +453,58 @@ enum ns_return_frame_mode
|
||||
@end
|
||||
|
||||
|
||||
@@ -29,8 +29,9 @@ index 7c1ee4c..855d302 100644
|
||||
+typedef struct ns_ax_visible_run
|
||||
+{
|
||||
+ ptrdiff_t charpos; /* Buffer charpos where this visible run starts. */
|
||||
+ ptrdiff_t length; /* Number of visible characters in this run. */
|
||||
+ ptrdiff_t length; /* Number of visible Emacs characters in this run. */
|
||||
+ NSUInteger ax_start; /* Starting index in the accessibility string. */
|
||||
+ NSUInteger ax_length; /* Length in accessibility string (UTF-16 units). */
|
||||
+} ns_ax_visible_run;
|
||||
+
|
||||
+/* Virtual AXTextArea element — one per visible Emacs window (buffer). */
|
||||
@@ -60,7 +61,7 @@ index 7c1ee4c..855d302 100644
|
||||
/* ==========================================================================
|
||||
|
||||
The main Emacs view
|
||||
@@ -471,6 +522,14 @@ enum ns_return_frame_mode
|
||||
@@ -471,6 +523,14 @@ enum ns_return_frame_mode
|
||||
#ifdef NS_IMPL_COCOA
|
||||
char *old_title;
|
||||
BOOL maximizing_resize;
|
||||
@@ -75,7 +76,7 @@ index 7c1ee4c..855d302 100644
|
||||
#endif
|
||||
BOOL font_panel_active;
|
||||
NSFont *font_panel_result;
|
||||
@@ -528,6 +587,13 @@ enum ns_return_frame_mode
|
||||
@@ -528,6 +588,13 @@ enum ns_return_frame_mode
|
||||
- (void)windowWillExitFullScreen;
|
||||
- (void)windowDidExitFullScreen;
|
||||
- (void)windowDidBecomeKey;
|
||||
@@ -90,7 +91,7 @@ index 7c1ee4c..855d302 100644
|
||||
|
||||
|
||||
diff --git a/src/nsterm.m b/src/nsterm.m
|
||||
index 932d209..ca6b969 100644
|
||||
index 932d209..043477b 100644
|
||||
--- a/src/nsterm.m
|
||||
+++ b/src/nsterm.m
|
||||
@@ -1104,6 +1104,11 @@ ns_update_end (struct frame *f)
|
||||
@@ -143,29 +144,23 @@ index 932d209..ca6b969 100644
|
||||
ns_focus (f, NULL, 0);
|
||||
|
||||
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
||||
@@ -6849,265 +6885,1333 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
||||
@@ -6847,6 +6883,1074 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ==========================================================================
|
||||
|
||||
- EmacsView implementation
|
||||
+/* ==========================================================================
|
||||
+
|
||||
+ Accessibility virtual elements (macOS / Cocoa only)
|
||||
|
||||
========================================================================== */
|
||||
|
||||
+
|
||||
+ ========================================================================== */
|
||||
+
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
|
||||
-@implementation EmacsView
|
||||
+
|
||||
+/* ---- Helper: extract buffer text for accessibility ---- */
|
||||
|
||||
-- (void)windowDidEndLiveResize:(NSNotification *)notification
|
||||
-{
|
||||
- [self updateFramePosition];
|
||||
-}
|
||||
+
|
||||
+/* Maximum characters exposed via accessibilityValue. */
|
||||
+#define NS_AX_TEXT_CAP 100000
|
||||
|
||||
-/* Needed to inform when window closed from lisp. */
|
||||
-- (void) setWindowClosing: (BOOL)closing
|
||||
+
|
||||
+/* Build accessibility text for window W, skipping invisible text.
|
||||
+ Populates *OUT_START with the buffer start charpos.
|
||||
+ Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS
|
||||
@@ -174,71 +169,45 @@ index 932d209..ca6b969 100644
|
||||
+static NSString *
|
||||
+ns_ax_buffer_text (struct window *w, ptrdiff_t *out_start,
|
||||
+ ns_ax_visible_run **out_runs, NSUInteger *out_nruns)
|
||||
{
|
||||
- NSTRACE ("[EmacsView setWindowClosing:%d]", closing);
|
||||
+{
|
||||
+ *out_runs = NULL;
|
||||
+ *out_nruns = 0;
|
||||
|
||||
- windowClosing = closing;
|
||||
-}
|
||||
+
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ {
|
||||
+ *out_start = 0;
|
||||
+ return @"";
|
||||
+ }
|
||||
|
||||
+
|
||||
+ struct buffer *b = XBUFFER (w->contents);
|
||||
+ if (!b)
|
||||
+ {
|
||||
+ *out_start = 0;
|
||||
+ return @"";
|
||||
+ }
|
||||
|
||||
-- (void)dealloc
|
||||
-{
|
||||
- NSTRACE ("[EmacsView dealloc]");
|
||||
+
|
||||
+ ptrdiff_t begv = BUF_BEGV (b);
|
||||
+ ptrdiff_t zv = BUF_ZV (b);
|
||||
|
||||
- /* Clear the view resize notification. */
|
||||
- [[NSNotificationCenter defaultCenter]
|
||||
- removeObserver:self
|
||||
- name:NSViewFrameDidChangeNotification
|
||||
- object:nil];
|
||||
+
|
||||
+ *out_start = begv;
|
||||
|
||||
- if (fs_state == FULLSCREEN_BOTH)
|
||||
- [nonfs_window release];
|
||||
+
|
||||
+ if (zv <= begv)
|
||||
+ return @"";
|
||||
|
||||
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
|
||||
- /* Release layer and menu */
|
||||
- EmacsLayer *layer = (EmacsLayer *)[self layer];
|
||||
- [layer release];
|
||||
-#endif
|
||||
+
|
||||
+ struct buffer *oldb = current_buffer;
|
||||
+ if (b != current_buffer)
|
||||
+ set_buffer_internal_1 (b);
|
||||
|
||||
- [[self menu] release];
|
||||
- [super dealloc];
|
||||
-}
|
||||
+
|
||||
+ /* First pass: count visible runs to allocate the mapping array. */
|
||||
+ NSUInteger run_capacity = 64;
|
||||
+ ns_ax_visible_run *runs = xmalloc (run_capacity
|
||||
+ * sizeof (ns_ax_visible_run));
|
||||
+ NSUInteger nruns = 0;
|
||||
+ NSUInteger ax_offset = 0;
|
||||
|
||||
+
|
||||
+ NSMutableString *result = [NSMutableString string];
|
||||
+ ptrdiff_t pos = begv;
|
||||
|
||||
-/* Called on font panel selection. */
|
||||
-- (void) changeFont: (id) sender
|
||||
-{
|
||||
- struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
|
||||
- NSFont *nsfont;
|
||||
+
|
||||
+ while (pos < zv)
|
||||
+ {
|
||||
+ /* Check invisible property (text properties + overlays). */
|
||||
@@ -258,19 +227,12 @@ index 932d209..ca6b969 100644
|
||||
+ pos = FIXNUMP (next) ? XFIXNUM (next) : zv;
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
-#ifdef NS_IMPL_GNUSTEP
|
||||
- nsfont = ((struct nsfont_info *) font)->nsfont;
|
||||
-#else
|
||||
- nsfont = (NSFont *) macfont_get_nsctfont (font);
|
||||
-#endif
|
||||
+
|
||||
+ /* Find end of this visible run: where invisible property changes. */
|
||||
+ Lisp_Object next = Fnext_single_char_property_change (
|
||||
+ make_fixnum (pos), Qinvisible, Qnil, make_fixnum (zv));
|
||||
+ ptrdiff_t run_end = FIXNUMP (next) ? XFIXNUM (next) : zv;
|
||||
|
||||
- if (!font_panel_active)
|
||||
- return;
|
||||
+
|
||||
+ /* Cap total text at NS_AX_TEXT_CAP. */
|
||||
+ ptrdiff_t run_len = run_end - pos;
|
||||
+ if (ax_offset + (NSUInteger) run_len > NS_AX_TEXT_CAP)
|
||||
@@ -278,22 +240,17 @@ index 932d209..ca6b969 100644
|
||||
+ if (run_len <= 0)
|
||||
+ break;
|
||||
+ run_end = pos + run_len;
|
||||
|
||||
- if (font_panel_result)
|
||||
- [font_panel_result release];
|
||||
+ /* Extract this visible run's text. */
|
||||
+ ptrdiff_t pos_byte = buf_charpos_to_bytepos (b, pos);
|
||||
+ ptrdiff_t end_byte = buf_charpos_to_bytepos (b, run_end);
|
||||
+ unsigned char *data = BUF_BYTE_ADDRESS (b, pos_byte);
|
||||
+ ptrdiff_t nbytes = end_byte - pos_byte;
|
||||
|
||||
- font_panel_result = (NSFont *) [sender convertFont: nsfont];
|
||||
+ Lisp_Object lstr = make_string_from_bytes ((char *) data,
|
||||
+ run_len, nbytes);
|
||||
+ [result appendString:[NSString stringWithLispString:lstr]];
|
||||
|
||||
- if (font_panel_result)
|
||||
- [font_panel_result retain];
|
||||
+
|
||||
+ /* Extract this visible run's text. Use
|
||||
+ Fbuffer_substring_no_properties which correctly handles the
|
||||
+ buffer gap — raw BUF_BYTE_ADDRESS reads across the gap would
|
||||
+ include garbage bytes when the run spans the gap position. */
|
||||
+ Lisp_Object lstr = Fbuffer_substring_no_properties (
|
||||
+ make_fixnum (pos), make_fixnum (run_end));
|
||||
+ NSString *nsstr = [NSString stringWithLispString:lstr];
|
||||
+ NSUInteger ns_len = [nsstr length];
|
||||
+ [result appendString:nsstr];
|
||||
+
|
||||
+ /* Record this visible run in the mapping. */
|
||||
+ if (nruns >= run_capacity)
|
||||
+ {
|
||||
@@ -304,13 +261,10 @@ index 932d209..ca6b969 100644
|
||||
+ runs[nruns].charpos = pos;
|
||||
+ runs[nruns].length = run_len;
|
||||
+ runs[nruns].ax_start = ax_offset;
|
||||
+ runs[nruns].ax_length = ns_len;
|
||||
+ nruns++;
|
||||
|
||||
-#ifndef NS_IMPL_COCOA
|
||||
- font_panel_active = NO;
|
||||
- [NSApp stop: self];
|
||||
-#endif
|
||||
+ ax_offset += (NSUInteger) run_len;
|
||||
+
|
||||
+ ax_offset += ns_len;
|
||||
+ pos = run_end;
|
||||
+ }
|
||||
+
|
||||
@@ -320,36 +274,26 @@ index 932d209..ca6b969 100644
|
||||
+ *out_runs = runs;
|
||||
+ *out_nruns = nruns;
|
||||
+ return result;
|
||||
}
|
||||
|
||||
-#ifdef NS_IMPL_COCOA
|
||||
-- (void) noteUserSelectedFont
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* ---- Helper: extract mode line text from glyph rows ---- */
|
||||
+
|
||||
+static NSString *
|
||||
+ns_ax_mode_line_text (struct window *w)
|
||||
{
|
||||
- font_panel_active = NO;
|
||||
+{
|
||||
+ if (!w || !w->current_matrix)
|
||||
+ return @"";
|
||||
|
||||
- /* If no font was previously selected, use the currently selected
|
||||
- font. */
|
||||
+
|
||||
+ struct glyph_matrix *matrix = w->current_matrix;
|
||||
+ NSMutableString *text = [NSMutableString string];
|
||||
|
||||
- if (!font_panel_result && FRAME_FONT (emacsframe))
|
||||
+
|
||||
+ for (int i = 0; i < matrix->nrows; i++)
|
||||
{
|
||||
- font_panel_result
|
||||
- = macfont_get_nsctfont (FRAME_FONT (emacsframe));
|
||||
+ {
|
||||
+ struct glyph_row *row = matrix->rows + i;
|
||||
+ if (!row->enabled_p || !row->mode_line_p)
|
||||
+ continue;
|
||||
|
||||
- if (font_panel_result)
|
||||
- [font_panel_result retain];
|
||||
+
|
||||
+ struct glyph *g = row->glyphs[TEXT_AREA];
|
||||
+ struct glyph *end = g + row->used[TEXT_AREA];
|
||||
+ for (; g < end; g++)
|
||||
@@ -361,64 +305,28 @@ index 932d209..ca6b969 100644
|
||||
+ length:1]];
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
-
|
||||
- [NSApp stop: self];
|
||||
+ }
|
||||
+ return text;
|
||||
}
|
||||
|
||||
-- (void) noteUserCancelledSelection
|
||||
-{
|
||||
- font_panel_active = NO;
|
||||
-
|
||||
- if (font_panel_result)
|
||||
- [font_panel_result release];
|
||||
- font_panel_result = nil;
|
||||
|
||||
- [NSApp stop: self];
|
||||
-}
|
||||
-#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* ---- Helper: screen rect for a character range via glyph matrix ---- */
|
||||
|
||||
-- (Lisp_Object) showFontPanel
|
||||
+
|
||||
+static NSRect
|
||||
+ns_ax_frame_for_range (struct window *w, EmacsView *view,
|
||||
+ ptrdiff_t text_start, NSRange range)
|
||||
{
|
||||
- id fm = [NSFontManager sharedFontManager];
|
||||
- struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
|
||||
- NSFont *nsfont, *result;
|
||||
- struct timespec timeout;
|
||||
-#ifdef NS_IMPL_COCOA
|
||||
- NSView *buttons;
|
||||
- BOOL canceled;
|
||||
-#endif
|
||||
+{
|
||||
+ if (!w || !w->current_matrix || !view)
|
||||
+ return NSZeroRect;
|
||||
|
||||
-#ifdef NS_IMPL_GNUSTEP
|
||||
- nsfont = ((struct nsfont_info *) font)->nsfont;
|
||||
-#else
|
||||
- nsfont = (NSFont *) macfont_get_nsctfont (font);
|
||||
-#endif
|
||||
+
|
||||
+ /* Convert range indices back to buffer charpos. */
|
||||
+ ptrdiff_t cp_start = text_start + (ptrdiff_t) range.location;
|
||||
+ ptrdiff_t cp_end = cp_start + (ptrdiff_t) range.length;
|
||||
|
||||
-#ifdef NS_IMPL_COCOA
|
||||
- buttons
|
||||
- = ns_create_font_panel_buttons (self,
|
||||
- @selector (noteUserSelectedFont),
|
||||
- @selector (noteUserCancelledSelection));
|
||||
- [[fm fontPanel: YES] setAccessoryView: buttons];
|
||||
- [buttons release];
|
||||
-#endif
|
||||
+
|
||||
+ struct glyph_matrix *matrix = w->current_matrix;
|
||||
+ NSRect result = NSZeroRect;
|
||||
+ BOOL found = NO;
|
||||
|
||||
- [fm setSelectedFont: nsfont isMultiple: NO];
|
||||
- [fm orderFrontFontPanel: NSApp];
|
||||
+
|
||||
+ for (int i = 0; i < matrix->nrows; i++)
|
||||
+ {
|
||||
+ struct glyph_row *row = matrix->rows + i;
|
||||
@@ -426,22 +334,10 @@ index 932d209..ca6b969 100644
|
||||
+ continue;
|
||||
+ if (!row->displays_text_p && !row->ends_at_zv_p)
|
||||
+ continue;
|
||||
|
||||
- font_panel_active = YES;
|
||||
- timeout = make_timespec (0, 100000000);
|
||||
+
|
||||
+ ptrdiff_t row_start = MATRIX_ROW_START_CHARPOS (row);
|
||||
+ ptrdiff_t row_end = MATRIX_ROW_END_CHARPOS (row);
|
||||
|
||||
- block_input ();
|
||||
- while (font_panel_active
|
||||
-#ifdef NS_IMPL_COCOA
|
||||
- && (canceled = [[fm fontPanel: YES] isVisible])
|
||||
-#else
|
||||
- && [[fm fontPanel: YES] isVisible]
|
||||
-#endif
|
||||
- )
|
||||
- ns_select_1 (0, NULL, NULL, NULL, &timeout, NULL, YES);
|
||||
- unblock_input ();
|
||||
+
|
||||
+ if (row_start < cp_end && row_end > cp_start)
|
||||
+ {
|
||||
+ int window_x, window_y, window_width;
|
||||
@@ -464,16 +360,10 @@ index 932d209..ca6b969 100644
|
||||
+ result = NSUnionRect (result, rowRect);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (font_panel_result)
|
||||
- [font_panel_result autorelease];
|
||||
+
|
||||
+ if (!found)
|
||||
+ return NSZeroRect;
|
||||
|
||||
-#ifdef NS_IMPL_COCOA
|
||||
- if (!canceled)
|
||||
- font_panel_result = nil;
|
||||
-#endif
|
||||
+
|
||||
+ /* Clip result to text area bounds. */
|
||||
+ {
|
||||
+ int text_area_x, text_area_y, text_area_w, text_area_h;
|
||||
@@ -483,23 +373,15 @@ index 932d209..ca6b969 100644
|
||||
+ if (NSMaxY (result) > max_y)
|
||||
+ result.size.height = max_y - result.origin.y;
|
||||
+ }
|
||||
|
||||
- result = font_panel_result;
|
||||
- font_panel_result = nil;
|
||||
+
|
||||
+ /* Convert from EmacsView (flipped) coords to screen coords. */
|
||||
+ NSRect winRect = [view convertRect:result toView:nil];
|
||||
+ return [[view window] convertRectToScreen:winRect];
|
||||
+}
|
||||
|
||||
- [[fm fontPanel: YES] setIsVisible: NO];
|
||||
- font_panel_active = NO;
|
||||
|
||||
- if (result)
|
||||
- return ns_font_desc_to_font_spec ([result fontDescriptor],
|
||||
- result);
|
||||
+
|
||||
+
|
||||
+@implementation EmacsAccessibilityElement
|
||||
|
||||
- return Qnil;
|
||||
+
|
||||
+- (NSRect)screenRectFromEmacsX:(int)x y:(int)y width:(int)ew height:(int)eh
|
||||
+{
|
||||
+ EmacsView *view = self.emacsView;
|
||||
@@ -509,55 +391,33 @@ index 932d209..ca6b969 100644
|
||||
+ NSRect r = NSMakeRect (x, y, ew, eh);
|
||||
+ NSRect winRect = [view convertRect:r toView:nil];
|
||||
+ return [[view window] convertRectToScreen:winRect];
|
||||
}
|
||||
|
||||
-- (BOOL)acceptsFirstResponder
|
||||
+}
|
||||
+
|
||||
+- (BOOL)isAccessibilityElement
|
||||
{
|
||||
- NSTRACE ("[EmacsView acceptsFirstResponder]");
|
||||
return YES;
|
||||
}
|
||||
|
||||
-/* Tell NS we want to accept clicks that activate the window */
|
||||
-- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
+{
|
||||
+ return YES;
|
||||
+}
|
||||
+
|
||||
+/* ---- 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
|
||||
+}
|
||||
+
|
||||
+- (id)accessibilityWindow
|
||||
{
|
||||
- NSRect visible = [self visibleRect];
|
||||
- NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
|
||||
- NSTRACE ("[EmacsView resetCursorRects]");
|
||||
+{
|
||||
+ return [self.emacsView window];
|
||||
+}
|
||||
|
||||
- if (currentCursor == nil)
|
||||
- currentCursor = [NSCursor arrowCursor];
|
||||
+
|
||||
+- (id)accessibilityTopLevelUIElement
|
||||
+{
|
||||
+ return [self.emacsView window];
|
||||
+}
|
||||
|
||||
- if (!NSIsEmptyRect (visible))
|
||||
- [self addCursorRect: visible cursor: currentCursor];
|
||||
+
|
||||
+@end
|
||||
|
||||
-#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
|
||||
- if ([currentCursor respondsToSelector: @selector(setOnMouseEntered:)])
|
||||
-#endif
|
||||
- [currentCursor setOnMouseEntered: YES];
|
||||
-#endif
|
||||
-}
|
||||
|
||||
+
|
||||
+
|
||||
+@implementation EmacsAccessibilityBuffer
|
||||
+@synthesize cachedText;
|
||||
+@synthesize cachedTextModiff;
|
||||
@@ -565,7 +425,7 @@ index 932d209..ca6b969 100644
|
||||
+@synthesize cachedModiff;
|
||||
+@synthesize cachedPoint;
|
||||
+@synthesize cachedMarkActive;
|
||||
|
||||
+
|
||||
+- (void)dealloc
|
||||
+{
|
||||
+ [cachedText release];
|
||||
@@ -573,20 +433,11 @@ index 932d209..ca6b969 100644
|
||||
+ xfree (visibleRuns);
|
||||
+ [super dealloc];
|
||||
+}
|
||||
|
||||
-/*****************************************************************************/
|
||||
-/* Keyboard handling. */
|
||||
-#define NS_KEYLOG 0
|
||||
+
|
||||
+/* ---- Text cache ---- */
|
||||
|
||||
-- (void)keyDown: (NSEvent *)theEvent
|
||||
+
|
||||
+- (void)invalidateTextCache
|
||||
{
|
||||
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
|
||||
- int code;
|
||||
- unsigned fnKeysym = 0;
|
||||
- static NSMutableArray *nsEvArray;
|
||||
- unsigned int flags = [theEvent modifierFlags];
|
||||
+{
|
||||
+ [cachedText release];
|
||||
+ cachedText = nil;
|
||||
+ if (visibleRuns)
|
||||
@@ -596,21 +447,17 @@ index 932d209..ca6b969 100644
|
||||
+ }
|
||||
+ visibleRunCount = 0;
|
||||
+}
|
||||
|
||||
- NSTRACE ("[EmacsView keyDown:]");
|
||||
+
|
||||
+- (void)ensureTextCache
|
||||
+{
|
||||
+ struct window *w = self.emacsWindow;
|
||||
+ if (!w || !WINDOW_LEAF_P (w))
|
||||
+ return;
|
||||
|
||||
- /* Rhapsody and macOS give up and down events for the arrow keys. */
|
||||
- if ([theEvent type] != NSEventTypeKeyDown)
|
||||
+
|
||||
+ struct buffer *b = XBUFFER (w->contents);
|
||||
+ if (!b)
|
||||
return;
|
||||
|
||||
- if (!emacs_event)
|
||||
+ return;
|
||||
+
|
||||
+ ptrdiff_t modiff = BUF_MODIFF (b);
|
||||
+ ptrdiff_t pt = BUF_PT (b);
|
||||
+ NSUInteger textLen = cachedText ? [cachedText length] : 0;
|
||||
@@ -618,53 +465,31 @@ index 932d209..ca6b969 100644
|
||||
+ && pt >= cachedTextStart
|
||||
+ && (textLen == 0
|
||||
+ || [self accessibilityIndexForCharpos:pt] <= textLen))
|
||||
return;
|
||||
|
||||
- if (![[self window] isKeyWindow]
|
||||
- && [[theEvent window] isKindOfClass: [EmacsWindow class]]
|
||||
- /* We must avoid an infinite loop here. */
|
||||
- && (EmacsView *)[[theEvent window] delegate] != self)
|
||||
- {
|
||||
- /* XXX: There is an occasional condition in which, when Emacs display
|
||||
- updates a different frame from the current one, and temporarily
|
||||
- selects it, then processes some interrupt-driven input
|
||||
- (dispnew.c:3878), OS will send the event to the correct NSWindow, but
|
||||
- for some reason that window has its first responder set to the NSView
|
||||
- most recently updated (I guess), which is not the correct one. */
|
||||
- [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
|
||||
- return;
|
||||
- }
|
||||
+ return;
|
||||
+
|
||||
+ ptrdiff_t start;
|
||||
+ ns_ax_visible_run *runs = NULL;
|
||||
+ NSUInteger nruns = 0;
|
||||
+ NSString *text = ns_ax_buffer_text (w, &start, &runs, &nruns);
|
||||
|
||||
- if (nsEvArray == nil)
|
||||
- nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
|
||||
+
|
||||
+ [cachedText release];
|
||||
+ cachedText = [text retain];
|
||||
+ cachedTextModiff = modiff;
|
||||
+ cachedTextStart = start;
|
||||
|
||||
- [NSCursor setHiddenUntilMouseMoves:! NILP (Vmake_pointer_invisible)];
|
||||
+
|
||||
+ if (visibleRuns)
|
||||
+ xfree (visibleRuns);
|
||||
+ visibleRuns = runs;
|
||||
+ visibleRunCount = nruns;
|
||||
+}
|
||||
|
||||
- if (!hlinfo->mouse_face_hidden
|
||||
- && FIXNUMP (Vmouse_highlight)
|
||||
- && !EQ (emacsframe->tab_bar_window, hlinfo->mouse_face_window))
|
||||
+
|
||||
+/* ---- Index mapping ---- */
|
||||
+
|
||||
+/* Convert buffer charpos to accessibility string index. */
|
||||
+- (NSUInteger)accessibilityIndexForCharpos:(ptrdiff_t)charpos
|
||||
+{
|
||||
+ for (NSUInteger i = 0; i < visibleRunCount; i++)
|
||||
{
|
||||
- clear_mouse_face (hlinfo);
|
||||
- hlinfo->mouse_face_hidden = true;
|
||||
+ {
|
||||
+ ns_ax_visible_run *r = &visibleRuns[i];
|
||||
+ if (charpos >= r->charpos && charpos < r->charpos + r->length)
|
||||
+ return r->ax_start + (NSUInteger) (charpos - r->charpos);
|
||||
@@ -672,17 +497,12 @@ index 932d209..ca6b969 100644
|
||||
+ map it to the start of the next visible run. */
|
||||
+ if (charpos < r->charpos)
|
||||
+ return r->ax_start;
|
||||
}
|
||||
-
|
||||
- if (!processingCompose)
|
||||
+ }
|
||||
+ /* Past end — return total length. */
|
||||
+ if (visibleRunCount > 0)
|
||||
{
|
||||
- /* FIXME: What should happen for key sequences with more than
|
||||
- one character? */
|
||||
- code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
|
||||
+ {
|
||||
+ ns_ax_visible_run *last = &visibleRuns[visibleRunCount - 1];
|
||||
+ return last->ax_start + (NSUInteger) last->length;
|
||||
+ return last->ax_start + last->ax_length;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
@@ -694,7 +514,7 @@ index 932d209..ca6b969 100644
|
||||
+ {
|
||||
+ ns_ax_visible_run *r = &visibleRuns[i];
|
||||
+ if (ax_idx >= r->ax_start
|
||||
+ && ax_idx < r->ax_start + (NSUInteger) r->length)
|
||||
+ && ax_idx < r->ax_start + r->ax_length)
|
||||
+ return r->charpos + (ptrdiff_t) (ax_idx - r->ax_start);
|
||||
+ }
|
||||
+ /* Past end — return last charpos. */
|
||||
@@ -1396,272 +1216,18 @@ index 932d209..ca6b969 100644
|
||||
+#endif /* NS_IMPL_COCOA */
|
||||
+
|
||||
+
|
||||
+/* ==========================================================================
|
||||
+
|
||||
+ EmacsView implementation
|
||||
+
|
||||
+ ========================================================================== */
|
||||
+
|
||||
+
|
||||
+@implementation EmacsView
|
||||
+
|
||||
+- (void)windowDidEndLiveResize:(NSNotification *)notification
|
||||
+{
|
||||
+ [self updateFramePosition];
|
||||
+}
|
||||
+
|
||||
+/* Needed to inform when window closed from lisp. */
|
||||
+- (void) setWindowClosing: (BOOL)closing
|
||||
+{
|
||||
+ NSTRACE ("[EmacsView setWindowClosing:%d]", closing);
|
||||
+
|
||||
+ windowClosing = closing;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+- (void)dealloc
|
||||
+{
|
||||
+ NSTRACE ("[EmacsView dealloc]");
|
||||
+
|
||||
+ /* Clear the view resize notification. */
|
||||
+ [[NSNotificationCenter defaultCenter]
|
||||
+ removeObserver:self
|
||||
+ name:NSViewFrameDidChangeNotification
|
||||
+ object:nil];
|
||||
+
|
||||
+ if (fs_state == FULLSCREEN_BOTH)
|
||||
+ [nonfs_window release];
|
||||
+
|
||||
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
|
||||
+ /* Release layer and menu */
|
||||
+ EmacsLayer *layer = (EmacsLayer *)[self layer];
|
||||
+ [layer release];
|
||||
+#endif
|
||||
+
|
||||
+ [accessibilityElements release];
|
||||
+ [[self menu] release];
|
||||
+ [super dealloc];
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Called on font panel selection. */
|
||||
+- (void) changeFont: (id) sender
|
||||
+{
|
||||
+ struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
|
||||
+ NSFont *nsfont;
|
||||
+
|
||||
+#ifdef NS_IMPL_GNUSTEP
|
||||
+ nsfont = ((struct nsfont_info *) font)->nsfont;
|
||||
+#else
|
||||
+ nsfont = (NSFont *) macfont_get_nsctfont (font);
|
||||
+#endif
|
||||
+
|
||||
+ if (!font_panel_active)
|
||||
+ return;
|
||||
+
|
||||
+ if (font_panel_result)
|
||||
+ [font_panel_result release];
|
||||
+
|
||||
+ font_panel_result = (NSFont *) [sender convertFont: nsfont];
|
||||
+
|
||||
+ if (font_panel_result)
|
||||
+ [font_panel_result retain];
|
||||
+
|
||||
+#ifndef NS_IMPL_COCOA
|
||||
+ font_panel_active = NO;
|
||||
+ [NSApp stop: self];
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+- (void) noteUserSelectedFont
|
||||
+{
|
||||
+ font_panel_active = NO;
|
||||
+
|
||||
+ /* If no font was previously selected, use the currently selected
|
||||
+ font. */
|
||||
+
|
||||
+ if (!font_panel_result && FRAME_FONT (emacsframe))
|
||||
+ {
|
||||
+ font_panel_result
|
||||
+ = macfont_get_nsctfont (FRAME_FONT (emacsframe));
|
||||
+
|
||||
+ if (font_panel_result)
|
||||
+ [font_panel_result retain];
|
||||
+ }
|
||||
+
|
||||
+ [NSApp stop: self];
|
||||
+}
|
||||
+
|
||||
+- (void) noteUserCancelledSelection
|
||||
+{
|
||||
+ font_panel_active = NO;
|
||||
+
|
||||
+ if (font_panel_result)
|
||||
+ [font_panel_result release];
|
||||
+ font_panel_result = nil;
|
||||
+
|
||||
+ [NSApp stop: self];
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+- (Lisp_Object) showFontPanel
|
||||
+{
|
||||
+ id fm = [NSFontManager sharedFontManager];
|
||||
+ struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
|
||||
+ NSFont *nsfont, *result;
|
||||
+ struct timespec timeout;
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ NSView *buttons;
|
||||
+ BOOL canceled;
|
||||
+#endif
|
||||
+
|
||||
+#ifdef NS_IMPL_GNUSTEP
|
||||
+ nsfont = ((struct nsfont_info *) font)->nsfont;
|
||||
+#else
|
||||
+ nsfont = (NSFont *) macfont_get_nsctfont (font);
|
||||
+#endif
|
||||
+
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ buttons
|
||||
+ = ns_create_font_panel_buttons (self,
|
||||
+ @selector (noteUserSelectedFont),
|
||||
+ @selector (noteUserCancelledSelection));
|
||||
+ [[fm fontPanel: YES] setAccessoryView: buttons];
|
||||
+ [buttons release];
|
||||
+#endif
|
||||
+
|
||||
+ [fm setSelectedFont: nsfont isMultiple: NO];
|
||||
+ [fm orderFrontFontPanel: NSApp];
|
||||
+
|
||||
+ font_panel_active = YES;
|
||||
+ timeout = make_timespec (0, 100000000);
|
||||
+
|
||||
+ block_input ();
|
||||
+ while (font_panel_active
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ && (canceled = [[fm fontPanel: YES] isVisible])
|
||||
+#else
|
||||
+ && [[fm fontPanel: YES] isVisible]
|
||||
+#endif
|
||||
+ )
|
||||
+ ns_select_1 (0, NULL, NULL, NULL, &timeout, NULL, YES);
|
||||
+ unblock_input ();
|
||||
+
|
||||
+ if (font_panel_result)
|
||||
+ [font_panel_result autorelease];
|
||||
+
|
||||
+#ifdef NS_IMPL_COCOA
|
||||
+ if (!canceled)
|
||||
+ font_panel_result = nil;
|
||||
+#endif
|
||||
+
|
||||
+ result = font_panel_result;
|
||||
+ font_panel_result = nil;
|
||||
+
|
||||
+ [[fm fontPanel: YES] setIsVisible: NO];
|
||||
+ font_panel_active = NO;
|
||||
+
|
||||
+ if (result)
|
||||
+ return ns_font_desc_to_font_spec ([result fontDescriptor],
|
||||
+ result);
|
||||
+
|
||||
+ return Qnil;
|
||||
+}
|
||||
+
|
||||
+- (BOOL)acceptsFirstResponder
|
||||
+{
|
||||
+ NSTRACE ("[EmacsView acceptsFirstResponder]");
|
||||
+ return YES;
|
||||
+}
|
||||
+
|
||||
+/* Tell NS we want to accept clicks that activate the window */
|
||||
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
+{
|
||||
+ NSTRACE_MSG ("First mouse event: type=%ld, clickCount=%ld",
|
||||
+ [theEvent type], [theEvent clickCount]);
|
||||
+ return ns_click_through;
|
||||
+}
|
||||
+- (void)resetCursorRects
|
||||
+{
|
||||
+ NSRect visible = [self visibleRect];
|
||||
+ NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
|
||||
+ NSTRACE ("[EmacsView resetCursorRects]");
|
||||
+
|
||||
+ if (currentCursor == nil)
|
||||
+ currentCursor = [NSCursor arrowCursor];
|
||||
+
|
||||
+ if (!NSIsEmptyRect (visible))
|
||||
+ [self addCursorRect: visible cursor: currentCursor];
|
||||
+
|
||||
+#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
|
||||
+ if ([currentCursor respondsToSelector: @selector(setOnMouseEntered:)])
|
||||
+#endif
|
||||
+ [currentCursor setOnMouseEntered: YES];
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*****************************************************************************/
|
||||
+/* Keyboard handling. */
|
||||
+#define NS_KEYLOG 0
|
||||
+
|
||||
+- (void)keyDown: (NSEvent *)theEvent
|
||||
+{
|
||||
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
|
||||
+ int code;
|
||||
+ unsigned fnKeysym = 0;
|
||||
+ static NSMutableArray *nsEvArray;
|
||||
+ unsigned int flags = [theEvent modifierFlags];
|
||||
+
|
||||
+ NSTRACE ("[EmacsView keyDown:]");
|
||||
+
|
||||
+ /* Rhapsody and macOS give up and down events for the arrow keys. */
|
||||
+ if ([theEvent type] != NSEventTypeKeyDown)
|
||||
+ return;
|
||||
+
|
||||
+ if (!emacs_event)
|
||||
+ return;
|
||||
+
|
||||
+ if (![[self window] isKeyWindow]
|
||||
+ && [[theEvent window] isKindOfClass: [EmacsWindow class]]
|
||||
+ /* We must avoid an infinite loop here. */
|
||||
+ && (EmacsView *)[[theEvent window] delegate] != self)
|
||||
+ {
|
||||
+ /* XXX: There is an occasional condition in which, when Emacs display
|
||||
+ updates a different frame from the current one, and temporarily
|
||||
+ selects it, then processes some interrupt-driven input
|
||||
+ (dispnew.c:3878), OS will send the event to the correct NSWindow, but
|
||||
+ for some reason that window has its first responder set to the NSView
|
||||
+ most recently updated (I guess), which is not the correct one. */
|
||||
+ [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (nsEvArray == nil)
|
||||
+ nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
|
||||
+
|
||||
+ [NSCursor setHiddenUntilMouseMoves:! NILP (Vmake_pointer_invisible)];
|
||||
+
|
||||
+ if (!hlinfo->mouse_face_hidden
|
||||
+ && FIXNUMP (Vmouse_highlight)
|
||||
+ && !EQ (emacsframe->tab_bar_window, hlinfo->mouse_face_window))
|
||||
+ {
|
||||
+ clear_mouse_face (hlinfo);
|
||||
+ hlinfo->mouse_face_hidden = true;
|
||||
+ }
|
||||
+
|
||||
+ if (!processingCompose)
|
||||
+ {
|
||||
+ /* FIXME: What should happen for key sequences with more than
|
||||
+ one character? */
|
||||
+ code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
|
||||
0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
|
||||
/* ==========================================================================
|
||||
|
||||
/* Is it a "function key"? */
|
||||
@@ -8237,6 +9341,27 @@ ns_in_echo_area (void)
|
||||
EmacsView implementation
|
||||
@@ -6889,6 +7993,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
|
||||
[layer release];
|
||||
#endif
|
||||
|
||||
+ [accessibilityElements release];
|
||||
[[self menu] release];
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -8237,6 +9342,27 @@ ns_in_echo_area (void)
|
||||
XSETFRAME (event.frame_or_window, emacsframe);
|
||||
kbd_buffer_store_event (&event);
|
||||
ns_send_appdefined (-1); // Kick main loop
|
||||
@@ -1689,7 +1255,7 @@ index 932d209..ca6b969 100644
|
||||
}
|
||||
|
||||
|
||||
@@ -9474,6 +10599,297 @@ ns_in_echo_area (void)
|
||||
@@ -9474,6 +10600,297 @@ ns_in_echo_area (void)
|
||||
return fs_state;
|
||||
}
|
||||
|
||||
@@ -1987,7 +1553,7 @@ index 932d209..ca6b969 100644
|
||||
@end /* EmacsView */
|
||||
|
||||
|
||||
@@ -9941,6 +11357,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
|
||||
@@ -9941,6 +11358,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user