Unverified Commit 7ab8767a authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix focus traversal regions to account for transforms. (#55600)

parent a60e4d1f
......@@ -640,38 +640,38 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
/// Returns the size of the attached widget's [RenderObject], in logical
/// units.
Size get size {
assert(
context != null,
"Tried to get the size of a focus node that didn't have its context set yet.\n"
'The context needs to be set before trying to evaluate traversal policies. This '
'is typically done with the attach method.');
return context.findRenderObject().semanticBounds.size;
}
///
/// Size is the size of the transformed widget in global coordinates.
Size get size => rect.size;
/// Returns the global offset to the upper left corner of the attached
/// widget's [RenderObject], in logical units.
///
/// Offset is the offset of the transformed widget in global coordinates.
Offset get offset {
assert(
context != null,
"Tried to get the offset of a focus node that didn't have its context set yet.\n"
'The context needs to be set before trying to evaluate traversal policies. This '
'is typically done with the attach method.');
'The context needs to be set before trying to evaluate traversal policies. '
'Setting the context is typically done with the attach method.');
final RenderObject object = context.findRenderObject();
return MatrixUtils.transformPoint(object.getTransformTo(null), object.semanticBounds.topLeft);
}
/// Returns the global rectangle of the attached widget's [RenderObject], in
/// logical units.
///
/// Rect is the rectangle of the transformed widget in global coordinates.
Rect get rect {
assert(
context != null,
"Tried to get the bounds of a focus node that didn't have its context set yet.\n"
'The context needs to be set before trying to evaluate traversal policies. This '
'is typically done with the attach method.');
'The context needs to be set before trying to evaluate traversal policies. '
'Setting the context is typically done with the attach method.');
final RenderObject object = context.findRenderObject();
final Offset globalOffset = MatrixUtils.transformPoint(object.getTransformTo(null), object.semanticBounds.topLeft);
return globalOffset & object.semanticBounds.size;
final Offset topLeft = MatrixUtils.transformPoint(object.getTransformTo(null), object.semanticBounds.topLeft);
final Offset bottomRight = MatrixUtils.transformPoint(object.getTransformTo(null), object.semanticBounds.bottomRight);
return Rect.fromLTRB(topLeft.dx, topLeft.dy, bottomRight.dx, bottomRight.dy);
}
/// Removes the focus on this node by moving the primary focus to another node.
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
......@@ -62,6 +64,39 @@ void main() {
expect(child2.parent, isNull);
expect(parent.children, isEmpty);
});
testWidgets('Geometry is transformed properly.', (WidgetTester tester) async {
final FocusNode focusNode1 = FocusNode(debugLabel: 'Test Node 1');
final FocusNode focusNode2 = FocusNode(debugLabel: 'Test Node 2');
await tester.pumpWidget(
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Focus(focusNode: focusNode1, child: Container(width: 200, height: 100),),
Transform.translate(
offset: const Offset(10, 20),
child: Transform.scale(
scale: 0.33,
child: Transform.rotate(
angle: math.pi,
child: Focus(focusNode: focusNode2, child: Container(width: 200, height: 100)),
),
),
),
],
),
),
);
focusNode2.requestFocus();
await tester.pump();
expect(focusNode1.rect, equals(const Rect.fromLTRB(300.0, 8.0, 500.0, 108.0)));
expect(focusNode2.rect, equals(const Rect.fromLTRB(443.0, 194.5, 377.0, 161.5)));
expect(focusNode1.size, equals(const Size(200.0, 100.0)));
expect(focusNode2.size, equals(const Size(-66.0, -33.0)));
expect(focusNode1.offset, equals(const Offset(300.0, 8.0)));
expect(focusNode2.offset, equals(const Offset(443.0, 194.5)));
});
testWidgets('implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
FocusNode(
......
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