-
Notifications
You must be signed in to change notification settings - Fork 6k
Fix focus management for text fields #51009
Changes from all commits
d2e4ccc
ea09d6e
edab1dc
8bbc206
ed2f851
78521ec
72d3956
7a6c596
11b7dae
df75938
edfdacf
7daf2a1
7e811da
c23c944
08ab966
8c99cb4
153eee4
e8cf8e8
5cf50ac
6f85439
e931fbc
d70596d
e5af604
e54f9ad
9a194d3
dca6a02
318a2dd
2a6c339
e35705e
39c5c8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -658,7 +658,16 @@ extension DomElementExtension on DomElement { | |
external JSNumber? get _tabIndex; | ||
double? get tabIndex => _tabIndex?.toDartDouble; | ||
|
||
external JSVoid focus(); | ||
@JS('focus') | ||
external JSVoid _focus(JSAny options); | ||
|
||
void focus({bool? preventScroll, bool? focusVisible}) { | ||
final Map<String, bool> options = <String, bool>{ | ||
if (preventScroll != null) 'preventScroll': preventScroll, | ||
if (focusVisible != null) 'focusVisible': focusVisible, | ||
}; | ||
_focus(options.toJSAnyDeep); | ||
} | ||
|
||
@JS('scrollTop') | ||
external JSNumber get _scrollTop; | ||
|
@@ -2249,9 +2258,11 @@ extension DomKeyboardEventExtension on DomKeyboardEvent { | |
external JSBoolean? get _repeat; | ||
bool? get repeat => _repeat?.toDart; | ||
|
||
// Safari injects synthetic keyboard events after auto-complete that don't | ||
// have a `shiftKey` attribute, so this property must be nullable. | ||
@JS('shiftKey') | ||
external JSBoolean get _shiftKey; | ||
bool get shiftKey => _shiftKey.toDart; | ||
external JSBoolean? get _shiftKey; | ||
bool? get shiftKey => _shiftKey?.toDart; | ||
Comment on lines
+2264
to
+2265
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is unrelated to this PR, I can move it to a separate PR to keep this one small. |
||
|
||
@JS('isComposing') | ||
external JSBoolean get _isComposing; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ final class ViewFocusBinding { | |
/// | ||
/// DO NOT rely on this bit as it will go away soon. You're warned :)! | ||
@visibleForTesting | ||
static bool isEnabled = false; | ||
static bool isEnabled = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ditman we might want to reland these changes but with this one set to false. Not sure what's breaking on the framework side but don't think the rest of these changes is related. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will take a look! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
final FlutterViewManager _viewManager; | ||
final ui.ViewFocusChangeCallback _onViewFocusChange; | ||
|
@@ -51,7 +51,7 @@ final class ViewFocusBinding { | |
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(); | ||
viewElement?.focus(preventScroll: true); | ||
} | ||
} else { | ||
viewElement?.blur(); | ||
|
@@ -70,7 +70,7 @@ final class ViewFocusBinding { | |
|
||
late final DomEventListener _handleKeyDown = createDomEventListener((DomEvent event) { | ||
event as DomKeyboardEvent; | ||
if (event.shiftKey) { | ||
if (event.shiftKey ?? false) { | ||
_viewFocusDirection = ui.ViewFocusDirection.backward; | ||
} | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -982,6 +982,22 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { | |
); | ||
_convertEventsToPointerData(data: pointerData, event: event, details: down); | ||
_callback(event, pointerData); | ||
|
||
if (event.target == _viewTarget) { | ||
// Ensure smooth focus transitions between text fields within the Flutter view. | ||
// Without preventing the default and this delay, the engine may not have fully | ||
// rendered the next input element, leading to the focus incorrectly returning to | ||
// the main Flutter view instead. | ||
// A zero-length timer is sufficient in all tested browsers to achieve this. | ||
event.preventDefault(); | ||
Timer(Duration.zero, () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be useful to comment on the choice of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PTAL
ditman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
EnginePlatformDispatcher.instance.requestViewFocusChange( | ||
viewId: _view.viewId, | ||
state: ui.ViewFocusState.focused, | ||
direction: ui.ViewFocusDirection.undefined, | ||
); | ||
}); | ||
} | ||
}); | ||
|
||
// Why `domWindow` you ask? See this fiddle: https://jsfiddle.net/ditman/7towxaqp | ||
|
Uh oh!
There was an error while loading. Please reload this page.