From 45437650c36628da4396f7d9d43c6a0a2d6114de Mon Sep 17 00:00:00 2001 From: nbayati <99771966+nbayati@users.noreply.github.com> Date: Tue, 17 Jan 2023 16:54:47 -0800 Subject: [PATCH] wrap focus() in a post update callback (#38958) --- .../lib/src/engine/semantics/tappable.dart | 4 +++- .../test/engine/semantics/semantics_test.dart | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/semantics/tappable.dart b/lib/web_ui/lib/src/engine/semantics/tappable.dart index 2c8ad8a6012df..311b5b77a00c6 100644 --- a/lib/web_ui/lib/src/engine/semantics/tappable.dart +++ b/lib/web_ui/lib/src/engine/semantics/tappable.dart @@ -61,7 +61,9 @@ class Tappable extends RoleManager { // Request focus so that the AT shifts a11y focus to this node. if (semanticsObject.isFlagsDirty && semanticsObject.hasFocus) { - element.focus(); + semanticsObject.owner.addOneTimePostUpdateCallback(() { + element.focus(); + }); } } diff --git a/lib/web_ui/test/engine/semantics/semantics_test.dart b/lib/web_ui/test/engine/semantics/semantics_test.dart index 3de8054bc9844..e35d5f6e40dc1 100644 --- a/lib/web_ui/test/engine/semantics/semantics_test.dart +++ b/lib/web_ui/test/engine/semantics/semantics_test.dart @@ -1628,6 +1628,27 @@ void _testTappable() { semantics().semanticsEnabled = false; }); + + test('focuses on tappable after element has been attached', () async { + semantics() + ..debugOverrideTimestampFunction(() => _testTime) + ..semanticsEnabled = true; + + final SemanticsTester tester = SemanticsTester(semantics()); + tester.updateNode( + id: 0, + hasTap: true, + hasEnabledState: true, + isEnabled: true, + isButton: true, + isFocused: true, + rect: const ui.Rect.fromLTRB(0, 0, 100, 50), + ); + tester.apply(); + + expect(flutterViewEmbedder.glassPaneShadow!.activeElement, tester.getSemanticsObject(0).element); + semantics().semanticsEnabled = false; + }); } void _testImage() {