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

Commit 004a305

Browse files
authored
[fuchsia] embedding-flutter test (#37052)
* Add embedding-flutter test * Lint CC files * GN formatting * Remove changes to embedder * Minor refactor * Remove unused dependencies * Lint CC files * Remove comments * Rename pubspec
1 parent df60207 commit 004a305

File tree

13 files changed

+451
-62
lines changed

13 files changed

+451
-62
lines changed

shell/platform/fuchsia/flutter/tests/integration/touch-input/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ executable("touch-input-test-bin") {
4646
"$fuchsia_sdk_root/pkg:scenic_cpp",
4747
"$fuchsia_sdk_root/pkg:sys_component_cpp_testing",
4848
"$fuchsia_sdk_root/pkg:zx",
49+
"embedding-flutter-view:package",
4950
"touch-input-view:package",
5051
"//build/fuchsia/fidl:fuchsia.ui.gfx",
5152
"//flutter/fml",

shell/platform/fuchsia/flutter/tests/integration/touch-input/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# touch-input
22

33
`touch-input-test` exercises touch through a child view (in this case, the `touch-input-view` Dart component) and asserting
4-
the precise location of the touch event. We do this by attaching the child view, injecting touch, and validating that the view
5-
reports the touch event back with the correct coordinates.
4+
the precise location of the touch event. We validate a touch event as valid through two ways:
5+
- By attaching the child view, injecting touch, and validating that the view reports the touch event back with the correct coordinates.
6+
- By embedding a child view into a parent view, injecting touch into both views, and validating that each view reports its touch event back with the correct coordinates.
67

78
```shell
89
Injecting the tap event
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2013 The Flutter Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
import("//build/fuchsia/sdk.gni")
6+
import("//flutter/tools/fuchsia/dart/dart_library.gni")
7+
import("//flutter/tools/fuchsia/flutter/flutter_component.gni")
8+
import("//flutter/tools/fuchsia/gn-sdk/component.gni")
9+
import("//flutter/tools/fuchsia/gn-sdk/package.gni")
10+
11+
dart_library("lib") {
12+
package_name = "embedding-flutter-view"
13+
sources = [ "embedding-flutter-view.dart" ]
14+
15+
deps = [
16+
"//flutter/tools/fuchsia/dart:fuchsia_services",
17+
"//flutter/tools/fuchsia/dart:zircon",
18+
"//flutter/tools/fuchsia/fidl:fuchsia.ui.app",
19+
"//flutter/tools/fuchsia/fidl:fuchsia.ui.scenic",
20+
"//flutter/tools/fuchsia/fidl:fuchsia.ui.test.input",
21+
"//flutter/tools/fuchsia/fidl:fuchsia.ui.views",
22+
]
23+
}
24+
25+
flutter_component("component") {
26+
testonly = true
27+
component_name = "embedding-flutter-view"
28+
manifest = rebase_path("meta/embedding-flutter-view.cml")
29+
main_package = "embedding-flutter-view"
30+
main_dart = "embedding-flutter-view.dart"
31+
32+
deps = [ ":lib" ]
33+
}
34+
35+
fuchsia_package("package") {
36+
testonly = true
37+
package_name = "embedding-flutter-view"
38+
39+
deps = [ ":component" ]
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:convert';
6+
import 'dart:typed_data';
7+
import 'dart:io';
8+
import 'dart:ui';
9+
10+
import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
11+
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
12+
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_touch;
13+
import 'package:fuchsia_services/services.dart';
14+
import 'package:zircon/zircon.dart';
15+
16+
void main(List<String> args) {
17+
print('Launching embedding-flutter-view');
18+
TestApp app = TestApp(ChildView.gfx(_launchGfxChildView()));
19+
app.run();
20+
}
21+
22+
class TestApp {
23+
static const _black = Color.fromARGB(255, 0, 0, 0);
24+
static const _blue = Color.fromARGB(255, 0, 0, 255);
25+
26+
final ChildView childView;
27+
final _responseListener = test_touch.TouchInputListenerProxy();
28+
29+
Color _backgroundColor = _blue;
30+
31+
TestApp(this.childView) {}
32+
33+
void run() {
34+
childView.create((ByteData reply) {
35+
// Set up window callbacks.
36+
window.onPointerDataPacket = (PointerDataPacket packet) {
37+
this.pointerDataPacket(packet);
38+
};
39+
window.onMetricsChanged = () {
40+
window.scheduleFrame();
41+
};
42+
window.onBeginFrame = (Duration duration) {
43+
this.beginFrame(duration);
44+
};
45+
46+
// The child view should be attached to Scenic now.
47+
// Ready to build the scene.
48+
window.scheduleFrame();
49+
});
50+
}
51+
52+
void beginFrame(Duration duration) {
53+
// Convert physical screen size of device to values
54+
final pixelRatio = window.devicePixelRatio;
55+
final size = window.physicalSize / pixelRatio;
56+
final physicalBounds = Offset.zero & window.physicalSize;
57+
final windowBounds = Offset.zero & size;
58+
// Set up a Canvas that uses the screen size
59+
final recorder = PictureRecorder();
60+
final canvas = Canvas(recorder, physicalBounds);
61+
canvas.scale(pixelRatio);
62+
// Draw something
63+
final paint = Paint()..color = this._backgroundColor;
64+
canvas.drawRect(windowBounds, paint);
65+
final picture = recorder.endRecording();
66+
// Build the scene
67+
final sceneBuilder = SceneBuilder()
68+
..pushClipRect(physicalBounds)
69+
..addPicture(Offset.zero, picture);
70+
// Child view should take up half the screen
71+
final childPhysicalSize = window.physicalSize * 0.5;
72+
sceneBuilder
73+
..addPlatformView(childView.viewId,
74+
width: childPhysicalSize.width,
75+
height: size.height)
76+
..pop();
77+
sceneBuilder.pop();
78+
window.render(sceneBuilder.build());
79+
}
80+
81+
void pointerDataPacket(PointerDataPacket packet) async {
82+
int nowNanos = System.clockGetMonotonic();
83+
84+
for (PointerData data in packet.data) {
85+
print('embedding-flutter-view received tap: ${data.toStringFull()}');
86+
87+
if (data.change == PointerChange.down) {
88+
this._backgroundColor = _black;
89+
}
90+
91+
if (data.change == PointerChange.down || data.change == PointerChange.move) {
92+
Incoming.fromSvcPath()
93+
..connectToService(_responseListener)
94+
..close();
95+
96+
_respond(test_touch.TouchInputListenerReportTouchInputRequest(
97+
localX: data.physicalX,
98+
localY: data.physicalY,
99+
timeReceived: nowNanos,
100+
componentName: 'embedding-flutter-view',
101+
));
102+
}
103+
}
104+
105+
window.scheduleFrame();
106+
}
107+
108+
void _respond(test_touch.TouchInputListenerReportTouchInputRequest request) async {
109+
print('embedding-flutter-view reporting touch input to TouchInputListener');
110+
await _responseListener.reportTouchInput(request);
111+
}
112+
}
113+
114+
class ChildView {
115+
final ViewHolderToken viewHolderToken;
116+
final ViewportCreationToken viewportCreationToken;
117+
final int viewId;
118+
119+
ChildView(this.viewportCreationToken) : viewHolderToken = null, viewId = viewportCreationToken.value.handle.handle {
120+
assert(viewId != null);
121+
}
122+
123+
ChildView.gfx(this.viewHolderToken) : viewportCreationToken = null, viewId = viewHolderToken.value.handle.handle {
124+
assert(viewId != null);
125+
}
126+
127+
void create(PlatformMessageResponseCallback callback) {
128+
// Construct the dart:ui platform message to create the view, and when the
129+
// return callback is invoked, build the scene. At that point, it is safe
130+
// to embed the child view in the scene.
131+
final viewOcclusionHint = Rect.zero;
132+
final Map<String, dynamic> args = <String, dynamic>{
133+
'viewId': viewId,
134+
'hitTestable': true,
135+
'focusable': true,
136+
'viewOcclusionHintLTRB': <double>[
137+
viewOcclusionHint.left,
138+
viewOcclusionHint.top,
139+
viewOcclusionHint.right,
140+
viewOcclusionHint.bottom
141+
],
142+
};
143+
144+
final ByteData createViewMessage = utf8.encoder.convert(
145+
json.encode(<String, Object>{
146+
'method': 'View.create',
147+
'args': args,
148+
})
149+
).buffer.asByteData();
150+
151+
final platformViewsChannel = 'flutter/platform_views';
152+
153+
PlatformDispatcher.instance.sendPlatformMessage(
154+
platformViewsChannel,
155+
createViewMessage,
156+
callback);
157+
}
158+
}
159+
160+
ViewHolderToken _launchGfxChildView() {
161+
ViewProviderProxy viewProvider = ViewProviderProxy();
162+
Incoming.fromSvcPath()
163+
..connectToService(viewProvider)
164+
..close();
165+
166+
final viewTokens = EventPairPair();
167+
assert(viewTokens.status == ZX.OK);
168+
final viewHolderToken = ViewHolderToken(value: viewTokens.first);
169+
final viewToken = ViewToken(value: viewTokens.second);
170+
171+
viewProvider.createView(viewToken.value, null, null);
172+
viewProvider.ctrl.close();
173+
174+
return viewHolderToken;
175+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
{
5+
include: [ "syslog/client.shard.cml" ],
6+
program: {
7+
data: "data/embedding-flutter-view",
8+
9+
// Always use the jit runner for now.
10+
// TODO(fxbug.dev/106577): Implement manifest merging build rules for V2 components.
11+
runner: "flutter_jit_runner",
12+
},
13+
capabilities: [
14+
{
15+
protocol: [ "fuchsia.ui.app.ViewProvider" ],
16+
},
17+
],
18+
expose: [
19+
{
20+
protocol: [ "fuchsia.ui.app.ViewProvider" ],
21+
from: "self",
22+
},
23+
],
24+
use: [
25+
{
26+
protocol: [
27+
"fuchsia.ui.app.ViewProvider",
28+
"fuchsia.ui.scenic.Scenic",
29+
"fuchsia.ui.test.input.TouchInputListener",
30+
]
31+
},
32+
{
33+
directory: "config-data",
34+
rights: [ "r*" ],
35+
path: "/config/data",
36+
},
37+
]
38+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2013 The Flutter Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
name: embedding-flutter-view
6+
7+
environment:
8+
sdk: '>=2.18.0 <3.0.0'

0 commit comments

Comments
 (0)