Status Update
Comments
lp...@google.com <lp...@google.com>
ap...@google.com <ap...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-main
Author: Anton Beloglazov <
Link:
Fix a bug where when moving focus from a parent to a child, the parent first receives an focus changed event with the Inactive state before receiving an event with the ActiveParent state.
Expand for full commit details
Fix a bug where when moving focus from a parent to a child, the parent
first receives an focus changed event with the Inactive state before
receiving an event with the ActiveParent state.
When isTrackFocusEnabled is off, the parent is not sent the Inactive
state and instead receives the ActiveParent state straight away.
Bug: 395895685
Test: RequestFocusTest
Change-Id: If4e95b5a4015f40187478f4ff506951ffb862399
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
Hash: f6d91b2ec5c1777311e5f99bc8b65f1f2f2997b0
Date: Tue Feb 18 17:16:55 2025
al...@jetbrains.com <al...@jetbrains.com> #3
Is that CL just the first in a series? For me it changes the behavior to a different, but still incorrect one.
Upon clicking the textfield and then the button, both the button and the textfield think they are focused (the button is red, the textfield has a blinking cursor).
With ComposeUiFlags.isTrackFocusEnabled = false
the behavior is different, but also incorrect. On mouse-down, the button receives focus, on mouse-up the textfield steals it back.
be...@google.com <be...@google.com> #4
Hey Alexander, your use case uncovered a few related issues in the new implementation. The CL above fixes one of them, where we were sending an extra focus change event, which was not sent in the previous implementation. I have a pending CL that fixes another issue in
I did notice that with ComposeUiFlags.isTrackFocusEnabled = false
the text field steals focus, which seems wrong. However, there is no intention to turn the flag off, as the new implementation is significantly more performant. I would like to make sure the new implementation has the correct behaviour.
ap...@google.com <ap...@google.com> #5
Project: platform/frameworks/support
Branch: androidx-main
Author: Anton Beloglazov <
Link:
Fix a focus bug where the new implementation did not dispatch the correct onFocusChange callback for the previous active node when focus moves from the parent to a child.
Expand for full commit details
Fix a focus bug where the new implementation did not dispatch the
correct onFocusChange callback for the previous active node when focus
moves from the parent to a child.
Before this change, the previous active node was receiving a callback
saying that the state changed from Inactive to ActiveParent, while in
fact the state changed from Active to ActiveParent.
Bug: 395895685
Test: FocusTargetModifierNodeTest
Change-Id: I3f799beeef354ab641e217c665b720fb0ae54f2a
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusTargetModifierNodeTest.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
Hash: 12aa54f28ab2cb1027508264e353335ef4ce308e
Date: Wed Feb 19 17:27:47 2025
al...@jetbrains.com <al...@jetbrains.com> #6
I have a pending CL that fixes another issue in
https://android-review.googlesource.com/3501610 .
Ah, thank you, I was worried that this was considered fixed.
I did notice that with ComposeUiFlags.isTrackFocusEnabled = false the text field steals focus, which seems wrong.
My guess would be that this is an issue in the textfield itself, and once the behavior of the new focus implementation is aligned with the old one, we'll see it too.
ap...@google.com <ap...@google.com> #7
Project: platform/frameworks/support
Branch: androidx-main
Author: Anton Beloglazov <
Link:
Fix a focus bug in the invalidation logic where incorrect focus events were sent when the active focus target node is a delegated node.
Expand for full commit details
Fix a focus bug in the invalidation logic where incorrect focus events
were sent when the active focus target node is a delegated node.
Bug: 395895685
Test: FocusEventCountTest
Change-Id: I9278a3e08bb4718c0601d153766f265105117ad3
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusEventCountTest.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
Hash: fcd264a09c71538829b7e146779babe638a9093a
Date: Wed Feb 26 18:23:56 2025
be...@google.com <be...@google.com> #8
I believe the last CL fixes the last remaining issue related to this use case.
I found that the issue of focus being "stolen" by the TextField
is caused by the fact that the pointerInput
modifier on the trailing icon does no consume the event. Since the event is not consumed, the TextField
handles it as well and requests the focus. To fix that, change awaitFirstDown()
to awaitFirstDown().also { it.consume() }
.
al...@jetbrains.com <al...@jetbrains.com> #9
Thanks! The bug no longer reproduces after cherry-picking these 3 commits to compose multiplatform.
be...@google.com <be...@google.com> #10
Great, thanks for confirming, Alexander!
na...@google.com <na...@google.com> #11
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.compose.ui:ui:1.8.0-rc01
androidx.compose.ui:ui-android:1.8.0-rc01
androidx.compose.ui:ui-jvmstubs:1.8.0-rc01
androidx.compose.ui:ui-linuxx64stubs:1.8.0-rc01
Description
Jetpack Compose version: 1.8.0-beta01
Jetpack Compose component used: TextField
Code Sample to Reproduce
Note that the
lineLimits
argument is there just to cause a recomposition ofTextField
, which triggers the bug. The line limits themselves are not related to the bug.Analysis
The problem appears to be with focus management; not the text field itself. The issue doesn't reproduce with
ComposeUiFlags.isTrackFocusEnabled = false
(although it seems to trigger a different issue - the text field steals the focus back on each click).The issue appears to be that when the "button" becomes focused,
TextFieldDecoratorModifierNode.onFocusEvent
receives an incorrect call (fromFocusInvalidationManager.invalidateNodesOptimized
) with aFocusState.Active
argument.Perhaps the algorithm in
FocusInvalidationManager.invalidateNodesOptimized
is incorrect? It goes up the modifier node tree, starting from the active focus target node, until it encounters the firstFocusTargetNode
infocusEventNodes
(means invalidated?), and then tells it that it isFocusState.Active
. In the case of the issue, we have is a chain like this:Now,
TextFieldDecoratorModifierNode
expects to be toldFocusState.Active
when theFocusTargetNode
of the text field is active. But the logic ofFocusInvalidationManager.invalidateNodesOptimized
is such that it will also receiveFocusState.Active
when theFocusTargetNode
of the button is active. This leads to confusion, because the text field itself is not focused at this point, butTextFieldDecoratorModifierNode
thinks that it is (isElementFocused
istrue
), and so it doesn't request focus on click.