Add support of MacOS 10.14 Mojave when app is linked with SDK 10.14
Mojave support requires to draw windows using so-called "layer-backed views". git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@13077 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
a2ff8ee535
commit
4c8b7c99ea
343
src/Fl_cocoa.mm
343
src/Fl_cocoa.mm
@ -100,6 +100,7 @@ static int main_screen_height; // height of menubar-containing screen used to co
|
||||
static BOOL through_drawRect = NO;
|
||||
// through_Fl_X_flush = YES means Fl_X::flush() was called
|
||||
static BOOL through_Fl_X_flush = NO;
|
||||
static BOOL views_use_CA = NO; // YES means views are layer-backed, as on macOS 10.14 when linked with SDK 10.14
|
||||
static int im_enabled = -1;
|
||||
// OS version-dependent pasteboard type names
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
|
||||
@ -660,6 +661,65 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
||||
@interface FLView : NSView <NSTextInput
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
, NSTextInputClient
|
||||
#endif
|
||||
> {
|
||||
BOOL in_key_event; // YES means keypress is being processed by handleEvent
|
||||
BOOL need_handle; // YES means Fl::handle(FL_KEYBOARD,) is needed after handleEvent processing
|
||||
NSInteger identifier;
|
||||
NSRange selectedRange;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
@public
|
||||
CGContextRef layer_gc;
|
||||
#endif
|
||||
}
|
||||
+ (void)prepareEtext:(NSString*)aString;
|
||||
+ (void)concatEtext:(NSString*)aString;
|
||||
- (BOOL)process_keydown:(NSEvent*)theEvent;
|
||||
- (id)initWithFrame:(NSRect)frameRect;
|
||||
- (void)drawRect:(NSRect)rect;
|
||||
- (BOOL)acceptsFirstResponder;
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
|
||||
- (void)resetCursorRects;
|
||||
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
|
||||
- (void)mouseUp:(NSEvent *)theEvent;
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent;
|
||||
- (void)otherMouseUp:(NSEvent *)theEvent;
|
||||
- (void)mouseDown:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDown:(NSEvent *)theEvent;
|
||||
- (void)mouseMoved:(NSEvent *)theEvent;
|
||||
- (void)mouseDragged:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)scrollWheel:(NSEvent *)theEvent;
|
||||
- (void)magnifyWithEvent:(NSEvent *)theEvent;
|
||||
- (void)keyDown:(NSEvent *)theEvent;
|
||||
- (void)keyUp:(NSEvent *)theEvent;
|
||||
- (void)flagsChanged:(NSEvent *)theEvent;
|
||||
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender;
|
||||
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender;
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
|
||||
- (void)draggingExited:(id < NSDraggingInfo >)sender;
|
||||
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange;
|
||||
- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange;
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;
|
||||
- (NSInteger)windowLevel;
|
||||
#endif
|
||||
- (BOOL)did_view_resolution_change;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
- (BOOL)wantsLayer;
|
||||
- (void)displayLayer:(CALayer *)layer;
|
||||
- (void)viewFrameDidChange;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@implementation FLWindow
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
- (NSPoint)convertBaseToScreen:(NSPoint)aPoint
|
||||
@ -889,9 +949,9 @@ double fl_mac_flush_and_wait(double time_to_wait) {
|
||||
// the idle function may turn off idle, we can then wait:
|
||||
if (Fl::idle) time_to_wait = 0.0;
|
||||
}
|
||||
NSDisableScreenUpdates(); // 10.3 Makes updates to all windows appear as a single event
|
||||
if (fl_mac_os_version < 1011) NSDisableScreenUpdates(); // 10.3 Makes updates to all windows appear as a single event
|
||||
Fl::flush();
|
||||
NSEnableScreenUpdates(); // 10.3
|
||||
if (fl_mac_os_version < 1011) NSEnableScreenUpdates(); // 10.3
|
||||
if (Fl::idle && !in_idle) // 'idle' may have been set within flush()
|
||||
time_to_wait = 0.0;
|
||||
double retval = fl_wait(time_to_wait);
|
||||
@ -1216,6 +1276,9 @@ static FLTextView *fltextview_instance = nil;
|
||||
- (void)windowDidMiniaturize:(NSNotification *)notif;
|
||||
- (BOOL)windowShouldClose:(id)fl;
|
||||
- (void)anyWindowWillClose:(NSNotification *)notif;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
- (void)viewFrameDidChangeNotification:(NSNotification *)notif;
|
||||
#endif
|
||||
- (void)doNothing:(id)unused;
|
||||
@end
|
||||
|
||||
@ -1378,6 +1441,18 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
|
||||
// FLTK sets position of parent and children. setSubwindowFrame is no longer necessary.
|
||||
if (fl_mac_os_version < 101000) [nsw recursivelySendToSubwindows:@selector(setSubwindowFrame)];
|
||||
[nsw checkSubwindowFrame];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
if (views_use_CA && [(FLView*)[nsw contentView] did_view_resolution_change]) {
|
||||
if (window->as_gl_window()) { // move layered GL window to different resolution
|
||||
NSView *view = [nsw contentView];
|
||||
[view display]; [view display]; // 2 necessary for toplevel GL windows
|
||||
} else [(FLView*)[nsw contentView] viewFrameDidChange];
|
||||
if (window->parent()) {
|
||||
[nsw setSubwindowFrame];
|
||||
[[nsw contentView] display];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fl_unlock_function();
|
||||
}
|
||||
- (void)windowDidResize:(NSNotification *)notif
|
||||
@ -1501,6 +1576,13 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
|
||||
}
|
||||
fl_unlock_function();
|
||||
}
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
-(void)viewFrameDidChangeNotification:(NSNotification *)notif
|
||||
{
|
||||
NSView *view = (NSView*)[notif object];
|
||||
if ([view layer] && [view isMemberOfClass:[FLView class]]) [(FLView*)view viewFrameDidChange];
|
||||
}
|
||||
#endif
|
||||
- (void)doNothing:(id)unused
|
||||
{
|
||||
return;
|
||||
@ -1831,6 +1913,12 @@ void fl_open_display() {
|
||||
selector:@selector(anyWindowWillClose:)
|
||||
name:NSWindowWillCloseNotification
|
||||
object:nil];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
[[NSNotificationCenter defaultCenter] addObserver:[FLWindowDelegate singleInstance]
|
||||
selector:@selector(viewFrameDidChangeNotification:)
|
||||
name:NSViewFrameDidChangeNotification
|
||||
object:nil];
|
||||
#endif
|
||||
if (![NSThread isMultiThreaded]) {
|
||||
// With old OS X versions, it is necessary to create one thread for secondary pthreads to be
|
||||
// allowed to use cocoa, especially to create an NSAutoreleasePool.
|
||||
@ -1981,18 +2069,8 @@ static void handleUpdateEvent( Fl_Window *window )
|
||||
{
|
||||
if ( !window ) return;
|
||||
Fl_X *i = Fl_X::i( window );
|
||||
if (fl_mac_os_version >= 100700) { // determine whether window is mapped to a retina display
|
||||
bool previous = i->mapped_to_retina();
|
||||
// rewrite next call that requires 10.7 and therefore triggers a compiler warning on old SDKs
|
||||
//NSSize s = [[i->xid contentView] convertSizeToBacking:NSMakeSize(10, 10)];
|
||||
typedef NSSize (*convertSizeIMP)(id, SEL, NSSize);
|
||||
static convertSizeIMP addr = (convertSizeIMP)[NSView instanceMethodForSelector:@selector(convertSizeToBacking:)];
|
||||
NSSize s = addr([i->xid contentView], @selector(convertSizeToBacking:), NSMakeSize(10, 10));
|
||||
i->mapped_to_retina( int(s.width + 0.5) > 10 );
|
||||
if (i->wait_for_expose == 0 && previous != i->mapped_to_retina()) i->changed_resolution(true);
|
||||
}
|
||||
i->wait_for_expose = 0;
|
||||
|
||||
[(FLView*)[fl_xid(window) contentView] did_view_resolution_change];
|
||||
if (!views_use_CA) i->wait_for_expose = 0;
|
||||
if ( i->region ) {
|
||||
XDestroyRegion(i->region);
|
||||
i->region = 0;
|
||||
@ -2258,55 +2336,127 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface FLView : NSView <NSTextInput
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
, NSTextInputClient
|
||||
#endif
|
||||
> {
|
||||
BOOL in_key_event; // YES means keypress is being processed by handleEvent
|
||||
BOOL need_handle; // YES means Fl::handle(FL_KEYBOARD,) is needed after handleEvent processing
|
||||
NSInteger identifier;
|
||||
NSRange selectedRange;
|
||||
/* Implementation note for the support of layer-backed views.
|
||||
MacOS 10.14 Mojave changes the way all drawing to displays is performed:
|
||||
all NSView objects become layer-backed, that is, the drawing is done by
|
||||
Core Animation to a CALayer object whose content is then displayed by the NSView.
|
||||
The global variable views_use_CA is set to YES when such change applies,
|
||||
that is, for apps running under 10.14 and linked to SDK 10.14.
|
||||
When views_use_CA is NO, views are not supposed to be layer-backed.
|
||||
|
||||
Each layer-backed non-OpenGL window has a single FLView object which itself has an associated CALayer.
|
||||
FLView implements displayLayer:. Consequently, FLView objects are drawn
|
||||
by the displayLayer: method. An FLView manages also a member variable
|
||||
CGContextRef layer_gc, a bitmap context the size of the view (double on Retina).
|
||||
All Quartz drawings go to this bitmap. updateLayer finishes by using an image copy
|
||||
of the bitmap as the layer's contents. That step fills the window.
|
||||
FLView implements viewFrameDidChange which deletes the bitmap and zeros layer_gc.
|
||||
This ensures the bitmap is recreated when the window is resized.
|
||||
viewFrameDidChange is also called when the window flips between low/high resolution displays.
|
||||
|
||||
Each layer-backed OpenGL window has an associated FLViewGL object, derived from FLView.
|
||||
FLViewGL objects are drawn by the displayLayer: method which calls drawRect:
|
||||
which draws the GL scene.
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
static CGContextRef prepare_bitmap_for_layer(int w, int h ) {
|
||||
CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef gc = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, cspace, kCGImageAlphaPremultipliedFirst);
|
||||
CGColorSpaceRelease(cspace);
|
||||
CGContextClearRect(gc, CGRectMake(0,0,w,h));
|
||||
return gc;
|
||||
}
|
||||
+ (void)prepareEtext:(NSString*)aString;
|
||||
+ (void)concatEtext:(NSString*)aString;
|
||||
- (BOOL)process_keydown:(NSEvent*)theEvent;
|
||||
- (id)initWithFrame:(NSRect)frameRect;
|
||||
- (void)drawRect:(NSRect)rect;
|
||||
- (BOOL)acceptsFirstResponder;
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
|
||||
- (void)resetCursorRects;
|
||||
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
|
||||
- (void)mouseUp:(NSEvent *)theEvent;
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent;
|
||||
- (void)otherMouseUp:(NSEvent *)theEvent;
|
||||
- (void)mouseDown:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDown:(NSEvent *)theEvent;
|
||||
- (void)mouseMoved:(NSEvent *)theEvent;
|
||||
- (void)mouseDragged:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)scrollWheel:(NSEvent *)theEvent;
|
||||
- (void)magnifyWithEvent:(NSEvent *)theEvent;
|
||||
- (void)keyDown:(NSEvent *)theEvent;
|
||||
- (void)keyUp:(NSEvent *)theEvent;
|
||||
- (void)flagsChanged:(NSEvent *)theEvent;
|
||||
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender;
|
||||
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender;
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
|
||||
- (void)draggingExited:(id < NSDraggingInfo >)sender;
|
||||
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange;
|
||||
- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange;
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;
|
||||
- (NSInteger)windowLevel;
|
||||
#endif
|
||||
|
||||
@interface FLViewGL : FLView // only for layered GL windows
|
||||
- (void)displayLayer:(CALayer *)layer;
|
||||
@end
|
||||
|
||||
@implementation FLViewGL
|
||||
- (void)displayLayer:(CALayer *)layer {
|
||||
if (!Fl::use_high_res_GL()) layer.contentsScale = 1.;
|
||||
[self drawRect:[self frame]];
|
||||
Fl_Window *window = [(FLWindow*)[self window] getFl_Window];
|
||||
if (window->parent()) window->redraw(); // useful during resize of GL subwindow
|
||||
Fl_X *i = Fl_X::i( window );
|
||||
if (i->wait_for_expose) {
|
||||
// 1st drawing of GL window
|
||||
NSRect r = [[self window] frame];
|
||||
r.size.width -= 1;
|
||||
[[self window] setFrame:r display:NO]; // very dirty but works. Should find something better.
|
||||
r.size.width += 1;
|
||||
[[self window] setFrame:r display:YES];
|
||||
i->wait_for_expose = 0;
|
||||
}
|
||||
}
|
||||
@end
|
||||
#endif //>= MAC_OS_X_VERSION_10_8
|
||||
|
||||
|
||||
@implementation FLView
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
- (BOOL)wantsLayer {
|
||||
return views_use_CA;
|
||||
}
|
||||
- (void)displayLayer:(CALayer *)layer {
|
||||
// called if views are layered (but not for GL) : all drawing to window goes through this
|
||||
Fl_Window *window = [(FLWindow*)[self window] getFl_Window];
|
||||
Fl_X *i = Fl_X::i( window );
|
||||
if (!layer_gc) { // runs when window is created, resized, changed screen resolution
|
||||
NSRect r = [self frame];
|
||||
layer.bounds = NSRectToCGRect(r);
|
||||
i->wait_for_expose = 0;
|
||||
[self did_view_resolution_change];
|
||||
if (i->mapped_to_retina()) {
|
||||
r.size.width *= 2; r.size.height *= 2;
|
||||
layer.contentsScale = 2.;
|
||||
} else layer.contentsScale = 1.;
|
||||
layer_gc = prepare_bitmap_for_layer(r.size.width, r.size.height);
|
||||
Fl_X *i = Fl_X::i(window);
|
||||
if ( i->region ) {
|
||||
XDestroyRegion(i->region);
|
||||
i->region = 0;
|
||||
}
|
||||
window->clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
if (window->damage()) {
|
||||
through_drawRect = YES;
|
||||
i->flush();
|
||||
Fl_X::q_release_context();
|
||||
through_drawRect = NO;
|
||||
window->clear_damage();
|
||||
CGImageRef cgimg = CGBitmapContextCreateImage(layer_gc); // requires 10.4
|
||||
layer.contents = (id)cgimg;
|
||||
CGImageRelease(cgimg);
|
||||
}
|
||||
}
|
||||
-(void)viewFrameDidChange
|
||||
{
|
||||
CGContextRelease(layer_gc);
|
||||
layer_gc = NULL;
|
||||
}
|
||||
-(void)dealloc {
|
||||
CGContextRelease(layer_gc);
|
||||
[super dealloc];
|
||||
}
|
||||
#endif //>= MAC_OS_X_VERSION_10_8
|
||||
|
||||
- (BOOL)did_view_resolution_change {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if (fl_mac_os_version >= 100700) { // determine whether window is mapped to a retina display
|
||||
Fl_Window *window = [(FLWindow*)[self window] getFl_Window];
|
||||
Fl_X *i = Fl_X::i( window );
|
||||
bool previous = i->mapped_to_retina();
|
||||
NSSize s = [self convertSizeToBacking:NSMakeSize(10, 10)]; // 10.7
|
||||
i->mapped_to_retina( int(s.width + 0.5) > 10 );
|
||||
BOOL retval = (i->wait_for_expose == 0 && previous != i->mapped_to_retina());
|
||||
if (retval) i->changed_resolution(true);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)process_keydown:(NSEvent*)theEvent
|
||||
{
|
||||
id o = fl_mac_os_version >= 100600 ? [self performSelector:@selector(inputContext)] : [FLTextInputContext singleInstance];
|
||||
@ -2959,6 +3109,14 @@ void Fl_X::flush()
|
||||
{
|
||||
if (w->as_gl_window()) {
|
||||
w->flush();
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
} else if (views_use_CA) {
|
||||
if (!through_drawRect) {
|
||||
FLView *view = (FLView*)[fl_xid(w) contentView];
|
||||
[view displayLayer:[view layer]];
|
||||
} else
|
||||
w->flush();
|
||||
#endif
|
||||
} else {
|
||||
make_current_counts = 1;
|
||||
if (!through_drawRect) [[xid contentView] lockFocus];
|
||||
@ -3112,7 +3270,12 @@ void Fl_X::make(Fl_Window* w)
|
||||
x->next = NULL;
|
||||
Fl_X::first = x;
|
||||
}
|
||||
FLView *myview = [[FLView alloc] initWithFrame:crect];
|
||||
FLView *myview =
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
views_use_CA && w->as_gl_window() ? [FLViewGL alloc] :
|
||||
#endif
|
||||
[FLView alloc];
|
||||
myview = [myview initWithFrame:crect];
|
||||
[cw setContentView:myview];
|
||||
[myview release];
|
||||
[cw setLevel:winlevel];
|
||||
@ -3359,23 +3522,36 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
|
||||
*/
|
||||
void Fl_Window::make_current()
|
||||
{
|
||||
if (make_current_counts > 1) return;
|
||||
if (make_current_counts > 1 && !views_use_CA) return;
|
||||
if (make_current_counts) make_current_counts++;
|
||||
if (views_use_CA && !through_drawRect) { // detect direct calls from the app
|
||||
damage(FL_DAMAGE_CHILD); // make next draws to this window displayed at next event loop
|
||||
}
|
||||
Fl_X::q_release_context();
|
||||
fl_window = i->xid;
|
||||
Fl_X::set_high_resolution( i->mapped_to_retina() );
|
||||
current_ = this;
|
||||
|
||||
NSGraphicsContext *nsgc;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
||||
if (fl_mac_os_version >= 100400)
|
||||
nsgc = [fl_window graphicsContext]; // 10.4
|
||||
else
|
||||
//NSLog(@"region-count=%d damage=%u",i->region?i->region->count:0, damage());
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
if (views_use_CA) {
|
||||
i->gc = ((FLView*)[fl_window contentView])->layer_gc;
|
||||
} else
|
||||
#endif
|
||||
nsgc = through_Fl_X_flush ? [NSGraphicsContext currentContext] : [NSGraphicsContext graphicsContextWithWindow:fl_window];
|
||||
i->gc = (CGContextRef)[nsgc graphicsPort];
|
||||
{
|
||||
NSGraphicsContext *nsgc;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
||||
if (fl_mac_os_version >= 100400)
|
||||
nsgc = [fl_window graphicsContext]; // 10.4
|
||||
else
|
||||
#endif
|
||||
nsgc = through_Fl_X_flush ? [NSGraphicsContext currentContext] : [NSGraphicsContext graphicsContextWithWindow:fl_window];
|
||||
i->gc = (CGContextRef)[nsgc graphicsPort];
|
||||
}
|
||||
|
||||
fl_gc = i->gc;
|
||||
CGContextSaveGState(fl_gc); // native context
|
||||
if (views_use_CA && i->mapped_to_retina()) CGContextScaleCTM(fl_gc, 2,2);
|
||||
// antialiasing must be deactivated because it applies to rectangles too
|
||||
// and escapes even clipping!!!
|
||||
// it gets activated when needed (e.g., draw text)
|
||||
@ -4281,6 +4457,26 @@ static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static NSBitmapImageRep* rect_to_NSBitmapImageRep_layer(Fl_Window *win, int x, int y, int w, int h)
|
||||
{ // capture window data for layer-based views because initWithFocusedViewRect: does not work for them
|
||||
NSBitmapImageRep *bitmap = nil;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
|
||||
CGContextRef gc = ((FLView*)[fl_xid(win) contentView])->layer_gc;
|
||||
CGImageRef cgimg = CGBitmapContextCreateImage(gc); // requires 10.4
|
||||
Fl_X *i = Fl_X::i( win );
|
||||
int resolution = i->mapped_to_retina() ? 2 : 1;
|
||||
if (x || y || w != win->w() || h != win->h()) {
|
||||
CGRect rect = CGRectMake(x * resolution, y * resolution, w * resolution, h * resolution);
|
||||
CGImageRef cgimg2 = CGImageCreateWithImageInRect(cgimg, rect);
|
||||
CGImageRelease(cgimg);
|
||||
cgimg = cgimg2;
|
||||
}
|
||||
bitmap = [[NSBitmapImageRep alloc] initWithCGImage:cgimg];//10.5
|
||||
CGImageRelease(cgimg);
|
||||
#endif
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h)
|
||||
/* Captures a rectangle from a mapped window.
|
||||
On retina displays, the resulting bitmap has 2 pixels per screen unit.
|
||||
@ -4291,6 +4487,8 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
|
||||
NSRect rect;
|
||||
if (win->as_gl_window() && y >= 0) {
|
||||
bitmap = GL_rect_to_nsbitmap(win, x, y, w, h);
|
||||
} else if (views_use_CA) {
|
||||
bitmap = rect_to_NSBitmapImageRep_layer(win, x, y, w, h);
|
||||
} else {
|
||||
NSView *winview = nil;
|
||||
if ( through_Fl_X_flush && Fl_Window::current() == win ) {
|
||||
@ -4642,7 +4840,12 @@ int Fl_X::calc_mac_os_version() {
|
||||
sscanf(s, "%d.%d.%d", &M, &m, &b);
|
||||
}
|
||||
[localPool release];
|
||||
return M*10000 + m*100 + b;
|
||||
fl_mac_os_version = M*10000 + m*100 + b;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14
|
||||
if (fl_mac_os_version >= 101400) views_use_CA = YES;
|
||||
#endif
|
||||
//if (fl_mac_os_version >= 101300) views_use_CA = YES; // to get as with mojave
|
||||
return fl_mac_os_version;
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
Loading…
Reference in New Issue
Block a user