Unverified Commit f88d2d9c authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Revert 20917 platform view arena (#21086)

This reverts commit c594696f.
parent 3313f518
...@@ -42,13 +42,7 @@ enum _PlatformViewState { ...@@ -42,13 +42,7 @@ enum _PlatformViewState {
/// Android [View](https://developer.android.com/reference/android/view/View). /// Android [View](https://developer.android.com/reference/android/view/View).
/// ///
/// The render object's layout behavior is to fill all available space, the parent of this object must /// The render object's layout behavior is to fill all available space, the parent of this object must
/// provide bounded layout constraints. /// provide bounded layout constraints
///
/// RenderAndroidView participates in Flutter's [GestureArena]s, and dispatches touch events to the
/// Android view iff it won the arena. Specific gestures that should be dispatched to the Android
/// view can be specified in [RenderAndroidView.gestureRecognizers]. If
/// [RenderAndroidView.gestureRecognizers] is empty, the gesture will be dispatched to the Android
/// view iff it was not claimed by any other gesture recognizer.
/// ///
/// See also: /// See also:
/// * [AndroidView] which is a widget that is used to show an Android view. /// * [AndroidView] which is a widget that is used to show an Android view.
...@@ -59,14 +53,10 @@ class RenderAndroidView extends RenderBox { ...@@ -59,14 +53,10 @@ class RenderAndroidView extends RenderBox {
RenderAndroidView({ RenderAndroidView({
@required AndroidViewController viewController, @required AndroidViewController viewController,
@required this.hitTestBehavior, @required this.hitTestBehavior,
List<OneSequenceGestureRecognizer> gestureRecognizers = const <OneSequenceGestureRecognizer> [],
}) : assert(viewController != null), }) : assert(viewController != null),
assert(hitTestBehavior != null), assert(hitTestBehavior != null),
assert(gestureRecognizers != null), _viewController = viewController {
_viewController = viewController
{
_motionEventsDispatcher = new _MotionEventsDispatcher(globalToLocal, viewController); _motionEventsDispatcher = new _MotionEventsDispatcher(globalToLocal, viewController);
this.gestureRecognizers = gestureRecognizers;
} }
_PlatformViewState _state = _PlatformViewState.uninitialized; _PlatformViewState _state = _PlatformViewState.uninitialized;
...@@ -90,18 +80,6 @@ class RenderAndroidView extends RenderBox { ...@@ -90,18 +80,6 @@ class RenderAndroidView extends RenderBox {
// any newly arriving events there's nothing we need to invalidate. // any newly arriving events there's nothing we need to invalidate.
PlatformViewHitTestBehavior hitTestBehavior; PlatformViewHitTestBehavior hitTestBehavior;
/// Which gestures should be forwarded to the Android view.
///
/// The gesture recognizers on this list participate in the gesture arena for each pointer
/// that was put down on the render box. If any of the recognizers on this list wins the
/// gesture arena, the entire pointer event sequence starting from the pointer down event
/// will be dispatched to the Android view.
set gestureRecognizers(List<OneSequenceGestureRecognizer> recognizers) {
assert(recognizers != null);
_gestureRecognizer?.dispose();
_gestureRecognizer = new _AndroidViewGestureRecognizer(_motionEventsDispatcher, recognizers);
}
@override @override
bool get sizedByParent => true; bool get sizedByParent => true;
...@@ -113,8 +91,6 @@ class RenderAndroidView extends RenderBox { ...@@ -113,8 +91,6 @@ class RenderAndroidView extends RenderBox {
_MotionEventsDispatcher _motionEventsDispatcher; _MotionEventsDispatcher _motionEventsDispatcher;
_AndroidViewGestureRecognizer _gestureRecognizer;
@override @override
void performResize() { void performResize() {
size = constraints.biggest; size = constraints.biggest;
...@@ -193,109 +169,7 @@ class RenderAndroidView extends RenderBox { ...@@ -193,109 +169,7 @@ class RenderAndroidView extends RenderBox {
@override @override
void handleEvent(PointerEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
if (event is PointerDownEvent) { _motionEventsDispatcher.handlePointerEvent(event);
_gestureRecognizer.addPointer(event);
}
}
@override
void detach() {
_gestureRecognizer.reset();
super.detach();
}
}
class _AndroidViewGestureRecognizer extends OneSequenceGestureRecognizer {
_AndroidViewGestureRecognizer(this.dispatcher, List<OneSequenceGestureRecognizer> gestureRecognizers) {
this.gestureRecognizers = gestureRecognizers;
}
final _MotionEventsDispatcher dispatcher;
// Maps a pointer to a list of its cached pointer events.
// Before the arena for a pointer is resolved all events are cached here, if we win the arena
// the cached events are dispatched to the view, if we lose the arena we clear the cache for
// the pointer.
final Map<int, List<PointerEvent>> cachedEvents = <int, List<PointerEvent>> {};
// Pointer for which we have already won the arena, events for pointers in this set are
// immediately dispatched to the Android view.
final Set<int> forwardedPointers = new Set<int>();
// We use OneSequenceGestureRecognizers as they support gesture arena teams.
// TODO(amirh): get a list of GestureRecognizers here.
// https://github.com/flutter/flutter/issues/20953
List<OneSequenceGestureRecognizer> _gestureRecognizers;
set gestureRecognizers(List<OneSequenceGestureRecognizer> recognizers) {
_gestureRecognizers = recognizers;
team = new GestureArenaTeam();
team.captain = this;
for (OneSequenceGestureRecognizer recognizer in _gestureRecognizers) {
recognizer.team = team;
}
}
@override
void addPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer);
for (OneSequenceGestureRecognizer recognizer in _gestureRecognizers) {
recognizer.addPointer(event);
}
}
@override
String get debugDescription => 'Android view';
@override
void didStopTrackingLastPointer(int pointer) {
resolve(GestureDisposition.rejected);
}
@override
void handleEvent(PointerEvent event) {
if (!forwardedPointers.contains(event.pointer)) {
cacheEvent(event);
} else {
dispatcher.handlePointerEvent(event);
}
stopTrackingIfPointerNoLongerDown(event);
}
@override
void acceptGesture(int pointer) {
flushPointerCache(pointer);
forwardedPointers.add(pointer);
}
@override
void rejectGesture(int pointer) {
stopTrackingPointer(pointer);
cachedEvents.remove(pointer);
}
void cacheEvent(PointerEvent event) {
if (!cachedEvents.containsKey(event.pointer)) {
cachedEvents[event.pointer] = <PointerEvent> [];
}
cachedEvents[event.pointer].add(event);
}
void flushPointerCache(int pointer) {
cachedEvents.remove(pointer)?.forEach(dispatcher.handlePointerEvent);
}
@override
void stopTrackingPointer(int pointer) {
super.stopTrackingPointer(pointer);
forwardedPointers.remove(pointer);
}
void reset() {
forwardedPointers.forEach(super.stopTrackingPointer);
forwardedPointers.clear();
cachedEvents.keys.forEach(super.stopTrackingPointer);
cachedEvents.clear();
resolve(GestureDisposition.rejected);
} }
} }
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -22,12 +21,6 @@ import 'framework.dart'; ...@@ -22,12 +21,6 @@ import 'framework.dart';
/// The widget fill all available space, the parent of this object must provide bounded layout /// The widget fill all available space, the parent of this object must provide bounded layout
/// constraints. /// constraints.
/// ///
/// AndroidView participates in Flutter's [GestureArena]s, and dispatches touch events to the
/// Android view iff it won the arena. Specific gestures that should be dispatched to the Android
/// view can be specified in [AndroidView.gestureRecognizers]. If
/// [AndroidView.gestureRecognizers] is empty, the gesture will be dispatched to the Android
/// view iff it was not claimed by any other gesture recognizer.
///
/// The Android view object is created using a [PlatformViewFactory](/javadoc/io/flutter/plugin/platform/PlatformViewFactory.html). /// The Android view object is created using a [PlatformViewFactory](/javadoc/io/flutter/plugin/platform/PlatformViewFactory.html).
/// Plugins can register platform view factories with [PlatformViewRegistry#registerViewFactory](/javadoc/io/flutter/plugin/platform/PlatformViewRegistry.html#registerViewFactory-java.lang.String-io.flutter.plugin.platform.PlatformViewFactory-). /// Plugins can register platform view factories with [PlatformViewRegistry#registerViewFactory](/javadoc/io/flutter/plugin/platform/PlatformViewRegistry.html#registerViewFactory-java.lang.String-io.flutter.plugin.platform.PlatformViewFactory-).
/// ///
...@@ -48,7 +41,7 @@ import 'framework.dart'; ...@@ -48,7 +41,7 @@ import 'framework.dart';
class AndroidView extends StatefulWidget { class AndroidView extends StatefulWidget {
/// Creates a widget that embeds an Android view. /// Creates a widget that embeds an Android view.
/// ///
/// The `viewType`, `hitTestBehavior`, and `gestureRecognizers` parameters must not be null. /// The `viewType` and `hitTestBehavior` parameters must not be null.
/// If `creationParams` is not null then `creationParamsCodec` must not be null. /// If `creationParams` is not null then `creationParamsCodec` must not be null.
AndroidView({ AndroidView({
Key key, Key key,
...@@ -56,12 +49,10 @@ class AndroidView extends StatefulWidget { ...@@ -56,12 +49,10 @@ class AndroidView extends StatefulWidget {
this.onPlatformViewCreated, this.onPlatformViewCreated,
this.hitTestBehavior = PlatformViewHitTestBehavior.opaque, this.hitTestBehavior = PlatformViewHitTestBehavior.opaque,
this.layoutDirection, this.layoutDirection,
this.gestureRecognizers = const <OneSequenceGestureRecognizer> [],
this.creationParams, this.creationParams,
this.creationParamsCodec this.creationParamsCodec
}) : assert(viewType != null), }) : assert(viewType != null),
assert(hitTestBehavior != null), assert(hitTestBehavior != null),
assert(gestureRecognizers != null),
assert(creationParams == null || creationParamsCodec != null), assert(creationParams == null || creationParamsCodec != null),
super(key: key); super(key: key);
...@@ -87,17 +78,6 @@ class AndroidView extends StatefulWidget { ...@@ -87,17 +78,6 @@ class AndroidView extends StatefulWidget {
/// If this is null, the ambient [Directionality] is used instead. /// If this is null, the ambient [Directionality] is used instead.
final TextDirection layoutDirection; final TextDirection layoutDirection;
/// Which gestures should be forwarded to the Android view.
///
/// The gesture recognizers on this list participate in the gesture arena for each pointer
/// that was put down on the widget. If any of the recognizers on this list wins the
/// gesture arena, the entire pointer event sequence starting from the pointer down event
/// will be dispatched to the Android view.
// We use OneSequenceGestureRecognizers as they support gesture arena teams.
// TODO(amirh): get a list of GestureRecognizers here.
// https://github.com/flutter/flutter/issues/20953
final List<OneSequenceGestureRecognizer> gestureRecognizers;
/// Passed as the args argument of [PlatformViewFactory#create](/javadoc/io/flutter/plugin/platform/PlatformViewFactory.html#create-android.content.Context-int-java.lang.Object-) /// Passed as the args argument of [PlatformViewFactory#create](/javadoc/io/flutter/plugin/platform/PlatformViewFactory.html#create-android.content.Context-int-java.lang.Object-)
/// ///
/// This can be used by plugins to pass constructor parameters to the embedded Android view. /// This can be used by plugins to pass constructor parameters to the embedded Android view.
...@@ -125,8 +105,7 @@ class _AndroidViewState extends State<AndroidView> { ...@@ -125,8 +105,7 @@ class _AndroidViewState extends State<AndroidView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new _AndroidPlatformView( return new _AndroidPlatformView(
controller: _controller, controller: _controller,
hitTestBehavior: widget.hitTestBehavior, hitTestBehavior: widget.hitTestBehavior
gestureRecognizers: widget.gestureRecognizers,
); );
} }
...@@ -203,28 +182,20 @@ class _AndroidPlatformView extends LeafRenderObjectWidget { ...@@ -203,28 +182,20 @@ class _AndroidPlatformView extends LeafRenderObjectWidget {
Key key, Key key,
@required this.controller, @required this.controller,
@required this.hitTestBehavior, @required this.hitTestBehavior,
@required this.gestureRecognizers,
}) : assert(controller != null), }) : assert(controller != null),
assert(hitTestBehavior != null), assert(hitTestBehavior != null),
assert(gestureRecognizers != null),
super(key: key); super(key: key);
final AndroidViewController controller; final AndroidViewController controller;
final PlatformViewHitTestBehavior hitTestBehavior; final PlatformViewHitTestBehavior hitTestBehavior;
final List<OneSequenceGestureRecognizer> gestureRecognizers;
@override @override
RenderObject createRenderObject(BuildContext context) => RenderObject createRenderObject(BuildContext context) =>
new RenderAndroidView( new RenderAndroidView(viewController: controller, hitTestBehavior: hitTestBehavior);
viewController: controller,
hitTestBehavior: hitTestBehavior,
gestureRecognizers: gestureRecognizers,
);
@override @override
void updateRenderObject(BuildContext context, RenderAndroidView renderObject) { void updateRenderObject(BuildContext context, RenderAndroidView renderObject) {
renderObject.viewController = controller; renderObject.viewController = controller;
renderObject.hitTestBehavior = hitTestBehavior; renderObject.hitTestBehavior = hitTestBehavior;
renderObject.gestureRecognizers = gestureRecognizers;
} }
} }
...@@ -513,75 +513,4 @@ void main() { ...@@ -513,75 +513,4 @@ void main() {
]), ]),
); );
}); });
testWidgets('Android view can lose gesture arenas', (WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
final FakePlatformViewsController viewsController = new FakePlatformViewsController(TargetPlatform.android);
viewsController.registerViewType('webview');
bool verticalDragAcceptedByParent = false;
await tester.pumpWidget(
new Align(
alignment: Alignment.topLeft,
child: new Container(
margin: const EdgeInsets.all(10.0),
child: GestureDetector(
onVerticalDragStart: (DragStartDetails d) { verticalDragAcceptedByParent = true; },
child: SizedBox(
width: 200.0,
height: 100.0,
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
),
),
),
),
);
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
await gesture.moveBy(const Offset(0.0, 100.0));
await gesture.up();
expect(verticalDragAcceptedByParent, true);
expect(
viewsController.motionEvents[currentViewId + 1],
isNull,
);
});
testWidgets('Android view gesture recognizers', (WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
final FakePlatformViewsController viewsController = new FakePlatformViewsController(TargetPlatform.android);
viewsController.registerViewType('webview');
bool verticalDragAcceptedByParent = false;
await tester.pumpWidget(
new Align(
alignment: Alignment.topLeft,
child: GestureDetector(
onVerticalDragStart: (DragStartDetails d) { verticalDragAcceptedByParent = true; },
child: SizedBox(
width: 200.0,
height: 100.0,
child: AndroidView(
viewType: 'webview',
gestureRecognizers: <OneSequenceGestureRecognizer> [new VerticalDragGestureRecognizer()],
layoutDirection: TextDirection.ltr,
),
),
),
),
);
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
await gesture.moveBy(const Offset(0.0, 100.0));
await gesture.up();
expect(verticalDragAcceptedByParent, false);
expect(
viewsController.motionEvents[currentViewId + 1],
orderedEquals(<FakeMotionEvent> [
const FakeMotionEvent(AndroidViewController.kActionDown, <int> [0], <Offset> [Offset(50.0, 50.0)]),
const FakeMotionEvent(AndroidViewController.kActionMove, <int> [0], <Offset> [Offset(50.0, 150.0)]),
const FakeMotionEvent(AndroidViewController.kActionUp, <int> [0], <Offset> [Offset(50.0, 150.0)]),
]),
);
});
} }
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