* bug#65817: 30.0.50; Abort with NSInvalidArgumentException on macOS Big Sur
2023-09-08 7:01 bug#65817: 30.0.50; Abort with NSInvalidArgumentException on macOS Big Sur Gerd Möllmann
@ 2023-09-08 9:51 ` Gerd Möllmann
2023-09-08 18:53 ` Alan Third
1 sibling, 0 replies; 6+ messages in thread
From: Gerd Möllmann @ 2023-09-08 9:51 UTC (permalink / raw)
To: 65817
I can reproduce this, but only with my .init.el, by
(progn
(setq display-buffer-alist '((".*" display-buffer-in-child-frame)))
(describe-variable 'display-buffer-alist))
Lisp and C backtrace:
(lldb) xbacktrace
(unsigned char *) data = 0x00000001003d1855 "x-create-frame"
(unsigned char *) data = 0x0000000103be8e01 "x-create-frame-with-faces"
PVEC_COMPILED
(unsigned char *) data = 0x00000001003c5d4d "apply"
(unsigned char *) data = 0x0000000103be8f0e "frame-creation-function"
(unsigned char *) data = 0x0000000103c01ad2 "make-frame"
(unsigned char *) data = 0x0000000103c01b68 "display-buffer-in-child-frame"
PVEC_COMPILED
(unsigned char *) data = 0x00000001094df890 "ad-Advice-display-buffer"
(unsigned char *) data = 0x00000001003c5d4d "apply"
(unsigned char *) data = 0x00000001003c8e79 "display-buffer"
(unsigned char *) data = 0x0000000103c149d1 "temp-buffer-window-show"
(unsigned char *) data = 0x0000000103b8b037 "help--window-setup"
(unsigned char *) data = 0x0000000103bbbdfa "describe-variable"
(unsigned char *) data = 0x00000001003c5bf4 "progn"
(unsigned char *) data = 0x00000001003c5bf4 "progn"
(unsigned char *) data = 0x00000001003c5d48 "eval"
(unsigned char *) data = 0x0000000103bdc9b2 "elisp--eval-last-sexp"
(unsigned char *) data = 0x0000000103bdca01 "eval-last-sexp"
(unsigned char *) data = 0x0000000103bdca22 "eval-print-last-sexp"
(unsigned char *) data = 0x00000001003c5764 "funcall-interactively"
(unsigned char *) data = 0x00000001003c5751 "call-interactively"
(unsigned char *) data = 0x00000001003c8b70 "command-execute"
thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff205ce90e libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff205fd5bd libsystem_pthread.dylib`pthread_kill + 263
frame #2: 0x00007fff20552406 libsystem_c.dylib`abort + 125
frame #3: 0x00007fff205c0ef2 libc++abi.dylib`abort_message + 241
frame #4: 0x00007fff205b25fd libc++abi.dylib`demangling_terminate_handler() + 266
frame #5: 0x00007fff204ab58d libobjc.A.dylib`_objc_terminate() + 96
frame #6: 0x00007fff205c0307 libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x00007fff205c2dd1 libc++abi.dylib`__cxa_rethrow + 99
frame #8: 0x00007fff204a9110 libobjc.A.dylib`objc_exception_rethrow + 37
frame #9: 0x00007fff2306d45d AppKit`-[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] + 1119
frame #10: 0x00007fff26e89271 QuartzCore`CABackingStoreUpdate_ + 219
frame #11: 0x00007fff26ef084d QuartzCore`invocation function for block in CA::Layer::display_() + 53
frame #12: 0x00007fff26e88787 QuartzCore`-[CALayer _display] + 2247
frame #13: 0x00007fff2306cf35 AppKit`-[_NSBackingLayer display] + 475
frame #14: 0x00007fff22fd8022 AppKit`-[_NSViewBackingLayer display] + 555
frame #15: 0x00007fff26e876f3 QuartzCore`CA::Layer::display_if_needed(CA::Transaction*) + 863
frame #16: 0x00007fff26fd2bee QuartzCore`CA::Context::commit_transaction(CA::Transaction*, double, double*) + 666
frame #17: 0x00007fff26e68b6f QuartzCore`CA::Transaction::commit() + 713
frame #18: 0x00007fff22f500a5 AppKit`NSPerformVisuallyAtomicChange + 154
frame #19: 0x00007fff2314c06f AppKit`-[NSWindow addChildWindow:ordered:] + 640
frame #20: 0x000000010033fe08 emacs`-[EmacsWindow setParentChildRelationships](self=0x0000000120b0f1b0, _cmd="setParentChildRelationships") at nsterm.m:9320:7
frame #21: 0x000000010033f2ad emacs`-[EmacsWindow initWithEmacsFrame:fullscreen:screen:](self=0x0000000120b0f1b0, _cmd="initWithEmacsFrame:fullscreen:screen:", f=0x0000000108e99fd0, fullscreen=NO, screen=0x0000000000000000) at nsterm.m:9139:7
frame #22: 0x000000010033ecd0 emacs`-[EmacsWindow initWithEmacsFrame:](self=0x0000000120b0f1b0, _cmd="initWithEmacsFrame:", f=0x0000000108e99fd0) at nsterm.m:9065:10
frame #23: 0x000000010033ace5 emacs`-[EmacsView initFrameFromEmacs:](self=0x000000011c5ffd40, _cmd="initFrameFromEmacs:", f=0x0000000108e99fd0) at nsterm.m:7925:3
frame #24: 0x00000001003579a1 emacs`Fx_create_frame(parms=(struct Lisp_Cons *) $172 = 0x0000000120a5ac70) at nsfns.m:1502:3
frame #25: 0x0000000100242b25 emacs`funcall_subr(subr=0x00000001003fe3f8, numargs=1, args=(struct Lisp_Symbol *) $175 = 0x0000000100939020) at eval.c:3047:15
frame #26: 0x00000001002a4701 emacs`exec_byte_code(fun=(struct Lisp_Vector *) $180 = 0x0000000103010908, args_template=770, nargs=3, args=(struct Lisp_Symbol *) $183 = 0x0000000100939020) at bytecode.c:815:14
frame #27: 0x0000000100246617 emacs`fetch_and_exec_byte_code(fun=(struct Lisp_Vector *) $188 = 0x00000001032cfec0, args_template=257, nargs=1, args=(struct Lisp_Symbol *) $191 = 0x0000000100939020) at eval.c:3094:10
frame #28: 0x0000000100242f71 emacs`funcall_lambda(fun=(struct Lisp_Vector *) $196 = 0x00000001032cfec0, nargs=1, arg_vector=(struct Lisp_Symbol *) $199 = 0x0000000100939020) at eval.c:3166:9
frame #29: 0x0000000100242857 emacs`funcall_general(fun=(struct Lisp_Vector *) $204 = 0x00000001032cfec0, numargs=1, args=(struct Lisp_Symbol *) $207 = 0x0000000100939020) at eval.c:2958:12
frame #30: 0x000000010023dda4 emacs`Ffuncall(nargs=2, args=(struct Lisp_Symbol *) $210 = 0x0000000100939020) at eval.c:3008:21
frame #31: 0x00000001002415e7 emacs`Fapply(nargs=2, args=(struct Lisp_Symbol *) $213 = 0x0000000100939020) at eval.c:2636:14
frame #32: 0x0000000100242d0a emacs`funcall_subr(subr=0x00000001003f75b8, numargs=2, args=(struct Lisp_Symbol *) $216 = 0x0000000100939020) at eval.c:3072:9
frame #33: 0x00000001002a4701 emacs`exec_byte_code(fun=(struct Lisp_Vector *) $221 = 0x00000001030c66a0, args_template=128, nargs=1, args=(struct Lisp_Symbol *) $224 = 0x0000000100939020) at bytecode.c:815:14
frame #34: 0x0000000100246617 emacs`fetch_and_exec_byte_code(fun=(struct Lisp_Vector *) $229 = 0x0000000109e6ffb8, args_template=0, nargs=0, args=(struct Lisp_Symbol *) $232 = 0x0000000100939020) at eval.c:3094:10
frame #35: 0x0000000100243382 emacs`funcall_lambda(fun=(struct Lisp_Vector *) $237 = 0x0000000109e6ffb8, nargs=3, arg_vector=(struct Lisp_Symbol *) $240 = 0x0000000100939020) at eval.c:3255:11
frame #36: 0x0000000100242857 emacs`funcall_general(fun=(struct Lisp_Vector *) $245 = 0x0000000109e6ffb8, numargs=3, args=(struct Lisp_Symbol *) $248 = 0x0000000100939020) at eval.c:2958:12
frame #37: 0x000000010023dda4 emacs`Ffuncall(nargs=4, args=(struct Lisp_Symbol *) $251 = 0x0000000100939020) at eval.c:3008:21
frame #38: 0x0000000100241de2 emacs`Fapply(nargs=3, args=(struct Lisp_Symbol *) $254 = 0x0000000100939020) at eval.c:2679:24
frame #39: 0x0000000100242d0a emacs`funcall_subr(subr=0x00000001003f75b8, numargs=3, args=(struct Lisp_Symbol *) $257 = 0x0000000100939020) at eval.c:3072:9
frame #40: 0x00000001002a4701 emacs`exec_byte_code(fun=(struct Lisp_Vector *) $262 = 0x0000000102963cf8, args_template=128, nargs=2, args=(struct Lisp_Symbol *) $265 = 0x0000000100939020) at bytecode.c:815:14
frame #41: 0x0000000100246617 emacs`fetch_and_exec_byte_code(fun=(struct Lisp_Vector *) $270 = 0x0000000109361260, args_template=769, nargs=1, args=(struct Lisp_Symbol *) $273 = 0x0000000100939020) at eval.c:3094:10
frame #42: 0x0000000100242f71 emacs`funcall_lambda(fun=(struct Lisp_Vector *) $278 = 0x0000000109361260, nargs=1, arg_vector=(struct Lisp_Symbol *) $281 = 0x0000000100939020) at eval.c:3166:9
frame #43: 0x0000000100242857 emacs`funcall_general(fun=(struct Lisp_Vector *) $286 = 0x0000000109361260, numargs=1, args=(struct Lisp_Symbol *) $289 = 0x0000000100939020) at eval.c:2958:12
frame #44: 0x000000010023dda4 emacs`Ffuncall(nargs=2, args=(struct Lisp_Symbol *) $292 = 0x0000000100939020) at eval.c:3008:21
frame #45: 0x000000010023559f emacs`Ffuncall_interactively(nargs=2, args=(struct Lisp_Symbol *) $295 = 0x0000000100939020) at callint.c:250:32
frame #46: 0x0000000100242d0a emacs`funcall_subr(subr=0x00000001003f6e48, numargs=2, args=(struct Lisp_Symbol *) $298 = 0x0000000100939020) at eval.c:3072:9
frame #47: 0x0000000100242805 emacs`funcall_general(fun=(struct Lisp_Subr *) $303 = 0x00000001003f6e48, numargs=2, args=(struct Lisp_Symbol *) $306 = 0x0000000100939020) at eval.c:2954:12
frame #48: 0x000000010023dda4 emacs`Ffuncall(nargs=3, args=(struct Lisp_Symbol *) $309 = 0x0000000100939020) at eval.c:3008:21
frame #49: 0x00000001002415e7 emacs`Fapply(nargs=3, args=(struct Lisp_Symbol *) $312 = 0x0000000100939020) at eval.c:2636:14
frame #50: 0x0000000100235a0b emacs`Fcall_interactively(function=(struct Lisp_Symbol *) $315 = 0x0000000103223338, record_flag=(struct Lisp_Symbol *) $318 = 0x0000000100939020, keys=(struct Lisp_Vector *) $322 = 0x0000000103afd8f8) at callint.c:342:36
frame #51: 0x0000000100242b71 emacs`funcall_subr(subr=0x00000001003f6e10, numargs=3, args=(struct Lisp_Symbol *) $325 = 0x0000000100939020) at eval.c:3051:15
frame #52: 0x00000001002a4701 emacs`exec_byte_code(fun=(struct Lisp_Vector *) $330 = 0x00000001030a9630, args_template=1025, nargs=1, args=(struct Lisp_Symbol *) $333 = 0x0000000100939020) at bytecode.c:815:14
* frame #53: 0x0000000100246617 emacs`fetch_and_exec_byte_code(fun=(struct Lisp_Vector *) $338 = 0x00000001030a9630, args_template=1025, nargs=1, args=(struct Lisp_Symbol *) $341 = 0x0000000100939020) at eval.c:3094:10
frame #54: 0x0000000100242f71 emacs`funcall_lambda(fun=(struct Lisp_Vector *) $346 = 0x00000001030a9630, nargs=1, arg_vector=(struct Lisp_Symbol *) $349 = 0x0000000100939020) at eval.c:3166:9
frame #55: 0x0000000100242857 emacs`funcall_general(fun=(struct Lisp_Vector *) $354 = 0x00000001030a9630, numargs=1, args=(struct Lisp_Symbol *) $357 = 0x0000000100939020) at eval.c:2958:12
frame #56: 0x000000010023dda4 emacs`Ffuncall(nargs=2, args=(struct Lisp_Symbol *) $360 = 0x0000000100939020) at eval.c:3008:21
frame #57: 0x000000010015952f emacs`call1(fn=(struct Lisp_Symbol *) $363 = 0x000000010093d2b0, arg1=(struct Lisp_Symbol *) $366 = 0x0000000103223338) at lisp.h:3245:10
frame #58: 0x0000000100155006 emacs`command_loop_1 at keyboard.c:1529:13
frame #59: 0x000000010023ec9a emacs`internal_condition_case(bfun=(emacs`command_loop_1 at keyboard.c:1302), handlers=(struct Lisp_Symbol *) $369 = 0x00000001009390b0, hfun=(emacs`cmd_error at keyboard.c:960)) at eval.c:1486:25
frame #60: 0x0000000100154563 emacs`command_loop_2(handlers=(struct Lisp_Symbol *) $372 = 0x00000001009390b0) at keyboard.c:1157:11
frame #61: 0x000000010023e446 emacs`internal_catch(tag=(struct Lisp_Symbol *) $375 = 0x0000000100948170, func=(emacs`command_loop_2 at keyboard.c:1153), arg=(struct Lisp_Symbol *) $378 = 0x00000001009390b0) at eval.c:1209:25
frame #62: 0x00000001001538bd emacs`command_loop at keyboard.c:1135:2
frame #63: 0x00000001001536c5 emacs`recursive_edit_1 at keyboard.c:744:9
frame #64: 0x0000000100153c37 emacs`Frecursive_edit at keyboard.c:827:3
frame #65: 0x0000000100150a55 emacs`main(argc=1, argv=0x00007ffeefbff588) at emacs.c:2625:3
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#65817: 30.0.50; Abort with NSInvalidArgumentException on macOS Big Sur
2023-09-08 7:01 bug#65817: 30.0.50; Abort with NSInvalidArgumentException on macOS Big Sur Gerd Möllmann
2023-09-08 9:51 ` Gerd Möllmann
@ 2023-09-08 18:53 ` Alan Third
2023-09-08 19:37 ` Gerd Möllmann
1 sibling, 1 reply; 6+ messages in thread
From: Alan Third @ 2023-09-08 18:53 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 65817
[-- Attachment #1: Type: text/plain, Size: 1939 bytes --]
On Fri, Sep 08, 2023 at 09:01:06AM +0200, Gerd Möllmann wrote:
> System Description: macOS 11.7.9
>
> This is a 10 year old Mac. I can't reproduce it at will. Below is what
> was printed to the terminal, then Emacs aborted.
This is odd. The system is trying to draw the frame to the screen
*long* before we've finished creating it.
I don't know why this would be happening, it's possible that we've hit
an edge case where we accidentally mark the view for display early,
but I don't know how we would be doing that.
> 5 emacs 0x000000010033d481 -[EmacsView lockFocus] + 49
> 6 emacs 0x000000010032ee27 ns_focus + 87
> 7 emacs 0x000000010033df80 ns_clear_frame_area + 400
> 8 emacs 0x000000010033dda1 -[EmacsView drawRect:] + 321
<snip>
> 21 AppKit 0x00007fff2314c06f -[NSWindow addChildWindow:ordered:] + 640
> 22 emacs 0x000000010033fe08 -[EmacsWindow setParentChildRelationships] + 696
> 23 emacs 0x000000010033f2ad -[EmacsWindow initWithEmacsFrame:fullscreen:screen:] + 1485
> 24 emacs 0x000000010033ecd0 -[EmacsWindow initWithEmacsFrame:] + 48
> 25 emacs 0x000000010033ace5 -[EmacsView initFrameFromEmacs:] + 1045
> 26 emacs 0x00000001003579a1 Fx_create_frame + 7937
At the point lockFocus is called here, we haven't yet set up the layer
we want to draw into. I can't find any indication that addChildWindow
may trigger a display, but this is Apple's documentation I'm talking
about...
I've attached a patch that reorders some of the initialisation,
hopefully avoiding this problem.
I've also attached another patch that you may need to apply first to
make the second one apply cleanly.
--
Alan Third
[-- Attachment #2: v2-0001-Simplify-the-EmacsLayer-double-buffering-code-bug.patch --]
[-- Type: text/x-diff, Size: 8169 bytes --]
From 72b13fa67981c40f0e3c63092aa796525fe61344 Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Sun, 23 Jul 2023 12:00:30 +0100
Subject: [PATCH v2] Simplify the EmacsLayer double buffering code (bug#63187)
---
src/nsfns.m | 30 +++++++++++++++++++++++++++++-
src/nsterm.h | 13 ++++++++++++-
src/nsterm.m | 50 ++++++++++++++++++++++++++------------------------
3 files changed, 67 insertions(+), 26 deletions(-)
diff --git a/src/nsfns.m b/src/nsfns.m
index a79892f73b6..082e06698b2 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -799,6 +799,26 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
}
}
+static void
+ns_set_inhibit_double_buffering (struct frame *f,
+ Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ if (!EQ (new_value, old_value))
+ {
+ FRAME_DOUBLE_BUFFERED (f) = NILP (new_value);
+
+ /* If the view or layer haven't been created yet this will be a
+ noop. */
+ [(EmacsLayer *)[FRAME_NS_VIEW (f) layer]
+ setDoubleBuffered:FRAME_DOUBLE_BUFFERED (f)];
+
+ SET_FRAME_GARBAGED (f);
+ }
+#endif
+}
+
static void
ns_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
@@ -1073,7 +1093,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
gui_set_alpha,
0, /* x_set_sticky */
ns_set_tool_bar_position,
- 0, /* x_set_inhibit_double_buffering */
+ ns_set_inhibit_double_buffering,
ns_set_undecorated,
ns_set_parent_frame,
0, /* x_set_skip_taskbar */
@@ -1461,6 +1481,14 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
RES_TYPE_STRING);
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ tem = gui_display_get_arg (dpyinfo, parms, Qinhibit_double_buffering, NULL, NULL,
+ RES_TYPE_BOOLEAN);
+ FRAME_DOUBLE_BUFFERED (f) = NILP (tem) || EQ (tem, Qunbound);
+ store_frame_param (f, Qinhibit_double_buffering,
+ FRAME_DOUBLE_BUFFERED (f) ? Qnil : Qt);
+#endif
+
parms = get_geometry_from_preferences (dpyinfo, parms);
window_prompting = gui_figure_window_size (f, parms, false, true);
diff --git a/src/nsterm.h b/src/nsterm.h
index b6e5a813a6d..8d6c58290cc 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -746,9 +746,11 @@ #define NSTRACE_UNSILENCE()
CGColorSpaceRef colorSpace;
IOSurfaceRef currentSurface;
CGContextRef context;
+ bool doubleBuffered;
}
-- (id) initWithColorSpace: (CGColorSpaceRef)cs;
+- (id) initWithColorSpace: (CGColorSpaceRef)cs doubleBuffered: (bool)db;
- (void) setColorSpace: (CGColorSpaceRef)cs;
+- (void) setDoubleBuffered: (bool)db;
- (CGContextRef) getContext;
@end
#endif
@@ -996,6 +998,11 @@ #define KEY_NS_SHOW_PREFS ((1<<28)|(0<<16)|14)
/* Non-zero if we are doing an animation, e.g. toggling the tool bar. */
int in_animation;
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ /* Is the frame double buffered? */
+ bool double_buffered;
+#endif
+
#ifdef NS_IMPL_GNUSTEP
/* Zero if this is the first time a toolbar has been updated on this
frame. */
@@ -1030,6 +1037,10 @@ #define FRAME_POINTER_TYPE(f) ((f)->output_data.ns->current_pointer)
#define FRAME_FONT(f) ((f)->output_data.ns->font)
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#define FRAME_DOUBLE_BUFFERED(f) ((f)->output_data.ns->double_buffered)
+#endif
+
#ifdef __OBJC__
#define XNS_SCROLL_BAR(vec) ((id) xmint_pointer (vec))
#else
diff --git a/src/nsterm.m b/src/nsterm.m
index 78089906752..28502ad1a2a 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2704,11 +2704,10 @@ Hide the window (X11 semantics)
{
NSRect srcRect = NSMakeRect (x, from_y, width, height);
NSPoint dest = NSMakePoint (x, to_y);
- NSRect destRect = NSMakeRect (x, from_y, width, height);
EmacsView *view = FRAME_NS_VIEW (f);
[view copyRect:srcRect to:dest];
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED < 101400
[view setNeedsDisplayInRect:destRect];
#endif
}
@@ -8607,7 +8606,8 @@ - (instancetype)toggleToolbar: (id)sender
- (CALayer *)makeBackingLayer
{
EmacsLayer *l = [[EmacsLayer alloc]
- initWithColorSpace:[[[self window] colorSpace] CGColorSpace]];
+ initWithColorSpace:[[[self window] colorSpace] CGColorSpace]
+ doubleBuffered:FRAME_DOUBLE_BUFFERED (emacsframe)];
[l setDelegate:(id)self];
[l setContentsScale:[[self window] backingScaleFactor]];
@@ -8664,8 +8664,10 @@ - (void)copyRect:(NSRect)srcRect to:(NSPoint)dest
NSHeight (srcRect));
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
- double scale = [[self window] backingScaleFactor];
CGContextRef context = [(EmacsLayer *)[self layer] getContext];
+ CGContextFlush (context);
+
+ double scale = [[self window] backingScaleFactor];
int bpp = CGBitmapContextGetBitsPerPixel (context) / 8;
void *pixels = CGBitmapContextGetData (context);
int rowSize = CGBitmapContextGetBytesPerRow (context);
@@ -10435,22 +10437,20 @@ @implementation EmacsLayer
cache. If no free surfaces are found in the cache then a new one
is created. */
-#define CACHE_MAX_SIZE 2
-
- (id) initWithColorSpace: (CGColorSpaceRef)cs
+ doubleBuffered: (bool)db
{
- NSTRACE ("[EmacsLayer initWithColorSpace:]");
+ NSTRACE ("[EmacsLayer initWithColorSpace:doubleBuffered:]");
self = [super init];
if (self)
{
- cache = [[NSMutableArray arrayWithCapacity:CACHE_MAX_SIZE] retain];
[self setColorSpace:cs];
+ [self setDoubleBuffered:db];
+ cache = [[NSMutableArray arrayWithCapacity:(doubleBuffered ? 2 : 1)] retain];
}
else
- {
- return nil;
- }
+ return nil;
return self;
}
@@ -10467,6 +10467,15 @@ - (void) setColorSpace: (CGColorSpaceRef)cs
}
+- (void) setDoubleBuffered: (bool)db
+{
+ if (doubleBuffered != db)
+ [self releaseSurfaces];
+
+ doubleBuffered = db;
+}
+
+
- (void) dealloc
{
[self releaseSurfaces];
@@ -10538,7 +10547,7 @@ - (CGContextRef) getContext
}
}
- if (!surface && [cache count] >= CACHE_MAX_SIZE)
+ if (!surface && [cache count] >= (doubleBuffered ? 2 : 1))
{
/* Just grab the first one off the cache. This may result
in tearing effects. The alternative is to wait for one
@@ -10591,7 +10600,7 @@ - (CGContextRef) getContext
return nil;
}
- CGContextTranslateCTM(context, 0, IOSurfaceGetHeight (currentSurface));
+ CGContextTranslateCTM(context, 0, IOSurfaceGetHeight (surface));
CGContextScaleCTM(context, scale, -scale);
}
@@ -10608,6 +10617,7 @@ - (void) releaseContext
if (!context)
return;
+ CGContextFlush (context);
CGContextRelease (context);
context = NULL;
@@ -10621,26 +10631,18 @@ - (void) display
{
NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "[EmacsLayer display]");
- if (context)
+ if (context && context != [[NSGraphicsContext currentContext] CGContext])
{
[self releaseContext];
-#if CACHE_MAX_SIZE == 1
- /* This forces the layer to see the surface as updated. */
+ /* This forces the layer to see the surface as updated even if
+ we replace it with itself. */
[self setContents:nil];
-#endif
-
[self setContents:(id)currentSurface];
/* Put currentSurface back on the end of the cache. */
[cache addObject:(id)currentSurface];
currentSurface = NULL;
-
- /* Schedule a run of getContext so that if Emacs is idle it will
- perform the buffer copy, etc. */
- [self performSelectorOnMainThread:@selector (getContext)
- withObject:nil
- waitUntilDone:NO];
}
}
--
2.40.1
[-- Attachment #3: 0001-Fix-crash-on-child-frame-creation-bug-65817.patch --]
[-- Type: text/x-diff, Size: 3606 bytes --]
From 893f079f51c3bc81d8719c48fe539f72b1025fb8 Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Fri, 8 Sep 2023 19:33:06 +0100
Subject: [PATCH] Fix crash on child frame creation (bug#65817)
* src/nsterm.m ([EmacsView initFrameFromEmacs:]): Reorder the way the
frame and layers are created.
([EmacsView makeBackingLayer]): Change to the newly renamed method
below.
([EmacsLayer initWithColorSpace:doubleBuffered:]):
([EmacsLayer initWithDoubleBuffered:]): Rename the method and remove
the colorspace argument as it's no longer able to be set on initial
creation.
* src/nsterm.h: Use new method prototype.
---
src/nsterm.h | 2 +-
src/nsterm.m | 25 +++++++++++++------------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/nsterm.h b/src/nsterm.h
index 8d6c58290cc..cb162039ad8 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -748,7 +748,7 @@ #define NSTRACE_UNSILENCE()
CGContextRef context;
bool doubleBuffered;
}
-- (id) initWithColorSpace: (CGColorSpaceRef)cs doubleBuffered: (bool)db;
+- (id) initWithDoubleBuffered: (bool)db;
- (void) setColorSpace: (CGColorSpaceRef)cs;
- (void) setDoubleBuffered: (bool)db;
- (CGContextRef) getContext;
diff --git a/src/nsterm.m b/src/nsterm.m
index 28502ad1a2a..a3603171bb0 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7921,8 +7921,6 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
maximizing_resize = NO;
#endif
- [[EmacsWindow alloc] initWithEmacsFrame:f];
-
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
/* These settings mean AppKit will retain the contents of the frame
on resize. Unfortunately it also means the frame will not be
@@ -7933,9 +7931,14 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
NSViewLayerContentsRedrawOnSetNeedsDisplay];
[self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft];
- /* initWithEmacsFrame can't create the toolbar before the layer is
- set, so have another go at creating the toolbar here. */
- [(EmacsWindow*)[self window] createToolbar:f];
+ [[EmacsWindow alloc] initWithEmacsFrame:f];
+
+ /* Now the NSWindow has been created, we can finish up configuring
+ the layer. */
+ [(EmacsLayer *)[self layer] setColorSpace:[[[self window] colorSpace] CGColorSpace]];
+ [(EmacsLayer *)[self layer] setContentsScale:[[self window] backingScaleFactor]];
+#else
+ [[EmacsWindow alloc] initWithEmacsFrame:f];
#endif
if (ns_drag_types)
@@ -8606,10 +8609,9 @@ - (instancetype)toggleToolbar: (id)sender
- (CALayer *)makeBackingLayer
{
EmacsLayer *l = [[EmacsLayer alloc]
- initWithColorSpace:[[[self window] colorSpace] CGColorSpace]
- doubleBuffered:FRAME_DOUBLE_BUFFERED (emacsframe)];
+ initWithDoubleBuffered:FRAME_DOUBLE_BUFFERED (emacsframe)];
+
[l setDelegate:(id)self];
- [l setContentsScale:[[self window] backingScaleFactor]];
return l;
}
@@ -10437,15 +10439,14 @@ @implementation EmacsLayer
cache. If no free surfaces are found in the cache then a new one
is created. */
-- (id) initWithColorSpace: (CGColorSpaceRef)cs
- doubleBuffered: (bool)db
+- (id) initWithDoubleBuffered: (bool)db
{
- NSTRACE ("[EmacsLayer initWithColorSpace:doubleBuffered:]");
+ NSTRACE ("[EmacsLayer initWithDoubleBuffered:]");
self = [super init];
if (self)
{
- [self setColorSpace:cs];
+ [self setColorSpace:nil];
[self setDoubleBuffered:db];
cache = [[NSMutableArray arrayWithCapacity:(doubleBuffered ? 2 : 1)] retain];
}
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread