mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Implement PlatformDispatcher.requestViewFocusChange on web. (flutter/engine#50535)
Implement PlatformDispatcher.requestViewFocusChange on web. Relevant Issues are: * Design doc: https://flutter.dev/go/focus-management * Focus in web multiview: https://github.com/flutter/flutter/issues/137443 * Platform dispatcher changes: https://github.com/flutter/engine/pull/49841 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
parent
674874e613
commit
db857bd325
@ -257,7 +257,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
required ui.ViewFocusState state,
|
||||
required ui.ViewFocusDirection direction,
|
||||
}) {
|
||||
// TODO(tugorez): implement this method. At the moment will be a no op call.
|
||||
_viewFocusBinding.changeViewFocus(viewId, state);
|
||||
}
|
||||
|
||||
/// A set of views which have rendered in the current `onBeginFrame` or
|
||||
|
||||
@ -34,6 +34,19 @@ final class ViewFocusBinding {
|
||||
_onViewCreatedListener?.cancel();
|
||||
}
|
||||
|
||||
void changeViewFocus(int viewId, ui.ViewFocusState state) {
|
||||
final DomElement? viewElement = _viewManager[viewId]?.dom.rootElement;
|
||||
|
||||
if (state == ui.ViewFocusState.focused) {
|
||||
// Only move the focus to the flutter view if nothing inside it is focused already.
|
||||
if (viewId != _viewId(domDocument.activeElement)) {
|
||||
viewElement?.focus();
|
||||
}
|
||||
} else {
|
||||
viewElement?.blur();
|
||||
}
|
||||
}
|
||||
|
||||
late final DomEventListener _handleFocusin = createDomEventListener((DomEvent event) {
|
||||
event as DomFocusEvent;
|
||||
_handleFocusChange(event.target as DomElement?);
|
||||
|
||||
@ -164,6 +164,108 @@ void testMain() {
|
||||
expect(dispatchedViewFocusEvents[2].state, ui.ViewFocusState.unfocused);
|
||||
expect(dispatchedViewFocusEvents[2].direction, ui.ViewFocusDirection.undefined);
|
||||
});
|
||||
|
||||
test('requestViewFocusChange focuses the view', () {
|
||||
final EngineFlutterView view = createAndRegisterView(dispatcher);
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
|
||||
expect(domDocument.activeElement, view.dom.rootElement);
|
||||
|
||||
expect(dispatchedViewFocusEvents, hasLength(1));
|
||||
|
||||
expect(dispatchedViewFocusEvents[0].viewId, view.viewId);
|
||||
expect(dispatchedViewFocusEvents[0].state, ui.ViewFocusState.focused);
|
||||
expect(dispatchedViewFocusEvents[0].direction, ui.ViewFocusDirection.forward);
|
||||
});
|
||||
|
||||
test('requestViewFocusChange blurs the view', () {
|
||||
final EngineFlutterView view = createAndRegisterView(dispatcher);
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.unfocused,
|
||||
direction: ui.ViewFocusDirection.undefined,
|
||||
);
|
||||
|
||||
expect(domDocument.activeElement, isNot(view.dom.rootElement));
|
||||
|
||||
expect(dispatchedViewFocusEvents, hasLength(2));
|
||||
|
||||
expect(dispatchedViewFocusEvents[0].viewId, view.viewId);
|
||||
expect(dispatchedViewFocusEvents[0].state, ui.ViewFocusState.focused);
|
||||
expect(dispatchedViewFocusEvents[0].direction, ui.ViewFocusDirection.forward);
|
||||
|
||||
expect(dispatchedViewFocusEvents[1].viewId, view.viewId);
|
||||
expect(dispatchedViewFocusEvents[1].state, ui.ViewFocusState.unfocused);
|
||||
expect(dispatchedViewFocusEvents[1].direction, ui.ViewFocusDirection.undefined);
|
||||
});
|
||||
|
||||
test('requestViewFocusChange does nothing if the view does not exist', () {
|
||||
final EngineFlutterView view = createAndRegisterView(dispatcher);
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: 5094555,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
|
||||
expect(domDocument.activeElement, isNot(view.dom.rootElement));
|
||||
expect(dispatchedViewFocusEvents, isEmpty);
|
||||
});
|
||||
|
||||
test('requestViewFocusChange does nothing if the view is already focused', () {
|
||||
final EngineFlutterView view = createAndRegisterView(dispatcher);
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
|
||||
expect(dispatchedViewFocusEvents, hasLength(1));
|
||||
|
||||
expect(dispatchedViewFocusEvents[0].viewId, view.viewId);
|
||||
expect(dispatchedViewFocusEvents[0].state, ui.ViewFocusState.focused);
|
||||
expect(dispatchedViewFocusEvents[0].direction, ui.ViewFocusDirection.forward);
|
||||
});
|
||||
|
||||
test('requestViewFocusChange does not move the focus to the view', () {
|
||||
final DomElement input = createDomElement('input');
|
||||
final EngineFlutterView view = createAndRegisterView(dispatcher);
|
||||
|
||||
view.dom.rootElement.append(input);
|
||||
input.focus();
|
||||
|
||||
dispatcher.requestViewFocusChange(
|
||||
viewId: view.viewId,
|
||||
state: ui.ViewFocusState.focused,
|
||||
direction: ui.ViewFocusDirection.forward,
|
||||
);
|
||||
|
||||
expect(domDocument.activeElement, input);
|
||||
|
||||
expect(dispatchedViewFocusEvents, hasLength(1));
|
||||
|
||||
expect(dispatchedViewFocusEvents[0].viewId, view.viewId);
|
||||
expect(dispatchedViewFocusEvents[0].state, ui.ViewFocusState.focused);
|
||||
expect(dispatchedViewFocusEvents[0].direction, ui.ViewFocusDirection.forward);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user