Unverified Commit a0379f45 authored by Amir Hardon's avatar Amir Hardon Committed by GitHub

Test touch for Android windows added by platform views (#55068)

parent 3e2293ec
...@@ -6,8 +6,13 @@ package io.flutter.integration.platformviews; ...@@ -6,8 +6,13 @@ package io.flutter.integration.platformviews;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
...@@ -24,7 +29,7 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal ...@@ -24,7 +29,7 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal
view = new View(context) { view = new View(context) {
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event); return true;
} }
}; };
view.setBackgroundColor(0xff0000ff); view.setBackgroundColor(0xff0000ff);
...@@ -55,6 +60,10 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal ...@@ -55,6 +60,10 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal
case "showAndHideAlertDialog": case "showAndHideAlertDialog":
showAndHideAlertDialog(result); showAndHideAlertDialog(result);
return; return;
case "addWindowAndWaitForClick":
addWindow(result);
return;
} }
result.notImplemented(); result.notImplemented();
} }
...@@ -75,4 +84,18 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal ...@@ -75,4 +84,18 @@ public class SimplePlatformView implements PlatformView, MethodChannel.MethodCal
}, 1000); }, 1000);
} }
private void addWindow(final MethodChannel.Result result) {
Context context = view.getContext();
final Button button = new Button(context);
button.setText("This view is added as a window");
final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 0, PixelFormat.OPAQUE);
layoutParams.gravity = Gravity.FILL;
windowManager.addView(button, layoutParams);
button.setOnClickListener(v -> {
windowManager.removeView(button);
result.success(null);
});
}
} }
...@@ -35,6 +35,8 @@ class WindowManagerBodyState extends State<WindowManagerBody> { ...@@ -35,6 +35,8 @@ class WindowManagerBodyState extends State<WindowManagerBody> {
MethodChannel viewChannel; MethodChannel viewChannel;
_LastTestStatus lastTestStatus = _LastTestStatus.pending; _LastTestStatus lastTestStatus = _LastTestStatus.pending;
String lastError; String lastError;
int id;
int windowClickCount = 0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -52,11 +54,32 @@ class WindowManagerBodyState extends State<WindowManagerBody> { ...@@ -52,11 +54,32 @@ class WindowManagerBodyState extends State<WindowManagerBody> {
), ),
), ),
if (lastTestStatus != _LastTestStatus.pending) _statusWidget(), if (lastTestStatus != _LastTestStatus.pending) _statusWidget(),
if (viewChannel != null) RaisedButton( if (viewChannel != null) ... <Widget>[
key: const ValueKey<String>('ShowAlertDialog'), RaisedButton(
child: const Text('SHOW ALERT DIALOG'), key: const ValueKey<String>('ShowAlertDialog'),
onPressed: onShowAlertDialogPressed, child: const Text('SHOW ALERT DIALOG'),
), onPressed: onShowAlertDialogPressed,
),
Row(
children: <Widget>[
RaisedButton(
key: const ValueKey<String>('AddWindow'),
child: const Text('ADD WINDOW'),
onPressed: onAddWindowPressed,
),
RaisedButton(
key: const ValueKey<String>('TapWindow'),
child: const Text('TAP WINDOW'),
onPressed: onTapWindowPressed,
),
if (windowClickCount > 0)
Text(
'Click count: $windowClickCount',
key: const ValueKey<String>('WindowClickCount'),
),
],
),
],
], ],
), ),
); );
...@@ -96,9 +119,139 @@ class WindowManagerBodyState extends State<WindowManagerBody> { ...@@ -96,9 +119,139 @@ class WindowManagerBodyState extends State<WindowManagerBody> {
} }
} }
Future<void> onAddWindowPressed() async {
try {
await viewChannel.invokeMethod<void>('addWindowAndWaitForClick');
setState(() {
windowClickCount++;
});
} catch(e) {
setState(() {
lastTestStatus = _LastTestStatus.error;
lastError = '$e';
});
}
}
Future<void> onTapWindowPressed() async {
await Future<void>.delayed(const Duration(seconds: 1));
for (final AndroidMotionEvent event in _tapSequence) {
await SystemChannels.platform_views.invokeMethod<dynamic>(
'touch',
_motionEventasList(event, id),
);
}
}
void onPlatformViewCreated(int id) { void onPlatformViewCreated(int id) {
this.id = id;
setState(() { setState(() {
viewChannel = MethodChannel('simple_view/$id'); viewChannel = MethodChannel('simple_view/$id');
}); });
} }
static List<double> _pointerCoordsAsList(AndroidPointerCoords coords) {
return <double>[
coords.orientation,
coords.pressure,
coords.size,
coords.toolMajor,
coords.toolMinor,
coords.touchMajor,
coords.touchMinor,
coords.x,
coords.y,
];
}
static List<dynamic> _motionEventasList(AndroidMotionEvent event, int viewId) {
return <dynamic>[
viewId,
event.downTime,
event.eventTime,
event.action,
event.pointerCount,
event.pointerProperties.map<List<int>>((AndroidPointerProperties p) => <int> [p.id, p.toolType]).toList(),
event.pointerCoords.map<List<double>>((AndroidPointerCoords p) => _pointerCoordsAsList(p)).toList(),
event.metaState,
event.buttonState,
event.xPrecision,
event.yPrecision,
event.deviceId,
event.edgeFlags,
event.source,
event.flags,
];
}
static final List<AndroidMotionEvent> _tapSequence = <AndroidMotionEvent> [
AndroidMotionEvent(
downTime: 723657071,
pointerCount: 1,
pointerCoords: <AndroidPointerCoords> [
const AndroidPointerCoords(
orientation: 0.0,
touchMajor: 5.0,
size: 0.019607843831181526,
x: 180.0,
y: 200.0,
touchMinor: 5.0,
pressure: 1.0,
toolMajor: 5.0,
toolMinor: 5.0,
),
],
yPrecision: 1.0,
buttonState: 0,
flags: 0,
source: 4098,
deviceId: 4,
metaState: 0,
pointerProperties: <AndroidPointerProperties> [
const AndroidPointerProperties(
id: 0,
toolType: 1,
),
],
edgeFlags: 0,
eventTime: 723657071,
action: 0,
xPrecision: 1.0,
),
AndroidMotionEvent(
downTime: 723657071,
eventTime: 723657137,
action: 1,
pointerCount: 1,
pointerProperties: <AndroidPointerProperties> [
const AndroidPointerProperties(
id: 0,
toolType: 1,
),
],
pointerCoords: <AndroidPointerCoords> [
const AndroidPointerCoords(
orientation: 0.0,
touchMajor: 5.0,
size: 0.019607843831181526,
x: 180.0,
y: 200.0,
touchMinor: 5.0,
pressure: 1.0,
toolMajor: 5.0,
toolMinor: 5.0,
)
],
metaState: 0,
buttonState: 0,
xPrecision: 1.0,
yPrecision: 1.0,
deviceId: 4,
edgeFlags: 0,
source: 4098,
flags: 0,
),
];
} }
...@@ -30,17 +30,38 @@ Future<void> main() async { ...@@ -30,17 +30,38 @@ Future<void> main() async {
await driver.tap(backButton); await driver.tap(backButton);
}); });
test('AlertDialog from platform view context', () async { group('WindowManager', ()
final SerializableFinder wmListTile = {
find.byValueKey('WmIntegrationsListTile'); setUpAll(() async {
await driver.tap(wmListTile); final SerializableFinder wmListTile =
find.byValueKey('WmIntegrationsListTile');
final SerializableFinder showAlertDialog = find.byValueKey('ShowAlertDialog'); await driver.tap(wmListTile);
await driver.waitFor(showAlertDialog); });
await driver.tap(showAlertDialog);
final String status = await driver.getText(find.byValueKey('Status')); tearDownAll(() async {
expect(status, 'Success'); await driver.waitFor(find.pageBack());
await driver.waitFor(find.pageBack()); await driver.tap(find.pageBack());
await driver.tap(find.pageBack()); });
test('AlertDialog from platform view context', () async {
final SerializableFinder showAlertDialog = find.byValueKey(
'ShowAlertDialog');
await driver.waitFor(showAlertDialog);
await driver.tap(showAlertDialog);
final String status = await driver.getText(find.byValueKey('Status'));
expect(status, 'Success');
});
test('Child windows can handle touches', () async {
final SerializableFinder addWindow = find.byValueKey('AddWindow');
await driver.waitFor(addWindow);
await driver.tap(addWindow);
final SerializableFinder tapWindow = find.byValueKey('TapWindow');
await driver.tap(tapWindow);
final String windowClickCount = await driver.getText(find.byValueKey('WindowClickCount'));
expect(windowClickCount, 'Click count: 1');
},
// TODO(amirh): enable this after fixing https://github.com/flutter/flutter/issues/55066
skip:true);
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment