Status Update
Comments
lp...@google.com <lp...@google.com> #2
First of all thanks for this detailed issue.
This issue had been investigated thoroughly when it was first reported internally. The surprising detail in this report is that the issue is not reproducible before 1.7
. I will look into this.
The main problem with POBox is the fact that it is deprecated. Since 2021 Sony has been shipping new Xperia devices with Gboard pre-installed. Although we are aware that there is still a considerable amount of users still using POBox, the described behavior is caused by POBox's noncompliant behavior with InputConnection
and InputMethodManager
documentation. However, this is understandable since TextView
implementation was also not respecting the behavior that is expected from Editors.
Ultimately we have decided to enforce the documented behavior with specifically regards to when editors should call InputMethodManager.updateSelection
. Also, although unconfirmed, there were traces of possible custom code being included in Sony OEM images that changed how InputMethodManager was notified from TextView. If POBox also depended on something like this, it would be impossible for Compose code to replicate the same unknown behavior.
ap...@google.com <ap...@google.com> #3
Or is that option not available?
Even if the root cause is POBox, from the perspective of the app's customers, it looks like an app bug, so this issue is a blocker against updating Jetpack Compose.
ap...@google.com <ap...@google.com> #4
Just to be sure, it is dangerous to replace Compose TextField with Android View EditText as a workaround for this issue.
Compose 1.7 has a bug that causes ANR when the focus is on EditText.
Another View-related bug in Compose 1.7 is that an Android View is focused by calling FocusManager.clearFocus().
Perhaps there is a lack of testing of Compose 1.7 in combination with Android View. There is also a possibility that there are other fatal bugs related to View.
In other words, the only options for apps targeting the Japanese market that require POBox support are to continue using Compose 1.6 or to use EditText in combination with various workarounds.
lp...@google.com <lp...@google.com>
ma...@google.com <ma...@google.com>
ap...@google.com <ap...@google.com> #5
Project: platform/frameworks/support
Branch: androidx-main
Author: Halil Ozercan <
Link:
Fix POBox keyboard issue
Expand for full commit details
Fix POBox keyboard issue
Fix: 373743376
Fix: 329209241
Test: NullableInputConnectionWrapperTest
Change-Id: I94e0e598274fb88b255f977f9fbd50dfbbb1ecb1
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapperTest.kt
- M
compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapper.android.kt
Hash: 57f58c4b80d5d8470b2aca325dfdcd55f235231e
Date: Thu Oct 24 01:25:20 2024
ju...@google.com <ju...@google.com> #6
Many thanks again for this report. Especially for giving us a huge clue in terms of what could be going wrong. The fix is now merged and I will ask for a cherry-pick into a stable release.
jo...@muzz.com <jo...@muzz.com> #7
Do you have any concrete plan to cherry-pick the fix into current stable version (1.7.x)? We are currently waiting it.
lp...@google.com <lp...@google.com> #8
Yes, this fix is planned to be included in a future 1.7.x
release.
jd...@google.com <jd...@google.com> #9
Thanks for the fix. Sorry to follow up on this. is it possible for you to share specific release version/date for the stable version? We are waiting on this to decide on our direction.
lp...@google.com <lp...@google.com> #10
That said there might be other use cases that care about scrollable containers separately, such as scrolling screenshots, so it's unclear what the overlap is and what the API(s) that would accomplish these use cases in a consistent manner are. I might be able to do a brief exploration though to see what we would need to do to unblock at least some of the current use cases.
For your custom gesture handler, what are the 'rules' for the transitions here - does it convert horizontal / vertical swipes past a touch slop into a transition?
jd...@google.com <jd...@google.com> #11
Thanks for the quick reply!
For your custom gesture handler, what are the 'rules' for the transitions here - does it convert horizontal / vertical swipes past a touch slop into a transition?
Yes that's exactly what it does, using awaitHorizontalTouchSlopOrCancellation
and awaitVerticalTouchSlopOrCancellation
:-) We had to fork Draggable
because we also needed to support multiple fingers down. See the code in
jd...@google.com <jd...@google.com> #12
@lpf any update on this by any chance? :-)
lp...@google.com <lp...@google.com> #13
jd...@google.com <jd...@google.com> #14
Any news? :-) Pinging this again because this is preventing us from correctling measuring performance on some of our benchmarks: when the ripple is triggered during a transition, it's causing a lot of frames to be marked as dropped. See
lp...@google.com <lp...@google.com> #15
There's work planned in this space in our general tracker, but not at a high priority compared to other ongoing work.
For the benchmark case specifically, you could still end up in cases where the ripple is triggered if the gesture is 'slow' so that the move doesn't start until after the minimum press time: what specifically is your goal here for the benchmarks?
jd...@google.com <jd...@google.com> #16
what specifically is your goal here for the benchmarks?
I want the benchmark to be stable and have the least number of dropped frames. But we also want to make sure that in most cases this path is not triggered in production, so I don't want to just disable ripples in the benchmark either. Once we can disable the ripple inside our custom draggable, I'll make sure that the benchmark gesture is fast enough to not trigger the ripple.
jj...@google.com <jj...@google.com> #17
FYI this is real jank, not just showing up in the benchmark.
lp...@google.com <lp...@google.com> #18
I'll make sure that the benchmark gesture is fast enough to not trigger the ripple.
Hard to say without looking into some method traces for this, but it is likely that most of the cost isn't in drawing the ripple itself (because this is all done on the render thread), but in creating the ripple node in preparation to draw it. So even if you were to delay the interaction, it might still be slower regardless.
Do you have a link to the component with the ripple?
jj...@google.com <jj...@google.com> #19
updates. Some history here:
On Fri, May 24, 2024 at 6:21 PM lpf <buganizer-system+lpf@google.com> wrote:
lp...@google.com <lp...@google.com> #20
Not sure I understand the discussion in that bug, but it sounds like a framework issue on some API levels? Is there something actionable from the Compose side to mitigate this issue?
jj...@google.com <jj...@google.com> #21
Friendly ping on this - note this is a clear regression from the View framework. View's are able to handle this properly.
jd...@google.com <jd...@google.com> #22
To make sure there is no misunderstanding of the bug, here is an example that shows that the ripple is not triggered when dragging a clickable View
but that is is triggered when dragging a clickable Composable :-) See the video below.
import android.widget.Button
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.draggable2D
import androidx.compose.foundation.gestures.rememberDraggable2DState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import androidx.compose.ui.viewinterop.AndroidView
@Composable
fun DraggableDemo(modifier: Modifier = Modifier) {
Column(modifier.fillMaxSize()) {
var offset by remember { mutableStateOf(Offset.Zero) }
Box(
Modifier.offset { offset.round() }
.draggable2D(rememberDraggable2DState { offset += it })
.size(200.dp)
.border(1.dp, Color.Red),
contentAlignment = Alignment.Center,
) {
Column {
Button(onClick = {}) { Text("Compose button") }
AndroidView(factory = { Button(it).apply { text = "View button" } })
}
}
}
}
lp...@google.com <lp...@google.com> #23
For this issue specifically, all AndroidViews inside Compose are treated defensively as if they might scroll, so ripples will always be delayed (even if there is nothing scrollable in the hierarchy). In the future when we have public API we would implement this to follow the same logic used within compose.
For the compose case, we only apply this logic to scrollable() and other scrolling containers, not to draggable. If the 'issue' here is that you want the compose case to not instantly show a ripple, as a workaround if you add an empty scrollable with zero size somewhere in the hierarchy above the rippling component, it might work.
Note that this work is tracked in our backlog, but not being actively worked on / won't be for a minimum of a few months.
jd...@google.com <jd...@google.com> #24
For the compose case, we only apply this logic to scrollable() and other scrolling containers, not to draggable
Any chance we can have an early experimental version of a public API to be able to do the same in our custom pointer inputs/draggables?
lp...@google.com <lp...@google.com> #25
Current update:
There are some similar issues in the same problem space that we aim to solve together, rather than trying to patch over these issues with different hard-to-maintain APIs. Basically there's a general issue here of gesture coordination, where high level gestures (e.g 'drag') need some level of coordination between each other. This is true for this case, cases like handling touch slop for multiple lazy lists, etc.
The current loose idea is building some higher level abstraction around gestures, built on top of pointerInput. E.g you could imagine some Modifier.gesture() API, that allows for some higher level logic, and communication between gestures in a hierarchy. As mentioned previously this is on our backlog, and this should solve this specific bug too when we get around to implementing it
Description
In b/168524931 we globally added a delay before emitting a
PressInteraction
in case we are in a scrollable container, and in case the 'down' event is actually part of a scroll. This is important so that we don't show a ripple if the user is actually beginning a scroll motion.However, currently because we don't have any 'in scrollable container' metadata, this is globally enabled, whether or not we actually need to delay. This has the unfortunate effect of delaying
PressInteraction
s unnecessarily, and hence causing ripples and other indication to be delayed and feel laggy.With the recently added
ModifierLocal
APIs, we can now provide and consume this metadata, so we should now implement support for this so we only delayPressInteraction
s if necessary.Compose work:
ModifierLocal
to represent scrollable container metadataModifier.scrollable
- this is used in other APIs such as lazy lists andModifier.verticalScroll
, so just setting it here should cover all cases.PressInteraction
, so that we only delay if we are truly inside a scrollable containerInterop work:
ComposeView
is in a scrollable container, as even if there are no scrollable containers in the Compose part of the hierarchy, if theComposeView
itself is in a scrollableViewGroup
, we should still delay pressesAndroidViewHolder
should also consume this metadata and use it to overrideViewGroup#shouldDelayChildPressedState()
, so anyView
s hosted inside of Compose can also delay their pressed state if they are inside scrollable Compose containers, or inside non-scrollable Compose containers inside a non-scrollableAndroidView
inside a scrollable Compose container...Because the interop work requires APIs between
ui
andfoundation
(presumably theModifierLocal
needs to be public API inui
, so we can use it fromfoundation
), for now we can just ignore theAndroidViewHolder
support, and just queryLocalView
instead of setting this metadata at theComposeView
layer to unblock the most common cases.