-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix double tap & drag on Android #76791
Fix double tap & drag on Android #76791
Conversation
} | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure why this was always returning true even for cases when it wasn't actually handling the event. I've changed it to only return true when it handles the event, consistent with the other event listeners here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look correct, this callback should receive both down and up events and with this update the logic now returns false for down events, which would have the effect of cancelling the next up event.
Can you log the events passing through this method and check we are still receiving the expected flow.
@@ -197,8 +197,13 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi | |||
if (event.actionMasked == MotionEvent.ACTION_UP) { | |||
nextDownIsDoubleTap = false | |||
GodotInputHandler.handleMotionEvent(event) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, is this correct, that a ACTION_UP should trigger a motion event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct, this correspond to the release of the double tap event.
} | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look correct, this callback should receive both down and up events and with this update the logic now returns false for down events, which would have the effect of cancelling the next up event.
Can you log the events passing through this method and check we are still receiving the expected flow.
9913a04
to
6b3b0b9
Compare
Thanks for the feedback @m4gr3d, I've force pushed an update (my understanding this is the preferred workflow to keep the commit history squashed). It now maintains the original behavior, but just handles the motion event. I was able to confirm with additional logging the incorrect behavior you expected in my original attempt. We get an |
Also just noting down here, this could be implemented in the following way and I tested that it has the same behavior (my test was double tap, drag, & release, and comparing the events emitted on the GDScript side): override fun onDoubleTapEvent(event: MotionEvent): Boolean {
if (event.actionMasked == MotionEvent.ACTION_UP) {
nextDownIsDoubleTap = false
GodotInputHandler.handleMotionEvent(event)
return true
}
if (event.actionMasked == MotionEvent.ACTION_MOVE) {
GodotInputHandler.handleMotionEvent(event)
return true
}
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
// No need to handle this, just need to return true
// otherwise you get 2 extra events (pressed=true & pressed=false) when double tapping
return true
}
return false
} The version I pushed is more concise/closer to the original code. |
@@ -197,7 +197,10 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi | |||
if (event.actionMasked == MotionEvent.ACTION_UP) { | |||
nextDownIsDoubleTap = false | |||
GodotInputHandler.handleMotionEvent(event) | |||
} else if (event.actionMasked == MotionEvent.ACTION_MOVE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update, this looks like it should handle the issue!
There's one more scenario to consider and incorporate in the logic; when panning and scaling is enabled (panningAndScalingEnabled == true
), the ScaleGestureDetector
logic treats double_tap
followed by swipe
as a magnify
event:
- For the documentation, see https://developer.android.com/reference/android/view/ScaleGestureDetector#setQuickScaleEnabled(boolean)
- And the scale callback is
godot/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
Line 242 in cf8ad12
override fun onScale(detector: ScaleGestureDetector): Boolean {
This capability is still private (not exposed to GDScript) and only being used by the Android editor to support scaling in the spatial editor.
To complement your fix and not break that functionality, you'll need to check that panningAndScalingEnabled == false
before forwarding the motion event.
6b3b0b9
to
0c94750
Compare
@m4gr3d just updated to prevent handling the event in the case of this.godotGestureHandler.setPanningAndScalingEnabled(true); Let me know if this looks right! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks for the fix!
Thanks! And congrats for your first merged Godot contribution 🎉 |
Thank you so much @akien-mga !! Thank you & all the contributors who spent the time & effort creating this amazing engine & documenting everything so well that made me feel confident enough to give this a shot 🙏 |
Cherry-picked for 4.0.3. |
Cherry-picked for 3.6. |
This fix can't be cherry-picked for 3.5.x as is, the code is significantly different and I can't find easily where to do a similar change. |
This fixes #76587. This is very easy to reproduce, just compile on Android device a project which prints all input events:
In
master
, if you double tap & drag, no events are emitted for the drag. In this PR, you correctly see the drag events. This makes Android consistent with iOS and Windows (I haven't tested other platforms behavior).The fix involves listening for motion events in the
onDoubleTapEvent
listener, because the native AndroidGestureDetector
differentiates between motion events after a double tap and regular motion events.