forked from firka/flutter
Allow FlutterViewController to specify whether its FlutterView is opaque (flutter/engine#6570)
* Allow FlutterViewController to specify whether its FlutterView is opaque
This commit is contained in:
@@ -93,6 +93,15 @@ FLUTTER_EXPORT
|
||||
*/
|
||||
@property(strong, nonatomic) UIView* splashScreenView;
|
||||
|
||||
/**
|
||||
* Controls whether the created view will be opaque or not.
|
||||
*
|
||||
* Default is `YES`. Note that setting this to `NO` may negatively impact performance
|
||||
* when using hardware acceleration, and toggling this will trigger a re-layout of the
|
||||
* view.
|
||||
*/
|
||||
@property(nonatomic, getter=isViewOpaque) BOOL viewOpaque;
|
||||
|
||||
@end
|
||||
|
||||
#endif // FLUTTER_FLUTTERVIEWCONTROLLER_H_
|
||||
|
||||
@@ -9,10 +9,25 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/memory/weak_ptr.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
|
||||
|
||||
@protocol FlutterScreenshotDelegate <NSObject>
|
||||
|
||||
- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
|
||||
asBase64Encoded:(BOOL)base64Encode;
|
||||
|
||||
@end
|
||||
|
||||
@interface FlutterView : UIView
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
|
||||
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate
|
||||
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
|
||||
- (std::unique_ptr<shell::IOSSurface>)createSurface;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/common/rasterizer.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
|
||||
#include "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
|
||||
#include "flutter/shell/platform/darwin/ios/ios_surface_software.h"
|
||||
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
|
||||
@@ -24,28 +22,42 @@
|
||||
|
||||
@implementation FlutterView
|
||||
|
||||
- (FlutterViewController*)flutterViewController {
|
||||
// Find the first view controller in the responder chain and see if it is a FlutterViewController.
|
||||
for (UIResponder* responder = self.nextResponder; responder != nil;
|
||||
responder = responder.nextResponder) {
|
||||
if ([responder isKindOfClass:[UIViewController class]]) {
|
||||
if ([responder isKindOfClass:[FlutterViewController class]]) {
|
||||
return reinterpret_cast<FlutterViewController*>(responder);
|
||||
} else {
|
||||
// Should only happen if a non-FlutterViewController tries to somehow (via dynamic class
|
||||
// resolution or reparenting) set a FlutterView as its view.
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
id<FlutterScreenshotDelegate> _delegate;
|
||||
|
||||
- (instancetype)init {
|
||||
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
|
||||
reason:nil
|
||||
userInfo:nil]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
|
||||
reason:nil
|
||||
userInfo:nil]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder*)aDecoder {
|
||||
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
|
||||
reason:nil
|
||||
userInfo:nil]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate opaque:(BOOL)opaque {
|
||||
FML_DCHECK(delegate) << "Delegate must not be nil.";
|
||||
self = [super initWithFrame:CGRectNull];
|
||||
|
||||
if (self) {
|
||||
_delegate = delegate;
|
||||
self.layer.opaque = opaque;
|
||||
}
|
||||
return nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
|
||||
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
|
||||
layer.allowsGroupOpacity = YES;
|
||||
layer.opaque = YES;
|
||||
CGFloat screenScale = [UIScreen mainScreen].scale;
|
||||
layer.contentsScale = screenScale;
|
||||
layer.rasterizationScale = screenScale;
|
||||
@@ -84,16 +96,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
FlutterViewController* controller = [self flutterViewController];
|
||||
|
||||
if (controller == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& shell = [controller shell];
|
||||
|
||||
auto screenshot = shell.Screenshot(shell::Rasterizer::ScreenshotType::UncompressedImage,
|
||||
false /* base64 encode */);
|
||||
auto screenshot = [_delegate takeScreenshot:shell::Rasterizer::ScreenshotType::UncompressedImage
|
||||
asBase64Encoded:NO];
|
||||
|
||||
if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
|
||||
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
|
||||
|
||||
@interface FlutterViewController () <FlutterTextInputDelegate>
|
||||
@interface FlutterViewController () <FlutterTextInputDelegate, FlutterScreenshotDelegate>
|
||||
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
|
||||
@end
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
blink::ViewportMetrics _viewportMetrics;
|
||||
int64_t _nextTextureId;
|
||||
BOOL _initialized;
|
||||
BOOL _viewOpaque;
|
||||
|
||||
fml::scoped_nsobject<FlutterObservatoryPublisher> _publisher;
|
||||
}
|
||||
@@ -75,6 +76,8 @@
|
||||
else
|
||||
_dartProject.reset([projectOrNil retain]);
|
||||
|
||||
self.viewOpaque = YES;
|
||||
|
||||
[self performCommonViewControllerInitialization];
|
||||
}
|
||||
|
||||
@@ -146,7 +149,7 @@
|
||||
_threadHost.io_thread->GetTaskRunner() // io
|
||||
);
|
||||
|
||||
_flutterView.reset([[FlutterView alloc] init]);
|
||||
_flutterView.reset([[FlutterView alloc] initWithDelegate:self opaque:self.isViewOpaque]);
|
||||
|
||||
// Lambda captures by pointers to ObjC objects are fine here because the create call is
|
||||
// synchronous.
|
||||
@@ -180,6 +183,18 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- (BOOL)isViewOpaque {
|
||||
return _viewOpaque;
|
||||
}
|
||||
|
||||
- (void)viewOpaque:(BOOL)value {
|
||||
_viewOpaque = value;
|
||||
if (_flutterView.get().layer.opaque != value) {
|
||||
_flutterView.get().layer.opaque = value;
|
||||
[_flutterView.get().layer setNeedsLayout];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupChannels {
|
||||
_localizationChannel.reset([[FlutterMethodChannel alloc]
|
||||
initWithName:@"flutter/localization"
|
||||
@@ -840,6 +855,14 @@ static blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) {
|
||||
arguments:@[ @(client), actionString ]];
|
||||
}
|
||||
|
||||
#pragma mark - Screenshot Delegate
|
||||
|
||||
- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
|
||||
asBase64Encoded:(BOOL)base64Encode {
|
||||
FML_DCHECK(_shell) << "Cannot takeScreenshot without a shell";
|
||||
return _shell->Screenshot(type, base64Encode);
|
||||
}
|
||||
|
||||
#pragma mark - Orientation updates
|
||||
|
||||
- (void)onOrientationPreferencesUpdated:(NSNotification*)notification {
|
||||
|
||||
Reference in New Issue
Block a user