Skip to content

Commit 23d258d

Browse files
authored
Remove deprecated updateSemantics API usage. (#113382)
1 parent 671c532 commit 23d258d

File tree

7 files changed

+100
-22
lines changed

7 files changed

+100
-22
lines changed

packages/flutter/lib/src/rendering/binding.dart

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
import 'dart:developer';
6+
import 'dart:ui' as ui show SemanticsUpdate;
67

78
import 'package:flutter/foundation.dart';
89
import 'package:flutter/gestures.dart';
@@ -31,6 +32,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
3132
_pipelineOwner = PipelineOwner(
3233
onNeedVisualUpdate: ensureVisualUpdate,
3334
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
35+
onSemanticsUpdate: _handleSemanticsUpdate,
3436
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
3537
);
3638
platformDispatcher
@@ -367,6 +369,10 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
367369
renderView.scheduleInitialSemantics();
368370
}
369371

372+
void _handleSemanticsUpdate(ui.SemanticsUpdate update) {
373+
renderView.updateSemantics(update);
374+
}
375+
370376
void _handleSemanticsOwnerDisposed() {
371377
renderView.clearSemantics();
372378
}

packages/flutter/lib/src/rendering/object.dart

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:developer';
66
import 'dart:ui' as ui show PictureRecorder;
7+
import 'dart:ui';
78

