Minor improvement of macOS 10.14 mojave support: draw window views with the displayLayer: method

The doc recommends to draw views with the displayLayer: method when the view manages itself
completely its own bitmap:
       If your delegate implements the displayLayer: method, that implementation is responsible 
       for creating a bitmap and assigning it to the layer’s contents property. 

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@13075 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2018-10-20 07:24:27 +00:00
parent 75b6cee6cc
commit 1741a6c128

View File

@ -592,8 +592,7 @@ void Fl_Cocoa_Screen_Driver::breakMacEventLoop()
- (BOOL)did_view_resolution_change;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- (BOOL)wantsLayer;
- (BOOL)wantsUpdateLayer;
- (void)updateLayer;
- (void)displayLayer:(CALayer *)layer;
- (void)viewFrameDidChange;
#endif
@end
@ -2180,8 +2179,8 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
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 sets wantsUpdateLayer to YES. Consequently, FLView objects are drawn
by the updateLayer message. An FLView has also a member variable
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.
@ -2190,8 +2189,8 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
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 sets wantsUpdateLayer to NO. Consequently, FLViewGL objects are drawn
by the drawLayer:inContext: message which calls drawRect: which draws the GL scene.
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
@ -2204,17 +2203,12 @@ static CGContextRef prepare_bitmap_for_layer(int w, int h ) {
}
@interface FLViewGL : FLView // only for layered GL windows
- (BOOL)wantsUpdateLayer;
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
- (void)viewFrameDidChange;
- (void)displayLayer:(CALayer *)layer;
@end
@implementation FLViewGL
- (BOOL)wantsUpdateLayer {
return NO;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
[self drawRect:[self frame]];//essai
- (void)displayLayer:(CALayer *)layer {
[self drawRect:[self frame]];
Fl_Window *window = [(FLWindow*)[self window] getFl_Window];
if (window->parent()) window->redraw(); // useful during resize of GL subwindow
if (Fl_Cocoa_Window_Driver::driver(window)->wait_for_expose_value) {
@ -2223,14 +2217,10 @@ static CGContextRef prepare_bitmap_for_layer(int w, int h ) {
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];
[[self window] setFrame:r display:YES];
}
Fl_Cocoa_Window_Driver::driver(window)->wait_for_expose_value = 0;
}
- (void)viewFrameDidChange
{
[[self layer] display]; // for layered GL windows
}
@end
#endif //>= MAC_OS_X_VERSION_10_8
@ -2239,29 +2229,27 @@ static CGContextRef prepare_bitmap_for_layer(int w, int h ) {
- (BOOL)wantsLayer {
return views_use_CA;
}
- (BOOL)wantsUpdateLayer {
return views_use_CA;
}
- (void)updateLayer {
- (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_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window);
float scale = Fl::screen_driver()->scale(0);
NSRect rect = [self frame];
if (!window->parent() && window->border() && fabs(rect.size.height - window->h() * scale) > 5. ) { // this happens with tabbed windows
window->resize([[self window] frame].origin.x/scale,
(main_screen_height - ([[self window] frame].origin.y + rect.size.height))/scale,
rect.size.width/scale, rect.size.height/scale);
}
if (!layer_gc) { // runs when window is created, resized, changed screen resolution
float scale = Fl::screen_driver()->scale(0);
NSRect rect = [self frame];
if (!window->parent() && window->border() && fabs(rect.size.height - window->h() * scale) > 5. ) {
// this happens with tabbed windows
window->resize([[self window] frame].origin.x/scale,
(main_screen_height - ([[self window] frame].origin.y + rect.size.height))/scale,
rect.size.width/scale, rect.size.height/scale);
}
NSRect r = [self frame];
[self layer].bounds = NSRectToCGRect(r);
layer.bounds = NSRectToCGRect(r);
d->wait_for_expose_value = 0;
[self did_view_resolution_change];
if (d->mapped_to_retina()) {
r.size.width *= 2; r.size.height *= 2;
[self layer].contentsScale = 2.;
} else [self layer].contentsScale = 1.;
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 ) {
@ -2277,7 +2265,7 @@ static CGContextRef prepare_bitmap_for_layer(int w, int h ) {
through_drawRect = NO;
window->clear_damage();
CGImageRef cgimg = CGBitmapContextCreateImage(layer_gc); // requires 10.4
[self layer].contents = (id)cgimg;
layer.contents = (id)cgimg;
CGImageRelease(cgimg);
}
}
@ -2953,8 +2941,11 @@ void Fl_Cocoa_Window_Driver::flush()
{
if (pWindow->as_gl_window()) {
Fl_Window_Driver::flush();
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
} else if (views_use_CA) {
[[fl_xid(pWindow) contentView] updateLayer];
FLView *view = (FLView*)[fl_xid(pWindow) contentView];
[view displayLayer:[view layer]];
#endif
} else {
make_current_counts = 1;
NSView *view = (through_drawRect ? nil : [fl_xid(pWindow) contentView]);
@ -3401,8 +3392,8 @@ void Fl_Cocoa_Window_Driver::make_current()
{
if (make_current_counts > 1 && !views_use_CA) return;
if (make_current_counts) make_current_counts++;
if (views_use_CA && !through_drawRect) {
pWindow->damage(FL_DAMAGE_CHILD); // force display of previous draws to this window
if (views_use_CA && !through_drawRect) { // detect direct calls from the app
pWindow->damage(FL_DAMAGE_CHILD); // make next draws to this window displayed at next event loop
}
q_release_context();
Fl_X *i = Fl_X::i(pWindow);
@ -4475,7 +4466,7 @@ int Fl_Darwin_System_Driver::calc_mac_os_version() {
#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
//if (fl_mac_os_version >= 101300) views_use_CA = YES; // to get as with mojave
return fl_mac_os_version;
}