Commit 3b76e7e2 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Make tear-offs cacheable for RenderSemanticsGestureHandler (#11556)

* Make tear-offs cachable for RenderSemanticsGestureHandler

Fixes https://github.com/flutter/flutter/issues/11552

* comment fix

* refactor
parent 1d9f834f
......@@ -530,7 +530,7 @@ class RawGestureDetectorState extends State<RawGestureDetector> {
final RenderSemanticsGestureHandler semanticsGestureHandler = context.findRenderObject();
context.visitChildElements((Element element) {
final _GestureSemantics widget = element.widget;
widget._updateHandlers(semanticsGestureHandler, _recognizers);
widget._updateHandlers(semanticsGestureHandler);
});
}
}
......@@ -600,45 +600,8 @@ class RawGestureDetectorState extends State<RawGestureDetector> {
return widget.child == null ? HitTestBehavior.translucent : HitTestBehavior.deferToChild;
}
@override
Widget build(BuildContext context) {
Widget result = new Listener(
onPointerDown: _handlePointerDown,
behavior: widget.behavior ?? _defaultBehavior,
child: widget.child
);
if (!widget.excludeFromSemantics)
result = new _GestureSemantics(owner: this, child: result);
return result;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
if (_recognizers == null) {
description.add(new DiagnosticsNode.message('DISPOSED'));
} else {
final List<String> gestures = _recognizers.values.map<String>((GestureRecognizer recognizer) => recognizer.debugDescription).toList();
if (gestures.isEmpty)
gestures.add('<none>');
description.add(new IterableProperty<String>('gestures', gestures));
description.add(new IterableProperty<GestureRecognizer>('recognizers', _recognizers.values, hidden: true));
}
description.add(new EnumProperty<HitTestBehavior>('behavior', widget.behavior, defaultValue: null));
}
}
class _GestureSemantics extends SingleChildRenderObjectWidget {
const _GestureSemantics({
Key key,
Widget child,
this.owner
}) : super(key: key, child: child);
final RawGestureDetectorState owner;
void _handleTap() {
final TapGestureRecognizer recognizer = owner._recognizers[TapGestureRecognizer];
void _handleSemanticsTap() {
final TapGestureRecognizer recognizer = _recognizers[TapGestureRecognizer];
assert(recognizer != null);
if (recognizer.onTapDown != null)
recognizer.onTapDown(new TapDownDetails());
......@@ -648,16 +611,16 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
recognizer.onTap();
}
void _handleLongPress() {
final LongPressGestureRecognizer recognizer = owner._recognizers[LongPressGestureRecognizer];
void _handleSemanticsLongPress() {
final LongPressGestureRecognizer recognizer = _recognizers[LongPressGestureRecognizer];
assert(recognizer != null);
if (recognizer.onLongPress != null)
recognizer.onLongPress();
}
void _handleHorizontalDragUpdate(DragUpdateDetails updateDetails) {
void _handleSemanticsHorizontalDragUpdate(DragUpdateDetails updateDetails) {
{
final HorizontalDragGestureRecognizer recognizer = owner._recognizers[HorizontalDragGestureRecognizer];
final HorizontalDragGestureRecognizer recognizer = _recognizers[HorizontalDragGestureRecognizer];
if (recognizer != null) {
if (recognizer.onDown != null)
recognizer.onDown(new DragDownDetails());
......@@ -671,7 +634,7 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
}
}
{
final PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer];
final PanGestureRecognizer recognizer = _recognizers[PanGestureRecognizer];
if (recognizer != null) {
if (recognizer.onDown != null)
recognizer.onDown(new DragDownDetails());
......@@ -686,9 +649,9 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
}
}
void _handleVerticalDragUpdate(DragUpdateDetails updateDetails) {
void _handleSemanticsVerticalDragUpdate(DragUpdateDetails updateDetails) {
{
final VerticalDragGestureRecognizer recognizer = owner._recognizers[VerticalDragGestureRecognizer];
final VerticalDragGestureRecognizer recognizer = _recognizers[VerticalDragGestureRecognizer];
if (recognizer != null) {
if (recognizer.onDown != null)
recognizer.onDown(new DragDownDetails());
......@@ -702,7 +665,7 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
}
}
{
final PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer];
final PanGestureRecognizer recognizer = _recognizers[PanGestureRecognizer];
if (recognizer != null) {
if (recognizer.onDown != null)
recognizer.onDown(new DragDownDetails());
......@@ -718,20 +681,58 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
}
@override
RenderSemanticsGestureHandler createRenderObject(BuildContext context) {
final RenderSemanticsGestureHandler result = new RenderSemanticsGestureHandler();
updateRenderObject(context, result);
Widget build(BuildContext context) {
Widget result = new Listener(
onPointerDown: _handlePointerDown,
behavior: widget.behavior ?? _defaultBehavior,
child: widget.child
);
if (!widget.excludeFromSemantics)
result = new _GestureSemantics(owner: this, child: result);
return result;
}
void _updateHandlers(RenderSemanticsGestureHandler renderObject, Map<Type, GestureRecognizer> recognizers) {
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
if (_recognizers == null) {
description.add(new DiagnosticsNode.message('DISPOSED'));
} else {
final List<String> gestures = _recognizers.values.map<String>((GestureRecognizer recognizer) => recognizer.debugDescription).toList();
if (gestures.isEmpty)
gestures.add('<none>');
description.add(new IterableProperty<String>('gestures', gestures));
description.add(new IterableProperty<GestureRecognizer>('recognizers', _recognizers.values, hidden: true));
}
description.add(new EnumProperty<HitTestBehavior>('behavior', widget.behavior, defaultValue: null));
}
}
class _GestureSemantics extends SingleChildRenderObjectWidget {
const _GestureSemantics({
Key key,
Widget child,
this.owner
}) : super(key: key, child: child);
final RawGestureDetectorState owner;
@override
RenderSemanticsGestureHandler createRenderObject(BuildContext context) {
final RenderSemanticsGestureHandler renderObject = new RenderSemanticsGestureHandler();
_updateHandlers(renderObject);
return renderObject;
}
void _updateHandlers(RenderSemanticsGestureHandler renderObject) {
final Map<Type, GestureRecognizer> recognizers = owner._recognizers;
renderObject
..onTap = recognizers.containsKey(TapGestureRecognizer) ? _handleTap : null
..onLongPress = recognizers.containsKey(LongPressGestureRecognizer) ? _handleLongPress : null
..onTap = recognizers.containsKey(TapGestureRecognizer) ? owner._handleSemanticsTap : null
..onLongPress = recognizers.containsKey(LongPressGestureRecognizer) ? owner._handleSemanticsLongPress : null
..onHorizontalDragUpdate = recognizers.containsKey(HorizontalDragGestureRecognizer) ||
recognizers.containsKey(PanGestureRecognizer) ? _handleHorizontalDragUpdate : null
recognizers.containsKey(PanGestureRecognizer) ? owner._handleSemanticsHorizontalDragUpdate : null
..onVerticalDragUpdate = recognizers.containsKey(VerticalDragGestureRecognizer) ||
recognizers.containsKey(PanGestureRecognizer) ? _handleVerticalDragUpdate : null;
recognizers.containsKey(PanGestureRecognizer) ? owner._handleSemanticsVerticalDragUpdate : null;
}
void _updateSemanticsActions(RenderSemanticsGestureHandler renderObject, Set<SemanticsAction> actions) {
......@@ -740,6 +741,6 @@ class _GestureSemantics extends SingleChildRenderObjectWidget {
@override
void updateRenderObject(BuildContext context, RenderSemanticsGestureHandler renderObject) {
_updateHandlers(renderObject, owner._recognizers);
_updateHandlers(renderObject);
}
}
......@@ -4,6 +4,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/gestures.dart';
void main() {
......@@ -216,4 +217,35 @@ void main() {
await tester.tapAt(const Offset(10.0, 10.0));
expect(didTap, isFalse);
});
testWidgets('cache unchanged callbacks', (WidgetTester tester) async {
final GestureTapCallback inputCallback = () {};
await tester.pumpWidget(
new Center(
child: new GestureDetector(
onTap: inputCallback,
child: new Container(),
)
)
);
final RenderSemanticsGestureHandler renderObj1 = tester.renderObject(find.byType(GestureDetector));
final GestureTapCallback actualCallback1 = renderObj1.onTap;
await tester.pumpWidget(
new Center(
child: new GestureDetector(
onTap: inputCallback,
child: new Container(),
)
)
);
final RenderSemanticsGestureHandler renderObj2 = tester.renderObject(find.byType(GestureDetector));
final GestureTapCallback actualCallback2 = renderObj2.onTap;
expect(renderObj1, same(renderObj2));
expect(actualCallback1, same(actualCallback2)); // Should be cached.
});
}
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