diff options
| author | Alan Third | 2020-04-11 14:18:39 +0100 |
|---|---|---|
| committer | Alan Third | 2020-04-16 19:11:05 +0100 |
| commit | c019f03e38850b3ba3a2bcbcc84960d5b8d9663f (patch) | |
| tree | 7f1ab25650ae0aa954d6079a827ef7d5c7552bbe /src | |
| parent | 24cb6908d70c14792c686679cb08091447b9c3b1 (diff) | |
| download | emacs-c019f03e38850b3ba3a2bcbcc84960d5b8d9663f.tar.gz emacs-c019f03e38850b3ba3a2bcbcc84960d5b8d9663f.zip | |
Allow dynamic choice of drawing path on NS (bug#39883)
* src/nsterm.h (NS_DRAW_TO_BUFFER): Let this be enabled on versions
older than 10.14.
* src/nsterm.m (ns_update_begin):
(ns_update_end):
(ns_focus):
(ns_unfocus):
([EmacsView viewDidResize:]):
([EmacsView createDrawingBuffer]):
([EmacsView windowDidChangeBackingProperties:]):
([EmacsView copyRect:to:]):
([EmacsView wantsUpdateLayer]): Dynamically switch between drawing to a
buffer and drawing to the screen, depending on the version of AppKit
in use.
([EmacsView dealloc]): We can't release the context unless
NS_DRAW_TO_BUFFER is defined.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.h | 10 | ||||
| -rw-r--r-- | src/nsterm.m | 229 |
2 files changed, 167 insertions, 72 deletions
diff --git a/src/nsterm.h b/src/nsterm.h index e142dbd4f07..f5d3c32b8b3 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -343,14 +343,8 @@ typedef id instancetype; | |||
| 343 | therefore we draw to an offscreen buffer and swap it in when the | 343 | therefore we draw to an offscreen buffer and swap it in when the |
| 344 | toolkit wants to draw the frame. GNUstep and macOS 10.7 and below | 344 | toolkit wants to draw the frame. GNUstep and macOS 10.7 and below |
| 345 | do not support this method, so we revert to drawing directly to the | 345 | do not support this method, so we revert to drawing directly to the |
| 346 | glass. | 346 | glass. */ |
| 347 | 347 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 | |
| 348 | FIXME: Should we make this macOS 10.8+, or macOS 10.14+? I'm | ||
| 349 | inclined to go with 10.14+ as there have been some reports of funny | ||
| 350 | behaviour on 10.13 and below. It may be worth adding a variable to | ||
| 351 | allow people in the overlapping region to switch between drawing | ||
| 352 | paths. */ | ||
| 353 | #if defined (NS_IMPL_COCOA) && defined (MAC_OS_X_VERSION_10_14) | ||
| 354 | #define NS_DRAW_TO_BUFFER 1 | 348 | #define NS_DRAW_TO_BUFFER 1 |
| 355 | #endif | 349 | #endif |
| 356 | 350 | ||
diff --git a/src/nsterm.m b/src/nsterm.m index a75c3ef4dba..9cd1c9d8602 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -1144,10 +1144,25 @@ ns_update_begin (struct frame *f) | |||
| 1144 | 1144 | ||
| 1145 | ns_updating_frame = f; | 1145 | ns_updating_frame = f; |
| 1146 | #ifdef NS_DRAW_TO_BUFFER | 1146 | #ifdef NS_DRAW_TO_BUFFER |
| 1147 | [view focusOnDrawingBuffer]; | 1147 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 1148 | #else | 1148 | if ([FRAME_NS_VIEW (f) wantsUpdateLayer]) |
| 1149 | [view lockFocus]; | 1149 | { |
| 1150 | #endif | 1150 | #endif |
| 1151 | [view focusOnDrawingBuffer]; | ||
| 1152 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1153 | } | ||
| 1154 | else | ||
| 1155 | { | ||
| 1156 | #endif | ||
| 1157 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 1158 | |||
| 1159 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1160 | [view lockFocus]; | ||
| 1161 | #endif | ||
| 1162 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1163 | } | ||
| 1164 | #endif | ||
| 1165 | |||
| 1151 | } | 1166 | } |
| 1152 | 1167 | ||
| 1153 | 1168 | ||
| @@ -1166,15 +1181,29 @@ ns_update_end (struct frame *f) | |||
| 1166 | MOUSE_HL_INFO (f)->mouse_face_defer = 0; | 1181 | MOUSE_HL_INFO (f)->mouse_face_defer = 0; |
| 1167 | 1182 | ||
| 1168 | #ifdef NS_DRAW_TO_BUFFER | 1183 | #ifdef NS_DRAW_TO_BUFFER |
| 1169 | [NSGraphicsContext setCurrentContext:nil]; | 1184 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 1170 | [view setNeedsDisplay:YES]; | 1185 | if ([FRAME_NS_VIEW (f) wantsUpdateLayer]) |
| 1171 | #else | 1186 | { |
| 1172 | block_input (); | 1187 | #endif |
| 1188 | [NSGraphicsContext setCurrentContext:nil]; | ||
| 1189 | [view setNeedsDisplay:YES]; | ||
| 1190 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1191 | } | ||
| 1192 | else | ||
| 1193 | { | ||
| 1194 | #endif | ||
| 1195 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 1173 | 1196 | ||
| 1174 | [view unlockFocus]; | 1197 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 1175 | [[view window] flushWindow]; | 1198 | block_input (); |
| 1176 | 1199 | ||
| 1177 | unblock_input (); | 1200 | [view unlockFocus]; |
| 1201 | [[view window] flushWindow]; | ||
| 1202 | |||
| 1203 | unblock_input (); | ||
| 1204 | #endif | ||
| 1205 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1206 | } | ||
| 1178 | #endif | 1207 | #endif |
| 1179 | ns_updating_frame = NULL; | 1208 | ns_updating_frame = NULL; |
| 1180 | } | 1209 | } |
| @@ -1199,24 +1228,39 @@ ns_focus (struct frame *f, NSRect *r, int n) | |||
| 1199 | } | 1228 | } |
| 1200 | 1229 | ||
| 1201 | if (f != ns_updating_frame) | 1230 | if (f != ns_updating_frame) |
| 1202 | #ifdef NS_DRAW_TO_BUFFER | ||
| 1203 | [view focusOnDrawingBuffer]; | ||
| 1204 | #else | ||
| 1205 | { | 1231 | { |
| 1206 | if (view != focus_view) | 1232 | #ifdef NS_DRAW_TO_BUFFER |
| 1233 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1234 | if ([FRAME_NS_VIEW (f) wantsUpdateLayer]) | ||
| 1207 | { | 1235 | { |
| 1208 | if (focus_view != NULL) | 1236 | #endif |
| 1237 | [view focusOnDrawingBuffer]; | ||
| 1238 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1239 | } | ||
| 1240 | else | ||
| 1241 | { | ||
| 1242 | #endif | ||
| 1243 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 1244 | |||
| 1245 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1246 | if (view != focus_view) | ||
| 1209 | { | 1247 | { |
| 1210 | [focus_view unlockFocus]; | 1248 | if (focus_view != NULL) |
| 1211 | [[focus_view window] flushWindow]; | 1249 | { |
| 1212 | } | 1250 | [focus_view unlockFocus]; |
| 1251 | [[focus_view window] flushWindow]; | ||
| 1252 | } | ||
| 1213 | 1253 | ||
| 1214 | if (view) | 1254 | if (view) |
| 1215 | [view lockFocus]; | 1255 | [view lockFocus]; |
| 1216 | focus_view = view; | 1256 | focus_view = view; |
| 1257 | } | ||
| 1258 | #endif | ||
| 1259 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1217 | } | 1260 | } |
| 1218 | } | ||
| 1219 | #endif | 1261 | #endif |
| 1262 | } | ||
| 1263 | |||
| 1220 | 1264 | ||
| 1221 | /* clipping */ | 1265 | /* clipping */ |
| 1222 | if (r) | 1266 | if (r) |
| @@ -1246,16 +1290,30 @@ ns_unfocus (struct frame *f) | |||
| 1246 | } | 1290 | } |
| 1247 | 1291 | ||
| 1248 | #ifdef NS_DRAW_TO_BUFFER | 1292 | #ifdef NS_DRAW_TO_BUFFER |
| 1249 | [FRAME_NS_VIEW (f) setNeedsDisplay:YES]; | 1293 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 1250 | #else | 1294 | if ([FRAME_NS_VIEW (f) wantsUpdateLayer]) |
| 1251 | if (f != ns_updating_frame) | 1295 | { |
| 1296 | #endif | ||
| 1297 | [FRAME_NS_VIEW (f) setNeedsDisplay:YES]; | ||
| 1298 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1299 | } | ||
| 1300 | else | ||
| 1252 | { | 1301 | { |
| 1253 | if (focus_view != NULL) | 1302 | #endif |
| 1303 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 1304 | |||
| 1305 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1306 | if (f != ns_updating_frame) | ||
| 1254 | { | 1307 | { |
| 1255 | [focus_view unlockFocus]; | 1308 | if (focus_view != NULL) |
| 1256 | [[focus_view window] flushWindow]; | 1309 | { |
| 1257 | focus_view = NULL; | 1310 | [focus_view unlockFocus]; |
| 1311 | [[focus_view window] flushWindow]; | ||
| 1312 | focus_view = NULL; | ||
| 1313 | } | ||
| 1258 | } | 1314 | } |
| 1315 | #endif | ||
| 1316 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 1259 | } | 1317 | } |
| 1260 | #endif | 1318 | #endif |
| 1261 | } | 1319 | } |
| @@ -6254,7 +6312,9 @@ not_in_argv (NSString *arg) | |||
| 6254 | name:NSViewFrameDidChangeNotification | 6312 | name:NSViewFrameDidChangeNotification |
| 6255 | object:nil]; | 6313 | object:nil]; |
| 6256 | 6314 | ||
| 6315 | #ifdef NS_DRAW_TO_BUFFER | ||
| 6257 | CGContextRelease (drawingBuffer); | 6316 | CGContextRelease (drawingBuffer); |
| 6317 | #endif | ||
| 6258 | 6318 | ||
| 6259 | [toolbar release]; | 6319 | [toolbar release]; |
| 6260 | if (fs_state == FULLSCREEN_BOTH) | 6320 | if (fs_state == FULLSCREEN_BOTH) |
| @@ -7268,13 +7328,27 @@ not_in_argv (NSString *arg) | |||
| 7268 | return; | 7328 | return; |
| 7269 | 7329 | ||
| 7270 | #ifdef NS_DRAW_TO_BUFFER | 7330 | #ifdef NS_DRAW_TO_BUFFER |
| 7271 | CGFloat scale = [[self window] backingScaleFactor]; | 7331 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 7272 | oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale; | 7332 | if ([self wantsUpdateLayer]) |
| 7273 | oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale; | 7333 | { |
| 7274 | #else | 7334 | #endif |
| 7275 | oldw = FRAME_PIXEL_WIDTH (emacsframe); | 7335 | CGFloat scale = [[self window] backingScaleFactor]; |
| 7276 | oldh = FRAME_PIXEL_HEIGHT (emacsframe); | 7336 | oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale; |
| 7337 | oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale; | ||
| 7338 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 7339 | } | ||
| 7340 | else | ||
| 7341 | { | ||
| 7277 | #endif | 7342 | #endif |
| 7343 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 7344 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 7345 | oldw = FRAME_PIXEL_WIDTH (emacsframe); | ||
| 7346 | oldh = FRAME_PIXEL_HEIGHT (emacsframe); | ||
| 7347 | #endif | ||
| 7348 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 7349 | } | ||
| 7350 | #endif | ||
| 7351 | |||
| 7278 | neww = (int)NSWidth (frame); | 7352 | neww = (int)NSWidth (frame); |
| 7279 | newh = (int)NSHeight (frame); | 7353 | newh = (int)NSHeight (frame); |
| 7280 | 7354 | ||
| @@ -8304,6 +8378,9 @@ not_in_argv (NSString *arg) | |||
| 8304 | { | 8378 | { |
| 8305 | NSTRACE ("EmacsView createDrawingBuffer]"); | 8379 | NSTRACE ("EmacsView createDrawingBuffer]"); |
| 8306 | 8380 | ||
| 8381 | if (! [self wantsUpdateLayer]) | ||
| 8382 | return; | ||
| 8383 | |||
| 8307 | NSGraphicsContext *screen; | 8384 | NSGraphicsContext *screen; |
| 8308 | CGColorSpaceRef colorSpace = [[[self window] colorSpace] CGColorSpace]; | 8385 | CGColorSpaceRef colorSpace = [[[self window] colorSpace] CGColorSpace]; |
| 8309 | CGFloat scale = [[self window] backingScaleFactor]; | 8386 | CGFloat scale = [[self window] backingScaleFactor]; |
| @@ -8339,6 +8416,9 @@ not_in_argv (NSString *arg) | |||
| 8339 | { | 8416 | { |
| 8340 | NSTRACE ("EmacsView windowDidChangeBackingProperties:]"); | 8417 | NSTRACE ("EmacsView windowDidChangeBackingProperties:]"); |
| 8341 | 8418 | ||
| 8419 | if (! [self wantsUpdateLayer]) | ||
| 8420 | return; | ||
| 8421 | |||
| 8342 | CGFloat old = [[[notification userInfo] | 8422 | CGFloat old = [[[notification userInfo] |
| 8343 | objectForKey:@"NSBackingPropertyOldScaleFactorKey"] | 8423 | objectForKey:@"NSBackingPropertyOldScaleFactorKey"] |
| 8344 | doubleValue]; | 8424 | doubleValue]; |
| @@ -8362,41 +8442,56 @@ not_in_argv (NSString *arg) | |||
| 8362 | NSTRACE_RECT ("Destination", dstRect); | 8442 | NSTRACE_RECT ("Destination", dstRect); |
| 8363 | 8443 | ||
| 8364 | #ifdef NS_DRAW_TO_BUFFER | 8444 | #ifdef NS_DRAW_TO_BUFFER |
| 8365 | CGImageRef copy; | 8445 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 8366 | NSRect frame = [self frame]; | 8446 | if ([self wantsUpdateLayer]) |
| 8367 | NSAffineTransform *setOrigin = [NSAffineTransform transform]; | 8447 | { |
| 8448 | #endif | ||
| 8449 | CGImageRef copy; | ||
| 8450 | NSRect frame = [self frame]; | ||
| 8451 | NSAffineTransform *setOrigin = [NSAffineTransform transform]; | ||
| 8368 | 8452 | ||
| 8369 | [[NSGraphicsContext currentContext] saveGraphicsState]; | 8453 | [[NSGraphicsContext currentContext] saveGraphicsState]; |
| 8370 | 8454 | ||
| 8371 | /* Set the clipping before messing with the buffer's | 8455 | /* Set the clipping before messing with the buffer's |
| 8372 | orientation. */ | 8456 | orientation. */ |
| 8373 | NSRectClip (dstRect); | 8457 | NSRectClip (dstRect); |
| 8374 | 8458 | ||
| 8375 | /* Unflip the buffer as the copied image will be unflipped, and | 8459 | /* Unflip the buffer as the copied image will be unflipped, and |
| 8376 | offset the top left so when we draw back into the buffer the | 8460 | offset the top left so when we draw back into the buffer the |
| 8377 | correct part of the image is drawn. */ | 8461 | correct part of the image is drawn. */ |
| 8378 | CGContextScaleCTM(drawingBuffer, 1, -1); | 8462 | CGContextScaleCTM(drawingBuffer, 1, -1); |
| 8379 | CGContextTranslateCTM(drawingBuffer, | 8463 | CGContextTranslateCTM(drawingBuffer, |
| 8380 | NSMinX (dstRect) - NSMinX (srcRect), | 8464 | NSMinX (dstRect) - NSMinX (srcRect), |
| 8381 | -NSHeight (frame) - (NSMinY (dstRect) - NSMinY (srcRect))); | 8465 | -NSHeight (frame) - (NSMinY (dstRect) - NSMinY (srcRect))); |
| 8382 | 8466 | ||
| 8383 | /* Take a copy of the buffer and then draw it back to the buffer, | 8467 | /* Take a copy of the buffer and then draw it back to the buffer, |
| 8384 | limited by the clipping rectangle. */ | 8468 | limited by the clipping rectangle. */ |
| 8385 | copy = CGBitmapContextCreateImage (drawingBuffer); | 8469 | copy = CGBitmapContextCreateImage (drawingBuffer); |
| 8386 | CGContextDrawImage (drawingBuffer, frame, copy); | 8470 | CGContextDrawImage (drawingBuffer, frame, copy); |
| 8387 | 8471 | ||
| 8388 | CGImageRelease (copy); | 8472 | CGImageRelease (copy); |
| 8389 | 8473 | ||
| 8390 | [[NSGraphicsContext currentContext] restoreGraphicsState]; | 8474 | [[NSGraphicsContext currentContext] restoreGraphicsState]; |
| 8391 | [self setNeedsDisplayInRect:dstRect]; | 8475 | [self setNeedsDisplayInRect:dstRect]; |
| 8392 | #else | ||
| 8393 | hide_bell(); // Ensure the bell image isn't scrolled. | ||
| 8394 | 8476 | ||
| 8395 | ns_focus (emacsframe, &dstRect, 1); | 8477 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 8396 | [self scrollRect: srcRect | 8478 | } |
| 8397 | by: NSMakeSize (dstRect.origin.x - srcRect.origin.x, | 8479 | else |
| 8398 | dstRect.origin.y - srcRect.origin.y)]; | 8480 | { |
| 8399 | ns_unfocus (emacsframe); | 8481 | #endif |
| 8482 | #endif /* NS_DRAW_TO_BUFFER */ | ||
| 8483 | |||
| 8484 | #if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 8485 | hide_bell(); // Ensure the bell image isn't scrolled. | ||
| 8486 | |||
| 8487 | ns_focus (emacsframe, &dstRect, 1); | ||
| 8488 | [self scrollRect: srcRect | ||
| 8489 | by: NSMakeSize (dstRect.origin.x - srcRect.origin.x, | ||
| 8490 | dstRect.origin.y - srcRect.origin.y)]; | ||
| 8491 | ns_unfocus (emacsframe); | ||
| 8492 | #endif | ||
| 8493 | #if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400 | ||
| 8494 | } | ||
| 8400 | #endif | 8495 | #endif |
| 8401 | } | 8496 | } |
| 8402 | 8497 | ||
| @@ -8404,7 +8499,13 @@ not_in_argv (NSString *arg) | |||
| 8404 | #ifdef NS_DRAW_TO_BUFFER | 8499 | #ifdef NS_DRAW_TO_BUFFER |
| 8405 | - (BOOL)wantsUpdateLayer | 8500 | - (BOOL)wantsUpdateLayer |
| 8406 | { | 8501 | { |
| 8407 | return YES; | 8502 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 |
| 8503 | if (NSAppKitVersionNumber < 1671) | ||
| 8504 | return NO; | ||
| 8505 | #endif | ||
| 8506 | |||
| 8507 | /* Running on macOS 10.14 or above. */ | ||
| 8508 | return YES; | ||
| 8408 | } | 8509 | } |
| 8409 | 8510 | ||
| 8410 | 8511 | ||