Unverified Commit 5398f5c5 authored by Tong Mu's avatar Tong Mu Committed by GitHub

Add tests for platform views' hover behavior (#61667)

parent 88a7d83a
......@@ -12,6 +12,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart';
import 'binding.dart';
import 'box.dart';
import 'layer.dart';
import 'mouse_cursor.dart';
......@@ -662,9 +663,15 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin {
mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
/// How to behave during hit testing.
// The implicit setter is enough here as changing this value will just affect
// any newly arriving events there's nothing we need to invalidate.
PlatformViewHitTestBehavior hitTestBehavior;
// Changing _hitTestBehavior might affect which objects are considered hovered over.
set hitTestBehavior(PlatformViewHitTestBehavior value) {
if (value != _hitTestBehavior) {
_hitTestBehavior = value;
if (owner != null)
RendererBinding.instance.mouseTracker.schedulePostFrameCheck();
}
}
PlatformViewHitTestBehavior _hitTestBehavior;
_HandlePointerEvent _handlePointerEvent;
......@@ -690,15 +697,15 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
@override
bool hitTest(BoxHitTestResult result, { Offset position }) {
if (hitTestBehavior == PlatformViewHitTestBehavior.transparent || !size.contains(position)) {
if (_hitTestBehavior == PlatformViewHitTestBehavior.transparent || !size.contains(position)) {
return false;
}
result.add(BoxHitTestEntry(this, position));
return hitTestBehavior == PlatformViewHitTestBehavior.opaque;
return _hitTestBehavior == PlatformViewHitTestBehavior.opaque;
}
@override
bool hitTestSelf(Offset position) => hitTestBehavior != PlatformViewHitTestBehavior.transparent;
bool hitTestSelf(Offset position) => _hitTestBehavior != PlatformViewHitTestBehavior.transparent;
@override
PointerEnterEventListener get onEnter => null;
......
......@@ -19,6 +19,7 @@ void main() {
FakePlatformViewController fakePlatformViewController;
PlatformViewRenderBox platformViewRenderBox;
setUp(() {
renderer; // Initialize bindings
fakePlatformViewController = FakePlatformViewController(0);
platformViewRenderBox = PlatformViewRenderBox(
controller: fakePlatformViewController,
......
......@@ -2433,4 +2433,144 @@ void main() {
expect(controller.focusCleared, true);
});
});
testWidgets('Platform views respect hitTestBehavior', (WidgetTester tester) async {
final FakePlatformViewController controller = FakePlatformViewController(0);
final List<String> logs = <String>[];
// -------------------------
// | MouseRegion1 | MouseRegion1
// | |-----------------| | |
// | | MouseRegion2 | | |- Stack
// | | |---------| | | |
// | | |Platform | | | |- MouseRegion2
// | | |View | | | |- PlatformView
// | | |---------| | |
// | | | |
// | |-----------------| |
// | |
// -------------------------
Widget scaffold(Widget target) {
return Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
width: 600,
height: 600,
child: MouseRegion(
onEnter: (_) { logs.add('enter1'); },
onExit: (_) { logs.add('exit1'); },
cursor: SystemMouseCursors.forbidden,
child: Stack(
children: <Widget>[
Center(
child: SizedBox(
width: 400,
height: 400,
child: MouseRegion(
onEnter: (_) { logs.add('enter2'); },
onExit: (_) { logs.add('exit2'); },
cursor: SystemMouseCursors.text,
),
),
),
Center(
child: SizedBox(
width: 200,
height: 200,
child: target,
),
),
],
)
),
),
),
);
}
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 0);
addTearDown(gesture.removePointer);
// Test: Opaque
await tester.pumpWidget(
scaffold(PlatformViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}
))
);
logs.clear();
await gesture.moveTo(const Offset(400, 300));
expect(logs, <String>['enter1']);
expect(controller.dispatchedPointerEvents, hasLength(1));
expect(controller.dispatchedPointerEvents[0].runtimeType, PointerHoverEvent);
logs.clear();
controller.dispatchedPointerEvents.clear();
// Test: changing no option does not trigger events
await tester.pumpWidget(
scaffold(PlatformViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}
))
);
expect(logs, isEmpty);
expect(controller.dispatchedPointerEvents, isEmpty);
// Test: Transluscent
await tester.pumpWidget(
scaffold(PlatformViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.translucent,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}
))
);
expect(logs, <String>['enter2']);
expect(controller.dispatchedPointerEvents, isEmpty);
logs.clear();
await gesture.moveBy(const Offset(1, 1));
expect(logs, isEmpty);
expect(controller.dispatchedPointerEvents, hasLength(1));
expect(controller.dispatchedPointerEvents[0].runtimeType, PointerHoverEvent);
expect(controller.dispatchedPointerEvents[0].position, const Offset(401, 301));
expect(controller.dispatchedPointerEvents[0].localPosition, const Offset(101, 101));
controller.dispatchedPointerEvents.clear();
// Test: Transparent
await tester.pumpWidget(
scaffold(PlatformViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.transparent,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}
))
);
expect(logs, isEmpty);
expect(controller.dispatchedPointerEvents, isEmpty);
await gesture.moveBy(const Offset(1, 1));
expect(logs, isEmpty);
expect(controller.dispatchedPointerEvents, isEmpty);
// Test: Back to opaque
await tester.pumpWidget(
scaffold(PlatformViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}
))
);
expect(logs, <String>['exit2']);
expect(controller.dispatchedPointerEvents, isEmpty);
logs.clear();
await gesture.moveBy(const Offset(1, 1));
expect(logs, isEmpty);
expect(controller.dispatchedPointerEvents, hasLength(1));
expect(controller.dispatchedPointerEvents[0].runtimeType, PointerHoverEvent);
});
}
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