Revert "Reland Display Features support (Foldable and Cutout) (#29447)" (flutter/engine#29574)
This reverts commit 28a1c9b21b.
This commit is contained in:
2
DEPS
2
DEPS
@@ -570,7 +570,7 @@ deps = {
|
||||
'packages': [
|
||||
{
|
||||
'package': 'flutter/android/embedding_bundle',
|
||||
'version': 'last_updated:2021-11-03T10:29:50-0700'
|
||||
'version': 'last_updated:2021-10-28T23:34:47-0700'
|
||||
}
|
||||
],
|
||||
'condition': 'download_android_deps',
|
||||
|
||||
@@ -832,7 +832,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Rende
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreen.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreenProvider.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/TransparencyMode.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/WindowInfoRepositoryCallbackAdapterWrapper.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineCache.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java
|
||||
|
||||
@@ -339,7 +339,7 @@ void hooksTests() {
|
||||
window.onMetricsChanged!();
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
0.1234, // device pixel ratio
|
||||
0.0, // width
|
||||
@@ -355,11 +355,8 @@ void hooksTests() {
|
||||
0.0, // system gesture inset top
|
||||
0.0, // system gesture inset right
|
||||
0.0, // system gesture inset bottom
|
||||
0.0, // system gesture inset left
|
||||
0.0, // system gesture inset left,
|
||||
22.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectIdentical(originalZone, callbackZone);
|
||||
@@ -406,7 +403,7 @@ void hooksTests() {
|
||||
test('Window padding/insets/viewPadding/systemGestureInsets', () {
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@@ -424,9 +421,6 @@ void hooksTests() {
|
||||
0.0, // systemGestureInsetBottom
|
||||
0.0, // systemGestureInsetLeft
|
||||
22.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectEquals(window.viewInsets.bottom, 0.0);
|
||||
@@ -436,7 +430,7 @@ void hooksTests() {
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@@ -454,9 +448,6 @@ void hooksTests() {
|
||||
44.0, // systemGestureInsetBottom
|
||||
0.0, // systemGestureInsetLeft
|
||||
22.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectEquals(window.viewInsets.bottom, 400.0);
|
||||
@@ -468,7 +459,7 @@ void hooksTests() {
|
||||
test('Window physical touch slop', () {
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@@ -486,9 +477,6 @@ void hooksTests() {
|
||||
0.0, // systemGestureInsetBottom
|
||||
0.0, // systemGestureInsetLeft
|
||||
11.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectEquals(window.viewConfiguration.gestureSettings,
|
||||
@@ -496,7 +484,7 @@ void hooksTests() {
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@@ -514,9 +502,6 @@ void hooksTests() {
|
||||
44.0, // systemGestureInsetBottom
|
||||
0.0, // systemGestureInsetLeft
|
||||
-1.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectEquals(window.viewConfiguration.gestureSettings,
|
||||
@@ -524,7 +509,7 @@ void hooksTests() {
|
||||
|
||||
_callHook(
|
||||
'_updateWindowMetrics',
|
||||
20,
|
||||
17,
|
||||
0, // window Id
|
||||
1.0, // devicePixelRatio
|
||||
800.0, // width
|
||||
@@ -542,9 +527,6 @@ void hooksTests() {
|
||||
44.0, // systemGestureInsetBottom
|
||||
0.0, // systemGestureInsetLeft
|
||||
22.0, // physicalTouchSlop
|
||||
<double>[], // display features bounds
|
||||
<int>[], // display features types
|
||||
<int>[], // display features states
|
||||
);
|
||||
|
||||
expectEquals(window.viewConfiguration.gestureSettings,
|
||||
@@ -770,7 +752,4 @@ void _callHook(
|
||||
Object? arg15,
|
||||
Object? arg16,
|
||||
Object? arg17,
|
||||
Object? arg18,
|
||||
Object? arg19,
|
||||
Object? arg20,
|
||||
]) native 'CallHook';
|
||||
|
||||
@@ -26,9 +26,6 @@ void _updateWindowMetrics(
|
||||
double systemGestureInsetBottom,
|
||||
double systemGestureInsetLeft,
|
||||
double physicalTouchSlop,
|
||||
List<double> displayFeaturesBounds,
|
||||
List<int> displayFeaturesType,
|
||||
List<int> displayFeaturesState,
|
||||
) {
|
||||
PlatformDispatcher.instance._updateWindowMetrics(
|
||||
id,
|
||||
@@ -48,9 +45,6 @@ void _updateWindowMetrics(
|
||||
systemGestureInsetBottom,
|
||||
systemGestureInsetLeft,
|
||||
physicalTouchSlop,
|
||||
displayFeaturesBounds,
|
||||
displayFeaturesType,
|
||||
displayFeaturesState,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -183,9 +183,6 @@ class PlatformDispatcher {
|
||||
double systemGestureInsetBottom,
|
||||
double systemGestureInsetLeft,
|
||||
double physicalTouchSlop,
|
||||
List<double> displayFeaturesBounds,
|
||||
List<int> displayFeaturesType,
|
||||
List<int> displayFeaturesState,
|
||||
) {
|
||||
final ViewConfiguration previousConfiguration =
|
||||
_viewConfigurations[id] ?? const ViewConfiguration();
|
||||
@@ -224,43 +221,10 @@ class PlatformDispatcher {
|
||||
gestureSettings: GestureSettings(
|
||||
physicalTouchSlop: physicalTouchSlop == _kUnsetGestureSetting ? null : physicalTouchSlop,
|
||||
),
|
||||
displayFeatures: _decodeDisplayFeatures(
|
||||
bounds: displayFeaturesBounds,
|
||||
type: displayFeaturesType,
|
||||
state: displayFeaturesState,
|
||||
devicePixelRatio: devicePixelRatio,
|
||||
),
|
||||
);
|
||||
_invoke(onMetricsChanged, _onMetricsChangedZone);
|
||||
}
|
||||
|
||||
List<DisplayFeature> _decodeDisplayFeatures({
|
||||
required List<double> bounds,
|
||||
required List<int> type,
|
||||
required List<int> state,
|
||||
required double devicePixelRatio,
|
||||
}) {
|
||||
assert(bounds.length / 4 == type.length, 'Bounds are rectangles, requiring 4 measurements each');
|
||||
assert(type.length == state.length);
|
||||
final List<DisplayFeature> result = <DisplayFeature>[];
|
||||
for(int i = 0; i < type.length; i++){
|
||||
final int rectOffset = i * 4;
|
||||
result.add(DisplayFeature(
|
||||
bounds: Rect.fromLTRB(
|
||||
bounds[rectOffset] / devicePixelRatio,
|
||||
bounds[rectOffset + 1] / devicePixelRatio,
|
||||
bounds[rectOffset + 2] / devicePixelRatio,
|
||||
bounds[rectOffset + 3] / devicePixelRatio,
|
||||
),
|
||||
type: DisplayFeatureType.values[type[i]],
|
||||
state: state[i] < DisplayFeatureState.values.length
|
||||
? DisplayFeatureState.values[state[i]]
|
||||
: DisplayFeatureState.unknown,
|
||||
));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// A callback invoked when any view begins a frame.
|
||||
///
|
||||
/// A callback that is invoked to notify the application that it is an
|
||||
@@ -1071,7 +1035,6 @@ class ViewConfiguration {
|
||||
this.systemGestureInsets = WindowPadding.zero,
|
||||
this.padding = WindowPadding.zero,
|
||||
this.gestureSettings = const GestureSettings(),
|
||||
this.displayFeatures = const <DisplayFeature>[],
|
||||
});
|
||||
|
||||
/// Copy this configuration with some fields replaced.
|
||||
@@ -1084,8 +1047,7 @@ class ViewConfiguration {
|
||||
WindowPadding? viewPadding,
|
||||
WindowPadding? systemGestureInsets,
|
||||
WindowPadding? padding,
|
||||
GestureSettings? gestureSettings,
|
||||
List<DisplayFeature>? displayFeatures,
|
||||
GestureSettings? gestureSettings
|
||||
}) {
|
||||
return ViewConfiguration(
|
||||
window: window ?? this.window,
|
||||
@@ -1097,7 +1059,6 @@ class ViewConfiguration {
|
||||
systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets,
|
||||
padding: padding ?? this.padding,
|
||||
gestureSettings: gestureSettings ?? this.gestureSettings,
|
||||
displayFeatures: displayFeatures ?? this.displayFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1177,26 +1138,6 @@ class ViewConfiguration {
|
||||
/// touch slop constant.
|
||||
final GestureSettings gestureSettings;
|
||||
|
||||
/// {@template dart.ui.ViewConfiguration.displayFeatures}
|
||||
/// Areas of the display that are obstructed by hardware features.
|
||||
///
|
||||
/// This list is populated only on Android. If the device has no display
|
||||
/// features, this list is empty.
|
||||
///
|
||||
/// The coordinate space in which the [DisplayFeature.bounds] are defined spans
|
||||
/// across the screens currently in use. This means that the space between the screens
|
||||
/// is virtually part of the Flutter view space, with the [DisplayFeature.bounds]
|
||||
/// of the display feature as an obstructed area. The [DisplayFeature.type] can
|
||||
/// be used to determine if this display feature obstructs the screen or not.
|
||||
/// For example, [DisplayFeatureType.hinge] and [DisplayFeatureType.cutout] both
|
||||
/// obstruct the display, while [DisplayFeatureType.fold] is a crease in the display.
|
||||
///
|
||||
/// Folding [DisplayFeature]s like the [DisplayFeatureType.hinge] and
|
||||
/// [DisplayFeatureType.fold] also have a [DisplayFeature.state] which can be
|
||||
/// used to determine the posture the device is in.
|
||||
/// {@endtemplate}
|
||||
final List<DisplayFeature> displayFeatures;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$runtimeType[window: $window, geometry: $geometry]';
|
||||
@@ -1502,134 +1443,6 @@ class WindowPadding {
|
||||
}
|
||||
}
|
||||
|
||||
/// Area of the display that may be obstructed by a hardware feature.
|
||||
///
|
||||
/// This is populated only on Android.
|
||||
///
|
||||
/// The [bounds] are measured in logical pixels. On devices with two screens the
|
||||
/// coordinate system starts with [0,0] in the top-left corner of the left or top screen
|
||||
/// and expands to include both screens and the visual space between them.
|
||||
///
|
||||
/// The [type] describes the behaviour and if [DisplayFeature] obstructs the display.
|
||||
/// For example, [DisplayFeatureType.hinge] and [DisplayFeatureType.cutout] both obstruct the display,
|
||||
/// while [DisplayFeatureType.fold] does not.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// The [state] contains information about the posture for foldable features
|
||||
/// ([DisplayFeatureType.hinge] and [DisplayFeatureType.fold]). The posture is
|
||||
/// the shape of the display, for example [DisplayFeatureState.postureFlat] or
|
||||
/// [DisplayFeatureState.postureHalfOpened]. For [DisplayFeatureType.cutout],
|
||||
/// the state is not used and has the [DisplayFeatureState.unknown] value.
|
||||
class DisplayFeature {
|
||||
const DisplayFeature({
|
||||
required this.bounds,
|
||||
required this.type,
|
||||
required this.state,
|
||||
}) : assert(!identical(type, DisplayFeatureType.cutout) || identical(state, DisplayFeatureState.unknown));
|
||||
|
||||
/// The area of the flutter view occupied by this display feature, measured in logical pixels.
|
||||
///
|
||||
/// On devices with two screens, the Flutter view spans from the top-left corner
|
||||
/// of the left or top screen to the bottom-right corner of the right or bottom screen,
|
||||
/// including the visual area occupied by any display feature. Bounds of display
|
||||
/// features are reported in this coordinate system.
|
||||
///
|
||||
/// For example, on a dual screen device in portrait mode:
|
||||
///
|
||||
/// * [bounds.left] gives you the size of left screen, in logical pixels.
|
||||
/// * [bounds.right] gives you the size of the left screen + the hinge width.
|
||||
final Rect bounds;
|
||||
|
||||
/// Type of display feature, e.g. hinge, fold, cutout.
|
||||
final DisplayFeatureType type;
|
||||
|
||||
/// Posture of display feature, which is populated only for folds and hinges.
|
||||
///
|
||||
/// For cutouts, this is [DisplayFeatureState.unknown]
|
||||
final DisplayFeatureState state;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
return other is DisplayFeature && bounds == other.bounds &&
|
||||
type == other.type && state == other.state;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(bounds, type, state);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DisplayFeature(rect: $bounds, type: $type, state: $state)';
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of [DisplayFeature], describing the [DisplayFeature] behaviour and if
|
||||
/// it obstructs the display.
|
||||
///
|
||||
/// Some types of [DisplayFeature], like [DisplayFeatureType.fold], can be
|
||||
/// reported without actually impeding drawing on the screen. They are useful
|
||||
/// for knowing where the display is bent or has a crease. The
|
||||
/// [DisplayFeature.bounds] can be 0-width in such cases.
|
||||
///
|
||||
/// The shape formed by the screens for types [DisplayFeatureType.fold] and
|
||||
/// [DisplayFeatureType.hinge] is called the posture and is exposed in
|
||||
/// [DisplayFeature.state]. For example, the [DisplayFeatureState.postureFlat] posture
|
||||
/// means the screens form a flat surface, while [DisplayFeatureState.postureFlipped]
|
||||
/// posture means the screens are facing opposite directions.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 
|
||||
enum DisplayFeatureType {
|
||||
/// [DisplayFeature] type is new and not yet known to Flutter.
|
||||
unknown,
|
||||
/// A fold in the flexible screen without a physical gap.
|
||||
///
|
||||
/// The bounds for this display feature type indicate where the display makes a crease.
|
||||
fold,
|
||||
/// A physical separation with a hinge that allows two display panels to fold.
|
||||
hinge,
|
||||
/// A non-displaying area of the screen, usually housing cameras or sensors.
|
||||
cutout,
|
||||
}
|
||||
|
||||
/// State of the display feature, which contains information about the posture
|
||||
/// for foldable features.
|
||||
///
|
||||
/// The posture is the shape made by the parts of the flexible screen or
|
||||
/// physical screen panels. They are inspired by and similar to
|
||||
/// [Android Postures](https://developer.android.com/guide/topics/ui/foldables#postures).
|
||||
///
|
||||
/// * For [DisplayFeatureType.fold]s & [DisplayFeatureType.hinge]s, the state is
|
||||
/// the posture.
|
||||
/// * For [DisplayFeatureType.cutout]s, the state is not used and has the
|
||||
/// [DisplayFeatureState.unknown] value.
|
||||
enum DisplayFeatureState {
|
||||
/// The display feature is a [DisplayFeatureType.cutout] or this state is new
|
||||
/// and not yet known to Flutter.
|
||||
unknown,
|
||||
/// The foldable device is completely open.
|
||||
///
|
||||
/// The screen space that is presented to the user is flat.
|
||||
postureFlat,
|
||||
/// Fold angle is in an intermediate position between opened and closed state.
|
||||
///
|
||||
/// There is a non-flat angle between parts of the flexible screen or between
|
||||
/// physical screen panels such that the screens start to face each other.
|
||||
postureHalfOpened,
|
||||
}
|
||||
|
||||
/// An identifier used to select a user's language and formatting preferences.
|
||||
///
|
||||
/// This represents a [Unicode Language
|
||||
|
||||
@@ -225,17 +225,6 @@ abstract class FlutterView {
|
||||
/// applications.
|
||||
WindowPadding get padding => viewConfiguration.padding;
|
||||
|
||||
/// {@macro dart.ui.ViewConfiguration.displayFeatures}
|
||||
///
|
||||
/// When this changes, [onMetricsChanged] is called.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [WidgetsBindingObserver], for a mechanism at the widgets layer to
|
||||
/// observe when this value changes.
|
||||
/// * [MediaQuery.of], a simpler mechanism to access this data.
|
||||
List<DisplayFeature> get displayFeatures => viewConfiguration.displayFeatures;
|
||||
|
||||
/// Updates the view's rendering on the GPU with the newly provided [Scene].
|
||||
///
|
||||
/// This function must be called within the scope of the
|
||||
|
||||
@@ -19,26 +19,22 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
physical_height(p_physical_height),
|
||||
physical_touch_slop(p_physical_touch_slop) {}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(
|
||||
double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
double p_physical_padding_top,
|
||||
double p_physical_padding_right,
|
||||
double p_physical_padding_bottom,
|
||||
double p_physical_padding_left,
|
||||
double p_physical_view_inset_top,
|
||||
double p_physical_view_inset_right,
|
||||
double p_physical_view_inset_bottom,
|
||||
double p_physical_view_inset_left,
|
||||
double p_physical_system_gesture_inset_top,
|
||||
double p_physical_system_gesture_inset_right,
|
||||
double p_physical_system_gesture_inset_bottom,
|
||||
double p_physical_system_gesture_inset_left,
|
||||
double p_physical_touch_slop,
|
||||
const std::vector<double> p_physical_display_features_bounds,
|
||||
const std::vector<int> p_physical_display_features_type,
|
||||
const std::vector<int> p_physical_display_features_state)
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
double p_physical_padding_top,
|
||||
double p_physical_padding_right,
|
||||
double p_physical_padding_bottom,
|
||||
double p_physical_padding_left,
|
||||
double p_physical_view_inset_top,
|
||||
double p_physical_view_inset_right,
|
||||
double p_physical_view_inset_bottom,
|
||||
double p_physical_view_inset_left,
|
||||
double p_physical_system_gesture_inset_top,
|
||||
double p_physical_system_gesture_inset_right,
|
||||
double p_physical_system_gesture_inset_bottom,
|
||||
double p_physical_system_gesture_inset_left,
|
||||
double p_physical_touch_slop)
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height),
|
||||
@@ -56,10 +52,7 @@ ViewportMetrics::ViewportMetrics(
|
||||
physical_system_gesture_inset_bottom(
|
||||
p_physical_system_gesture_inset_bottom),
|
||||
physical_system_gesture_inset_left(p_physical_system_gesture_inset_left),
|
||||
physical_touch_slop(p_physical_touch_slop),
|
||||
physical_display_features_bounds(p_physical_display_features_bounds),
|
||||
physical_display_features_type(p_physical_display_features_type),
|
||||
physical_display_features_state(p_physical_display_features_state) {}
|
||||
physical_touch_slop(p_physical_touch_slop) {}
|
||||
|
||||
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
|
||||
return a.device_pixel_ratio == b.device_pixel_ratio &&
|
||||
@@ -81,11 +74,7 @@ bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
|
||||
b.physical_system_gesture_inset_bottom &&
|
||||
a.physical_system_gesture_inset_left ==
|
||||
b.physical_system_gesture_inset_left &&
|
||||
a.physical_touch_slop == b.physical_touch_slop &&
|
||||
a.physical_display_features_bounds ==
|
||||
b.physical_display_features_bounds &&
|
||||
a.physical_display_features_type == b.physical_display_features_type &&
|
||||
a.physical_display_features_state == b.physical_display_features_state;
|
||||
a.physical_touch_slop == b.physical_touch_slop;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
|
||||
@@ -100,8 +89,7 @@ std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
|
||||
<< "Gesture Insets: [" << a.physical_system_gesture_inset_top << "T "
|
||||
<< a.physical_system_gesture_inset_right << "R "
|
||||
<< a.physical_system_gesture_inset_bottom << "B "
|
||||
<< a.physical_system_gesture_inset_left << "L] "
|
||||
<< "Display Features: " << a.physical_display_features_type.size();
|
||||
<< a.physical_system_gesture_inset_left << "L]";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -31,10 +30,7 @@ struct ViewportMetrics {
|
||||
double p_physical_system_gesture_inset_right,
|
||||
double p_physical_system_gesture_inset_bottom,
|
||||
double p_physical_system_gesture_inset_left,
|
||||
double p_physical_touch_slop,
|
||||
const std::vector<double> p_physical_display_features_bounds,
|
||||
const std::vector<int> p_physical_display_features_type,
|
||||
const std::vector<int> p_physical_display_features_state);
|
||||
double p_physical_touch_slop);
|
||||
|
||||
double device_pixel_ratio = 1.0;
|
||||
double physical_width = 0;
|
||||
@@ -52,9 +48,6 @@ struct ViewportMetrics {
|
||||
double physical_system_gesture_inset_bottom = 0;
|
||||
double physical_system_gesture_inset_left = 0;
|
||||
double physical_touch_slop = -1.0;
|
||||
std::vector<double> physical_display_features_bounds;
|
||||
std::vector<int> physical_display_features_type;
|
||||
std::vector<int> physical_display_features_state;
|
||||
};
|
||||
|
||||
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b);
|
||||
|
||||
@@ -64,28 +64,22 @@ void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_updateWindowMetrics",
|
||||
{
|
||||
tonic::ToDart(window_id_),
|
||||
tonic::ToDart(metrics.device_pixel_ratio),
|
||||
tonic::ToDart(metrics.physical_width),
|
||||
tonic::ToDart(metrics.physical_height),
|
||||
tonic::ToDart(metrics.physical_padding_top),
|
||||
tonic::ToDart(metrics.physical_padding_right),
|
||||
tonic::ToDart(metrics.physical_padding_bottom),
|
||||
tonic::ToDart(metrics.physical_padding_left),
|
||||
tonic::ToDart(metrics.physical_view_inset_top),
|
||||
tonic::ToDart(metrics.physical_view_inset_right),
|
||||
tonic::ToDart(metrics.physical_view_inset_bottom),
|
||||
tonic::ToDart(metrics.physical_view_inset_left),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_top),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_right),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_bottom),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_left),
|
||||
tonic::ToDart(metrics.physical_touch_slop),
|
||||
tonic::ToDart(metrics.physical_display_features_bounds),
|
||||
tonic::ToDart(metrics.physical_display_features_type),
|
||||
tonic::ToDart(metrics.physical_display_features_state),
|
||||
}));
|
||||
{tonic::ToDart(window_id_), tonic::ToDart(metrics.device_pixel_ratio),
|
||||
tonic::ToDart(metrics.physical_width),
|
||||
tonic::ToDart(metrics.physical_height),
|
||||
tonic::ToDart(metrics.physical_padding_top),
|
||||
tonic::ToDart(metrics.physical_padding_right),
|
||||
tonic::ToDart(metrics.physical_padding_bottom),
|
||||
tonic::ToDart(metrics.physical_padding_left),
|
||||
tonic::ToDart(metrics.physical_view_inset_top),
|
||||
tonic::ToDart(metrics.physical_view_inset_right),
|
||||
tonic::ToDart(metrics.physical_view_inset_bottom),
|
||||
tonic::ToDart(metrics.physical_view_inset_left),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_top),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_right),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_bottom),
|
||||
tonic::ToDart(metrics.physical_system_gesture_inset_left),
|
||||
tonic::ToDart(metrics.physical_touch_slop)}));
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@@ -156,7 +156,6 @@ class ViewConfiguration {
|
||||
this.systemGestureInsets = WindowPadding.zero,
|
||||
this.padding = WindowPadding.zero,
|
||||
this.gestureSettings = const GestureSettings(),
|
||||
this.displayFeatures = const <DisplayFeature>[],
|
||||
});
|
||||
|
||||
ViewConfiguration copyWith({
|
||||
@@ -169,7 +168,6 @@ class ViewConfiguration {
|
||||
WindowPadding? systemGestureInsets,
|
||||
WindowPadding? padding,
|
||||
GestureSettings? gestureSettings,
|
||||
List<DisplayFeature>? displayFeatures,
|
||||
}) {
|
||||
return ViewConfiguration(
|
||||
window: window ?? this.window,
|
||||
@@ -181,7 +179,6 @@ class ViewConfiguration {
|
||||
systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets,
|
||||
padding: padding ?? this.padding,
|
||||
gestureSettings: gestureSettings ?? this.gestureSettings,
|
||||
displayFeatures: displayFeatures ?? this.displayFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -194,7 +191,6 @@ class ViewConfiguration {
|
||||
final WindowPadding systemGestureInsets;
|
||||
final WindowPadding padding;
|
||||
final GestureSettings gestureSettings;
|
||||
final List<DisplayFeature> displayFeatures;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -329,50 +325,6 @@ abstract class WindowPadding {
|
||||
}
|
||||
}
|
||||
|
||||
class DisplayFeature {
|
||||
const DisplayFeature({
|
||||
required this.bounds,
|
||||
required this.type,
|
||||
required this.state,
|
||||
});
|
||||
|
||||
final Rect bounds;
|
||||
final DisplayFeatureType type;
|
||||
final DisplayFeatureState state;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
return other is DisplayFeature && bounds == other.bounds &&
|
||||
type == other.type && state == other.state;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(bounds, type, state);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DisplayFeature(rect: $bounds, type: $type, state: $state)';
|
||||
}
|
||||
}
|
||||
|
||||
enum DisplayFeatureType {
|
||||
unknown,
|
||||
fold,
|
||||
hinge,
|
||||
cutout,
|
||||
}
|
||||
|
||||
enum DisplayFeatureState {
|
||||
unknown,
|
||||
postureFlat,
|
||||
postureHalfOpened,
|
||||
postureFlipped,
|
||||
}
|
||||
|
||||
class Locale {
|
||||
const Locale(
|
||||
this._languageCode, [
|
||||
|
||||
@@ -14,7 +14,6 @@ abstract class FlutterView {
|
||||
WindowPadding get viewPadding => viewConfiguration.viewPadding;
|
||||
WindowPadding get systemGestureInsets => viewConfiguration.systemGestureInsets;
|
||||
WindowPadding get padding => viewConfiguration.padding;
|
||||
List<DisplayFeature> get displayFeatures => viewConfiguration.displayFeatures;
|
||||
void render(Scene scene) => platformDispatcher.render(scene, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,25 +111,22 @@ void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
|
||||
|
||||
void ShellTest::SetViewportMetrics(Shell* shell, double width, double height) {
|
||||
flutter::ViewportMetrics viewport_metrics = {
|
||||
1, // device pixel ratio
|
||||
width, // physical width
|
||||
height, // physical height
|
||||
0, // padding top
|
||||
0, // padding right
|
||||
0, // padding bottom
|
||||
0, // padding left
|
||||
0, // view inset top
|
||||
0, // view inset right
|
||||
0, // view inset bottom
|
||||
0, // view inset left
|
||||
0, // gesture inset top
|
||||
0, // gesture inset right
|
||||
0, // gesture inset bottom
|
||||
0, // gesture inset left
|
||||
22, // physical touch slop
|
||||
std::vector<double>(), // display features bounds
|
||||
std::vector<int>(), // display features type
|
||||
std::vector<int>() // display features state
|
||||
1, // device pixel ratio
|
||||
width, // physical width
|
||||
height, // physical height
|
||||
0, // padding top
|
||||
0, // padding right
|
||||
0, // padding bottom
|
||||
0, // padding left
|
||||
0, // view inset top
|
||||
0, // view inset right
|
||||
0, // view inset bottom
|
||||
0, // view inset left
|
||||
0, // gesture inset top
|
||||
0, // gesture inset right
|
||||
0, // gesture inset bottom
|
||||
0, // gesture inset left
|
||||
22 // physical touch slop
|
||||
};
|
||||
// Set viewport to nonempty, and call Animator::BeginFrame to make the layer
|
||||
// tree pipeline nonempty. Without either of this, the layer tree below
|
||||
|
||||
@@ -179,7 +179,6 @@ android_java_sources = [
|
||||
"io/flutter/embedding/android/SplashScreen.java",
|
||||
"io/flutter/embedding/android/SplashScreenProvider.java",
|
||||
"io/flutter/embedding/android/TransparencyMode.java",
|
||||
"io/flutter/embedding/android/WindowInfoRepositoryCallbackAdapterWrapper.java",
|
||||
"io/flutter/embedding/engine/FlutterEngine.java",
|
||||
"io/flutter/embedding/engine/FlutterEngineCache.java",
|
||||
"io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java",
|
||||
|
||||
@@ -6,7 +6,6 @@ package io.flutter.embedding.android;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Insets;
|
||||
@@ -36,20 +35,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter;
|
||||
import androidx.window.layout.DisplayFeature;
|
||||
import androidx.window.layout.FoldingFeature;
|
||||
import androidx.window.layout.FoldingFeature.OcclusionType;
|
||||
import androidx.window.layout.FoldingFeature.State;
|
||||
import androidx.window.layout.WindowInfoRepository;
|
||||
import androidx.window.layout.WindowLayoutInfo;
|
||||
import io.flutter.Log;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
import io.flutter.embedding.engine.renderer.FlutterRenderer;
|
||||
import io.flutter.embedding.engine.renderer.FlutterRenderer.DisplayFeatureState;
|
||||
import io.flutter.embedding.engine.renderer.FlutterRenderer.DisplayFeatureType;
|
||||
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
|
||||
import io.flutter.embedding.engine.renderer.RenderSurface;
|
||||
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
|
||||
@@ -60,9 +48,7 @@ import io.flutter.plugin.platform.PlatformViewsController;
|
||||
import io.flutter.view.AccessibilityBridge;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -124,8 +110,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
|
||||
@Nullable private AndroidTouchProcessor androidTouchProcessor;
|
||||
@Nullable private AccessibilityBridge accessibilityBridge;
|
||||
|
||||
// Provides access to foldable/hinge information
|
||||
@Nullable private WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo;
|
||||
// Directly implemented View behavior that communicates with Flutter.
|
||||
private final FlutterRenderer.ViewportMetrics viewportMetrics =
|
||||
new FlutterRenderer.ViewportMetrics();
|
||||
@@ -160,14 +144,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
|
||||
}
|
||||
};
|
||||
|
||||
private final Consumer<WindowLayoutInfo> windowInfoListener =
|
||||
new Consumer<WindowLayoutInfo>() {
|
||||
@Override
|
||||
public void accept(WindowLayoutInfo layoutInfo) {
|
||||
setWindowInfoListenerDisplayFeatures(layoutInfo);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a {@code FlutterView} programmatically, without any XML attributes.
|
||||
*
|
||||
@@ -450,114 +426,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
|
||||
sendViewportMetricsToFlutter();
|
||||
}
|
||||
|
||||
@VisibleForTesting()
|
||||
protected WindowInfoRepositoryCallbackAdapterWrapper createWindowInfoRepo() {
|
||||
try {
|
||||
return new WindowInfoRepositoryCallbackAdapterWrapper(
|
||||
new WindowInfoRepositoryCallbackAdapter(
|
||||
WindowInfoRepository.getOrCreate((Activity) getContext())));
|
||||
} catch (NoClassDefFoundError noClassDefFoundError) {
|
||||
// Testing environment uses gn/javac, which does not work with aar files. This is why aar
|
||||
// are converted to jar files, losing resources and other android-specific files.
|
||||
// androidx.window does contain resources, which causes it to fail during testing, since the
|
||||
// class androidx.window.R is not found.
|
||||
// This method is mocked in the tests involving androidx.window, but this catch block is
|
||||
// needed for other tests, which would otherwise fail during onAttachedToWindow().
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when this is attached to the window.
|
||||
*
|
||||
* <p>We register for {@link androidx.window.layout.WindowInfoRepository} updates.
|
||||
*/
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
this.windowInfoRepo = createWindowInfoRepo();
|
||||
if (windowInfoRepo != null) {
|
||||
windowInfoRepo.addWindowLayoutInfoListener(
|
||||
ContextCompat.getMainExecutor(getContext()), windowInfoListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when this is detached from the window.
|
||||
*
|
||||
* <p>We unregister from {@link androidx.window.layout.WindowInfoRepository} updates.
|
||||
*/
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
if (windowInfoRepo != null) {
|
||||
windowInfoRepo.removeWindowLayoutInfoListener(windowInfoListener);
|
||||
}
|
||||
this.windowInfoRepo = null;
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh {@link androidx.window.layout.WindowInfoRepository} and {@link
|
||||
* android.view.DisplayCutout} display features. Fold, hinge and cutout areas are populated here.
|
||||
*/
|
||||
@TargetApi(28)
|
||||
protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo) {
|
||||
List<DisplayFeature> displayFeatures = layoutInfo.getDisplayFeatures();
|
||||
List<FlutterRenderer.DisplayFeature> result = new ArrayList<>();
|
||||
|
||||
// Data from WindowInfoRepository display features. Fold and hinge areas are
|
||||
// populated here.
|
||||
for (DisplayFeature displayFeature : displayFeatures) {
|
||||
Log.v(
|
||||
TAG,
|
||||
"WindowInfoRepository Display Feature reported with bounds = "
|
||||
+ displayFeature.getBounds().toString()
|
||||
+ " and type = "
|
||||
+ displayFeature.getClass().getSimpleName());
|
||||
if (displayFeature instanceof FoldingFeature) {
|
||||
DisplayFeatureType type;
|
||||
DisplayFeatureState state;
|
||||
final FoldingFeature feature = (FoldingFeature) displayFeature;
|
||||
if (feature.getOcclusionType() == OcclusionType.FULL) {
|
||||
type = DisplayFeatureType.HINGE;
|
||||
} else {
|
||||
type = DisplayFeatureType.FOLD;
|
||||
}
|
||||
if (feature.getState() == State.FLAT) {
|
||||
state = DisplayFeatureState.POSTURE_FLAT;
|
||||
} else if (feature.getState() == State.HALF_OPENED) {
|
||||
state = DisplayFeatureState.POSTURE_HALF_OPENED;
|
||||
} else {
|
||||
state = DisplayFeatureState.UNKNOWN;
|
||||
}
|
||||
result.add(new FlutterRenderer.DisplayFeature(displayFeature.getBounds(), type, state));
|
||||
} else {
|
||||
result.add(
|
||||
new FlutterRenderer.DisplayFeature(
|
||||
displayFeature.getBounds(),
|
||||
DisplayFeatureType.UNKNOWN,
|
||||
DisplayFeatureState.UNKNOWN));
|
||||
}
|
||||
}
|
||||
|
||||
// Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
|
||||
// populated here. DisplayCutout was introduced in API 28.
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
WindowInsets insets = getRootWindowInsets();
|
||||
if (insets != null) {
|
||||
DisplayCutout cutout = insets.getDisplayCutout();
|
||||
if (cutout != null) {
|
||||
for (Rect bounds : cutout.getBoundingRects()) {
|
||||
Log.v(TAG, "DisplayCutout area reported with bounds = " + bounds.toString());
|
||||
result.add(new FlutterRenderer.DisplayFeature(bounds, DisplayFeatureType.CUTOUT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewportMetrics.displayFeatures = result;
|
||||
sendViewportMetricsToFlutter();
|
||||
}
|
||||
|
||||
// TODO(garyq): Add support for notch cutout API: https://github.com/flutter/flutter/issues/56592
|
||||
// Decide if we want to zero the padding of the sides. When in Landscape orientation,
|
||||
// android may decide to place the software navigation bars on the side. When the nav
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.embedding.android;
|
||||
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter;
|
||||
import androidx.window.layout.WindowLayoutInfo;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Wraps {@link WindowInfoRepositoryCallbackAdapter} in order to be able to mock it during testing.
|
||||
*/
|
||||
public class WindowInfoRepositoryCallbackAdapterWrapper {
|
||||
|
||||
final WindowInfoRepositoryCallbackAdapter adapter;
|
||||
|
||||
public WindowInfoRepositoryCallbackAdapterWrapper(WindowInfoRepositoryCallbackAdapter adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public void addWindowLayoutInfoListener(Executor executor, Consumer<WindowLayoutInfo> consumer) {
|
||||
adapter.addWindowLayoutInfoListener(executor, consumer);
|
||||
}
|
||||
|
||||
public void removeWindowLayoutInfoListener(Consumer<WindowLayoutInfo> consumer) {
|
||||
adapter.removeWindowLayoutInfoListener(consumer);
|
||||
}
|
||||
}
|
||||
@@ -580,10 +580,7 @@ public class FlutterJNI {
|
||||
int systemGestureInsetRight,
|
||||
int systemGestureInsetBottom,
|
||||
int systemGestureInsetLeft,
|
||||
int physicalTouchSlop,
|
||||
int[] displayFeaturesBounds,
|
||||
int[] displayFeaturesType,
|
||||
int[] displayFeaturesState) {
|
||||
int physicalTouchSlop) {
|
||||
ensureRunningOnMainThread();
|
||||
ensureAttachedToNative();
|
||||
nativeSetViewportMetrics(
|
||||
@@ -603,10 +600,7 @@ public class FlutterJNI {
|
||||
systemGestureInsetRight,
|
||||
systemGestureInsetBottom,
|
||||
systemGestureInsetLeft,
|
||||
physicalTouchSlop,
|
||||
displayFeaturesBounds,
|
||||
displayFeaturesType,
|
||||
displayFeaturesState);
|
||||
physicalTouchSlop);
|
||||
}
|
||||
|
||||
private native void nativeSetViewportMetrics(
|
||||
@@ -626,10 +620,7 @@ public class FlutterJNI {
|
||||
int systemGestureInsetRight,
|
||||
int systemGestureInsetBottom,
|
||||
int systemGestureInsetLeft,
|
||||
int physicalTouchSlop,
|
||||
int[] displayFeaturesBounds,
|
||||
int[] displayFeaturesType,
|
||||
int[] displayFeaturesState);
|
||||
int physicalTouchSlop);
|
||||
// ----- End Render Surface Support -----
|
||||
|
||||
// ------ Start Touch Interaction Support ---
|
||||
|
||||
@@ -6,7 +6,6 @@ package io.flutter.embedding.engine.renderer;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
@@ -17,8 +16,6 @@ import io.flutter.Log;
|
||||
import io.flutter.embedding.engine.FlutterJNI;
|
||||
import io.flutter.view.TextureRegistry;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
@@ -329,23 +326,7 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
+ ", R: "
|
||||
+ viewportMetrics.systemGestureInsetRight
|
||||
+ ", B: "
|
||||
+ viewportMetrics.systemGestureInsetRight
|
||||
+ "\n"
|
||||
+ "Display Features: "
|
||||
+ viewportMetrics.displayFeatures.size());
|
||||
|
||||
int[] displayFeaturesBounds = new int[viewportMetrics.displayFeatures.size() * 4];
|
||||
int[] displayFeaturesType = new int[viewportMetrics.displayFeatures.size()];
|
||||
int[] displayFeaturesState = new int[viewportMetrics.displayFeatures.size()];
|
||||
for (int i = 0; i < viewportMetrics.displayFeatures.size(); i++) {
|
||||
DisplayFeature displayFeature = viewportMetrics.displayFeatures.get(i);
|
||||
displayFeaturesBounds[4 * i] = displayFeature.bounds.left;
|
||||
displayFeaturesBounds[4 * i + 1] = displayFeature.bounds.top;
|
||||
displayFeaturesBounds[4 * i + 2] = displayFeature.bounds.right;
|
||||
displayFeaturesBounds[4 * i + 3] = displayFeature.bounds.bottom;
|
||||
displayFeaturesType[i] = displayFeature.type.encodedValue;
|
||||
displayFeaturesState[i] = displayFeature.state.encodedValue;
|
||||
}
|
||||
+ viewportMetrics.viewInsetBottom);
|
||||
|
||||
flutterJNI.setViewportMetrics(
|
||||
viewportMetrics.devicePixelRatio,
|
||||
@@ -363,10 +344,7 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
viewportMetrics.systemGestureInsetRight,
|
||||
viewportMetrics.systemGestureInsetBottom,
|
||||
viewportMetrics.systemGestureInsetLeft,
|
||||
viewportMetrics.physicalTouchSlop,
|
||||
displayFeaturesBounds,
|
||||
displayFeaturesType,
|
||||
displayFeaturesState);
|
||||
viewportMetrics.physicalTouchSlop);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
@@ -451,103 +429,5 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
boolean validate() {
|
||||
return width > 0 && height > 0 && devicePixelRatio > 0;
|
||||
}
|
||||
|
||||
public List<DisplayFeature> displayFeatures = new ArrayList<DisplayFeature>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of a physical feature on the display.
|
||||
*
|
||||
* <p>A display feature is a distinctive physical attribute located within the display panel of
|
||||
* the device. It can intrude into the application window space and create a visual distortion,
|
||||
* visual or touch discontinuity, make some area invisible or create a logical divider or
|
||||
* separation in the screen space.
|
||||
*
|
||||
* <p>Based on {@link androidx.window.layout.DisplayFeature}, with added support for cutouts.
|
||||
*/
|
||||
public static final class DisplayFeature {
|
||||
public final Rect bounds;
|
||||
public final DisplayFeatureType type;
|
||||
public final DisplayFeatureState state;
|
||||
|
||||
public DisplayFeature(Rect bounds, DisplayFeatureType type, DisplayFeatureState state) {
|
||||
this.bounds = bounds;
|
||||
this.type = type;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public DisplayFeature(Rect bounds, DisplayFeatureType type) {
|
||||
this.bounds = bounds;
|
||||
this.type = type;
|
||||
this.state = DisplayFeatureState.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Types of display features that can appear on the viewport.
|
||||
*
|
||||
* <p>Some, like {@link #FOLD}, can be reported without actually occluding the screen. They are
|
||||
* useful for knowing where the display is bent or has a crease. The {@link DisplayFeature#bounds}
|
||||
* can be 0-width in such cases.
|
||||
*/
|
||||
public enum DisplayFeatureType {
|
||||
/**
|
||||
* Type of display feature not yet known to Flutter. This can happen if WindowManager is updated
|
||||
* with new types. The {@link DisplayFeature#bounds} is the only known property.
|
||||
*/
|
||||
UNKNOWN(0),
|
||||
|
||||
/**
|
||||
* A fold in the flexible display that does not occlude the screen. Corresponds to {@link
|
||||
* androidx.window.layout.FoldingFeature.OcclusionType#NONE}
|
||||
*/
|
||||
FOLD(1),
|
||||
|
||||
/**
|
||||
* Splits the display in two separate panels that can fold. Occludes the screen. Corresponds to
|
||||
* {@link androidx.window.layout.FoldingFeature.OcclusionType#FULL}
|
||||
*/
|
||||
HINGE(2),
|
||||
|
||||
/**
|
||||
* Area of the screen that usually houses cameras or sensors. Occludes the screen. Corresponds
|
||||
* to {@link android.view.DisplayCutout}
|
||||
*/
|
||||
CUTOUT(3);
|
||||
|
||||
public final int encodedValue;
|
||||
|
||||
DisplayFeatureType(int encodedValue) {
|
||||
this.encodedValue = encodedValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State of the display feature.
|
||||
*
|
||||
* <p>For foldables, the state is the posture. For cutouts, this property is {@link #UNKNOWN}
|
||||
*/
|
||||
public enum DisplayFeatureState {
|
||||
/** The display feature is a cutout or this state is new and not yet known to Flutter. */
|
||||
UNKNOWN(0),
|
||||
|
||||
/**
|
||||
* The foldable device is completely open. The screen space that is presented to the user is
|
||||
* flat. Corresponds to {@link androidx.window.layout.FoldingFeature.State#FLAT}
|
||||
*/
|
||||
POSTURE_FLAT(1),
|
||||
|
||||
/**
|
||||
* The foldable device's hinge is in an intermediate position between opened and closed state.
|
||||
* There is a non-flat angle between parts of the flexible screen or between physical display
|
||||
* panels. Corresponds to {@link androidx.window.layout.FoldingFeature.State#HALF_OPENED}
|
||||
*/
|
||||
POSTURE_HALF_OPENED(2);
|
||||
|
||||
public final int encodedValue;
|
||||
|
||||
DisplayFeatureState(int encodedValue) {
|
||||
this.encodedValue = encodedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,10 +751,7 @@ public class FlutterView extends SurfaceView
|
||||
mMetrics.systemGestureInsetRight,
|
||||
mMetrics.systemGestureInsetBottom,
|
||||
mMetrics.systemGestureInsetLeft,
|
||||
mMetrics.physicalTouchSlop,
|
||||
new int[0],
|
||||
new int[0],
|
||||
new int[0]);
|
||||
mMetrics.physicalTouchSlop);
|
||||
}
|
||||
|
||||
// Called by FlutterNativeView to notify first Flutter frame rendered.
|
||||
|
||||
@@ -281,28 +281,7 @@ static void SetViewportMetrics(JNIEnv* env,
|
||||
jint systemGestureInsetRight,
|
||||
jint systemGestureInsetBottom,
|
||||
jint systemGestureInsetLeft,
|
||||
jint physicalTouchSlop,
|
||||
jintArray javaDisplayFeaturesBounds,
|
||||
jintArray javaDisplayFeaturesType,
|
||||
jintArray javaDisplayFeaturesState) {
|
||||
// Convert java->c++. javaDisplayFeaturesBounds, javaDisplayFeaturesType and
|
||||
// javaDisplayFeaturesState cannot be null
|
||||
jsize rectSize = env->GetArrayLength(javaDisplayFeaturesBounds);
|
||||
std::vector<int> boundsIntVector(rectSize);
|
||||
env->GetIntArrayRegion(javaDisplayFeaturesBounds, 0, rectSize,
|
||||
&boundsIntVector[0]);
|
||||
std::vector<double> displayFeaturesBounds(boundsIntVector.begin(),
|
||||
boundsIntVector.end());
|
||||
jsize typeSize = env->GetArrayLength(javaDisplayFeaturesType);
|
||||
std::vector<int> displayFeaturesType(typeSize);
|
||||
env->GetIntArrayRegion(javaDisplayFeaturesType, 0, typeSize,
|
||||
&displayFeaturesType[0]);
|
||||
|
||||
jsize stateSize = env->GetArrayLength(javaDisplayFeaturesState);
|
||||
std::vector<int> displayFeaturesState(stateSize);
|
||||
env->GetIntArrayRegion(javaDisplayFeaturesState, 0, stateSize,
|
||||
&displayFeaturesState[0]);
|
||||
|
||||
jint physicalTouchSlop) {
|
||||
const flutter::ViewportMetrics metrics{
|
||||
static_cast<double>(devicePixelRatio),
|
||||
static_cast<double>(physicalWidth),
|
||||
@@ -320,9 +299,6 @@ static void SetViewportMetrics(JNIEnv* env,
|
||||
static_cast<double>(systemGestureInsetBottom),
|
||||
static_cast<double>(systemGestureInsetLeft),
|
||||
static_cast<double>(physicalTouchSlop),
|
||||
displayFeaturesBounds,
|
||||
displayFeaturesType,
|
||||
displayFeaturesState,
|
||||
};
|
||||
|
||||
ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics);
|
||||
@@ -724,7 +700,7 @@ bool RegisterApi(JNIEnv* env) {
|
||||
},
|
||||
{
|
||||
.name = "nativeSetViewportMetrics",
|
||||
.signature = "(JFIIIIIIIIIIIIIII[I[I[I)V",
|
||||
.signature = "(JFIIIIIIIIIIIIIII)V",
|
||||
.fnPtr = reinterpret_cast<void*>(&SetViewportMetrics),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ import static junit.framework.TestCase.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -15,13 +14,11 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.media.Image;
|
||||
@@ -35,9 +32,6 @@ import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.window.layout.FoldingFeature;
|
||||
import androidx.window.layout.WindowLayoutInfo;
|
||||
import io.flutter.TestUtils;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
import io.flutter.embedding.engine.FlutterJNI;
|
||||
@@ -46,7 +40,6 @@ import io.flutter.embedding.engine.renderer.FlutterRenderer;
|
||||
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
|
||||
import io.flutter.plugin.platform.PlatformViewsController;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -57,7 +50,6 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
@@ -82,7 +74,7 @@ public class FlutterViewTest {
|
||||
|
||||
@Test
|
||||
public void attachToFlutterEngine_alertsPlatformViews() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController);
|
||||
@@ -94,7 +86,7 @@ public class FlutterViewTest {
|
||||
|
||||
@Test
|
||||
public void detachFromFlutterEngine_alertsPlatformViews() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController);
|
||||
@@ -107,7 +99,7 @@ public class FlutterViewTest {
|
||||
|
||||
@Test
|
||||
public void detachFromFlutterEngine_turnsOffA11y() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
@@ -137,7 +129,7 @@ public class FlutterViewTest {
|
||||
|
||||
@Test
|
||||
public void onConfigurationChanged_fizzlesWhenNullEngine() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
|
||||
@@ -162,7 +154,7 @@ public class FlutterViewTest {
|
||||
new AtomicReference<>();
|
||||
|
||||
// FYI - The default brightness is LIGHT, which is why we don't need to configure it.
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
|
||||
@@ -200,7 +192,7 @@ public class FlutterViewTest {
|
||||
AtomicReference<SettingsChannel.PlatformBrightness> reportedBrightness =
|
||||
new AtomicReference<>();
|
||||
|
||||
Context spiedContext = spy(Robolectric.setupActivity(Activity.class));
|
||||
Context spiedContext = spy(RuntimeEnvironment.application);
|
||||
|
||||
Resources spiedResources = spy(spiedContext.getResources());
|
||||
when(spiedContext.getResources()).thenReturn(spiedResources);
|
||||
@@ -252,7 +244,7 @@ public class FlutterViewTest {
|
||||
FlutterViewTest.ShadowFullscreenViewGroup.class
|
||||
})
|
||||
public void setPaddingTopToZeroForFullscreenMode() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
@@ -292,7 +284,7 @@ public class FlutterViewTest {
|
||||
FlutterViewTest.ShadowFullscreenViewGroup.class
|
||||
})
|
||||
public void setPaddingTopToZeroForFullscreenModeLegacy() {
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
@@ -324,7 +316,7 @@ public class FlutterViewTest {
|
||||
@Config(sdk = 30)
|
||||
public void reportSystemInsetWhenNotFullscreen() {
|
||||
// Without custom shadows, the default system ui visibility flags is 0.
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
assertEquals(0, flutterView.getSystemUiVisibility());
|
||||
|
||||
FlutterEngine flutterEngine =
|
||||
@@ -363,7 +355,7 @@ public class FlutterViewTest {
|
||||
@Config(sdk = 28)
|
||||
public void reportSystemInsetWhenNotFullscreenLegacy() {
|
||||
// Without custom shadows, the default system ui visibility flags is 0.
|
||||
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
assertEquals(0, flutterView.getSystemUiVisibility());
|
||||
|
||||
FlutterEngine flutterEngine =
|
||||
@@ -633,84 +625,6 @@ public class FlutterViewTest {
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().viewInsetTop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itRegistersAndUnregistersToWindowManager() {
|
||||
Context context = Robolectric.setupActivity(Activity.class);
|
||||
FlutterView flutterView = spy(new FlutterView(context));
|
||||
ShadowDisplay display =
|
||||
Shadows.shadowOf(
|
||||
((WindowManager)
|
||||
RuntimeEnvironment.systemContext.getSystemService(Context.WINDOW_SERVICE))
|
||||
.getDefaultDisplay());
|
||||
WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo =
|
||||
mock(WindowInfoRepositoryCallbackAdapterWrapper.class);
|
||||
// For reasoning behing using doReturn instead of when, read "Important gotcha" at
|
||||
// https://www.javadoc.io/doc/org.mockito/mockito-core/1.10.19/org/mockito/Mockito.html#13
|
||||
doReturn(windowInfoRepo).when(flutterView).createWindowInfoRepo();
|
||||
|
||||
// When a new FlutterView is attached to the window
|
||||
flutterView.onAttachedToWindow();
|
||||
|
||||
// Then the WindowManager callback is registered
|
||||
verify(windowInfoRepo, times(1)).addWindowLayoutInfoListener(any(), any());
|
||||
|
||||
// When the FlutterView is detached from the window
|
||||
flutterView.onDetachedFromWindow();
|
||||
|
||||
// Then the WindowManager callback is unregistered
|
||||
verify(windowInfoRepo, times(1)).removeWindowLayoutInfoListener(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itSendsHingeDisplayFeatureToFlutter() {
|
||||
Context context = Robolectric.setupActivity(Activity.class);
|
||||
FlutterView flutterView = spy(new FlutterView(context));
|
||||
ShadowDisplay display =
|
||||
Shadows.shadowOf(
|
||||
((WindowManager)
|
||||
RuntimeEnvironment.systemContext.getSystemService(Context.WINDOW_SERVICE))
|
||||
.getDefaultDisplay());
|
||||
when(flutterView.getContext()).thenReturn(context);
|
||||
WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo =
|
||||
mock(WindowInfoRepositoryCallbackAdapterWrapper.class);
|
||||
doReturn(windowInfoRepo).when(flutterView).createWindowInfoRepo();
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
|
||||
|
||||
FoldingFeature displayFeature = mock(FoldingFeature.class);
|
||||
when(displayFeature.getBounds()).thenReturn(new Rect(0, 0, 100, 100));
|
||||
when(displayFeature.getOcclusionType()).thenReturn(FoldingFeature.OcclusionType.FULL);
|
||||
when(displayFeature.getState()).thenReturn(FoldingFeature.State.FLAT);
|
||||
|
||||
WindowLayoutInfo testWindowLayout = new WindowLayoutInfo(Arrays.asList(displayFeature));
|
||||
|
||||
// When FlutterView is attached to the engine and window, and a hinge display feature exists
|
||||
flutterView.attachToFlutterEngine(flutterEngine);
|
||||
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
|
||||
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
|
||||
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
assertEquals(Arrays.asList(), viewportMetricsCaptor.getValue().displayFeatures);
|
||||
flutterView.onAttachedToWindow();
|
||||
ArgumentCaptor<Consumer<WindowLayoutInfo>> wmConsumerCaptor =
|
||||
ArgumentCaptor.forClass((Class) Consumer.class);
|
||||
verify(windowInfoRepo).addWindowLayoutInfoListener(any(), wmConsumerCaptor.capture());
|
||||
Consumer<WindowLayoutInfo> wmConsumer = wmConsumerCaptor.getValue();
|
||||
wmConsumer.accept(testWindowLayout);
|
||||
|
||||
// Then the Renderer receives the display feature
|
||||
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
assertEquals(
|
||||
FlutterRenderer.DisplayFeatureType.HINGE,
|
||||
viewportMetricsCaptor.getValue().displayFeatures.get(0).type);
|
||||
assertEquals(
|
||||
FlutterRenderer.DisplayFeatureState.POSTURE_FLAT,
|
||||
viewportMetricsCaptor.getValue().displayFeatures.get(0).state);
|
||||
assertEquals(
|
||||
new Rect(0, 0, 100, 100), viewportMetricsCaptor.getValue().displayFeatures.get(0).bounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flutterImageView_acquiresImageAndInvalidates() {
|
||||
final ImageReader mockReader = mock(ImageReader.class);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package io.flutter.embedding.engine.renderer;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.anyFloat;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -11,7 +8,6 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Looper;
|
||||
import android.view.Surface;
|
||||
@@ -21,7 +17,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@@ -224,65 +219,4 @@ public class FlutterRendererTest {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itConvertsDisplayFeatureArrayToPrimitiveArrays() {
|
||||
// Setup the test.
|
||||
FlutterRenderer flutterRenderer = new FlutterRenderer(fakeFlutterJNI);
|
||||
FlutterRenderer.ViewportMetrics metrics = new FlutterRenderer.ViewportMetrics();
|
||||
metrics.width = 1000;
|
||||
metrics.height = 1000;
|
||||
metrics.devicePixelRatio = 2;
|
||||
metrics.displayFeatures.add(
|
||||
new FlutterRenderer.DisplayFeature(
|
||||
new Rect(10, 20, 30, 40),
|
||||
FlutterRenderer.DisplayFeatureType.FOLD,
|
||||
FlutterRenderer.DisplayFeatureState.POSTURE_HALF_OPENED));
|
||||
metrics.displayFeatures.add(
|
||||
new FlutterRenderer.DisplayFeature(
|
||||
new Rect(50, 60, 70, 80), FlutterRenderer.DisplayFeatureType.CUTOUT));
|
||||
|
||||
// Execute the behavior under test.
|
||||
flutterRenderer.setViewportMetrics(metrics);
|
||||
|
||||
// Verify behavior under test.
|
||||
ArgumentCaptor<int[]> boundsCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
ArgumentCaptor<int[]> typeCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
ArgumentCaptor<int[]> stateCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
verify(fakeFlutterJNI)
|
||||
.setViewportMetrics(
|
||||
anyFloat(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
boundsCaptor.capture(),
|
||||
typeCaptor.capture(),
|
||||
stateCaptor.capture());
|
||||
|
||||
assertArrayEquals(new int[] {10, 20, 30, 40, 50, 60, 70, 80}, boundsCaptor.getValue());
|
||||
assertArrayEquals(
|
||||
new int[] {
|
||||
FlutterRenderer.DisplayFeatureType.FOLD.encodedValue,
|
||||
FlutterRenderer.DisplayFeatureType.CUTOUT.encodedValue
|
||||
},
|
||||
typeCaptor.getValue());
|
||||
assertArrayEquals(
|
||||
new int[] {
|
||||
FlutterRenderer.DisplayFeatureState.POSTURE_HALF_OPENED.encodedValue,
|
||||
FlutterRenderer.DisplayFeatureState.UNKNOWN.encodedValue
|
||||
},
|
||||
stateCaptor.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Insets;
|
||||
@@ -68,7 +67,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
@@ -1441,7 +1439,7 @@ public class TextInputPluginTest {
|
||||
return;
|
||||
}
|
||||
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
@@ -1528,7 +1526,7 @@ public class TextInputPluginTest {
|
||||
return;
|
||||
}
|
||||
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
@@ -1580,7 +1578,7 @@ public class TextInputPluginTest {
|
||||
|
||||
TestAfm testAfm =
|
||||
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
@@ -1711,7 +1709,7 @@ public class TextInputPluginTest {
|
||||
|
||||
TestAfm testAfm =
|
||||
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
@@ -1805,7 +1803,7 @@ public class TextInputPluginTest {
|
||||
|
||||
TestAfm testAfm =
|
||||
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
@@ -1969,7 +1967,7 @@ public class TextInputPluginTest {
|
||||
@TargetApi(30)
|
||||
@Config(sdk = 30)
|
||||
public void ime_windowInsetsSync() {
|
||||
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
|
||||
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
|
||||
@@ -8,7 +8,6 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.view.PointerIcon;
|
||||
import io.flutter.embedding.android.FlutterView;
|
||||
import io.flutter.embedding.engine.dart.DartExecutor;
|
||||
@@ -19,8 +18,8 @@ import java.util.HashMap;
|
||||
import org.json.JSONException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@Config(
|
||||
@@ -32,7 +31,7 @@ public class MouseCursorPluginTest {
|
||||
@Test
|
||||
public void mouseCursorPlugin_SetsSystemCursorOnRequest() throws JSONException {
|
||||
// Initialize a general MouseCursorPlugin.
|
||||
FlutterView testView = spy(new FlutterView(Robolectric.setupActivity(Activity.class)));
|
||||
FlutterView testView = spy(new FlutterView(RuntimeEnvironment.application));
|
||||
MouseCursorChannel mouseCursorChannel = new MouseCursorChannel(mock(DartExecutor.class));
|
||||
|
||||
MouseCursorPlugin mouseCursorPlugin = new MouseCursorPlugin(testView, mouseCursorChannel);
|
||||
|
||||
@@ -985,10 +985,7 @@ public class PlatformViewsControllerTest {
|
||||
int systemGestureInsetRight,
|
||||
int systemGestureInsetBottom,
|
||||
int systemGestureInsetLeft,
|
||||
int physicalTouchSlop,
|
||||
int[] displayFeaturesBounds,
|
||||
int[] displayFeaturesType,
|
||||
int[] displayFeaturesState) {}
|
||||
int physicalTouchSlop) {}
|
||||
|
||||
@Implementation
|
||||
public void invokePlatformMessageResponseCallback(
|
||||
|
||||
@@ -43,7 +43,6 @@ android {
|
||||
testImplementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
|
||||
testImplementation "androidx.test:core:1.4.0"
|
||||
testImplementation "androidx.tracing:tracing:1.0.0"
|
||||
testImplementation "androidx.window:window-java:1.0.0-beta03"
|
||||
testImplementation "com.google.android.play:core:1.8.0"
|
||||
testImplementation "com.ibm.icu:icu4j:69.1"
|
||||
testImplementation "org.mockito:mockito-core:3.11.2"
|
||||
|
||||
@@ -91,9 +91,6 @@ void FlatlandPlatformView::OnGetLayout(
|
||||
0.0f, // p_physical_system_gesture_inset_bottom
|
||||
0.0f, // p_physical_system_gesture_inset_left,
|
||||
-1.0, // p_physical_touch_slop,
|
||||
{}, // p_physical_display_features_bounds
|
||||
{}, // p_physical_display_features_type
|
||||
{}, // p_physical_display_features_state
|
||||
});
|
||||
|
||||
parent_viewport_watcher_->GetLayout(
|
||||
|
||||
@@ -253,9 +253,6 @@ void GfxPlatformView::OnScenicEvent(
|
||||
0.0f, // p_physical_system_gesture_inset_bottom
|
||||
0.0f, // p_physical_system_gesture_inset_left,
|
||||
-1.0, // p_physical_touch_slop,
|
||||
{}, // p_physical_display_features_bounds
|
||||
{}, // p_physical_display_features_type
|
||||
{}, // p_physical_display_features_state
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,19 +65,5 @@
|
||||
"provides": [
|
||||
"androidx.core.view.WindowInsetsControllerCompat"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://maven.google.com/androidx/window/window-java/1.0.0-beta03/window-java-1.0.0-beta03.aar",
|
||||
"out_file_name": "androidx_window_java.aar",
|
||||
"maven_dependency": "androidx.window:window-java:1.0.0-beta03",
|
||||
"provides": [
|
||||
"androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter",
|
||||
"androidx.window.layout.DisplayFeature",
|
||||
"androidx.window.layout.FoldingFeature",
|
||||
"androidx.window.layout.FoldingFeature.OcclusionType",
|
||||
"androidx.window.layout.FoldingFeature.State",
|
||||
"androidx.window.layout.WindowLayoutInfo",
|
||||
"androidx.window.layout.WindowInfoRepository"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -44,7 +44,6 @@ android {
|
||||
embedding "androidx.core:core:1.6.0"
|
||||
embedding "androidx.fragment:fragment:1.1.0"
|
||||
embedding "androidx.tracing:tracing:1.0.0"
|
||||
embedding "androidx.window:window-java:1.0.0-beta03"
|
||||
|
||||
def lifecycle_version = "2.2.0"
|
||||
embedding "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
|
||||
|
||||
Reference in New Issue
Block a user