Use fling tap down gesture as a signal for touchpad contact
... to show the mouse cursor icon immediately upon contact with the
touchpad.
While the gestures library contains kGestureTypeContactInitiated, it is
no longer used. Instead, when there is contact with the touchpad, the
library produces a fling tap down gesture.
The fling tap down gesture can be used as a signal to mark the end of a
previouly started fling event. However, since the fling tap down gesture
being generated roughly corresponds to a stable contact being detected in
the current version of the library, we can use it as an
alias for "contact initiated" as a workaround. This works because the
fling tap down gesture is produced even if there was no fling start
gesture produced in the past.
Whenever we detect that a contact is initiated, we treat is as a move
event of zero magnitude so that the mouse cursor is shown and a hover
event is produced for apps to update their UI.
An alternative approach that was considered was to track touching
pointers from the evdev state, and use that ensure PointerController is
showing the cursor whenever there is a valid pointer. This was
disregarded as it could lead to inconsistencies with the gesture
library. For example, if the gestures library immediately detects a
contact as a palm, we don't want the cursor to be shown.
Bug: 281671810
Test: atest inputflinger_tests
Test: manual, with touchpad
Change-Id: I01dbdd8a139cc6766fcd7e545a961e32237c2af9
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 84de7d5..7eca6fa 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -315,15 +315,34 @@
std::list<NotifyArgs> GestureConverter::handleFling(nsecs_t when, nsecs_t readTime,
const Gesture& gesture) {
- // We don't actually want to use the gestures library's fling velocity values (to ensure
- // consistency between touchscreen and touchpad flings), so we're just using the "start fling"
- // gestures as a marker for the end of a two-finger scroll gesture.
- if (gesture.details.fling.fling_state != GESTURES_FLING_START ||
- mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
- return {};
+ switch (gesture.details.fling.fling_state) {
+ case GESTURES_FLING_START:
+ if (mCurrentClassification == MotionClassification::TWO_FINGER_SWIPE) {
+ // We don't actually want to use the gestures library's fling velocity values (to
+ // ensure consistency between touchscreen and touchpad flings), so we're just using
+ // the "start fling" gestures as a marker for the end of a two-finger scroll
+ // gesture.
+ return {endScroll(when, readTime)};
+ }
+ break;
+ case GESTURES_FLING_TAP_DOWN:
+ if (mCurrentClassification == MotionClassification::NONE) {
+ // Use the tap down state of a fling gesture as an indicator that a contact
+ // has been initiated with the touchpad. We treat this as a move event with zero
+ // magnitude, which will also result in the pointer icon being updated.
+ // TODO(b/282023644): Add a signal in libgestures for when a stable contact has been
+ // initiated with a touchpad.
+ return {handleMove(when, readTime,
+ Gesture(kGestureMove, gesture.start_time, gesture.end_time,
+ /*dx=*/0.f,
+ /*dy=*/0.f))};
+ }
+ break;
+ default:
+ break;
}
- return {endScroll(when, readTime)};
+ return {};
}
NotifyMotionArgs GestureConverter::endScroll(nsecs_t when, nsecs_t readTime) {
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index c6d541e..a723636 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -888,4 +888,21 @@
WithToolType(ToolType::FINGER)));
}
+TEST_F(GestureConverterTest, FlingTapDown) {
+ InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
+ GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
+
+ Gesture tapDownGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
+ /*vx=*/0.f, /*vy=*/0.f, GESTURES_FLING_TAP_DOWN);
+ std::list<NotifyArgs> args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, tapDownGesture);
+
+ ASSERT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ WithCoords(POINTER_X, POINTER_Y), WithRelativeMotion(0.f, 0.f),
+ WithToolType(ToolType::FINGER), WithButtonState(0), WithPressure(0.0f)));
+
+ ASSERT_NO_FATAL_FAILURE(mFakePointerController->assertPosition(POINTER_X, POINTER_Y));
+ ASSERT_TRUE(mFakePointerController->isPointerShown());
+}
+
} // namespace android