89
import 'package:flutter/animation.dart';
910
import 'package:flutter/foundation.dart';
@@ -894,6 +895,7 @@ class PipelineOwner {
894895
PipelineOwner({
895896
this.onNeedVisualUpdate,
896897
this.onSemanticsOwnerCreated,
898+
this.onSemanticsUpdate,
897899
this.onSemanticsOwnerDisposed,
898900
});
899901

@@ -912,6 +914,12 @@ class PipelineOwner {
912914
/// semantics tree.
913915
final VoidCallback? onSemanticsOwnerCreated;
914916

917+
/// Called whenever this pipeline owner's semantics owner emits a [SemanticsUpdate].
918+
///
919+
/// Typical implementations will delegate the [SemanticsUpdate] to a [FlutterView]
920+
/// that can handle the [SemanticsUpdate].
921+
final SemanticsUpdateCallback? onSemanticsUpdate;
922+
915923
/// Called whenever this pipeline owner disposes its semantics owner.
916924
///
917925
/// Typical implementations will tear down the semantics tree.
@@ -1183,7 +1191,8 @@ class PipelineOwner {
11831191
_outstandingSemanticsHandles += 1;
11841192
if (_outstandingSemanticsHandles == 1) {
11851193
assert(_semanticsOwner == null);
1186-
_semanticsOwner = SemanticsOwner();
1194+
assert(onSemanticsUpdate != null, 'Attempted to open a semantics handle without an onSemanticsUpdate callback.');
1195+
_semanticsOwner = SemanticsOwner(onSemanticsUpdate: onSemanticsUpdate!);
11871196
onSemanticsOwnerCreated?.call();
11881197
}
11891198
return SemanticsHandle._(this, listener);

packages/flutter/lib/src/rendering/view.dart

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import 'dart:developer';
66
import 'dart:io' show Platform;
7-
import 'dart:ui' as ui show FlutterView, Scene, SceneBuilder;
7+
import 'dart:ui' as ui show FlutterView, Scene, SceneBuilder, SemanticsUpdate;
88

99
import 'package:flutter/foundation.dart';
1010
import 'package:flutter/services.dart';
@@ -247,6 +247,15 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
247247
}
248248
}
249249

250+
/// Sends the provided [SemanticsUpdate] to the [FlutterView] associated with
251+
/// this [RenderView].
252+
///
253+
/// A [SemanticsUpdate] is produced by a [SemanticsOwner] during the
254+
/// [EnginePhase.flushSemantics] phase.
255+
void updateSemantics(ui.SemanticsUpdate update) {
256+
_window.updateSemantics(update);
257+
}
258+
250259
void _updateSystemChrome() {
251260
// Take overlay style from the place where a system status bar and system
252261
// navigation bar are placed to update system style overlay.

packages/flutter/lib/src/semantics/semantics.dart

+20-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ typedef SetTextHandler = void Function(String text);
4848
/// Returned by [SemanticsConfiguration.getActionHandler].
4949
typedef SemanticsActionHandler = void Function(Object? args);
5050

51+
/// Signature for a function that receives a semantics update and returns no result.
52+
///
53+
/// Used by [SemanticsOwner.onSemanticsUpdate].
54+
typedef SemanticsUpdateCallback = void Function(ui.SemanticsUpdate update);
55+
5156
/// A tag for a [SemanticsNode].
5257
///
5358
/// Tags can be interpreted by the parent of a [SemanticsNode]
@@ -3052,6 +3057,19 @@ class _TraversalSortNode implements Comparable<_TraversalSortNode> {
30523057
/// obtain a [SemanticsHandle]. This will create a [SemanticsOwner] if
30533058
/// necessary.
30543059
class SemanticsOwner extends ChangeNotifier {
3060+
/// Creates a [SemanticsOwner] that manages zero or more [SemanticsNode] objects.
3061+
SemanticsOwner({
3062+
required this.onSemanticsUpdate,
3063+
});
3064+
3065+
/// The [onSemanticsUpdate] callback is expected to dispatch [SemanticsUpdate]s
3066+
/// to the [FlutterView] that is associated with this [PipelineOwner] and/or
3067+
/// [SemanticsOwner].
3068+
///
3069+
/// A [SemanticsOwner] calls [onSemanticsUpdate] during [sendSemanticsUpdate]
3070+
/// after the [SemanticsUpdate] has been build, but before the [SemanticsOwner]'s
3071+
/// listeners have been notified.
3072+
final SemanticsUpdateCallback onSemanticsUpdate;
30553073
final Set<SemanticsNode> _dirtyNodes = <SemanticsNode>{};
30563074
final Map<int, SemanticsNode> _nodes = <int, SemanticsNode>{};
30573075
final Set<SemanticsNode> _detachedNodes = <SemanticsNode>{};
@@ -3069,7 +3087,7 @@ class SemanticsOwner extends ChangeNotifier {
30693087
super.dispose();
30703088
}
30713089

3072-
/// Update the semantics using [dart:ui.PlatformDispatcher.updateSemantics].
3090+
/// Update the semantics using [onSemanticsUpdate].
30733091
void sendSemanticsUpdate() {
30743092
if (_dirtyNodes.isEmpty) {
30753093
return;
@@ -3118,9 +3136,7 @@ class SemanticsOwner extends ChangeNotifier {
31183136
final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
31193137
builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
31203138
}
3121-
// TODO(a-wallen): https://github.com/flutter/flutter/issues/112221
3122-
// ignore: deprecated_member_use
3123-
SemanticsBinding.instance.platformDispatcher.updateSemantics(builder.build());
3139+
onSemanticsUpdate(builder.build());
31243140
notifyListeners();
31253141
}
31263142

packages/flutter/test/rendering/object_test.dart

+49-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ void main() {
1818
// Initialize all bindings because owner.flushSemantics() requires a window
1919
final TestRenderObject renderObject = TestRenderObject();
2020
int onNeedVisualUpdateCallCount = 0;
21-
final PipelineOwner owner = PipelineOwner(onNeedVisualUpdate: () {
22-
onNeedVisualUpdateCallCount +=1;
23-
});
21+
final PipelineOwner owner = PipelineOwner(
22+
onNeedVisualUpdate: () {
23+
onNeedVisualUpdateCallCount +=1;
24+
},
25+
onSemanticsUpdate: (ui.SemanticsUpdate update) {}
26+
);
2427
owner.ensureSemantics();
2528
renderObject.attach(owner);
2629
renderObject.layout(const BoxConstraints.tightForFinite()); // semantics are only calculated if layout information is up to date.
@@ -31,6 +34,49 @@ void main() {
3134
expect(onNeedVisualUpdateCallCount, 2);
3235
});
3336

37+
test('onSemanticsUpdate is called during flushSemantics.', () {
38+
int onSemanticsUpdateCallCount = 0;
39+
final PipelineOwner owner = PipelineOwner(
40+
onSemanticsUpdate: (ui.SemanticsUpdate update) {
41+
onSemanticsUpdateCallCount += 1;
42+
},
43+
);
44+
owner.ensureSemantics();
45+
46+
expect(onSemanticsUpdateCallCount, 0);
47+
48+
final TestRenderObject renderObject = TestRenderObject();
49+
renderObject.attach(owner);
50+
renderObject.layout(const BoxConstraints.tightForFinite());
51+
owner.flushSemantics();
52+
53+
expect(onSemanticsUpdateCallCount, 1);
54+
});
55+
56+
test('Enabling semantics without configuring onSemanticsUpdate is invalid.', () {
57+
final PipelineOwner pipelineOwner = PipelineOwner();
58+
expect(() => pipelineOwner.ensureSemantics(), throwsAssertionError);
59+
});
60+
61+
62+
test('onSemanticsUpdate during sendSemanticsUpdate.', () {
63+
int onSemanticsUpdateCallCount = 0;
64+
final SemanticsOwner owner = SemanticsOwner(
65+
onSemanticsUpdate: (ui.SemanticsUpdate update) {
66+
onSemanticsUpdateCallCount += 1;
67+
},
68+
);
69+
70+
final SemanticsNode node = SemanticsNode.root(owner: owner);
71+
node.rect = Rect.largest;
72+
73+
expect(onSemanticsUpdateCallCount, 0);
74+
75+
owner.sendSemanticsUpdate();
76+
77+
expect(onSemanticsUpdateCallCount, 1);
78+
});
79+
3480
test('detached RenderObject does not do semantics', () {
3581
final TestRenderObject renderObject = TestRenderObject();
3682
expect(renderObject.attached, isFalse);

packages/flutter/test/semantics/semantics_test.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:ui';
6+
57
import 'package:flutter/rendering.dart';
68
import 'package:flutter_test/flutter_test.dart';
79
import 'package:vector_math/vector_math_64.dart';
@@ -698,7 +700,9 @@ void main() {
698700
});
699701

700702
test('Semantics id does not repeat', () {
701-
final SemanticsOwner owner = SemanticsOwner();
703+
final SemanticsOwner owner = SemanticsOwner(
704+
onSemanticsUpdate: (SemanticsUpdate update) {},
705+
);
702706
const int expectId = 1400;
703707
SemanticsNode? nodeToRemove;
704708
for (int i = 0; i < kMaxFrameworkAccessibilityIdentifier; i++) {

packages/flutter_test/lib/src/window.dart

-12
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,6 @@ class TestWindow implements ui.SingletonFlutterWindow {
463463
platformDispatcher.onAccessibilityFeaturesChanged = callback;
464464
}
465465

466-
@override
467-
void updateSemantics(ui.SemanticsUpdate update) {
468-
platformDispatcher.updateSemantics(update);
469-
}
470-
471466
@override
472467
void setIsolateDebugName(String name) {
473468
platformDispatcher.setIsolateDebugName(name);
@@ -851,13 +846,6 @@ class TestPlatformDispatcher implements ui.PlatformDispatcher {
851846
_platformDispatcher.onAccessibilityFeaturesChanged = callback;
852847
}
853848

854-
@override
855-
void updateSemantics(ui.SemanticsUpdate update) {
856-
// TODO(a-wallen): https://github.com/flutter/flutter/issues/112221
857-
// ignore: deprecated_member_use
858-
_platformDispatcher.updateSemantics(update);
859-
}
860-
861849
@override
862850
void setIsolateDebugName(String name) {
863851
_platformDispatcher.setIsolateDebugName(name);

0 commit comments

Comments
 (0)