Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2642c24

Browse files
author
Emmanuel Garcia
committed
handle clamp
1 parent 110bdb5 commit 2642c24

File tree

5 files changed

+92
-22
lines changed

5 files changed

+92
-22
lines changed

shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import android.content.Context;
1212
import android.content.MutableContextWrapper;
1313
import android.os.Build;
14-
import android.util.DisplayMetrics;
1514
import android.util.SparseArray;
1615
import android.view.MotionEvent;
1716
import android.view.SurfaceView;
@@ -257,8 +256,6 @@ public long createForTextureLayer(
257256
|| Build.VERSION.SDK_INT < 23;
258257

259258
if (!usesSoftwareRendering && shouldUseVirtualDisplay) {
260-
validateVirtualDisplayDimensions(physicalWidth, physicalHeight);
261-
262259
Log.i(TAG, "Hosting view in a virtual display for platform view: " + viewId);
263260
// API level 20 is required to use VirtualDisplay#setSurface.
264261
ensureValidAndroidVersion(20);
@@ -952,21 +949,6 @@ private static PointerCoords parsePointerCoords(Object rawCoords, float density)
952949
return coords;
953950
}
954951

955-
// Creating a VirtualDisplay larger than the size of the device screen size
956-
// could cause the device to restart: https://github.com/flutter/flutter/issues/28978
957-
private void validateVirtualDisplayDimensions(int width, int height) {
958-
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
959-
if (height > metrics.heightPixels || width > metrics.widthPixels) {
960-
String message =
961-
String.format(
962-
"Creating a virtual display of size: [%d, %d] "
963-
+ "may result in problems (https://github.com/flutter/flutter/issues/2897). "
964-
+ "It is larger than the device screen size: [%d, %d].",
965-
width, height, metrics.widthPixels, metrics.heightPixels);
966-
Log.w(TAG, message);
967-
}
968-
}
969-
970952
private float getDisplayDensity() {
971953
return context.getResources().getDisplayMetrics().density;
972954
}

shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@
1010
import android.content.Context;
1111
import android.hardware.display.DisplayManager;
1212
import android.hardware.display.VirtualDisplay;
13+
import android.util.DisplayMetrics;
1314
import android.view.MotionEvent;
1415
import android.view.Surface;
1516
import android.view.View;
1617
import android.view.ViewTreeObserver;
1718
import androidx.annotation.NonNull;
1819
import androidx.annotation.VisibleForTesting;
20+
import io.flutter.Log;
1921
import io.flutter.view.TextureRegistry;
22+
import java.util.Locale;
2023

2124
@TargetApi(20)
2225
class VirtualDisplayController {
26+
private static String TAG = "VirtualDisplayController";
2327

2428
public static VirtualDisplayController create(
2529
Context context,
@@ -31,14 +35,53 @@ public static VirtualDisplayController create(
3135
int viewId,
3236
Object createParams,
3337
OnFocusChangeListener focusChangeListener) {
34-
textureEntry.surfaceTexture().setDefaultBufferSize(width, height);
38+
39+
int selectedWidth = width;
40+
int selectedHeight = height;
41+
42+
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
43+
if (selectedWidth == 0 || selectedHeight == 0) {
44+
return null;
45+
}
46+
// Prevent https://github.com/flutter/flutter/issues/2897.
47+
if (selectedWidth > metrics.widthPixels || selectedHeight > metrics.heightPixels) {
48+
float aspectRatio = (float) selectedWidth / (float) selectedHeight;
49+
int maybeWidth = (int) (metrics.heightPixels * aspectRatio);
50+
int maybeHeight = (int) (metrics.widthPixels / aspectRatio);
51+
52+
if (maybeHeight <= metrics.heightPixels) {
53+
selectedWidth = metrics.widthPixels;
54+
selectedHeight = maybeHeight;
55+
} else if (maybeWidth <= metrics.widthPixels) {
56+
selectedHeight = metrics.heightPixels;
57+
selectedWidth = maybeWidth;
58+
} else {
59+
return null;
60+
}
61+
62+
String message =
63+
String.format(
64+
Locale.US,
65+
"Resizing virtual display of size: [%d, %d] to size [%d, %d] "
66+
+ "since it's larger than the device display size [%d, %d].",
67+
width,
68+
height,
69+
selectedWidth,
70+
selectedHeight,
71+
metrics.widthPixels,
72+
metrics.heightPixels);
73+
Log.w(TAG, message);
74+
}
75+
76+
textureEntry.surfaceTexture().setDefaultBufferSize(selectedWidth, selectedHeight);
3577
Surface surface = new Surface(textureEntry.surfaceTexture());
3678
DisplayManager displayManager =
3779
(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
3880

3981
int densityDpi = context.getResources().getDisplayMetrics().densityDpi;
4082
VirtualDisplay virtualDisplay =
41-
displayManager.createVirtualDisplay("flutter-vd", width, height, densityDpi, surface, 0);
83+
displayManager.createVirtualDisplay(
84+
"flutter-vd", selectedWidth, selectedHeight, densityDpi, surface, 0);
4285

4386
if (virtualDisplay == null) {
4487
return null;
@@ -54,8 +97,8 @@ public static VirtualDisplayController create(
5497
focusChangeListener,
5598
viewId,
5699
createParams);
57-
controller.bufferWidth = width;
58-
controller.bufferHeight = height;
100+
controller.bufferWidth = selectedWidth;
101+
controller.bufferHeight = selectedHeight;
59102
return controller;
60103
}
61104

testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformViewWithSurfaceViewUiTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,12 @@ public void testPlatformViewWithoutOverlayIntersection() throws Exception {
123123
activityRule.launchActivity(intent),
124124
goldName("testPlatformViewWithoutOverlayIntersection"));
125125
}
126+
127+
@Test
128+
public void testPlatformViewLargerThanDisplaySize() throws Exception {
129+
// Regression test for https://github.com/flutter/flutter/issues/2897.
130+
intent.putExtra("scenario_name", "platform_view_larger_than_display_size");
131+
ScreenshotUtil.capture(
132+
activityRule.launchActivity(intent), goldName("testPlatformViewLargerThanDisplaySize"));
133+
}
126134
}

testing/scenario_app/lib/src/platform_view.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,42 @@ class PlatformViewNoOverlayIntersectionScenario extends Scenario
114114
}
115115
}
116116

117+
118+
/// A platform view that is larger than the display size.
119+
/// This is only applicable on Android while using virtual displays.
120+
/// Related issue https://github.com/flutter/flutter/issues/2897.
121+
class PlatformViewLargerThanDisplaySize extends Scenario
122+
with _BasePlatformViewScenarioMixin {
123+
/// Creates the PlatformView scenario.
124+
///
125+
/// The [dispatcher] parameter must not be null.
126+
PlatformViewLargerThanDisplaySize(
127+
PlatformDispatcher dispatcher, {
128+
required this.id,
129+
}) : assert(dispatcher != null),
130+
super(dispatcher);
131+
132+
/// The platform view identifier.
133+
final int id;
134+
135+
@override
136+
void onBeginFrame(Duration duration) {
137+
final SceneBuilder builder = SceneBuilder();
138+
139+
addPlatformView(
140+
id,
141+
dispatcher: dispatcher,
142+
sceneBuilder: builder,
143+
width: 15000,
144+
height: 60000,
145+
);
146+
147+
finishBuilder(
148+
builder,
149+
);
150+
}
151+
}
152+
117153
/// A simple platform view with an overlay that partially intersects with the platform view.
118154
class PlatformViewPartialIntersectionScenario extends Scenario
119155
with _BasePlatformViewScenarioMixin {

testing/scenario_app/lib/src/scenarios.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Map<String, ScenarioFactory> _scenarios = <String, ScenarioFactory>{
2424
'locale_initialization': () => LocaleInitialization(PlatformDispatcher.instance),
2525
'platform_view': () => PlatformViewScenario(PlatformDispatcher.instance, id: _viewId++),
2626
'platform_view_no_overlay_intersection': () => PlatformViewNoOverlayIntersectionScenario(PlatformDispatcher.instance, id: _viewId++),
27+
'platform_view_larger_than_display_size': () => PlatformViewLargerThanDisplaySize(PlatformDispatcher.instance, id: _viewId++),
2728
'platform_view_partial_intersection': () => PlatformViewPartialIntersectionScenario(PlatformDispatcher.instance, id: _viewId++),
2829
'platform_view_two_intersecting_overlays': () => PlatformViewTwoIntersectingOverlaysScenario(PlatformDispatcher.instance, id: _viewId++),
2930
'platform_view_one_overlay_two_intersecting_overlays': () => PlatformViewOneOverlayTwoIntersectingOverlaysScenario(PlatformDispatcher.instance, id: _viewId++),

0 commit comments

Comments
 (0)