-
Notifications
You must be signed in to change notification settings - Fork 6k
Implement unobstructed Platform Views on iOS #17049
Changes from 1 commit
ad66694
1fde093
9b747a3
e8cfa5d
ae64ac3
e722620
bce3c8a
b1975e1
4318306
84c3b0f
3635a70
39f0bad
62d8d8d
11242e9
fcaa142
2b27ed6
b7c2bc6
71ba25c
7002929
9f7f91c
4cb007a
326f339
6d283a9
781fb29
858849b
d482d2d
00f86a5
b35dde1
423036d
ed891cb
207beb4
f6d1269
af7b916
4100603
0c06c48
f705462
71e5beb
d4f4386
7f2d64e
f48860f
32fbc8c
165d9ea
41b8ac4
8488382
32f433a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,7 +370,7 @@ | |
| // | ||
| // The UIKit frame is set based on the logical resolution instead of physical. | ||
| // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). | ||
| // However, flow is based on the physical resolution. For example, 1000 pixels in flow equals | ||
| // However, flow is based on the physical resol ution. For eaxmple, 1000 pixels in flow equals | ||
| // 500 points in UIKit. And until this point, we did all the calculation based on the flow | ||
| // resolution. So we need to scale down to match UIKit's logical resolution. | ||
| CGFloat screenScale = [UIScreen mainScreen].scale; | ||
|
|
@@ -430,12 +430,23 @@ | |
| layer_pool_->RecycleLayers(); | ||
| } | ||
|
|
||
| SkRect FlutterPlatformViewsController::GetPlatformViewRect(int view_id) { | ||
| UIView* platform_view = [views_[view_id].get() view]; | ||
| UIScreen* screen = [UIScreen mainScreen]; | ||
| CGRect platform_view_cgrect = [platform_view convertRect:platform_view.bounds | ||
| toCoordinateSpace:screen.coordinateSpace]; | ||
| return SkRect::MakeXYWH(platform_view_cgrect.origin.x * screen.scale, // | ||
| platform_view_cgrect.origin.y * screen.scale, // | ||
| platform_view_cgrect.size.width * screen.scale, // | ||
| platform_view_cgrect.size.height * screen.scale // | ||
| ); | ||
| } | ||
|
|
||
| bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context, | ||
| std::shared_ptr<IOSContext> ios_context) { | ||
| DisposeViews(); | ||
|
|
||
| bool did_submit = true; | ||
| CGFloat screenScale = [UIScreen mainScreen].scale; | ||
|
|
||
| // Maps a platform view id to a vector of `FlutterPlatformViewLayer`. | ||
| LayersMap platform_view_layers; | ||
|
|
@@ -448,66 +459,10 @@ | |
| sk_sp<SkPicture> picture = | ||
| platform_views_recorder_[platform_view_id]->finishRecordingAsPicture(); | ||
|
|
||
| std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, gl_context); | ||
| std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(frame_size_); | ||
|
|
||
| layer->overlay_view.get().frame = flutter_view_.get().bounds; | ||
|
|
||
| std::vector<SkRect*> rects; | ||
| bbh->getAll(&rects); | ||
|
|
||
| SkCanvas* overlay_canvas = frame->SkiaCanvas(); | ||
| overlay_canvas->clear(SK_ColorTRANSPARENT); | ||
|
|
||
| auto paint = SkPaint(); | ||
| paint.setColor(SkColors::kRed); | ||
| paint.setStyle(SkPaint::Style::kStroke_Style); | ||
| paint.setStrokeWidth(5); | ||
|
|
||
|
|
||
| for (SkRect* rect : rects) { | ||
| FML_DLOG(ERROR) << " rect: " << rect->x() << "x" << rect->y(); | ||
| overlay_canvas->drawRect(*rect, paint); | ||
| } | ||
|
|
||
| frame->Submit(); | ||
|
|
||
| platform_view_layers[platform_view_id].push_back(layer); | ||
|
|
||
|
|
||
|
|
||
| // std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, gl_context); | ||
| // CGFloat screenScale = [UIScreen mainScreen].scale; | ||
| // // Set the size of the overlay UIView. | ||
| // layer->overlay_view.get().backgroundColor = [UIColor blueColor]; | ||
| // layer->overlay_view.get().frame = | ||
| // CGRectMake(rect.x() / screenScale, rect.y() / screenScale, rect.width() / screenScale, | ||
| // rect.height() / screenScale); | ||
|
|
||
| // SkISize rect_size = SkISize::Make(rect.width(), rect.height()); | ||
| // std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(rect_size); | ||
|
|
||
| // // If frame is null, AcquireFrame already printed out an error message. | ||
| // if (frame == nullptr) { | ||
| // return layer; | ||
| // } | ||
| // SkCanvas* overlay_canvas = frame->SkiaCanvas(); | ||
| // overlay_canvas->clear(SK_ColorTRANSPARENT); | ||
| // overlay_canvas->translate(-rect.x(), -rect.y()); | ||
| // overlay_canvas->drawPicture(picture); | ||
|
|
||
| // layer->did_submit_last_frame = frame->Submit(); | ||
|
|
||
| continue; | ||
|
|
||
| for (size_t j = i + 1; j > 0; j--) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nits:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that causes
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might have missed something, I don't see how j can go below 0 if we do something like: But yeah its just a personal style preference, feel free to ignore :)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the condition is |
||
| int current_platform_view_id = composition_order_[j - 1]; | ||
| EmbeddedViewParams params = platform_views_params_[current_platform_view_id]; | ||
| SkRect platform_view_rect = SkRect::MakeXYWH( | ||
| /*x=*/params.offsetPixels.x(), | ||
| /*y=*/params.offsetPixels.y(), | ||
| /*width=*/params.sizePoints.width() * screenScale, | ||
| /*height=*/params.sizePoints.height() * screenScale); | ||
|
|
||
| SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id); | ||
|
|
||
| std::vector<SkRect*> intersection_rects; | ||
| bbh->searchRects(platform_view_rect, &intersection_rects); | ||
|
|
@@ -522,7 +477,7 @@ | |
| } | ||
| // Get the intersection rect between the current joined rect | ||
| // and the platform view rect. | ||
| // joined_rect.intersect(platform_view_rect); | ||
| joined_rect.intersect(platform_view_rect); | ||
| auto layer = GetLayer(gr_context, ios_context, picture, joined_rect); | ||
| did_submit &= layer->did_submit_last_frame; | ||
| platform_view_layers[current_platform_view_id].push_back(layer); | ||
|
|
@@ -531,7 +486,7 @@ | |
| // Get the intersection rect between the current rect | ||
| // and the platform view rect. | ||
| SkRect joined_rect = *rect; | ||
| // joined_rect.intersect(platform_view_rect); | ||
| joined_rect.intersect(platform_view_rect); | ||
| auto layer = GetLayer(gr_context, ios_context, picture, joined_rect); | ||
| did_submit &= layer->did_submit_last_frame; | ||
| platform_view_layers[current_platform_view_id].push_back(layer); | ||
|
|
@@ -544,6 +499,7 @@ | |
|
|
||
| composition_order_.clear(); | ||
| layer_pool_->RecycleLayers(); | ||
|
|
||
| return did_submit; | ||
| } | ||
|
|
||
|
|
@@ -553,13 +509,13 @@ | |
| for (size_t i = 0; i < composition_order_.size(); i++) { | ||
| int platform_view_id = composition_order_[i]; | ||
| auto layers = layer_map[platform_view_id]; | ||
| // UIView* platform_view_root = root_views_[platform_view_id].get(); | ||
| UIView* platform_view_root = root_views_[platform_view_id].get(); | ||
|
|
||
| // if (platform_view_root.superview != flutter_view) { | ||
| // [flutter_view addSubview:platform_view_root]; | ||
| // } else { | ||
| // platform_view_root.layer.zPosition = zIndex++; | ||
| // } | ||
| if (platform_view_root.superview != flutter_view) { | ||
| [flutter_view addSubview:platform_view_root]; | ||
| } else { | ||
| platform_view_root.layer.zPosition = zIndex++; | ||
cyanglaz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| for (auto layer : layers) { | ||
| if ([layer->overlay_view superview] != flutter_view) { | ||
| [flutter_view addSubview:layer->overlay_view]; | ||
|
|
@@ -571,26 +527,6 @@ | |
| } | ||
| } | ||
|
|
||
| void FlutterPlatformViewsController::RemoveUnusedLayers() { | ||
| auto layers = layer_pool_->GetUnusedLayers(); | ||
| for (auto layer : layers) { | ||
| [layer->overlay_view removeFromSuperview]; | ||
| } | ||
|
|
||
| std::unordered_set<int64_t> composition_order_set; | ||
|
|
||
| for (int64_t view_id : composition_order_) { | ||
| composition_order_set.insert(view_id); | ||
| } | ||
| // Remove unused platform views. | ||
| for (int64_t view_id : active_composition_order_) { | ||
| if (composition_order_set.find(view_id) == composition_order_set.end()) { | ||
| UIView* platform_view_root = root_views_[view_id].get(); | ||
| [platform_view_root removeFromSuperview]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| std::shared_ptr<FlutterPlatformViewLayer> FlutterPlatformViewsController::GetLayer( | ||
| GrContext* gr_context, | ||
| std::shared_ptr<IOSContext> ios_context, | ||
|
|
@@ -599,10 +535,11 @@ | |
| std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, ios_context); | ||
| CGFloat screenScale = [UIScreen mainScreen].scale; | ||
| // Set the size of the overlay UIView. | ||
| layer->overlay_view.get().backgroundColor = [UIColor blueColor]; | ||
| layer->overlay_view.get().frame = | ||
| CGRectMake(rect.x() / screenScale, rect.y() / screenScale, rect.width() / screenScale, | ||
| rect.height() / screenScale); | ||
| layer->overlay_view.get().frame = CGRectMake(rect.x() / screenScale, // | ||
| rect.y() / screenScale, // | ||
| rect.width() / screenScale, // | ||
| rect.height() / screenScale // | ||
| ); | ||
|
|
||
| SkISize rect_size = SkISize::Make(rect.width(), rect.height()); | ||
| std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(rect_size); | ||
|
|
@@ -620,6 +557,26 @@ | |
| return layer; | ||
| } | ||
|
|
||
| void FlutterPlatformViewsController::RemoveUnusedLayers() { | ||
| auto layers = layer_pool_->GetUnusedLayers(); | ||
| for (auto layer : layers) { | ||
blasten marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [layer->overlay_view removeFromSuperview]; | ||
| } | ||
|
|
||
| std::unordered_set<int64_t> composition_order_set; | ||
|
|
||
| for (int64_t view_id : composition_order_) { | ||
| composition_order_set.insert(view_id); | ||
| } | ||
| // Remove unused platform views. | ||
| for (int64_t view_id : active_composition_order_) { | ||
| if (composition_order_set.find(view_id) == composition_order_set.end()) { | ||
| UIView* platform_view_root = root_views_[view_id].get(); | ||
| [platform_view_root removeFromSuperview]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void FlutterPlatformViewsController::DisposeViews() { | ||
| if (views_to_dispose_.empty()) { | ||
| return; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe consider get the
platform_viewrect based onflutter_view_rect instead? I'm not certain but there might be situations where the flutter_view_ is not the same size as the screen? (add to app?)Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. can you think of a test case to exercise that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might be a way to set a custom flutter_view_ when initializing the application? I am not able to find public API to do so in engine header tho.
Maybe try to override
FlutterViewController.viewwith a customUIViewto see if it works.@xster We want to run a test against a flutter_view_ with custom rect (different from window) on iOS. Is there a way to override the flutter_view_'s when initializing the engine or
FlutterViewController?