Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Send the correct view ID with semantics actions #56595

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1298,14 +1298,19 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
/// Engine code should use this method instead of the callback directly.
/// Otherwise zones won't work properly.
void invokeOnSemanticsAction(
int nodeId, ui.SemanticsAction action, ByteData? args) {
SemanticsObject semanticsObject,
ui.SemanticsAction action,
ByteData? args,
) {
final int nodeId = semanticsObject.id;
final EngineFlutterView? view = viewManager.findViewForElement(semanticsObject.owner.semanticsHost);
invoke1<ui.SemanticsActionEvent>(
_onSemanticsActionEvent,
_onSemanticsActionEventZone,
ui.SemanticsActionEvent(
type: action,
nodeId: nodeId,
viewId: 0, // TODO(goderbauer): Wire up the real view ID.
viewId: view?.viewId ?? kImplicitViewId,
arguments: args,
),
);
Expand Down
10 changes: 5 additions & 5 deletions lib/web_ui/lib/src/engine/pointer_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ class ClickDebouncer {
/// Forwards the event to the framework, unless it is deduplicated because
/// the corresponding pointer down/up events were recently flushed to the
/// framework already.
void onClick(DomEvent click, int semanticsNodeId, bool isListening) {
void onClick(DomEvent click, SemanticsObject semanticsObject, bool isListening) {
assert(click.type == 'click');

if (!isDebouncing) {
Expand All @@ -280,7 +280,7 @@ class ClickDebouncer {
// recently and if the node is currently listening to event, forward to
// the framework.
if (isListening && _shouldSendClickEventToFramework(click)) {
_sendSemanticsTapToFramework(click, semanticsNodeId);
_sendSemanticsTapToFramework(click, semanticsObject);
}
return;
}
Expand All @@ -292,7 +292,7 @@ class ClickDebouncer {
final DebounceState state = _state!;
_state = null;
state.timer.cancel();
_sendSemanticsTapToFramework(click, semanticsNodeId);
_sendSemanticsTapToFramework(click, semanticsObject);
} else {
// The semantic node is not listening to taps. Flush the pointer events
// for the framework to figure out what to do with them. It's possible
Expand All @@ -301,7 +301,7 @@ class ClickDebouncer {
}
}

void _sendSemanticsTapToFramework(DomEvent click, int semanticsNodeId) {
void _sendSemanticsTapToFramework(DomEvent click, SemanticsObject semanticsObject) {
// Tappable nodes can be nested inside other tappable nodes. If a click
// lands on an inner element and is allowed to propagate, it will also
// land on the ancestor tappable, leading to both the descendant and the
Expand All @@ -312,7 +312,7 @@ class ClickDebouncer {
click.stopPropagation();

EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsNodeId, ui.SemanticsAction.tap, null);
semanticsObject, ui.SemanticsAction.tap, null);
reset();
}

Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/semantics/focusable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class AccessibilityFocusManager {
// shifting focus.
if (_lastEvent != AccessibilityFocusManagerEvent.requestedFocus) {
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
target.semanticsNodeId,
_owner.getSemanticsObjectById(target.semanticsNodeId)!,
ui.SemanticsAction.focus,
null,
);
Expand Down
4 changes: 2 additions & 2 deletions lib/web_ui/lib/src/engine/semantics/incrementable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ class SemanticIncrementable extends SemanticRole {
if (newInputValue > _currentSurrogateValue) {
_currentSurrogateValue += 1;
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsObject.id, ui.SemanticsAction.increase, null);
semanticsObject, ui.SemanticsAction.increase, null);
} else if (newInputValue < _currentSurrogateValue) {
_currentSurrogateValue -= 1;
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsObject.id, ui.SemanticsAction.decrease, null);
semanticsObject, ui.SemanticsAction.decrease, null);
}
}));

Expand Down
9 changes: 4 additions & 5 deletions lib/web_ui/lib/src/engine/semantics/scrollable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,23 @@ class SemanticScrollable extends SemanticRole {
_neutralizeDomScrollPosition();
semanticsObject.recomputePositionAndSize();

final int semanticsId = semanticsObject.id;
if (doScrollForward) {
if (semanticsObject.isVerticalScrollContainer) {
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsId, ui.SemanticsAction.scrollUp, null);
semanticsObject, ui.SemanticsAction.scrollUp, null);
} else {
assert(semanticsObject.isHorizontalScrollContainer);
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsId, ui.SemanticsAction.scrollLeft, null);
semanticsObject, ui.SemanticsAction.scrollLeft, null);
}
} else {
if (semanticsObject.isVerticalScrollContainer) {
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsId, ui.SemanticsAction.scrollDown, null);
semanticsObject, ui.SemanticsAction.scrollDown, null);
} else {
assert(semanticsObject.isHorizontalScrollContainer);
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsId, ui.SemanticsAction.scrollRight, null);
semanticsObject, ui.SemanticsAction.scrollRight, null);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions lib/web_ui/lib/src/engine/semantics/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2415,6 +2415,11 @@ class EngineSemanticsOwner {
/// this frame.
Map<int, SemanticsObject> _attachments = <int, SemanticsObject>{};

/// Retrieves the [SemanticsObject] with the given [semanticsNodeId].
SemanticsObject? getSemanticsObjectById(int semanticsNodeId) {
return _semanticsTree[semanticsNodeId];
}

/// Declares that the [child] must be attached to the [parent].
///
/// Attachments take precedence over detachments (see [_detachObject]). This
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/semantics/tappable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Tappable extends SemanticBehavior {
_clickListener = createDomEventListener((DomEvent click) {
PointerBinding.clickDebouncer.onClick(
click,
semanticsObject.id,
semanticsObject,
_isListening,
);
});
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/semantics/text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class SemanticTextField extends SemanticRole {
// IMPORTANT: because this event listener can be triggered by either or
// both a "focus" and a "click" DOM events, this code must be idempotent.
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
semanticsObject.id, ui.SemanticsAction.focus, null);
semanticsObject, ui.SemanticsAction.focus, null);
}));
editableElement.addEventListener('click', createDomEventListener((DomEvent event) {
editableElement.focusWithoutScroll();
Expand Down
6 changes: 5 additions & 1 deletion lib/web_ui/test/engine/window_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,11 @@ Future<void> testMain() async {
expect(ui.PlatformDispatcher.instance.onSemanticsActionEvent, same(callback));
});

EnginePlatformDispatcher.instance.invokeOnSemanticsAction(0, ui.SemanticsAction.tap, null);
EnginePlatformDispatcher.instance.invokeOnSemanticsAction(
myWindow.semantics.getSemanticsObjectById(0)!,
ui.SemanticsAction.tap,
null,
);
});

test('onAccessibilityFeaturesChanged preserves the zone', () {
Expand Down