mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Engine Support for Dynamic View Resizing (#173610)
Part of https://github.com/flutter/flutter/issues/169147 (iOS) and https://github.com/flutter/flutter/issues/149033 (Android). Implementation PRs coming up! This enables support for dynamic view resizing in non-web embedders. While this PR enables support, it does not _implement_ support. Specifically, this creates the pipes (in viewport metrics) for min/max width/height constraints that tell the engine and framework that when rendering the frame it should adjust the width/height as needed for the content. The engine should also discard layer trees that do not fit the constraints. Since the engine now relies on BoxConstraints, geometry.h has now been moved out of embedder specific codepath so that both embedder and engine can depend on it. Related PRs: `dart:ui`: https://github.com/flutter/engine/pull/48090 `framework`: https://github.com/flutter/flutter/pull/138648 `framework reland`: https://github.com/flutter/flutter/pull/140918 `Web`: https://github.com/flutter/engine/pull/50271 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Matt Boetger <boetger@google.com> Co-authored-by: Matt Boetger <matt.boetger@gmail.com>
This commit is contained in:
parent
1dc51dbf6a
commit
b683af0cec
@ -213,6 +213,7 @@ group("unittests") {
|
||||
"//flutter/runtime:no_dart_plugin_registrant_unittests",
|
||||
"//flutter/runtime:runtime_unittests",
|
||||
"//flutter/shell/common:shell_unittests",
|
||||
"//flutter/shell/geometry:geometry_unittests",
|
||||
"//flutter/shell/platform/embedder:embedder_a11y_unittests",
|
||||
"//flutter/shell/platform/embedder:embedder_proctable_unittests",
|
||||
"//flutter/shell/platform/embedder:embedder_unittests",
|
||||
|
||||
@ -730,7 +730,7 @@ void hooksTests() async {
|
||||
window.onMetricsChanged!();
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
0.1234, // device pixel ratio
|
||||
0.0, // width
|
||||
@ -752,6 +752,10 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
0.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
0.0, // maxHeight
|
||||
);
|
||||
|
||||
expectIdentical(originalZone, callbackZone);
|
||||
@ -844,7 +848,7 @@ void hooksTests() async {
|
||||
await test('View padding/insets/viewPadding/systemGestureInsets', () {
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@ -866,6 +870,10 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
1000.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
1000.0, // maxHeight
|
||||
);
|
||||
|
||||
expectEquals(window.viewInsets.bottom, 0.0);
|
||||
@ -875,7 +883,7 @@ void hooksTests() async {
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@ -897,6 +905,10 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
0.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
0.0, // maxHeight
|
||||
);
|
||||
|
||||
expectEquals(window.viewInsets.bottom, 400.0);
|
||||
@ -908,7 +920,7 @@ void hooksTests() async {
|
||||
await test('Window physical touch slop', () {
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@ -930,13 +942,17 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
0.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
0.0, // maxHeight
|
||||
);
|
||||
|
||||
expectEquals(window.gestureSettings, GestureSettings(physicalTouchSlop: 11.0));
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@ -958,13 +974,17 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
0.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
0.0, // maxHeight
|
||||
);
|
||||
|
||||
expectEquals(window.gestureSettings, GestureSettings(physicalTouchSlop: null));
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
21,
|
||||
25,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@ -986,6 +1006,10 @@ void hooksTests() async {
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
0, // Display ID
|
||||
0.0, // minWidth
|
||||
0.0, // maxWidth
|
||||
0.0, // minHeight
|
||||
0.0, // maxHeight
|
||||
);
|
||||
|
||||
expectEquals(window.gestureSettings, GestureSettings(physicalTouchSlop: 22.0));
|
||||
@ -1382,4 +1406,8 @@ external void _callHook(
|
||||
Object? arg19,
|
||||
Object? arg20,
|
||||
Object? arg21,
|
||||
Object? arg22,
|
||||
Object? arg23,
|
||||
Object? arg24,
|
||||
Object? arg25,
|
||||
]);
|
||||
|
||||
@ -27,6 +27,10 @@ void _addView(
|
||||
List<int> displayFeaturesType,
|
||||
List<int> displayFeaturesState,
|
||||
int displayId,
|
||||
double minWidth,
|
||||
double maxWidth,
|
||||
double minHeight,
|
||||
double maxHeight,
|
||||
) {
|
||||
final _ViewConfiguration viewConfiguration = _buildViewConfiguration(
|
||||
devicePixelRatio,
|
||||
@ -49,6 +53,10 @@ void _addView(
|
||||
displayFeaturesType,
|
||||
displayFeaturesState,
|
||||
displayId,
|
||||
minWidth,
|
||||
maxWidth,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
);
|
||||
PlatformDispatcher.instance._addView(viewId, viewConfiguration);
|
||||
}
|
||||
@ -151,6 +159,10 @@ _ViewConfiguration _buildViewConfiguration(
|
||||
List<int> displayFeaturesType,
|
||||
List<int> displayFeaturesState,
|
||||
int displayId,
|
||||
double minWidth,
|
||||
double maxWidth,
|
||||
double minHeight,
|
||||
double maxHeight,
|
||||
) {
|
||||
return _ViewConfiguration(
|
||||
devicePixelRatio: devicePixelRatio,
|
||||
@ -189,6 +201,12 @@ _ViewConfiguration _buildViewConfiguration(
|
||||
devicePixelRatio: devicePixelRatio,
|
||||
),
|
||||
displayId: displayId,
|
||||
viewConstraints: ViewConstraints(
|
||||
minWidth: minWidth,
|
||||
maxWidth: maxWidth,
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -215,6 +233,10 @@ void _updateWindowMetrics(
|
||||
List<int> displayFeaturesType,
|
||||
List<int> displayFeaturesState,
|
||||
int displayId,
|
||||
double minWidth,
|
||||
double maxWidth,
|
||||
double minHeight,
|
||||
double maxHeight,
|
||||
) {
|
||||
final _ViewConfiguration viewConfiguration = _buildViewConfiguration(
|
||||
devicePixelRatio,
|
||||
@ -237,6 +259,10 @@ void _updateWindowMetrics(
|
||||
displayFeaturesType,
|
||||
displayFeaturesState,
|
||||
displayId,
|
||||
minWidth,
|
||||
maxWidth,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
);
|
||||
PlatformDispatcher.instance._updateWindowMetrics(viewId, viewConfiguration);
|
||||
}
|
||||
|
||||
@ -1886,12 +1886,16 @@ class _ViewConfiguration {
|
||||
this.gestureSettings = const GestureSettings(),
|
||||
this.displayFeatures = const <DisplayFeature>[],
|
||||
this.displayId = 0,
|
||||
this.viewConstraints = const ViewConstraints(maxWidth: 0, maxHeight: 0),
|
||||
});
|
||||
|
||||
/// The identifier for a display for this view, in
|
||||
/// [PlatformDispatcher._displays].
|
||||
final int displayId;
|
||||
|
||||
/// The sizing constraints for this view in physical pixels.
|
||||
final ViewConstraints viewConstraints;
|
||||
|
||||
/// The pixel density of the output surface.
|
||||
final double devicePixelRatio;
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ class FlutterView {
|
||||
///
|
||||
/// The view can take on any [Size] that fulfills these constraints. These
|
||||
/// constraints are typically used by an UI framework as the input for its
|
||||
/// layout algorithm to determine an approrpiate size for the view. To size
|
||||
/// layout algorithm to determine an appropriate size for the view. To size
|
||||
/// the view, the selected size must be provided to the [render] method and it
|
||||
/// must satisfy the constraints.
|
||||
///
|
||||
@ -164,10 +164,7 @@ class FlutterView {
|
||||
/// See also:
|
||||
///
|
||||
/// * [physicalSize], which returns the current size of the view.
|
||||
// TODO(goderbauer): Wire this up so embedders can configure it. This will
|
||||
// also require to message the size provided to the render call back to the
|
||||
// embedder.
|
||||
ViewConstraints get physicalConstraints => ViewConstraints.tight(physicalSize);
|
||||
ViewConstraints get physicalConstraints => _viewConfiguration.viewConstraints;
|
||||
|
||||
/// The current dimensions of the rectangle as last reported by the platform
|
||||
/// into which scenes rendered in this view are drawn.
|
||||
|
||||
@ -126,6 +126,10 @@ bool PlatformConfiguration::AddView(int64_t view_id,
|
||||
tonic::ToDart(view_metrics.physical_display_features_type),
|
||||
tonic::ToDart(view_metrics.physical_display_features_state),
|
||||
tonic::ToDart(view_metrics.display_id),
|
||||
tonic::ToDart(view_metrics.physical_min_width_constraint),
|
||||
tonic::ToDart(view_metrics.physical_max_width_constraint),
|
||||
tonic::ToDart(view_metrics.physical_min_height_constraint),
|
||||
tonic::ToDart(view_metrics.physical_max_height_constraint),
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
@ -224,6 +228,10 @@ bool PlatformConfiguration::UpdateViewMetrics(
|
||||
tonic::ToDart(view_metrics.physical_display_features_type),
|
||||
tonic::ToDart(view_metrics.physical_display_features_state),
|
||||
tonic::ToDart(view_metrics.display_id),
|
||||
tonic::ToDart(view_metrics.physical_min_width_constraint),
|
||||
tonic::ToDart(view_metrics.physical_max_width_constraint),
|
||||
tonic::ToDart(view_metrics.physical_min_height_constraint),
|
||||
tonic::ToDart(view_metrics.physical_max_height_constraint),
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -18,13 +18,20 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height),
|
||||
physical_min_width_constraint(p_physical_width),
|
||||
physical_max_width_constraint(p_physical_width),
|
||||
physical_min_height_constraint(p_physical_height),
|
||||
physical_max_height_constraint(p_physical_height),
|
||||
physical_touch_slop(p_physical_touch_slop),
|
||||
display_id(p_display_id) {}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(
|
||||
double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
double p_physical_min_width_constraint,
|
||||
double p_physical_max_width_constraint,
|
||||
double p_physical_min_height_constraint,
|
||||
double p_physical_max_height_constraint,
|
||||
double p_physical_padding_top,
|
||||
double p_physical_padding_right,
|
||||
double p_physical_padding_bottom,
|
||||
@ -45,6 +52,10 @@ ViewportMetrics::ViewportMetrics(
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height),
|
||||
physical_min_width_constraint(p_physical_min_width_constraint),
|
||||
physical_max_width_constraint(p_physical_max_width_constraint),
|
||||
physical_min_height_constraint(p_physical_min_height_constraint),
|
||||
physical_max_height_constraint(p_physical_max_height_constraint),
|
||||
physical_padding_top(p_physical_padding_top),
|
||||
physical_padding_right(p_physical_padding_right),
|
||||
physical_padding_bottom(p_physical_padding_bottom),
|
||||
@ -69,6 +80,10 @@ bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
|
||||
return a.device_pixel_ratio == b.device_pixel_ratio &&
|
||||
a.physical_width == b.physical_width &&
|
||||
a.physical_height == b.physical_height &&
|
||||
a.physical_min_width_constraint == b.physical_min_width_constraint &&
|
||||
a.physical_max_width_constraint == b.physical_max_width_constraint &&
|
||||
a.physical_min_height_constraint == b.physical_min_height_constraint &&
|
||||
a.physical_max_height_constraint == b.physical_max_height_constraint &&
|
||||
a.physical_padding_top == b.physical_padding_top &&
|
||||
a.physical_padding_right == b.physical_padding_right &&
|
||||
a.physical_padding_bottom == b.physical_padding_bottom &&
|
||||
@ -99,6 +114,10 @@ std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
|
||||
<< "W " << a.physical_height << "H] " << "Padding: ["
|
||||
<< a.physical_padding_top << "T " << a.physical_padding_right << "R "
|
||||
<< a.physical_padding_bottom << "B " << a.physical_padding_left << "L] "
|
||||
<< "View Constraints: [" << a.physical_min_width_constraint << "-"
|
||||
<< a.physical_max_width_constraint << "W "
|
||||
<< a.physical_min_height_constraint << "-"
|
||||
<< a.physical_max_height_constraint << "H] "
|
||||
<< "Insets: [" << a.physical_view_inset_top << "T "
|
||||
<< a.physical_view_inset_right << "R " << a.physical_view_inset_bottom
|
||||
<< "B " << a.physical_view_inset_left << "L] " << "Gesture Insets: ["
|
||||
|
||||
@ -20,6 +20,10 @@ struct ViewportMetrics {
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
double p_physical_min_width_constraint,
|
||||
double p_physical_max_width_constraint,
|
||||
double p_physical_min_height_constraint,
|
||||
double p_physical_max_height_constraint,
|
||||
double p_physical_padding_top,
|
||||
double p_physical_padding_right,
|
||||
double p_physical_padding_bottom,
|
||||
@ -37,10 +41,13 @@ struct ViewportMetrics {
|
||||
const std::vector<int>& p_physical_display_features_type,
|
||||
const std::vector<int>& p_physical_display_features_state,
|
||||
size_t p_display_id);
|
||||
|
||||
double device_pixel_ratio = 1.0;
|
||||
double physical_width = 0;
|
||||
double physical_height = 0;
|
||||
double physical_min_width_constraint = 0;
|
||||
double physical_max_width_constraint = 0;
|
||||
double physical_min_height_constraint = 0;
|
||||
double physical_max_height_constraint = 0;
|
||||
double physical_padding_top = 0;
|
||||
double physical_padding_right = 0;
|
||||
double physical_padding_bottom = 0;
|
||||
|
||||
@ -148,6 +148,7 @@ source_set("common") {
|
||||
"//flutter/lib/ui",
|
||||
"//flutter/runtime",
|
||||
"//flutter/shell/common:base64",
|
||||
"//flutter/shell/geometry",
|
||||
"//flutter/shell/profiling",
|
||||
"//flutter/skia",
|
||||
]
|
||||
|
||||
@ -149,6 +149,56 @@ void PerformInitializationTasks(Settings& settings) {
|
||||
#endif // !SLIMPELLER
|
||||
}
|
||||
|
||||
bool ValidateViewportMetrics(const ViewportMetrics& metrics) {
|
||||
// Pixel ratio cannot be zero.
|
||||
if (metrics.device_pixel_ratio <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If negative values are passed in.
|
||||
if (metrics.physical_width < 0 || metrics.physical_height < 0 ||
|
||||
metrics.physical_min_width_constraint < 0 ||
|
||||
metrics.physical_max_width_constraint < 0 ||
|
||||
metrics.physical_min_height_constraint < 0 ||
|
||||
metrics.physical_max_height_constraint < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If width is zero and the constraints are tight.
|
||||
if (metrics.physical_width == 0 &&
|
||||
metrics.physical_min_width_constraint ==
|
||||
metrics.physical_max_width_constraint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If not tight constraints, check the width fits in the constraints.
|
||||
if (metrics.physical_min_width_constraint !=
|
||||
metrics.physical_max_width_constraint) {
|
||||
if (metrics.physical_min_width_constraint > metrics.physical_width ||
|
||||
metrics.physical_width > metrics.physical_max_width_constraint) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If height is zero and the constraints are tight.
|
||||
if (metrics.physical_height == 0 &&
|
||||
metrics.physical_min_height_constraint ==
|
||||
metrics.physical_max_height_constraint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If not tight constraints, check the height fits in the constraints.
|
||||
if (metrics.physical_min_height_constraint !=
|
||||
metrics.physical_max_height_constraint) {
|
||||
if (metrics.physical_min_height_constraint > metrics.physical_height ||
|
||||
metrics.physical_height > metrics.physical_max_height_constraint) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::pair<DartVMRef, fml::RefPtr<const DartSnapshot>>
|
||||
@ -1078,8 +1128,7 @@ void Shell::OnPlatformViewSetViewportMetrics(int64_t view_id,
|
||||
FML_DCHECK(is_set_up_);
|
||||
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
|
||||
|
||||
if (metrics.device_pixel_ratio <= 0 || metrics.physical_width <= 0 ||
|
||||
metrics.physical_height <= 0) {
|
||||
if (!ValidateViewportMetrics(metrics)) {
|
||||
// Ignore invalid view-port metrics.
|
||||
return;
|
||||
}
|
||||
@ -1107,8 +1156,12 @@ void Shell::OnPlatformViewSetViewportMetrics(int64_t view_id,
|
||||
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(resize_mutex_);
|
||||
expected_frame_sizes_[view_id] =
|
||||
DlISize(metrics.physical_width, metrics.physical_height);
|
||||
|
||||
expected_frame_constraints_[view_id] =
|
||||
BoxConstraints(Size(metrics.physical_min_width_constraint,
|
||||
metrics.physical_min_height_constraint),
|
||||
Size(metrics.physical_max_width_constraint,
|
||||
metrics.physical_max_height_constraint));
|
||||
device_pixel_ratio_ = metrics.device_pixel_ratio;
|
||||
}
|
||||
}
|
||||
@ -1756,9 +1809,9 @@ fml::TimePoint Shell::GetLatestFrameTargetTime() const {
|
||||
bool Shell::ShouldDiscardLayerTree(int64_t view_id,
|
||||
const flutter::LayerTree& tree) {
|
||||
std::scoped_lock<std::mutex> lock(resize_mutex_);
|
||||
auto expected_frame_size = ExpectedFrameSize(view_id);
|
||||
return !expected_frame_size.IsEmpty() &&
|
||||
tree.frame_size() != expected_frame_size;
|
||||
auto expected_frame_constraints = ExpectedFrameConstraints(view_id);
|
||||
return !expected_frame_constraints.IsSatisfiedBy(
|
||||
Size(tree.frame_size().width, tree.frame_size().height));
|
||||
}
|
||||
|
||||
// |ServiceProtocol::Handler|
|
||||
@ -2169,8 +2222,10 @@ void Shell::OnPlatformViewRemoveView(int64_t view_id,
|
||||
FML_DCHECK(view_id != kFlutterImplicitViewId)
|
||||
<< "Unexpected request to remove the implicit view #"
|
||||
<< kFlutterImplicitViewId << ". This view should never be removed.";
|
||||
|
||||
expected_frame_sizes_.erase(view_id);
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(resize_mutex_);
|
||||
expected_frame_constraints_.erase(view_id);
|
||||
}
|
||||
task_runners_.GetUITaskRunner()->RunNowOrPostTask(
|
||||
task_runners_.GetUITaskRunner(),
|
||||
[&task_runners = task_runners_, //
|
||||
@ -2363,11 +2418,13 @@ Shell::GetConcurrentWorkerTaskRunner() const {
|
||||
return vm_->GetConcurrentWorkerTaskRunner();
|
||||
}
|
||||
|
||||
DlISize Shell::ExpectedFrameSize(int64_t view_id) {
|
||||
auto found = expected_frame_sizes_.find(view_id);
|
||||
if (found == expected_frame_sizes_.end()) {
|
||||
return DlISize();
|
||||
BoxConstraints Shell::ExpectedFrameConstraints(int64_t view_id) {
|
||||
auto found = expected_frame_constraints_.find(view_id);
|
||||
|
||||
if (found == expected_frame_constraints_.end()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return found->second;
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include "flutter/shell/common/rasterizer.h"
|
||||
#include "flutter/shell/common/resource_cache_limit_calculator.h"
|
||||
#include "flutter/shell/common/shell_io_manager.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "impeller/core/runtime_types.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/runtime_stage/runtime_stage.h"
|
||||
@ -511,13 +512,13 @@ class Shell final : public PlatformView::Delegate,
|
||||
/// any of the threads.
|
||||
std::unique_ptr<DisplayManager> display_manager_;
|
||||
|
||||
// protects expected_frame_size_ which is set on platform thread and read on
|
||||
// raster thread
|
||||
// Protects expected_frame_constraints_ which is set on platform thread and
|
||||
// read on raster thread.
|
||||
std::mutex resize_mutex_;
|
||||
|
||||
// used to discard wrong size layer tree produced during interactive
|
||||
// resizing
|
||||
std::unordered_map<int64_t, DlISize> expected_frame_sizes_;
|
||||
// Used to discard wrong size layer tree produced during interactive
|
||||
// resizing.
|
||||
std::unordered_map<int64_t, BoxConstraints> expected_frame_constraints_;
|
||||
|
||||
// Used to communicate the right frame bounds via service protocol.
|
||||
double device_pixel_ratio_ = 0.0;
|
||||
@ -804,7 +805,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
// directory.
|
||||
std::unique_ptr<DirectoryAssetBundle> RestoreOriginalAssetResolver();
|
||||
|
||||
DlISize ExpectedFrameSize(int64_t view_id);
|
||||
BoxConstraints ExpectedFrameConstraints(int64_t view_id);
|
||||
|
||||
// For accessing the Shell via the raster thread, necessary for various
|
||||
// rasterizer callbacks.
|
||||
|
||||
@ -165,6 +165,10 @@ void ShellTest::SetViewportMetrics(Shell* shell, double width, double height) {
|
||||
1, // device pixel ratio
|
||||
width, // physical width
|
||||
height, // physical height
|
||||
0, // min width constraint
|
||||
0, // max width constraint
|
||||
0, // min height constraint
|
||||
0, // max height constraint
|
||||
0, // padding top
|
||||
0, // padding right
|
||||
0, // padding bottom
|
||||
@ -425,5 +429,11 @@ void ShellTest::TurnOffGPU(Shell* shell, bool value) {
|
||||
shell->is_gpu_disabled_sync_switch_->SetSwitch(value);
|
||||
}
|
||||
|
||||
bool ShellTest::ShouldDiscardLayerTree(Shell* shell,
|
||||
int64_t view_id,
|
||||
const flutter::LayerTree& tree) {
|
||||
return shell->ShouldDiscardLayerTree(view_id, tree);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -163,6 +163,10 @@ class ShellTest : public FixtureTest {
|
||||
|
||||
static void TurnOffGPU(Shell* shell, bool value);
|
||||
|
||||
static bool ShouldDiscardLayerTree(Shell* shell,
|
||||
int64_t view_id,
|
||||
const flutter::LayerTree& tree);
|
||||
|
||||
private:
|
||||
ThreadHost thread_host_;
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "flutter/flow/layers/clip_rect_layer.h"
|
||||
#include "flutter/flow/layers/display_list_layer.h"
|
||||
#include "flutter/flow/layers/layer_raster_cache_item.h"
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/flow/layers/platform_view_layer.h"
|
||||
#include "flutter/flow/layers/transform_layer.h"
|
||||
#include "flutter/fml/backtrace.h"
|
||||
@ -5040,6 +5041,72 @@ TEST_F(ShellTest, ReleaseResourceContextWhenIOManagerIsDeleted) {
|
||||
ASSERT_TRUE(called_release_resource_context);
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, ShoulDiscardLayerTreeIfFrameIsSizedIncorrectly) {
|
||||
Settings settings = CreateSettingsForFixture();
|
||||
auto task_runner = CreateNewThread();
|
||||
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
|
||||
task_runner);
|
||||
std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
|
||||
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell]() {
|
||||
shell->GetPlatformView()->SetViewportMetrics(
|
||||
kImplicitViewId,
|
||||
{
|
||||
1.0, // p_device_pixel_ratio
|
||||
500, // p_physical_width
|
||||
800, // p_physical_height
|
||||
1, // p_min_width_constraint,
|
||||
1000, // p_max_width_constraint,
|
||||
1, // p_min_height_constraint,
|
||||
1000, // p_max_height_constraint,
|
||||
0, // p_physical_padding_top
|
||||
0, // p_physical_padding_right
|
||||
0, // p_physical_padding_bottom
|
||||
0, // p_physical_padding_left
|
||||
0, // p_physical_view_inset_top,
|
||||
0, // p_physical_view_inset_right,
|
||||
0, // p_physical_view_inset_bottom,
|
||||
0, // p_physical_view_inset_left,
|
||||
0, // p_physical_system_gesture_inset_top,
|
||||
0, // p_physical_system_gesture_inset_right,
|
||||
0, // p_physical_system_gesture_inset_bottom,
|
||||
0, // p_physical_system_gesture_inset_left,
|
||||
22, // p_physical_touch_slop,
|
||||
{}, // p_physical_display_features_bounds,
|
||||
{}, // p_physical_display_features_type,
|
||||
{}, // p_physical_display_features_state,
|
||||
0 // p_display_id
|
||||
});
|
||||
});
|
||||
PumpOneFrame(shell.get());
|
||||
|
||||
auto layer_tree =
|
||||
std::make_unique<LayerTree>(/*root_layer=*/nullptr,
|
||||
/*frame_size=*/DlISize(100, 100));
|
||||
ASSERT_FALSE(ShellTest::ShouldDiscardLayerTree(shell.get(), kImplicitViewId,
|
||||
*layer_tree));
|
||||
auto over_width =
|
||||
std::make_unique<LayerTree>(/*root_layer=*/nullptr,
|
||||
/*frame_size=*/DlISize(1010, 100));
|
||||
ASSERT_TRUE(ShellTest::ShouldDiscardLayerTree(shell.get(), kImplicitViewId,
|
||||
*over_width));
|
||||
auto over_height =
|
||||
std::make_unique<LayerTree>(/*root_layer=*/nullptr,
|
||||
/*frame_size=*/DlISize(100, 1010));
|
||||
ASSERT_TRUE(ShellTest::ShouldDiscardLayerTree(shell.get(), kImplicitViewId,
|
||||
*over_height));
|
||||
auto min_width = std::make_unique<LayerTree>(/*root_layer=*/nullptr,
|
||||
/*frame_size=*/DlISize(0, 100));
|
||||
ASSERT_TRUE(ShellTest::ShouldDiscardLayerTree(shell.get(), kImplicitViewId,
|
||||
*min_width));
|
||||
auto min_height = std::make_unique<LayerTree>(/*root_layer=*/nullptr,
|
||||
/*frame_size=*/DlISize(100, 0));
|
||||
ASSERT_TRUE(ShellTest::ShouldDiscardLayerTree(shell.get(), kImplicitViewId,
|
||||
*min_height));
|
||||
DestroyShell(std::move(shell), task_runners);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
|
||||
31
engine/src/flutter/shell/geometry/BUILD.gn
Normal file
31
engine/src/flutter/shell/geometry/BUILD.gn
Normal file
@ -0,0 +1,31 @@
|
||||
import("//flutter/common/config.gni")
|
||||
import("//flutter/testing/testing.gni")
|
||||
|
||||
source_set("geometry") {
|
||||
visibility = [
|
||||
":geometry_unittests",
|
||||
"//flutter/shell/common:*",
|
||||
"//flutter/shell/platform/common:*",
|
||||
"//flutter/shell/platform/windows:*",
|
||||
]
|
||||
|
||||
sources = [ "geometry.h" ]
|
||||
}
|
||||
|
||||
if (enable_unittests) {
|
||||
test_fixtures("geometry_fixtures") {
|
||||
fixtures = []
|
||||
}
|
||||
|
||||
executable("geometry_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "geometry_unittests.cc" ]
|
||||
|
||||
deps = [
|
||||
":geometry",
|
||||
":geometry_fixtures",
|
||||
"//flutter/testing",
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_COMMON_GEOMETRY_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_GEOMETRY_H_
|
||||
#ifndef FLUTTER_SHELL_GEOMETRY_GEOMETRY_H_
|
||||
#define FLUTTER_SHELL_GEOMETRY_GEOMETRY_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
@ -93,6 +93,13 @@ class BoxConstraints {
|
||||
Size biggest() const { return biggest_; }
|
||||
Size smallest() const { return smallest_; }
|
||||
|
||||
bool IsSatisfiedBy(Size size) {
|
||||
return smallest().width() <= size.width() &&
|
||||
size.width() <= biggest().width() &&
|
||||
smallest().height() <= size.height() &&
|
||||
size.height() <= biggest().height();
|
||||
}
|
||||
|
||||
private:
|
||||
Size smallest_ = Size(0, 0);
|
||||
Size biggest_ = Size(std::numeric_limits<double>::infinity(),
|
||||
@ -101,4 +108,4 @@ class BoxConstraints {
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_GEOMETRY_H_
|
||||
#endif // FLUTTER_SHELL_GEOMETRY_GEOMETRY_H_
|
||||
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@ -367,27 +367,38 @@ static void SetViewportMetrics(JNIEnv* env,
|
||||
env->GetIntArrayRegion(javaDisplayFeaturesState, 0, stateSize,
|
||||
&displayFeaturesState[0]);
|
||||
|
||||
// TODO(boetger): update for https://github.com/flutter/flutter/issues/149033
|
||||
const flutter::ViewportMetrics metrics{
|
||||
static_cast<double>(devicePixelRatio),
|
||||
static_cast<double>(physicalWidth),
|
||||
static_cast<double>(physicalHeight),
|
||||
static_cast<double>(physicalPaddingTop),
|
||||
static_cast<double>(physicalPaddingRight),
|
||||
static_cast<double>(physicalPaddingBottom),
|
||||
static_cast<double>(physicalPaddingLeft),
|
||||
static_cast<double>(physicalViewInsetTop),
|
||||
static_cast<double>(physicalViewInsetRight),
|
||||
static_cast<double>(physicalViewInsetBottom),
|
||||
static_cast<double>(physicalViewInsetLeft),
|
||||
static_cast<double>(systemGestureInsetTop),
|
||||
static_cast<double>(systemGestureInsetRight),
|
||||
static_cast<double>(systemGestureInsetBottom),
|
||||
static_cast<double>(systemGestureInsetLeft),
|
||||
static_cast<double>(physicalTouchSlop),
|
||||
displayFeaturesBounds,
|
||||
displayFeaturesType,
|
||||
displayFeaturesState,
|
||||
0, // Display ID
|
||||
static_cast<double>(devicePixelRatio), // p_device_pixel_ratio
|
||||
static_cast<double>(physicalWidth), // p_physical_width
|
||||
static_cast<double>(physicalHeight), // p_physical_height
|
||||
static_cast<double>(physicalWidth), // p_physical_min_width_constraint
|
||||
static_cast<double>(physicalWidth), // p_physical_max_width_constraint
|
||||
static_cast<double>(physicalHeight), // p_physical_min_height_constraint
|
||||
static_cast<double>(physicalHeight), // p_physical_max_height_constraint
|
||||
static_cast<double>(physicalPaddingTop), // p_physical_padding_top
|
||||
static_cast<double>(physicalPaddingRight), // p_physical_padding_right
|
||||
static_cast<double>(physicalPaddingBottom), // p_physical_padding_bottom
|
||||
static_cast<double>(physicalPaddingLeft), // p_physical_padding_left
|
||||
static_cast<double>(physicalViewInsetTop), // p_physical_view_inset_top
|
||||
static_cast<double>(
|
||||
physicalViewInsetRight), // p_physical_view_inset_right
|
||||
static_cast<double>(
|
||||
physicalViewInsetBottom), // p_physical_view_inset_bottom
|
||||
static_cast<double>(physicalViewInsetLeft), // p_physical_view_inset_left
|
||||
static_cast<double>(
|
||||
systemGestureInsetTop), // p_physical_system_gesture_inset_top
|
||||
static_cast<double>(
|
||||
systemGestureInsetRight), // p_physical_system_gesture_inset_right
|
||||
static_cast<double>(
|
||||
systemGestureInsetBottom), // p_physical_system_gesture_inset_bottom
|
||||
static_cast<double>(
|
||||
systemGestureInsetLeft), // p_physical_system_gesture_inset_left
|
||||
static_cast<double>(physicalTouchSlop), // p_physical_touch_slop
|
||||
displayFeaturesBounds, // p_physical_display_features_bounds
|
||||
displayFeaturesType, // p_physical_display_features_type
|
||||
displayFeaturesState, // p_physical_display_features_state
|
||||
0, // p_display_id
|
||||
};
|
||||
|
||||
ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(
|
||||
|
||||
@ -150,7 +150,6 @@ source_set("common_cpp") {
|
||||
# API surface there will be.
|
||||
source_set("common_cpp_core") {
|
||||
public = [
|
||||
"geometry.h",
|
||||
"path_utils.h",
|
||||
"windowing.h",
|
||||
]
|
||||
@ -159,7 +158,10 @@ source_set("common_cpp_core") {
|
||||
|
||||
public_configs = [ "//flutter:config" ]
|
||||
|
||||
deps = [ "//flutter/fml:fml" ]
|
||||
deps = [
|
||||
"//flutter/fml:fml",
|
||||
"//flutter/shell/geometry:geometry",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_unittests) {
|
||||
@ -191,7 +193,6 @@ if (enable_unittests) {
|
||||
|
||||
sources = [
|
||||
"engine_switches_unittests.cc",
|
||||
"geometry_unittests.cc",
|
||||
"incoming_message_dispatcher_unittests.cc",
|
||||
"json_message_codec_unittests.cc",
|
||||
"json_method_codec_unittests.cc",
|
||||
|
||||
@ -1478,6 +1478,11 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch)
|
||||
CGFloat scale = screen.scale;
|
||||
_viewportMetrics.physical_width = self.view.bounds.size.width * scale;
|
||||
_viewportMetrics.physical_height = self.view.bounds.size.height * scale;
|
||||
// TODO(louisehsu): update for https://github.com/flutter/flutter/issues/169147
|
||||
_viewportMetrics.physical_min_width_constraint = _viewportMetrics.physical_width;
|
||||
_viewportMetrics.physical_max_width_constraint = _viewportMetrics.physical_width;
|
||||
_viewportMetrics.physical_min_height_constraint = _viewportMetrics.physical_height;
|
||||
_viewportMetrics.physical_max_height_constraint = _viewportMetrics.physical_height;
|
||||
}
|
||||
|
||||
// Set _viewportMetrics physical paddings.
|
||||
|
||||
@ -1649,6 +1649,11 @@ MakeViewportMetricsFromWindowMetrics(
|
||||
"physical height or width.";
|
||||
}
|
||||
|
||||
metrics.physical_min_width_constraint = metrics.physical_width;
|
||||
metrics.physical_max_width_constraint = metrics.physical_width;
|
||||
metrics.physical_min_height_constraint = metrics.physical_height;
|
||||
metrics.physical_max_height_constraint = metrics.physical_height;
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
|
||||
@ -342,6 +342,14 @@ void PlatformView::OnGetLayout(fuchsia::ui::composition::LayoutInfo info) {
|
||||
pixel_ratio), // physical_width
|
||||
std::round(view_logical_size_.value()[1] *
|
||||
pixel_ratio), // physical_height
|
||||
std::round(view_logical_size_.value()[0] *
|
||||
pixel_ratio), // physical_min_width_constraint
|
||||
std::round(view_logical_size_.value()[0] *
|
||||
pixel_ratio), // physical_max_width_constraint
|
||||
std::round(view_logical_size_.value()[1] *
|
||||
pixel_ratio), // physical_min_height_constraint
|
||||
std::round(view_logical_size_.value()[1] *
|
||||
pixel_ratio), // physical_max_height_constraint
|
||||
0.0f, // physical_padding_top
|
||||
0.0f, // physical_padding_right
|
||||
0.0f, // physical_padding_bottom
|
||||
|
||||
@ -165,6 +165,7 @@ source_set("flutter_windows_source") {
|
||||
":flutter_windows_headers",
|
||||
"//flutter/fml:fml",
|
||||
"//flutter/impeller/renderer/backend/gles",
|
||||
"//flutter/shell/geometry:geometry",
|
||||
"//flutter/shell/platform/common:common_cpp",
|
||||
"//flutter/shell/platform/common:common_cpp_input",
|
||||
"//flutter/shell/platform/common:common_cpp_isolate_scope",
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/common/alert_platform_node_delegate.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/direct_manipulation.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_view.h"
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <optional>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/common/windowing.h"
|
||||
#include "flutter/shell/platform/windows/window_manager.h"
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
|
||||
@ -10,9 +10,9 @@
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h"
|
||||
#include "flutter/shell/platform/common/client_wrapper/include/flutter/method_channel.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/platform/common/json_method_codec.h"
|
||||
#include "flutter/shell/platform/common/text_editing_delta.h"
|
||||
#include "flutter/shell/platform/common/text_input_model.h"
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/common/alert_platform_node_delegate.h"
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/public/flutter_windows.h"
|
||||
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/geometry/geometry.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/windows_lifecycle_manager.h"
|
||||
#include "flutter/third_party/accessibility/ax/platform/ax_fragment_root_delegate_win.h"
|
||||
|
||||
@ -140,6 +140,10 @@ static void ConfigureShell(Shell* shell) {
|
||||
metrics.physical_width = physical_width;
|
||||
metrics.physical_height = physical_height;
|
||||
metrics.display_id = 0;
|
||||
metrics.physical_min_width_constraint = physical_width;
|
||||
metrics.physical_max_width_constraint = physical_width;
|
||||
metrics.physical_min_height_constraint = physical_height;
|
||||
metrics.physical_max_height_constraint = physical_height;
|
||||
shell->GetPlatformView()->SetViewportMetrics(kImplicitViewId, metrics);
|
||||
}
|
||||
|
||||
|
||||
@ -431,6 +431,7 @@ def run_cc_tests(build_dir, executable_filter, coverage, capture_core_dump):
|
||||
make_test('embedder_proctable_unittests'),
|
||||
make_test('embedder_unittests'),
|
||||
make_test('fml_unittests'),
|
||||
make_test('geometry_unittests'),
|
||||
make_test('no_dart_plugin_registrant_unittests'),
|
||||
make_test('runtime_unittests'),
|
||||
make_test('testing_unittests'),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user